AsyncWasmLoadingRuntimeModule.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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 RuntimeModule = require("../RuntimeModule");
  8. const Template = require("../Template");
  9. /** @typedef {import("../Chunk")} Chunk */
  10. /** @typedef {import("../Compilation")} Compilation */
  11. /**
  12. * @typedef {Object} AsyncWasmLoadingRuntimeModuleOptions
  13. * @property {function(string): string} generateLoadBinaryCode
  14. * @property {boolean} supportsStreaming
  15. */
  16. class AsyncWasmLoadingRuntimeModule extends RuntimeModule {
  17. /**
  18. * @param {AsyncWasmLoadingRuntimeModuleOptions} options options
  19. */
  20. constructor({ generateLoadBinaryCode, supportsStreaming }) {
  21. super("wasm loading", RuntimeModule.STAGE_NORMAL);
  22. this.generateLoadBinaryCode = generateLoadBinaryCode;
  23. this.supportsStreaming = supportsStreaming;
  24. }
  25. /**
  26. * @returns {string | null} runtime code
  27. */
  28. generate() {
  29. const compilation = /** @type {Compilation} */ (this.compilation);
  30. const chunk = /** @type {Chunk} */ (this.chunk);
  31. const { outputOptions, runtimeTemplate } = compilation;
  32. const fn = RuntimeGlobals.instantiateWasm;
  33. const wasmModuleSrcPath = compilation.getPath(
  34. JSON.stringify(outputOptions.webassemblyModuleFilename),
  35. {
  36. hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
  37. hashWithLength: length =>
  38. `" + ${RuntimeGlobals.getFullHash}}().slice(0, ${length}) + "`,
  39. module: {
  40. id: '" + wasmModuleId + "',
  41. hash: `" + wasmModuleHash + "`,
  42. hashWithLength(length) {
  43. return `" + wasmModuleHash.slice(0, ${length}) + "`;
  44. }
  45. },
  46. runtime: chunk.runtime
  47. }
  48. );
  49. return `${fn} = ${runtimeTemplate.basicFunction(
  50. "exports, wasmModuleId, wasmModuleHash, importsObj",
  51. [
  52. `var req = ${this.generateLoadBinaryCode(wasmModuleSrcPath)};`,
  53. this.supportsStreaming
  54. ? Template.asString([
  55. "if (typeof WebAssembly.instantiateStreaming === 'function') {",
  56. Template.indent([
  57. "return WebAssembly.instantiateStreaming(req, importsObj)",
  58. Template.indent([
  59. `.then(${runtimeTemplate.returningFunction(
  60. "Object.assign(exports, res.instance.exports)",
  61. "res"
  62. )});`
  63. ])
  64. ]),
  65. "}"
  66. ])
  67. : "// no support for streaming compilation",
  68. "return req",
  69. Template.indent([
  70. `.then(${runtimeTemplate.returningFunction("x.arrayBuffer()", "x")})`,
  71. `.then(${runtimeTemplate.returningFunction(
  72. "WebAssembly.instantiate(bytes, importsObj)",
  73. "bytes"
  74. )})`,
  75. `.then(${runtimeTemplate.returningFunction(
  76. "Object.assign(exports, res.instance.exports)",
  77. "res"
  78. )});`
  79. ])
  80. ]
  81. )};`;
  82. }
  83. }
  84. module.exports = AsyncWasmLoadingRuntimeModule;