diff options
author | Gus Caplan <me@gus.host> | 2022-04-23 19:23:18 -0500 |
---|---|---|
committer | Gus Caplan <me@gus.host> | 2022-04-23 19:23:18 -0500 |
commit | 9627235c1325ed03eb170a3f339104e5ae72cef5 (patch) | |
tree | f1f0dd2ed74a4ba1f0d0987f59a8f33a594d934b | |
parent | f9e0c4d5d22bb9a1bc2455c6f862e045381d2b7c (diff) | |
download | node-new-feature/wasm-streaming-handler.tar.gz |
-rw-r--r-- | doc/api/v8.md | 25 | ||||
-rw-r--r-- | lib/internal/bootstrap/pre_execution.js | 11 | ||||
-rw-r--r-- | src/node_wasm_web_api.cc | 6 |
3 files changed, 36 insertions, 6 deletions
diff --git a/doc/api/v8.md b/doc/api/v8.md index 03c8e0e957..f0210fc483 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -600,6 +600,31 @@ added: v8.0.0 A subclass of [`Deserializer`][] corresponding to the format written by [`DefaultSerializer`][]. +## `v8.setWasmStreamingHandler(handler)` + +* `handler` {object} + * `get` {function} + * `url` {string} + * `set` {function} + * `url` {string} + * `buffer` {ArrayBuffer} + * `delete` {function} + * `url` + +```js +import { setWasmStreamingHandler } from 'node:v8'; +import * as fs from 'node:fs/promises'; + +setWasmStreamingHandler({ + get: (url) => fs.readFile(`./${url}.cache`), + set: (url, buffer) => fs.writeFile(`./${url}.cache`, buffer), + delete: (url) => fs.unlink(`./${url}.cache`), +}); + +WebAssembly.instantiateStreaming(fetch('https://example.com/some.wasm')) + .then(() => {}); +``` + ## Promise hooks The `promiseHooks` interface can be used to track promise lifecycle events. diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index 3724e9fb9a..08cc5807b4 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -246,12 +246,12 @@ function setupFetch() { } const handler = require('internal/v8').getWasmStreamingHandler(); - const cached = handler?.get(response.url); + const cached = await handler?.get(response.url); if (cached !== undefined && cache !== null) { if (streamState.setCompiledModuleBytes(cached)) { return; } else { - handler.delete(response.url); + await handler.delete(response.url); } } @@ -270,8 +270,13 @@ function setupFetch() { }, (url, buffer) => { const handler = require('internal/v8').getWasmStreamingHandler(); try { - handler?.set(url, buffer); + Promise.resolve(handler?.set(url, buffer)) + .catch((e) => { + const { triggerUncaughtException } = internalBinding('errors'); + triggerUncaughtException(e, true); + }); } catch (e) { + const { triggerUncaughtException } = internalBinding('errors'); triggerUncaughtException(e, false); } }); diff --git a/src/node_wasm_web_api.cc b/src/node_wasm_web_api.cc index 9a5adc0db5..ab1a3802a3 100644 --- a/src/node_wasm_web_api.cc +++ b/src/node_wasm_web_api.cc @@ -170,12 +170,12 @@ void WasmStreamingObject::SetCompiledModuleBytes( size_t offset; size_t size; - if (LIKELY(chunk->IsArrayBufferView())) { + if (chunk->IsArrayBufferView()) { Local<ArrayBufferView> view = chunk.As<ArrayBufferView>(); bytes = view->Buffer()->GetBackingStore()->Data(); offset = view->ByteOffset(); size = view->ByteLength(); - } else if (LIKELY(chunk->IsArrayBuffer())) { + } else if (chunk->IsArrayBuffer()) { Local<ArrayBuffer> buffer = chunk.As<ArrayBuffer>(); bytes = buffer->GetBackingStore()->Data(); offset = 0; @@ -183,7 +183,7 @@ void WasmStreamingObject::SetCompiledModuleBytes( } else { return node::THROW_ERR_INVALID_ARG_TYPE( Environment::GetCurrent(args), - "chunk must be an ArrayBufferView or an ArrayBuffer"); + "buffer must be an ArrayBufferView or an ArrayBuffer"); } bool bytes_used = obj->streaming_->SetCompiledModuleBytes( |