diff --git a/wasi/snapshot_preview1.ts b/wasi/snapshot_preview1.ts index eb296c47db16..4c974fe1dd46 100644 --- a/wasi/snapshot_preview1.ts +++ b/wasi/snapshot_preview1.ts @@ -1588,4 +1588,37 @@ export default class Context { _start(); } + + /** + * Attempt to initialize instance as a reactor by invoking its _initialize() export. + * + * If instance contains a _start() export, then an exception is 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. + */ + initialize(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 _start == "function") { + throw new TypeError( + "WebAssembly.Instance export _start must not be a function", + ); + } + + if (typeof _initialize != "function") { + throw new TypeError( + "WebAsembly.instance export _initialize must be a function", + ); + } + + _initialize(); + } } diff --git a/wasi/snapshot_preview1_test.ts b/wasi/snapshot_preview1_test.ts index 44877117cc01..d7e29e19597b 100644 --- a/wasi/snapshot_preview1_test.ts +++ b/wasi/snapshot_preview1_test.ts @@ -180,3 +180,45 @@ Deno.test("context_start", function () { "export _start must be a function", ); }); + +Deno.test("context_initialize", function () { + assertThrows( + () => { + const context = new Context({}); + context.initialize({ + exports: { + _initialize() {}, + }, + }); + }, + TypeError, + "must provide a memory export", + ); + + assertThrows( + () => { + const context = new Context({}); + context.initialize({ + exports: { + _start() {}, + memory: new WebAssembly.Memory({ initial: 1 }), + }, + }); + }, + TypeError, + "export _start must not be a function", + ); + + assertThrows( + () => { + const context = new Context({}); + context.initialize({ + exports: { + memory: new WebAssembly.Memory({ initial: 1 }), + }, + }); + }, + TypeError, + "export _initialize must be a function", + ); +});