diff --git a/src/env.h b/src/env.h index 7a4804cdd45481..de8689f8a158fc 100644 --- a/src/env.h +++ b/src/env.h @@ -194,6 +194,7 @@ struct PackageConfig { V(message_port_string, "messagePort") \ V(message_port_constructor_string, "MessagePort") \ V(minttl_string, "minttl") \ + V(module_string, "Module") \ V(modulus_string, "modulus") \ V(name_string, "name") \ V(netmask_string, "netmask") \ @@ -288,6 +289,7 @@ struct PackageConfig { V(valid_from_string, "valid_from") \ V(valid_to_string, "valid_to") \ V(value_string, "value") \ + V(webassembly_string, "WebAssembly") \ V(verify_error_string, "verifyError") \ V(version_string, "version") \ V(weight_string, "weight") \ diff --git a/src/node.cc b/src/node.cc index c562403379bf22..53b6fcd5728de2 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3732,6 +3732,37 @@ bool AllowWasmCodeGenerationCallback( return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue(); } +void WasmCreateModule(const FunctionCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info.GetIsolate()); + Local context = env->context(); + Local buffer = info[0]; + CHECK(!buffer.IsEmpty()); + + Local wasm = Local::Cast( + context->Global()->Get(context, env->webassembly_string()) + .ToLocalChecked()); + Local module = Local::Cast(wasm->Get(context, + env->module_string()).ToLocalChecked()); + Local args[] = {buffer}; + Local module_instance = module->NewInstance(context, 1, args) + .ToLocalChecked(); + info.GetReturnValue().Set(module_instance); +} + +void WasmInstantiateStreamingCallback(const FunctionCallbackInfo& info) { + Environment* env = Environment::GetCurrent(info.GetIsolate()); + Local context = env->context(); + CHECK(!info[0]->IsUndefined()); + CHECK(info[0]->IsPromise()); + Local buffer_promise = info[0].As(); + + Local create_module = Function::New(context, WasmCreateModule) + .ToLocalChecked(); + Local module_promise = buffer_promise->Then(context, create_module) + .ToLocalChecked(); + info.GetReturnValue().Set(module_promise); +} + Isolate* NewIsolate(ArrayBufferAllocator* allocator) { Isolate::CreateParams params; params.array_buffer_allocator = allocator; @@ -3748,6 +3779,7 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator) { isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); isolate->SetFatalErrorHandler(OnFatalError); isolate->SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback); + isolate->SetWasmCompileStreamingCallback(WasmInstantiateStreamingCallback); return isolate; } diff --git a/test/fixtures/instantiate_streaming.wasm b/test/fixtures/instantiate_streaming.wasm new file mode 100644 index 00000000000000..fbdbb7316268f9 Binary files /dev/null and b/test/fixtures/instantiate_streaming.wasm differ diff --git a/test/fixtures/instantiate_streaming.wat b/test/fixtures/instantiate_streaming.wat new file mode 100644 index 00000000000000..47d853201265f7 --- /dev/null +++ b/test/fixtures/instantiate_streaming.wat @@ -0,0 +1,9 @@ +;; $ wat2wasm instantiate_streaming.wat -o instantiate_streaming.wasm +(module + (func $add (import "test" "add") (param i32) (param i32) (result i32)) + (func (export "add") (param i32) (param i32) (result i32) + get_local 0 + get_local 1 + call $add + ) +) diff --git a/test/parallel/test-wasm-instantiatestreaming.js b/test/parallel/test-wasm-instantiatestreaming.js new file mode 100644 index 00000000000000..0ec2a9fae8f425 --- /dev/null +++ b/test/parallel/test-wasm-instantiatestreaming.js @@ -0,0 +1,23 @@ +'use strict'; + +// This test verifies that instantiateStreaming can be used with node. + +require('../common'); +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const fs = require('fs'); + +const promise = fs.promises.readFile( + fixtures.path('instantiate_streaming.wasm')); + +// Using an import object just to verify that this works without anything +// needed to be specifically implemented for it to work. +const importObject = { + test: { + add: (arg1, arg2) => arg1 + arg2 + }, +} + +WebAssembly.instantiateStreaming(promise, importObject).then((results) => { + assert.strictEqual(results.instance.exports.add(2, 3), 5); +});