AsyncWebAssemblyParser.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const t = require("@webassemblyjs/ast");
  7. const { decode } = require("@webassemblyjs/wasm-parser");
  8. const EnvironmentNotSupportAsyncWarning = require("../EnvironmentNotSupportAsyncWarning");
  9. const Parser = require("../Parser");
  10. const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
  11. const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
  12. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  13. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  14. /** @typedef {import("../Parser").ParserState} ParserState */
  15. /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
  16. const decoderOpts = {
  17. ignoreCodeSection: true,
  18. ignoreDataSection: true,
  19. // this will avoid having to lookup with identifiers in the ModuleContext
  20. ignoreCustomNameSection: true
  21. };
  22. class WebAssemblyParser extends Parser {
  23. /**
  24. * @param {{}=} options parser options
  25. */
  26. constructor(options) {
  27. super();
  28. this.hooks = Object.freeze({});
  29. this.options = options;
  30. }
  31. /**
  32. * @param {string | Buffer | PreparsedAst} source the source to parse
  33. * @param {ParserState} state the parser state
  34. * @returns {ParserState} the parser state
  35. */
  36. parse(source, state) {
  37. if (!Buffer.isBuffer(source)) {
  38. throw new Error("WebAssemblyParser input must be a Buffer");
  39. }
  40. // flag it as async module
  41. const buildInfo = /** @type {BuildInfo} */ (state.module.buildInfo);
  42. buildInfo.strict = true;
  43. const BuildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
  44. BuildMeta.exportsType = "namespace";
  45. BuildMeta.async = true;
  46. EnvironmentNotSupportAsyncWarning.check(
  47. state.module,
  48. state.compilation.runtimeTemplate,
  49. "asyncWebAssembly"
  50. );
  51. // parse it
  52. const program = decode(source, decoderOpts);
  53. const module = program.body[0];
  54. /** @type {Array<string>} */
  55. const exports = [];
  56. t.traverse(module, {
  57. ModuleExport({ node }) {
  58. exports.push(node.name);
  59. },
  60. ModuleImport({ node }) {
  61. const dep = new WebAssemblyImportDependency(
  62. node.module,
  63. node.name,
  64. node.descr,
  65. false
  66. );
  67. state.module.addDependency(dep);
  68. }
  69. });
  70. state.module.addDependency(new StaticExportsDependency(exports, false));
  71. return state;
  72. }
  73. }
  74. module.exports = WebAssemblyParser;