EnableWasmLoadingPlugin.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. /** @typedef {import("../../declarations/WebpackOptions").WasmLoadingType} WasmLoadingType */
  7. /** @typedef {import("../Compiler")} Compiler */
  8. /** @typedef {Set<WasmLoadingType>} WasmLoadingTypes */
  9. /** @type {WeakMap<Compiler, Set<WasmLoadingType>>} */
  10. const enabledTypes = new WeakMap();
  11. /**
  12. * Returns the set of wasm loading backends that have already been enabled for
  13. * the compiler.
  14. * @param {Compiler} compiler compiler instance
  15. * @returns {WasmLoadingTypes} enabled types
  16. */
  17. const getEnabledTypes = (compiler) => {
  18. let set = enabledTypes.get(compiler);
  19. if (set === undefined) {
  20. /** @type {WasmLoadingTypes} */
  21. set = new Set();
  22. enabledTypes.set(compiler, set);
  23. }
  24. return set;
  25. };
  26. /**
  27. * Validates and enables named wasm loading backends by applying the plugin
  28. * implementations that provide their runtime support.
  29. */
  30. class EnableWasmLoadingPlugin {
  31. /**
  32. * Stores the wasm loading backend name that should be enabled for the
  33. * compiler.
  34. * @param {WasmLoadingType} type library type that should be available
  35. */
  36. constructor(type) {
  37. /** @type {WasmLoadingType} */
  38. this.type = type;
  39. }
  40. /**
  41. * Marks a custom or built-in wasm loading type as enabled for the compiler
  42. * without applying additional built-in behavior.
  43. * @param {Compiler} compiler the compiler instance
  44. * @param {WasmLoadingType} type type of library
  45. * @returns {void}
  46. */
  47. static setEnabled(compiler, type) {
  48. getEnabledTypes(compiler).add(type);
  49. }
  50. /**
  51. * Verifies that a wasm loading type has been enabled before code generation
  52. * attempts to use it.
  53. * @param {Compiler} compiler the compiler instance
  54. * @param {WasmLoadingType} type type of library
  55. * @returns {void}
  56. */
  57. static checkEnabled(compiler, type) {
  58. if (!getEnabledTypes(compiler).has(type)) {
  59. throw new Error(
  60. `Library type "${type}" is not enabled. ` +
  61. "EnableWasmLoadingPlugin need to be used to enable this type of wasm loading. " +
  62. 'This usually happens through the "output.enabledWasmLoadingTypes" option. ' +
  63. 'If you are using a function as entry which sets "wasmLoading", you need to add all potential library types to "output.enabledWasmLoadingTypes". ' +
  64. `These types are enabled: ${[...getEnabledTypes(compiler)].join(", ")}`
  65. );
  66. }
  67. }
  68. /**
  69. * Enables the requested wasm loading backend once and applies the
  70. * environment-specific plugins that provide its parser, generator, and
  71. * runtime support.
  72. * @param {Compiler} compiler the compiler instance
  73. * @returns {void}
  74. */
  75. apply(compiler) {
  76. const { type } = this;
  77. // Only enable once
  78. const enabled = getEnabledTypes(compiler);
  79. if (enabled.has(type)) return;
  80. enabled.add(type);
  81. if (typeof type === "string") {
  82. switch (type) {
  83. case "fetch": {
  84. if (compiler.options.experiments.syncWebAssembly) {
  85. const FetchCompileWasmPlugin = require("../web/FetchCompileWasmPlugin");
  86. new FetchCompileWasmPlugin({
  87. mangleImports: compiler.options.optimization.mangleWasmImports
  88. }).apply(compiler);
  89. }
  90. if (compiler.options.experiments.asyncWebAssembly) {
  91. const FetchCompileAsyncWasmPlugin = require("../web/FetchCompileAsyncWasmPlugin");
  92. new FetchCompileAsyncWasmPlugin().apply(compiler);
  93. }
  94. break;
  95. }
  96. case "async-node": {
  97. if (compiler.options.experiments.syncWebAssembly) {
  98. const ReadFileCompileWasmPlugin = require("../node/ReadFileCompileWasmPlugin");
  99. new ReadFileCompileWasmPlugin({
  100. mangleImports: compiler.options.optimization.mangleWasmImports,
  101. import:
  102. compiler.options.output.module &&
  103. compiler.options.output.environment.dynamicImport
  104. }).apply(compiler);
  105. }
  106. if (compiler.options.experiments.asyncWebAssembly) {
  107. const ReadFileCompileAsyncWasmPlugin = require("../node/ReadFileCompileAsyncWasmPlugin");
  108. new ReadFileCompileAsyncWasmPlugin({
  109. import:
  110. compiler.options.output.module &&
  111. compiler.options.output.environment.dynamicImport
  112. }).apply(compiler);
  113. }
  114. break;
  115. }
  116. case "universal": {
  117. if (compiler.options.experiments.syncWebAssembly) {
  118. throw new Error(
  119. "Universal wasm loading type is only supported by asynchronous web assembly."
  120. );
  121. }
  122. if (compiler.options.experiments.asyncWebAssembly) {
  123. const UniversalCompileAsyncWasmPlugin = require("../wasm-async/UniversalCompileAsyncWasmPlugin");
  124. new UniversalCompileAsyncWasmPlugin().apply(compiler);
  125. }
  126. break;
  127. }
  128. default:
  129. throw new Error(`Unsupported wasm loading type ${type}.
  130. Plugins which provide custom wasm loading types must call EnableWasmLoadingPlugin.setEnabled(compiler, type) to disable this error.`);
  131. }
  132. } else {
  133. // TODO support plugin instances here
  134. // apply them to the compiler
  135. }
  136. }
  137. }
  138. module.exports = EnableWasmLoadingPlugin;