summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--std/wasi/snapshot_preview1.ts21
-rw-r--r--std/wasi/snapshot_preview1_test.ts22
2 files changed, 40 insertions, 3 deletions
diff --git a/std/wasi/snapshot_preview1.ts b/std/wasi/snapshot_preview1.ts
index 4c974fe1d..30756fe82 100644
--- a/std/wasi/snapshot_preview1.ts
+++ b/std/wasi/snapshot_preview1.ts
@@ -207,6 +207,10 @@ function syscall<T extends CallableFunction>(target: T) {
try {
return target(...args);
} catch (err) {
+ if (err instanceof ExitStatus) {
+ throw err;
+ }
+
switch (err.name) {
case "NotFound":
return ERRNO_NOENT;
@@ -266,15 +270,25 @@ interface FileDescriptor {
entries?: Deno.DirEntry[];
}
+export class ExitStatus {
+ code: number;
+
+ constructor(code: number) {
+ this.code = code;
+ }
+}
+
export interface ContextOptions {
args?: string[];
env?: { [key: string]: string | undefined };
preopens?: { [key: string]: string };
+ exitOnReturn?: boolean;
}
export default class Context {
args: string[];
env: { [key: string]: string | undefined };
+ exitOnReturn: boolean;
memory: WebAssembly.Memory;
fds: FileDescriptor[];
@@ -284,6 +298,7 @@ export default class Context {
constructor(options: ContextOptions) {
this.args = options.args ? options.args : [];
this.env = options.env ? options.env : {};
+ this.exitOnReturn = options.exitOnReturn ?? true;
this.memory = null!;
this.fds = [
@@ -1497,7 +1512,11 @@ export default class Context {
"proc_exit": syscall((
rval: number,
): never => {
- Deno.exit(rval);
+ if (this.exitOnReturn) {
+ Deno.exit(rval);
+ }
+
+ throw new ExitStatus(rval);
}),
"proc_raise": syscall((
diff --git a/std/wasi/snapshot_preview1_test.ts b/std/wasi/snapshot_preview1_test.ts
index d7e29e195..01b91bc3e 100644
--- a/std/wasi/snapshot_preview1_test.ts
+++ b/std/wasi/snapshot_preview1_test.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import Context from "./snapshot_preview1.ts";
-import { assertEquals, assertThrows } from "../testing/asserts.ts";
+import Context, { ExitStatus } from "./snapshot_preview1.ts";
+import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
import { copy } from "../fs/mod.ts";
import * as path from "../path/mod.ts";
@@ -179,6 +179,24 @@ Deno.test("context_start", function () {
TypeError,
"export _start must be a function",
);
+
+ try {
+ const context = new Context({
+ exitOnReturn: false,
+ });
+ context.start({
+ exports: {
+ _start() {
+ const exit = context.exports["proc_exit"] as CallableFunction;
+ exit(0);
+ },
+ memory: new WebAssembly.Memory({ initial: 1 }),
+ },
+ });
+ } catch (err) {
+ assert(err instanceof ExitStatus);
+ assertEquals(err.code, 0);
+ }
});
Deno.test("context_initialize", function () {