WasmFinalizeExportsPlugin.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const formatLocation = require("../formatLocation");
  7. const UnsupportedWebAssemblyFeatureError = require("./UnsupportedWebAssemblyFeatureError");
  8. /** @typedef {import("../Compiler")} Compiler */
  9. class WasmFinalizeExportsPlugin {
  10. /**
  11. * Apply the plugin
  12. * @param {Compiler} compiler the compiler instance
  13. * @returns {void}
  14. */
  15. apply(compiler) {
  16. compiler.hooks.compilation.tap("WasmFinalizeExportsPlugin", compilation => {
  17. compilation.hooks.finishModules.tap(
  18. "WasmFinalizeExportsPlugin",
  19. modules => {
  20. for (const module of modules) {
  21. // 1. if a WebAssembly module
  22. if (module.type.startsWith("webassembly") === true) {
  23. const jsIncompatibleExports =
  24. module.buildMeta.jsIncompatibleExports;
  25. if (jsIncompatibleExports === undefined) {
  26. continue;
  27. }
  28. for (const connection of compilation.moduleGraph.getIncomingConnections(
  29. module
  30. )) {
  31. // 2. is active and referenced by a non-WebAssembly module
  32. if (
  33. connection.isTargetActive(undefined) &&
  34. connection.originModule.type.startsWith("webassembly") ===
  35. false
  36. ) {
  37. const referencedExports =
  38. compilation.getDependencyReferencedExports(
  39. connection.dependency,
  40. undefined
  41. );
  42. for (const info of referencedExports) {
  43. const names = Array.isArray(info) ? info : info.name;
  44. if (names.length === 0) continue;
  45. const name = names[0];
  46. if (typeof name === "object") continue;
  47. // 3. and uses a func with an incompatible JS signature
  48. if (
  49. Object.prototype.hasOwnProperty.call(
  50. jsIncompatibleExports,
  51. name
  52. )
  53. ) {
  54. // 4. error
  55. const error = new UnsupportedWebAssemblyFeatureError(
  56. `Export "${name}" with ${jsIncompatibleExports[name]} can only be used for direct wasm to wasm dependencies\n` +
  57. `It's used from ${connection.originModule.readableIdentifier(
  58. compilation.requestShortener
  59. )} at ${formatLocation(connection.dependency.loc)}.`
  60. );
  61. error.module = module;
  62. compilation.errors.push(error);
  63. }
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }
  70. );
  71. });
  72. }
  73. }
  74. module.exports = WasmFinalizeExportsPlugin;