You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
3.6 KiB

4 years ago
  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 WebAssemblyInInitialChunkError = require("./WebAssemblyInInitialChunkError");
  10. /** @typedef {import("../Compiler")} Compiler */
  11. let WebAssemblyGenerator;
  12. let WebAssemblyJavascriptGenerator;
  13. let WebAssemblyParser;
  14. class WebAssemblyModulesPlugin {
  15. constructor(options) {
  16. this.options = options;
  17. }
  18. /**
  19. * @param {Compiler} compiler compiler
  20. * @returns {void}
  21. */
  22. apply(compiler) {
  23. compiler.hooks.compilation.tap(
  24. "WebAssemblyModulesPlugin",
  25. (compilation, { normalModuleFactory }) => {
  26. compilation.dependencyFactories.set(
  27. WebAssemblyImportDependency,
  28. normalModuleFactory
  29. );
  30. compilation.dependencyFactories.set(
  31. WebAssemblyExportImportedDependency,
  32. normalModuleFactory
  33. );
  34. normalModuleFactory.hooks.createParser
  35. .for("webassembly/experimental")
  36. .tap("WebAssemblyModulesPlugin", () => {
  37. if (WebAssemblyParser === undefined) {
  38. WebAssemblyParser = require("./WebAssemblyParser");
  39. }
  40. return new WebAssemblyParser();
  41. });
  42. normalModuleFactory.hooks.createGenerator
  43. .for("webassembly/experimental")
  44. .tap("WebAssemblyModulesPlugin", () => {
  45. if (WebAssemblyGenerator === undefined) {
  46. WebAssemblyGenerator = require("./WebAssemblyGenerator");
  47. }
  48. if (WebAssemblyJavascriptGenerator === undefined) {
  49. WebAssemblyJavascriptGenerator = require("./WebAssemblyJavascriptGenerator");
  50. }
  51. return Generator.byType({
  52. javascript: new WebAssemblyJavascriptGenerator(),
  53. webassembly: new WebAssemblyGenerator(this.options)
  54. });
  55. });
  56. compilation.chunkTemplate.hooks.renderManifest.tap(
  57. "WebAssemblyModulesPlugin",
  58. (result, options) => {
  59. const chunk = options.chunk;
  60. const outputOptions = options.outputOptions;
  61. const moduleTemplates = options.moduleTemplates;
  62. const dependencyTemplates = options.dependencyTemplates;
  63. for (const module of chunk.modulesIterable) {
  64. if (module.type && module.type.startsWith("webassembly")) {
  65. const filenameTemplate =
  66. outputOptions.webassemblyModuleFilename;
  67. result.push({
  68. render: () =>
  69. this.renderWebAssembly(
  70. module,
  71. moduleTemplates.webassembly,
  72. dependencyTemplates
  73. ),
  74. filenameTemplate,
  75. pathOptions: {
  76. module
  77. },
  78. identifier: `webassemblyModule${module.id}`,
  79. hash: module.hash
  80. });
  81. }
  82. }
  83. return result;
  84. }
  85. );
  86. compilation.hooks.afterChunks.tap("WebAssemblyModulesPlugin", () => {
  87. const initialWasmModules = new Set();
  88. for (const chunk of compilation.chunks) {
  89. if (chunk.canBeInitial()) {
  90. for (const module of chunk.modulesIterable) {
  91. if (module.type.startsWith("webassembly")) {
  92. initialWasmModules.add(module);
  93. }
  94. }
  95. }
  96. }
  97. for (const module of initialWasmModules) {
  98. compilation.errors.push(
  99. new WebAssemblyInInitialChunkError(
  100. module,
  101. compilation.requestShortener
  102. )
  103. );
  104. }
  105. });
  106. }
  107. );
  108. }
  109. renderWebAssembly(module, moduleTemplate, dependencyTemplates) {
  110. return moduleTemplate.render(module, dependencyTemplates, {});
  111. }
  112. }
  113. module.exports = WebAssemblyModulesPlugin;