WebAssemblyModulesPlugin.js 4.1 KB

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