Skip to content

Commit

Permalink
feat(wasi): add start method to Context (denoland/deno#8141)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
caspervonb authored and denobot committed Feb 1, 2021
1 parent 9cecf19 commit ce6a3ff
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 25 deletions.
18 changes: 1 addition & 17 deletions wasi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```
38 changes: 36 additions & 2 deletions wasi/snapshot_preview1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 = [
{
Expand Down Expand Up @@ -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();
}
}
45 changes: 44 additions & 1 deletion wasi/snapshot_preview1_test.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand Down Expand Up @@ -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",
);
});
6 changes: 1 addition & 5 deletions wasi/snapshot_preview1_test_runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

0 comments on commit ce6a3ff

Please sign in to comment.