WebAssemblyModulesPlugin.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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 WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
  8. const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
  9. const { compareModulesByIdentifier } = require("../util/comparators");
  10. const memoize = require("../util/memoize");
  11. const WebAssemblyInInitialChunkError = require("./WebAssemblyInInitialChunkError");
  12. /** @typedef {import("webpack-sources").Source} Source */
  13. /** @typedef {import("../Compiler")} Compiler */
  14. /** @typedef {import("../Module")} Module */
  15. /** @typedef {import("../ModuleTemplate")} ModuleTemplate */
  16. /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
  17. const getWebAssemblyGenerator = memoize(() =>
  18. require("./WebAssemblyGenerator")
  19. );
  20. const getWebAssemblyJavascriptGenerator = memoize(() =>
  21. require("./WebAssemblyJavascriptGenerator")
  22. );
  23. const getWebAssemblyParser = memoize(() => require("./WebAssemblyParser"));
  24. class WebAssemblyModulesPlugin {
  25. constructor(options) {
  26. this.options = options;
  27. }
  28. /**
  29. * Apply the plugin
  30. * @param {Compiler} compiler the compiler instance
  31. * @returns {void}
  32. */
  33. apply(compiler) {
  34. compiler.hooks.compilation.tap(
  35. "WebAssemblyModulesPlugin",
  36. (compilation, { normalModuleFactory }) => {
  37. compilation.dependencyFactories.set(
  38. WebAssemblyImportDependency,
  39. normalModuleFactory
  40. );
  41. compilation.dependencyFactories.set(
  42. WebAssemblyExportImportedDependency,
  43. normalModuleFactory
  44. );
  45. normalModuleFactory.hooks.createParser
  46. .for("webassembly/sync")
  47. .tap("WebAssemblyModulesPlugin", () => {
  48. const WebAssemblyParser = getWebAssemblyParser();
  49. return new WebAssemblyParser();
  50. });
  51. normalModuleFactory.hooks.createGenerator
  52. .for("webassembly/sync")
  53. .tap("WebAssemblyModulesPlugin", () => {
  54. const WebAssemblyJavascriptGenerator =
  55. getWebAssemblyJavascriptGenerator();
  56. const WebAssemblyGenerator = getWebAssemblyGenerator();
  57. return Generator.byType({
  58. javascript: new WebAssemblyJavascriptGenerator(),
  59. webassembly: new WebAssemblyGenerator(this.options)
  60. });
  61. });
  62. compilation.hooks.renderManifest.tap(
  63. "WebAssemblyModulesPlugin",
  64. (result, options) => {
  65. const { chunkGraph } = compilation;
  66. const { chunk, outputOptions, codeGenerationResults } = options;
  67. for (const module of chunkGraph.getOrderedChunkModulesIterable(
  68. chunk,
  69. compareModulesByIdentifier
  70. )) {
  71. if (module.type === "webassembly/sync") {
  72. const filenameTemplate =
  73. outputOptions.webassemblyModuleFilename;
  74. result.push({
  75. render: () =>
  76. codeGenerationResults.getSource(
  77. module,
  78. chunk.runtime,
  79. "webassembly"
  80. ),
  81. filenameTemplate,
  82. pathOptions: {
  83. module,
  84. runtime: chunk.runtime,
  85. chunkGraph
  86. },
  87. auxiliary: true,
  88. identifier: `webassemblyModule${chunkGraph.getModuleId(
  89. module
  90. )}`,
  91. hash: chunkGraph.getModuleHash(module, chunk.runtime)
  92. });
  93. }
  94. }
  95. return result;
  96. }
  97. );
  98. compilation.hooks.afterChunks.tap("WebAssemblyModulesPlugin", () => {
  99. const chunkGraph = compilation.chunkGraph;
  100. const initialWasmModules = new Set();
  101. for (const chunk of compilation.chunks) {
  102. if (chunk.canBeInitial()) {
  103. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  104. if (module.type === "webassembly/sync") {
  105. initialWasmModules.add(module);
  106. }
  107. }
  108. }
  109. }
  110. for (const module of initialWasmModules) {
  111. compilation.errors.push(
  112. new WebAssemblyInInitialChunkError(
  113. module,
  114. compilation.moduleGraph,
  115. compilation.chunkGraph,
  116. compilation.requestShortener
  117. )
  118. );
  119. }
  120. });
  121. }
  122. );
  123. }
  124. }
  125. module.exports = WebAssemblyModulesPlugin;