ReadFileCompileAsyncWasmPlugin.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RuntimeGlobals = require("../RuntimeGlobals");
  7. const Template = require("../Template");
  8. const AsyncWasmLoadingRuntimeModule = require("../wasm-async/AsyncWasmLoadingRuntimeModule");
  9. /** @typedef {import("../Compiler")} Compiler */
  10. class ReadFileCompileAsyncWasmPlugin {
  11. constructor({ type = "async-node", import: useImport = false } = {}) {
  12. this._type = type;
  13. this._import = useImport;
  14. }
  15. /**
  16. * Apply the plugin
  17. * @param {Compiler} compiler the compiler instance
  18. * @returns {void}
  19. */
  20. apply(compiler) {
  21. compiler.hooks.thisCompilation.tap(
  22. "ReadFileCompileAsyncWasmPlugin",
  23. compilation => {
  24. const globalWasmLoading = compilation.outputOptions.wasmLoading;
  25. const isEnabledForChunk = chunk => {
  26. const options = chunk.getEntryOptions();
  27. const wasmLoading =
  28. options && options.wasmLoading !== undefined
  29. ? options.wasmLoading
  30. : globalWasmLoading;
  31. return wasmLoading === this._type;
  32. };
  33. const generateLoadBinaryCode = this._import
  34. ? path =>
  35. Template.asString([
  36. "Promise.all([import('fs'), import('url')]).then(([{ readFile }, { URL }]) => new Promise((resolve, reject) => {",
  37. Template.indent([
  38. `readFile(new URL(${path}, import.meta.url), (err, buffer) => {`,
  39. Template.indent([
  40. "if (err) return reject(err);",
  41. "",
  42. "// Fake fetch response",
  43. "resolve({",
  44. Template.indent(["arrayBuffer() { return buffer; }"]),
  45. "});"
  46. ]),
  47. "});"
  48. ]),
  49. "}))"
  50. ])
  51. : path =>
  52. Template.asString([
  53. "new Promise(function (resolve, reject) {",
  54. Template.indent([
  55. "try {",
  56. Template.indent([
  57. "var { readFile } = require('fs');",
  58. "var { join } = require('path');",
  59. "",
  60. `readFile(join(__dirname, ${path}), function(err, buffer){`,
  61. Template.indent([
  62. "if (err) return reject(err);",
  63. "",
  64. "// Fake fetch response",
  65. "resolve({",
  66. Template.indent(["arrayBuffer() { return buffer; }"]),
  67. "});"
  68. ]),
  69. "});"
  70. ]),
  71. "} catch (err) { reject(err); }"
  72. ]),
  73. "})"
  74. ]);
  75. compilation.hooks.runtimeRequirementInTree
  76. .for(RuntimeGlobals.instantiateWasm)
  77. .tap("ReadFileCompileAsyncWasmPlugin", (chunk, set) => {
  78. if (!isEnabledForChunk(chunk)) return;
  79. const chunkGraph = compilation.chunkGraph;
  80. if (
  81. !chunkGraph.hasModuleInGraph(
  82. chunk,
  83. m => m.type === "webassembly/async"
  84. )
  85. ) {
  86. return;
  87. }
  88. set.add(RuntimeGlobals.publicPath);
  89. compilation.addRuntimeModule(
  90. chunk,
  91. new AsyncWasmLoadingRuntimeModule({
  92. generateLoadBinaryCode,
  93. supportsStreaming: false
  94. })
  95. );
  96. });
  97. }
  98. );
  99. }
  100. }
  101. module.exports = ReadFileCompileAsyncWasmPlugin;