1'use strict'; 2 3const { 4 PromiseResolve, 5} = primordials; 6const { 7 ERR_INVALID_ARG_TYPE, 8 ERR_WEBASSEMBLY_RESPONSE, 9} = require('internal/errors').codes; 10 11let undici; 12function lazyUndici() { 13 return undici ??= require('internal/deps/undici/undici'); 14} 15 16// This is essentially an implementation of a v8::WasmStreamingCallback, except 17// that it is implemented in JavaScript because the fetch() implementation is 18// difficult to use from C++. See lib/internal/process/pre_execution.js and 19// src/node_wasm_web_api.cc that interact with this function. 20function wasmStreamingCallback(streamState, source) { 21 (async () => { 22 const response = await PromiseResolve(source); 23 if (!(response instanceof lazyUndici().Response)) { 24 throw new ERR_INVALID_ARG_TYPE( 25 'source', ['Response', 'Promise resolving to Response'], response); 26 } 27 28 const contentType = response.headers.get('Content-Type'); 29 if (contentType !== 'application/wasm') { 30 throw new ERR_WEBASSEMBLY_RESPONSE( 31 `has unsupported MIME type '${contentType}'`); 32 } 33 34 if (!response.ok) { 35 throw new ERR_WEBASSEMBLY_RESPONSE( 36 `has status code ${response.status}`); 37 } 38 39 if (response.bodyUsed !== false) { 40 throw new ERR_WEBASSEMBLY_RESPONSE('body has already been used'); 41 } 42 43 if (response.url) { 44 streamState.setURL(response.url); 45 } 46 47 // Pass all data from the response body to the WebAssembly compiler. 48 const { body } = response; 49 if (body != null) { 50 for await (const chunk of body) { 51 streamState.push(chunk); 52 } 53 } 54 })().then(() => { 55 // No error occurred. Tell the implementation that the stream has ended. 56 streamState.finish(); 57 }, (err) => { 58 // An error occurred, either because the given object was not a valid 59 // and usable Response or because a network error occurred. 60 streamState.abort(err); 61 }); 62} 63 64module.exports = { 65 wasmStreamingCallback, 66}; 67