WebAssemblyJavascriptGenerator.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Generator = require("../Generator");
  7. const Template = require("../Template");
  8. const { RawSource } = require("webpack-sources");
  9. const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
  10. const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
  11. /** @typedef {import("../NormalModule")} NormalModule */
  12. /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
  13. /** @typedef {import("webpack-sources").Source} Source */
  14. /** @typedef {import("../Dependency").DependencyTemplate} DependencyTemplate */
  15. class WebAssemblyJavascriptGenerator extends Generator {
  16. /**
  17. * @param {NormalModule} module module for which the code should be generated
  18. * @param {Map<Function, DependencyTemplate>} dependencyTemplates mapping from dependencies to templates
  19. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  20. * @param {string} type which kind of code should be generated
  21. * @returns {Source} generated code
  22. */
  23. generate(module, dependencyTemplates, runtimeTemplate, type) {
  24. const initIdentifer = Array.isArray(module.usedExports)
  25. ? Template.numberToIdentifer(module.usedExports.length)
  26. : "__webpack_init__";
  27. let needExportsCopy = false;
  28. const importedModules = new Map();
  29. const initParams = [];
  30. let index = 0;
  31. for (const dep of module.dependencies) {
  32. const depAsAny = /** @type {any} */ (dep);
  33. if (dep.module) {
  34. let importData = importedModules.get(dep.module);
  35. if (importData === undefined) {
  36. importedModules.set(
  37. dep.module,
  38. (importData = {
  39. importVar: `m${index}`,
  40. index,
  41. request:
  42. "userRequest" in depAsAny ? depAsAny.userRequest : undefined,
  43. names: new Set(),
  44. reexports: []
  45. })
  46. );
  47. index++;
  48. }
  49. if (dep instanceof WebAssemblyImportDependency) {
  50. importData.names.add(dep.name);
  51. if (dep.description.type === "GlobalType") {
  52. const exportName = dep.name;
  53. const usedName = dep.module && dep.module.isUsed(exportName);
  54. if (dep.module) {
  55. if (usedName) {
  56. initParams.push(
  57. runtimeTemplate.exportFromImport({
  58. module: dep.module,
  59. request: dep.request,
  60. importVar: importData.importVar,
  61. originModule: module,
  62. exportName: dep.name,
  63. asiSafe: true,
  64. isCall: false,
  65. callContext: null
  66. })
  67. );
  68. }
  69. }
  70. }
  71. }
  72. if (dep instanceof WebAssemblyExportImportedDependency) {
  73. importData.names.add(dep.name);
  74. const usedName = module.isUsed(dep.exportName);
  75. if (usedName) {
  76. const defineStatement = Template.asString([
  77. `${module.exportsArgument}[${JSON.stringify(
  78. usedName
  79. )}] = ${runtimeTemplate.exportFromImport({
  80. module: dep.module,
  81. request: dep.request,
  82. importVar: importData.importVar,
  83. originModule: module,
  84. exportName: dep.name,
  85. asiSafe: true,
  86. isCall: false,
  87. callContext: null
  88. })};`
  89. ]);
  90. importData.reexports.push(defineStatement);
  91. needExportsCopy = true;
  92. }
  93. }
  94. }
  95. }
  96. const importsCode = Template.asString(
  97. Array.from(
  98. importedModules,
  99. ([module, { importVar, request, reexports }]) => {
  100. const importStatement = runtimeTemplate.importStatement({
  101. module,
  102. request,
  103. importVar,
  104. originModule: module
  105. });
  106. return importStatement + reexports.join("\n");
  107. }
  108. )
  109. );
  110. // create source
  111. const source = new RawSource(
  112. [
  113. '"use strict";',
  114. "// Instantiate WebAssembly module",
  115. "var wasmExports = __webpack_require__.w[module.i];",
  116. !Array.isArray(module.usedExports)
  117. ? `__webpack_require__.r(${module.exportsArgument});`
  118. : "",
  119. // this must be before import for circular dependencies
  120. "// export exports from WebAssembly module",
  121. Array.isArray(module.usedExports) && !needExportsCopy
  122. ? `${module.moduleArgument}.exports = wasmExports;`
  123. : "for(var name in wasmExports) " +
  124. `if(name != ${JSON.stringify(initIdentifer)}) ` +
  125. `${module.exportsArgument}[name] = wasmExports[name];`,
  126. "// exec imports from WebAssembly module (for esm order)",
  127. importsCode,
  128. "",
  129. "// exec wasm module",
  130. `wasmExports[${JSON.stringify(initIdentifer)}](${initParams.join(
  131. ", "
  132. )})`
  133. ].join("\n")
  134. );
  135. return source;
  136. }
  137. }
  138. module.exports = WebAssemblyJavascriptGenerator;