/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const Generator = require("../Generator"); const Template = require("../Template"); const { RawSource } = require("webpack-sources"); const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency"); const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); /** @typedef {import("../NormalModule")} NormalModule */ /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */ /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../Dependency").DependencyTemplate} DependencyTemplate */ class WebAssemblyJavascriptGenerator extends Generator { /** * @param {NormalModule} module module for which the code should be generated * @param {Map<Function, DependencyTemplate>} dependencyTemplates mapping from dependencies to templates * @param {RuntimeTemplate} runtimeTemplate the runtime template * @param {string} type which kind of code should be generated * @returns {Source} generated code */ generate(module, dependencyTemplates, runtimeTemplate, type) { const initIdentifer = Array.isArray(module.usedExports) ? Template.numberToIdentifer(module.usedExports.length) : "__webpack_init__"; let needExportsCopy = false; const importedModules = new Map(); const initParams = []; let index = 0; for (const dep of module.dependencies) { const depAsAny = /** @type {any} */ (dep); if (dep.module) { let importData = importedModules.get(dep.module); if (importData === undefined) { importedModules.set( dep.module, (importData = { importVar: `m${index}`, index, request: "userRequest" in depAsAny ? depAsAny.userRequest : undefined, names: new Set(), reexports: [] }) ); index++; } if (dep instanceof WebAssemblyImportDependency) { importData.names.add(dep.name); if (dep.description.type === "GlobalType") { const exportName = dep.name; const usedName = dep.module && dep.module.isUsed(exportName); if (dep.module) { if (usedName) { initParams.push( runtimeTemplate.exportFromImport({ module: dep.module, request: dep.request, importVar: importData.importVar, originModule: module, exportName: dep.name, asiSafe: true, isCall: false, callContext: null }) ); } } } } if (dep instanceof WebAssemblyExportImportedDependency) { importData.names.add(dep.name); const usedName = module.isUsed(dep.exportName); if (usedName) { const exportProp = `${module.exportsArgument}[${JSON.stringify( usedName )}]`; const defineStatement = Template.asString([ `${exportProp} = ${runtimeTemplate.exportFromImport({ module: dep.module, request: dep.request, importVar: importData.importVar, originModule: module, exportName: dep.name, asiSafe: true, isCall: false, callContext: null })};`, `if(WebAssembly.Global) ${exportProp} = ` + `new WebAssembly.Global({ value: ${JSON.stringify( dep.valueType )} }, ${exportProp});` ]); importData.reexports.push(defineStatement); needExportsCopy = true; } } } } const importsCode = Template.asString( Array.from( importedModules, ([module, { importVar, request, reexports }]) => { const importStatement = runtimeTemplate.importStatement({ module, request, importVar, originModule: module }); return importStatement + reexports.join("\n"); } ) ); // create source const source = new RawSource( [ '"use strict";', "// Instantiate WebAssembly module", "var wasmExports = __webpack_require__.w[module.i];", !Array.isArray(module.usedExports) ? `__webpack_require__.r(${module.exportsArgument});` : "", // this must be before import for circular dependencies "// export exports from WebAssembly module", Array.isArray(module.usedExports) && !needExportsCopy ? `${module.moduleArgument}.exports = wasmExports;` : "for(var name in wasmExports) " + `if(name != ${JSON.stringify(initIdentifer)}) ` + `${module.exportsArgument}[name] = wasmExports[name];`, "// exec imports from WebAssembly module (for esm order)", importsCode, "", "// exec wasm module", `wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join( ", " )})` ].join("\n") ); return source; } } module.exports = WebAssemblyJavascriptGenerator;