ReadFileCompileAsyncWasmPlugin.js 3.3 KB

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