123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const RuntimeGlobals = require("../RuntimeGlobals");
- const RuntimeModule = require("../RuntimeModule");
- const Template = require("../Template");
- /** @typedef {import("../Chunk")} Chunk */
- /** @typedef {import("../Compilation")} Compilation */
- /**
- * @typedef {object} AsyncWasmLoadingRuntimeModuleOptions
- * @property {function(string): string} generateLoadBinaryCode
- * @property {boolean} supportsStreaming
- */
- class AsyncWasmLoadingRuntimeModule extends RuntimeModule {
- /**
- * @param {AsyncWasmLoadingRuntimeModuleOptions} options options
- */
- constructor({ generateLoadBinaryCode, supportsStreaming }) {
- super("wasm loading", RuntimeModule.STAGE_NORMAL);
- this.generateLoadBinaryCode = generateLoadBinaryCode;
- this.supportsStreaming = supportsStreaming;
- }
- /**
- * @returns {string | null} runtime code
- */
- generate() {
- const compilation = /** @type {Compilation} */ (this.compilation);
- const chunk = /** @type {Chunk} */ (this.chunk);
- const { outputOptions, runtimeTemplate } = compilation;
- const fn = RuntimeGlobals.instantiateWasm;
- const wasmModuleSrcPath = compilation.getPath(
- JSON.stringify(outputOptions.webassemblyModuleFilename),
- {
- hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
- hashWithLength: length =>
- `" + ${RuntimeGlobals.getFullHash}}().slice(0, ${length}) + "`,
- module: {
- id: '" + wasmModuleId + "',
- hash: `" + wasmModuleHash + "`,
- hashWithLength(length) {
- return `" + wasmModuleHash.slice(0, ${length}) + "`;
- }
- },
- runtime: chunk.runtime
- }
- );
- const loader = this.generateLoadBinaryCode(wasmModuleSrcPath);
- const fallback = [
- `.then(${runtimeTemplate.returningFunction("x.arrayBuffer()", "x")})`,
- `.then(${runtimeTemplate.returningFunction(
- "WebAssembly.instantiate(bytes, importsObj)",
- "bytes"
- )})`,
- `.then(${runtimeTemplate.returningFunction(
- "Object.assign(exports, res.instance.exports)",
- "res"
- )})`
- ];
- const getStreaming = () => {
- const concat = (/** @type {string[]} */ ...text) => text.join("");
- return [
- `var req = ${loader};`,
- `var fallback = ${runtimeTemplate.returningFunction(
- Template.asString(["req", Template.indent(fallback)])
- )};`,
- concat(
- "return req.then(",
- runtimeTemplate.basicFunction("res", [
- `if (typeof WebAssembly.instantiateStreaming === "function") {`,
- Template.indent([
- "return WebAssembly.instantiateStreaming(res, importsObj)",
- Template.indent([
- ".then(",
- Template.indent([
- runtimeTemplate.returningFunction(
- "Object.assign(exports, res.instance.exports)",
- "res"
- ) + ",",
- runtimeTemplate.basicFunction("e", [
- `if(res.headers.get("Content-Type") !== "application/wasm") {`,
- Template.indent([
- 'console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n", e);',
- "return fallback();"
- ]),
- "}",
- "throw e;"
- ])
- ]),
- ");"
- ])
- ]),
- "}",
- "return fallback();"
- ]),
- ");"
- )
- ];
- };
- return `${fn} = ${runtimeTemplate.basicFunction(
- "exports, wasmModuleId, wasmModuleHash, importsObj",
- this.supportsStreaming
- ? getStreaming()
- : [`return ${loader}`, Template.indent(fallback) + ";"]
- )};`;
- }
- }
- module.exports = AsyncWasmLoadingRuntimeModule;
|