summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2020-11-03 01:50:45 +0800
committerGitHub <noreply@github.com>2020-11-02 18:50:45 +0100
commitc5611636fb03ce71f50a9bca958c79d23b55be00 (patch)
treed9e5e3c9fbae15c7e0d636bd823e618d6a2cffef
parenta8ca9fe7bb93d031af865ffcf45fb265395f1e1b (diff)
feat(std/wasi): add start method to Context (#8141)
This adds a start method to the Context to make starting a command less tedious and yield consistent errors. Manually setting the memory is still valid for more complex scenarios, just undocumented for the time being.
-rw-r--r--std/wasi/README.md18
-rw-r--r--std/wasi/snapshot_preview1.ts38
-rw-r--r--std/wasi/snapshot_preview1_test.ts45
-rw-r--r--std/wasi/snapshot_preview1_test_runner.ts6
4 files changed, 82 insertions, 25 deletions
diff --git a/std/wasi/README.md b/std/wasi/README.md
index 1f78e9ac7..829b25174 100644
--- a/std/wasi/README.md
+++ b/std/wasi/README.md
@@ -68,21 +68,5 @@ const instance = await WebAssembly.instantiate(module, {
"wasi_snapshot_preview1": context.exports,
});
-const {
- _start: start,
- _initialize: initialize,
- memory,
-} = instance.exports;
-
-context.memory = memory as WebAssembly.Memory;
-
-if (start instanceof Function) {
- start();
-} else if (initialize instanceof Function) {
- initialize();
-} else {
- throw new Error(
- "No '_start' or '_initialize' entry point found in WebAssembly module, make sure to compile with wasm32-wasi as the target.",
- );
-}
+context.start(instance);
```
diff --git a/std/wasi/snapshot_preview1.ts b/std/wasi/snapshot_preview1.ts
index 1d9549f15..eb296c47d 100644
--- a/std/wasi/snapshot_preview1.ts
+++ b/std/wasi/snapshot_preview1.ts
@@ -270,7 +270,6 @@ export interface ContextOptions {
args?: string[];
env?: { [key: string]: string | undefined };
preopens?: { [key: string]: string };
- memory?: WebAssembly.Memory;
}
export default class Context {
@@ -285,7 +284,7 @@ export default class Context {
constructor(options: ContextOptions) {
this.args = options.args ? options.args : [];
this.env = options.env ? options.env : {};
- this.memory = options.memory!;
+ this.memory = null!;
this.fds = [
{
@@ -1554,4 +1553,39 @@ export default class Context {
}),
};
}
+
+ /**
+ * Attempt to begin execution of instance as a command by invoking its
+ * _start() export.
+ *
+ * If the instance does not contain a _start() export, or if the instance
+ * contains an _initialize export an error will be thrown.
+ *
+ * The instance must also have a WebAssembly.Memory export named "memory"
+ * which will be used as the address space, if it does not an error will be
+ * thrown.
+ */
+ start(instance: WebAssembly.Instance) {
+ const { _start, _initialize, memory } = instance.exports;
+
+ if (!(memory instanceof WebAssembly.Memory)) {
+ throw new TypeError("WebAsembly.instance must provide a memory export");
+ }
+
+ this.memory = memory;
+
+ if (typeof _initialize == "function") {
+ throw new TypeError(
+ "WebAsembly.instance export _initialize must not be a function",
+ );
+ }
+
+ if (typeof _start != "function") {
+ throw new TypeError(
+ "WebAssembly.Instance export _start must be a function",
+ );
+ }
+
+ _start();
+ }
}
diff --git a/std/wasi/snapshot_preview1_test.ts b/std/wasi/snapshot_preview1_test.ts
index 0ea57e089..44877117c 100644
--- a/std/wasi/snapshot_preview1_test.ts
+++ b/std/wasi/snapshot_preview1_test.ts
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { assertEquals } from "../testing/asserts.ts";
+import Context from "./snapshot_preview1.ts";
+import { assertEquals, assertThrows } from "../testing/asserts.ts";
import { copy } from "../fs/mod.ts";
import * as path from "../path/mod.ts";
@@ -137,3 +138,45 @@ for (const pathname of tests) {
},
});
}
+
+Deno.test("context_start", function () {
+ assertThrows(
+ () => {
+ const context = new Context({});
+ context.start({
+ exports: {
+ _start() {},
+ },
+ });
+ },
+ TypeError,
+ "must provide a memory export",
+ );
+
+ assertThrows(
+ () => {
+ const context = new Context({});
+ context.start({
+ exports: {
+ _initialize() {},
+ memory: new WebAssembly.Memory({ initial: 1 }),
+ },
+ });
+ },
+ TypeError,
+ "export _initialize must not be a function",
+ );
+
+ assertThrows(
+ () => {
+ const context = new Context({});
+ context.start({
+ exports: {
+ memory: new WebAssembly.Memory({ initial: 1 }),
+ },
+ });
+ },
+ TypeError,
+ "export _start must be a function",
+ );
+});
diff --git a/std/wasi/snapshot_preview1_test_runner.ts b/std/wasi/snapshot_preview1_test_runner.ts
index 39f32db57..65cb7bd3b 100644
--- a/std/wasi/snapshot_preview1_test_runner.ts
+++ b/std/wasi/snapshot_preview1_test_runner.ts
@@ -16,8 +16,4 @@ const instance = new WebAssembly.Instance(module, {
"wasi_snapshot_preview1": context.exports,
});
-const memory = instance.exports.memory as WebAssembly.Memory;
-context.memory = memory;
-
-const start = instance.exports._start as CallableFunction;
-start();
+context.start(instance);