| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /*
- 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 {(wasmModuleSrcPath: string) => string} GenerateBeforeLoadBinaryCode */
- /** @typedef {(wasmModuleSrcPath: string) => string} GenerateLoadBinaryCode */
- /** @typedef {() => string} GenerateBeforeCompileStreaming */
- /**
- * @typedef {object} AsyncWasmCompileRuntimeModuleOptions
- * @property {GenerateLoadBinaryCode} generateLoadBinaryCode
- * @property {GenerateBeforeLoadBinaryCode=} generateBeforeLoadBinaryCode
- * @property {GenerateBeforeCompileStreaming=} generateBeforeCompileStreaming
- * @property {boolean} supportsStreaming
- */
- class AsyncWasmCompileRuntimeModule extends RuntimeModule {
- /**
- * @param {AsyncWasmCompileRuntimeModuleOptions} options options
- */
- constructor({
- generateLoadBinaryCode,
- generateBeforeLoadBinaryCode,
- generateBeforeCompileStreaming,
- supportsStreaming
- }) {
- super("wasm compile", RuntimeModule.STAGE_NORMAL);
- /** @type {GenerateLoadBinaryCode} */
- this.generateLoadBinaryCode = generateLoadBinaryCode;
- /** @type {GenerateBeforeLoadBinaryCode | undefined} */
- this.generateBeforeLoadBinaryCode = generateBeforeLoadBinaryCode;
- /** @type {GenerateBeforeCompileStreaming | undefined} */
- this.generateBeforeCompileStreaming = generateBeforeCompileStreaming;
- /** @type {boolean} */
- this.supportsStreaming = supportsStreaming;
- }
- /**
- * Generates runtime code for this runtime module.
- * @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.compileWasm;
- 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);
- // Fallback path: fetch -> arrayBuffer -> WebAssembly.compile
- const fallback = [
- `.then(${runtimeTemplate.returningFunction("x.arrayBuffer()", "x")})`,
- `.then(${runtimeTemplate.returningFunction(
- "WebAssembly.compile(bytes)",
- "bytes"
- )})`
- ];
- const getStreaming = () => {
- /**
- * @param {string[]} text text
- * @returns {string} merged text
- */
- const concat = (...text) => text.join("");
- return [
- this.generateBeforeLoadBinaryCode
- ? this.generateBeforeLoadBinaryCode(wasmModuleSrcPath)
- : "",
- `var req = ${loader};`,
- `var fallback = ${runtimeTemplate.returningFunction(
- Template.asString(["req", Template.indent(fallback)])
- )};`,
- concat(
- "return req.then(",
- runtimeTemplate.basicFunction("res", [
- 'if (typeof WebAssembly.compileStreaming === "function") {',
- Template.indent(
- this.generateBeforeCompileStreaming
- ? this.generateBeforeCompileStreaming()
- : ""
- ),
- Template.indent([
- "return WebAssembly.compileStreaming(res)",
- Template.indent([
- ".catch(",
- Template.indent([
- runtimeTemplate.basicFunction("e", [
- 'if(res.headers.get("Content-Type") !== "application/wasm") {',
- Template.indent([
- 'console.warn("`WebAssembly.compileStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.compile` which is slower. Original error:\\n", e);',
- "return fallback();"
- ]),
- "}",
- "throw e;"
- ])
- ]),
- ");"
- ])
- ]),
- "}",
- "return fallback();"
- ]),
- ");"
- )
- ];
- };
- return `${fn} = ${runtimeTemplate.basicFunction(
- "wasmModuleId, wasmModuleHash",
- this.supportsStreaming
- ? getStreaming()
- : [
- this.generateBeforeLoadBinaryCode
- ? this.generateBeforeLoadBinaryCode(wasmModuleSrcPath)
- : "",
- `return ${loader}`,
- `${Template.indent(fallback)};`
- ]
- )};`;
- }
- }
- module.exports = AsyncWasmCompileRuntimeModule;
|