11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  PromiseResolve,
51cb0ef41Sopenharmony_ci} = primordials;
61cb0ef41Sopenharmony_ciconst {
71cb0ef41Sopenharmony_ci  ERR_INVALID_ARG_TYPE,
81cb0ef41Sopenharmony_ci  ERR_WEBASSEMBLY_RESPONSE,
91cb0ef41Sopenharmony_ci} = require('internal/errors').codes;
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cilet undici;
121cb0ef41Sopenharmony_cifunction lazyUndici() {
131cb0ef41Sopenharmony_ci  return undici ??= require('internal/deps/undici/undici');
141cb0ef41Sopenharmony_ci}
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// This is essentially an implementation of a v8::WasmStreamingCallback, except
171cb0ef41Sopenharmony_ci// that it is implemented in JavaScript because the fetch() implementation is
181cb0ef41Sopenharmony_ci// difficult to use from C++. See lib/internal/process/pre_execution.js and
191cb0ef41Sopenharmony_ci// src/node_wasm_web_api.cc that interact with this function.
201cb0ef41Sopenharmony_cifunction wasmStreamingCallback(streamState, source) {
211cb0ef41Sopenharmony_ci  (async () => {
221cb0ef41Sopenharmony_ci    const response = await PromiseResolve(source);
231cb0ef41Sopenharmony_ci    if (!(response instanceof lazyUndici().Response)) {
241cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_TYPE(
251cb0ef41Sopenharmony_ci        'source', ['Response', 'Promise resolving to Response'], response);
261cb0ef41Sopenharmony_ci    }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci    const contentType = response.headers.get('Content-Type');
291cb0ef41Sopenharmony_ci    if (contentType !== 'application/wasm') {
301cb0ef41Sopenharmony_ci      throw new ERR_WEBASSEMBLY_RESPONSE(
311cb0ef41Sopenharmony_ci        `has unsupported MIME type '${contentType}'`);
321cb0ef41Sopenharmony_ci    }
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci    if (!response.ok) {
351cb0ef41Sopenharmony_ci      throw new ERR_WEBASSEMBLY_RESPONSE(
361cb0ef41Sopenharmony_ci        `has status code ${response.status}`);
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci    if (response.bodyUsed !== false) {
401cb0ef41Sopenharmony_ci      throw new ERR_WEBASSEMBLY_RESPONSE('body has already been used');
411cb0ef41Sopenharmony_ci    }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci    if (response.url) {
441cb0ef41Sopenharmony_ci      streamState.setURL(response.url);
451cb0ef41Sopenharmony_ci    }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci    // Pass all data from the response body to the WebAssembly compiler.
481cb0ef41Sopenharmony_ci    const { body } = response;
491cb0ef41Sopenharmony_ci    if (body != null) {
501cb0ef41Sopenharmony_ci      for await (const chunk of body) {
511cb0ef41Sopenharmony_ci        streamState.push(chunk);
521cb0ef41Sopenharmony_ci      }
531cb0ef41Sopenharmony_ci    }
541cb0ef41Sopenharmony_ci  })().then(() => {
551cb0ef41Sopenharmony_ci    // No error occurred. Tell the implementation that the stream has ended.
561cb0ef41Sopenharmony_ci    streamState.finish();
571cb0ef41Sopenharmony_ci  }, (err) => {
581cb0ef41Sopenharmony_ci    // An error occurred, either because the given object was not a valid
591cb0ef41Sopenharmony_ci    // and usable Response or because a network error occurred.
601cb0ef41Sopenharmony_ci    streamState.abort(err);
611cb0ef41Sopenharmony_ci  });
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_cimodule.exports = {
651cb0ef41Sopenharmony_ci  wasmStreamingCallback,
661cb0ef41Sopenharmony_ci};
67