From c34940cd0354a0d2c6b32878e9958cb600fc0d42 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 1 Sep 2026 00:58:56 +0000 Subject: [PATCH] src: add a flag to keep the embedder's wasm streaming callback `SetIsolateMiscHandlers()` always installs Node.js's `WebAssembly.compileStreaming()` implementation, which is backed by the Environment's fetch-based handler. An embedder that provides its own streaming callback (for example one wired to its own network stack) has to re-install it after every `SetIsolateUpForNode()` or `NewIsolate()` call. Add `SHOULD_NOT_SET_WASM_STREAMING_CALLBACK` next to the existing `SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK` and `SHOULD_NOT_SET_PREPARE_STACK_TRACE_CALLBACK` flags so it can opt out the same way. Refs: https://github.com/nodejs/node/pull/36447 Signed-off-by: Shelley Vohr --- src/api/environment.cc | 4 +++- src/node.h | 1 + test/cctest/test_environment.cc | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/api/environment.cc b/src/api/environment.cc index 459830a2af80..316da3741785 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -269,7 +269,9 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) { isolate->SetModifyCodeGenerationFromStringsCallback( modify_code_generation_from_strings_callback); - isolate->SetWasmStreamingCallback(wasm_web_api::StartStreamingCompilation); + if ((s.flags & SHOULD_NOT_SET_WASM_STREAMING_CALLBACK) == 0) { + isolate->SetWasmStreamingCallback(wasm_web_api::StartStreamingCompilation); + } Mutex::ScopedLock lock(node::per_process::cli_options_mutex); if (per_process::cli_options->get_per_isolate_options() diff --git a/src/node.h b/src/node.h index e827a46e14dd..61c85884521f 100644 --- a/src/node.h +++ b/src/node.h @@ -420,6 +420,7 @@ enum IsolateSettingsFlags { DETAILED_SOURCE_POSITIONS_FOR_PROFILING = 1 << 1, SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK = 1 << 2, SHOULD_NOT_SET_PREPARE_STACK_TRACE_CALLBACK = 1 << 3, + SHOULD_NOT_SET_WASM_STREAMING_CALLBACK = 1 << 4, ALLOW_MODIFY_CODE_GENERATION_FROM_STRINGS_CALLBACK = 0, /* legacy no-op */ }; diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index 109e224f788d..e84a6d9c1f97 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -60,6 +60,39 @@ TEST_F(EnvironmentTest, ManagedBufferCache) { (*env)->release_managed_buffer(buffer); } +static int embedder_wasm_streaming_calls = 0; +static void EmbedderWasmStreaming(const v8::FunctionCallbackInfo&) { + embedder_wasm_streaming_calls++; +} + +TEST_F(EnvironmentTest, KeepsEmbedderWasmStreamingCallbackWhenAsked) { + const v8::HandleScope handle_scope(isolate_); + const Argv argv; + Env env{handle_scope, argv}; + + auto compile_streaming = [&]() { + v8::Local context = isolate_->GetCurrentContext(); + v8::Script::Compile(context, + v8::String::NewFromUtf8Literal( + isolate_, "WebAssembly.compileStreaming(0); 0")) + .ToLocalChecked() + ->Run(context) + .ToLocalChecked(); + isolate_->PerformMicrotaskCheckpoint(); + }; + + node::IsolateSettings settings; + settings.flags |= node::SHOULD_NOT_SET_WASM_STREAMING_CALLBACK; + isolate_->SetWasmStreamingCallback(EmbedderWasmStreaming); + node::SetIsolateUpForNode(isolate_, settings); + compile_streaming(); + EXPECT_EQ(embedder_wasm_streaming_calls, 1); + + node::SetIsolateUpForNode(isolate_); + compile_streaming(); + EXPECT_EQ(embedder_wasm_streaming_calls, 1); +} + TEST_F(EnvironmentTest, EnvironmentWithoutBrowserGlobals) { const v8::HandleScope handle_scope(isolate_); Argv argv;