123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const { RawSource } = require("webpack-sources");
- const Generator = require("../Generator");
- const InitFragment = require("../InitFragment");
- const RuntimeGlobals = require("../RuntimeGlobals");
- const Template = require("../Template");
- const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
- /** @typedef {import("webpack-sources").Source} Source */
- /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
- /** @typedef {import("../Generator").GenerateContext} GenerateContext */
- /** @typedef {import("../Module")} Module */
- /** @typedef {import("../NormalModule")} NormalModule */
- /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
- const TYPES = new Set(["webassembly"]);
- class AsyncWebAssemblyJavascriptGenerator extends Generator {
- constructor(filenameTemplate) {
- super();
- this.filenameTemplate = filenameTemplate;
- }
- /**
- * @param {NormalModule} module fresh module
- * @returns {Set<string>} available types (do not mutate)
- */
- getTypes(module) {
- return TYPES;
- }
- /**
- * @param {NormalModule} module the module
- * @param {string=} type source type
- * @returns {number} estimate size of the module
- */
- getSize(module, type) {
- return 40 + module.dependencies.length * 10;
- }
- /**
- * @param {NormalModule} module module for which the code should be generated
- * @param {GenerateContext} generateContext context for generate
- * @returns {Source} generated code
- */
- generate(module, generateContext) {
- const {
- runtimeTemplate,
- chunkGraph,
- moduleGraph,
- runtimeRequirements,
- runtime
- } = generateContext;
- runtimeRequirements.add(RuntimeGlobals.module);
- runtimeRequirements.add(RuntimeGlobals.moduleId);
- runtimeRequirements.add(RuntimeGlobals.exports);
- runtimeRequirements.add(RuntimeGlobals.instantiateWasm);
- /** @type {InitFragment[]} */
- const initFragments = [];
- /** @type {Map<Module, { request: string, importVar: string }>} */
- const depModules = new Map();
- /** @type {Map<string, WebAssemblyImportDependency[]>} */
- const wasmDepsByRequest = new Map();
- for (const dep of module.dependencies) {
- if (dep instanceof WebAssemblyImportDependency) {
- const module = moduleGraph.getModule(dep);
- if (!depModules.has(module)) {
- depModules.set(module, {
- request: dep.request,
- importVar: `WEBPACK_IMPORTED_MODULE_${depModules.size}`
- });
- }
- let list = wasmDepsByRequest.get(dep.request);
- if (list === undefined) {
- list = [];
- wasmDepsByRequest.set(dep.request, list);
- }
- list.push(dep);
- }
- }
- const promises = [];
- const importStatements = Array.from(
- depModules,
- ([importedModule, { request, importVar }]) => {
- if (moduleGraph.isAsync(importedModule)) {
- promises.push(importVar);
- }
- return runtimeTemplate.importStatement({
- update: false,
- module: importedModule,
- chunkGraph,
- request,
- originModule: module,
- importVar,
- runtimeRequirements
- });
- }
- );
- const importsCode = importStatements.map(([x]) => x).join("");
- const importsCompatCode = importStatements.map(([_, x]) => x).join("");
- const importObjRequestItems = Array.from(
- wasmDepsByRequest,
- ([request, deps]) => {
- const exportItems = deps.map(dep => {
- const importedModule = moduleGraph.getModule(dep);
- const importVar = depModules.get(importedModule).importVar;
- return `${JSON.stringify(
- dep.name
- )}: ${runtimeTemplate.exportFromImport({
- moduleGraph,
- module: importedModule,
- request,
- exportName: dep.name,
- originModule: module,
- asiSafe: true,
- isCall: false,
- callContext: false,
- defaultInterop: true,
- importVar,
- initFragments,
- runtime,
- runtimeRequirements
- })}`;
- });
- return Template.asString([
- `${JSON.stringify(request)}: {`,
- Template.indent(exportItems.join(",\n")),
- "}"
- ]);
- }
- );
- const importsObj =
- importObjRequestItems.length > 0
- ? Template.asString([
- "{",
- Template.indent(importObjRequestItems.join(",\n")),
- "}"
- ])
- : undefined;
- const instantiateCall =
- `${RuntimeGlobals.instantiateWasm}(${module.exportsArgument}, ${
- module.moduleArgument
- }.id, ${JSON.stringify(
- chunkGraph.getRenderedModuleHash(module, runtime)
- )}` + (importsObj ? `, ${importsObj})` : `)`);
- if (promises.length > 0)
- runtimeRequirements.add(RuntimeGlobals.asyncModule);
- const source = new RawSource(
- promises.length > 0
- ? Template.asString([
- `var __webpack_instantiate__ = ${runtimeTemplate.basicFunction(
- `[${promises.join(", ")}]`,
- `${importsCompatCode}return ${instantiateCall};`
- )}`,
- `${RuntimeGlobals.asyncModule}(${
- module.moduleArgument
- }, async ${runtimeTemplate.basicFunction(
- "__webpack_handle_async_dependencies__, __webpack_async_result__",
- [
- "try {",
- importsCode,
- `var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([${promises.join(
- ", "
- )}]);`,
- `var [${promises.join(
- ", "
- )}] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__;`,
- `${importsCompatCode}await ${instantiateCall};`,
- "__webpack_async_result__();",
- "} catch(e) { __webpack_async_result__(e); }"
- ]
- )}, 1);`
- ])
- : `${importsCode}${importsCompatCode}module.exports = ${instantiateCall};`
- );
- return InitFragment.addToSource(source, initFragments, generateContext);
- }
- }
- module.exports = AsyncWebAssemblyJavascriptGenerator;
|