Skip to content

Commit

Permalink
lib: move WebAssembly Web API into separate file
Browse files Browse the repository at this point in the history
Refs: #42960 (comment)

PR-URL: #42993
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
  • Loading branch information
tniessen authored May 8, 2022
1 parent f890ef5 commit e8e6d45
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 46 deletions.
48 changes: 2 additions & 46 deletions lib/internal/bootstrap/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const {
ObjectDefineProperties,
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptor,
PromiseResolve,
SafeMap,
SafeWeakMap,
StringPrototypeStartsWith,
Expand All @@ -26,9 +25,7 @@ const {

const { Buffer } = require('buffer');
const {
ERR_INVALID_ARG_TYPE,
ERR_MANIFEST_ASSERT_INTEGRITY,
ERR_WEBASSEMBLY_RESPONSE,
} = require('internal/errors').codes;
const assert = require('internal/assert');

Expand Down Expand Up @@ -222,49 +219,8 @@ function setupFetch() {
});

// The WebAssembly Web API: https://webassembly.github.io/spec/web-api
internalBinding('wasm_web_api').setImplementation((streamState, source) => {
(async () => {
const response = await PromiseResolve(source);
if (!(response instanceof lazyUndici().Response)) {
throw new ERR_INVALID_ARG_TYPE(
'source', ['Response', 'Promise resolving to Response'], response);
}

const contentType = response.headers.get('Content-Type');
if (contentType !== 'application/wasm') {
throw new ERR_WEBASSEMBLY_RESPONSE(
`has unsupported MIME type '${contentType}'`);
}

if (!response.ok) {
throw new ERR_WEBASSEMBLY_RESPONSE(
`has status code ${response.status}`);
}

if (response.bodyUsed !== false) {
throw new ERR_WEBASSEMBLY_RESPONSE('body has already been used');
}

if (response.url) {
streamState.setURL(response.url);
}

// Pass all data from the response body to the WebAssembly compiler.
const { body } = response;
if (body != null) {
for await (const chunk of body) {
streamState.push(chunk);
}
}
})().then(() => {
// No error occurred. Tell the implementation that the stream has ended.
streamState.finish();
}, (err) => {
// An error occurred, either because the given object was not a valid
// and usable Response or because a network error occurred.
streamState.abort(err);
});
});
const { wasmStreamingCallback } = require('internal/wasm_web_api');
internalBinding('wasm_web_api').setImplementation(wasmStreamingCallback);
}

// TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is
Expand Down
66 changes: 66 additions & 0 deletions lib/internal/wasm_web_api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict';

const {
PromiseResolve,
} = primordials;
const {
ERR_INVALID_ARG_TYPE,
ERR_WEBASSEMBLY_RESPONSE,
} = require('internal/errors').codes;

let undici;
function lazyUndici() {
return undici ??= require('internal/deps/undici/undici');
}

// This is essentially an implementation of a v8::WasmStreamingCallback, except
// that it is implemented in JavaScript because the fetch() implementation is
// difficult to use from C++. See lib/internal/bootstrap/pre_execution.js and
// src/node_wasm_web_api.cc that interact with this function.
function wasmStreamingCallback(streamState, source) {
(async () => {
const response = await PromiseResolve(source);
if (!(response instanceof lazyUndici().Response)) {
throw new ERR_INVALID_ARG_TYPE(
'source', ['Response', 'Promise resolving to Response'], response);
}

const contentType = response.headers.get('Content-Type');
if (contentType !== 'application/wasm') {
throw new ERR_WEBASSEMBLY_RESPONSE(
`has unsupported MIME type '${contentType}'`);
}

if (!response.ok) {
throw new ERR_WEBASSEMBLY_RESPONSE(
`has status code ${response.status}`);
}

if (response.bodyUsed !== false) {
throw new ERR_WEBASSEMBLY_RESPONSE('body has already been used');
}

if (response.url) {
streamState.setURL(response.url);
}

// Pass all data from the response body to the WebAssembly compiler.
const { body } = response;
if (body != null) {
for await (const chunk of body) {
streamState.push(chunk);
}
}
})().then(() => {
// No error occurred. Tell the implementation that the stream has ended.
streamState.finish();
}, (err) => {
// An error occurred, either because the given object was not a valid
// and usable Response or because a network error occurred.
streamState.abort(err);
});
}

module.exports = {
wasmStreamingCallback
};
1 change: 1 addition & 0 deletions test/parallel/test-bootstrap-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ const expectedModules = new Set([
'NativeModule internal/util/types',
'NativeModule internal/validators',
'NativeModule internal/vm/module',
'NativeModule internal/wasm_web_api',
'NativeModule internal/webstreams/adapters',
'NativeModule internal/webstreams/compression',
'NativeModule internal/webstreams/encoding',
Expand Down

0 comments on commit e8e6d45

Please sign in to comment.