source: frontend/node_modules/webpack/lib/wasm-sync/WebAssemblyParser.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const t = require("@webassemblyjs/ast");
9const { moduleContextFromModuleAST } = require("@webassemblyjs/ast");
10const { decode } = require("@webassemblyjs/wasm-parser");
11const Parser = require("../Parser");
12const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
13const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
14const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
15
16/** @typedef {import("@webassemblyjs/ast").ModuleImport} ModuleImport */
17/** @typedef {import("../Module").BuildInfo} BuildInfo */
18/** @typedef {import("../Module").BuildMeta} BuildMeta */
19/** @typedef {import("../Parser").ParserState} ParserState */
20/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
21
22const JS_COMPAT_TYPES = new Set(["i32", "i64", "f32", "f64", "externref"]);
23
24/**
25 * Gets js incompatible type.
26 * @param {t.Signature} signature the func signature
27 * @returns {null | string} the type incompatible with js types
28 */
29const getJsIncompatibleType = (signature) => {
30 for (const param of signature.params) {
31 if (!JS_COMPAT_TYPES.has(param.valtype)) {
32 return `${param.valtype} as parameter`;
33 }
34 }
35 for (const type of signature.results) {
36 if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`;
37 }
38 return null;
39};
40
41/**
42 * TODO why are there two different Signature types?
43 * @param {t.FuncSignature} signature the func signature
44 * @returns {null | string} the type incompatible with js types
45 */
46const getJsIncompatibleTypeOfFuncSignature = (signature) => {
47 for (const param of signature.args) {
48 if (!JS_COMPAT_TYPES.has(param)) {
49 return `${param} as parameter`;
50 }
51 }
52 for (const type of signature.result) {
53 if (!JS_COMPAT_TYPES.has(type)) return `${type} as result`;
54 }
55 return null;
56};
57
58const decoderOpts = {
59 ignoreCodeSection: true,
60 ignoreDataSection: true,
61
62 // this will avoid having to lookup with identifiers in the ModuleContext
63 ignoreCustomNameSection: true
64};
65
66class WebAssemblyParser extends Parser {
67 /**
68 * Parses the provided source and updates the parser state.
69 * @param {string | Buffer | PreparsedAst} source the source to parse
70 * @param {ParserState} state the parser state
71 * @returns {ParserState} the parser state
72 */
73 parse(source, state) {
74 if (!Buffer.isBuffer(source)) {
75 throw new Error("WebAssemblyParser input must be a Buffer");
76 }
77
78 // flag it as ESM
79 /** @type {BuildInfo} */
80 (state.module.buildInfo).strict = true;
81 /** @type {BuildMeta} */
82 (state.module.buildMeta).exportsType = "namespace";
83
84 // parse it
85 const program = decode(source, decoderOpts);
86 const module = program.body[0];
87
88 const moduleContext = moduleContextFromModuleAST(module);
89
90 // extract imports and exports
91 /** @type {string[]} */
92 const exports = [];
93 const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
94 /** @type {Record<string, string> | undefined} */
95 let jsIncompatibleExports = (buildMeta.jsIncompatibleExports = undefined);
96
97 /** @typedef {ModuleImport | null} ImportNode */
98 /** @type {ImportNode[]} */
99 const importedGlobals = [];
100
101 t.traverse(module, {
102 ModuleExport({ node }) {
103 const descriptor = node.descr;
104
105 if (descriptor.exportType === "Func") {
106 const funcIdx = descriptor.id.value;
107
108 /** @type {t.FuncSignature} */
109 const funcSignature = moduleContext.getFunction(funcIdx);
110
111 const incompatibleType =
112 getJsIncompatibleTypeOfFuncSignature(funcSignature);
113
114 if (incompatibleType) {
115 if (jsIncompatibleExports === undefined) {
116 jsIncompatibleExports =
117 /** @type {BuildMeta} */
118 (state.module.buildMeta).jsIncompatibleExports = {};
119 }
120 jsIncompatibleExports[node.name] = incompatibleType;
121 }
122 }
123
124 exports.push(node.name);
125
126 if (node.descr && node.descr.exportType === "Global") {
127 const refNode = importedGlobals[node.descr.id.value];
128 if (refNode) {
129 const dep = new WebAssemblyExportImportedDependency(
130 node.name,
131 refNode.module,
132 refNode.name,
133 /** @type {string} */
134 (refNode.descr.valtype)
135 );
136
137 state.module.addDependency(dep);
138 }
139 }
140 },
141
142 Global({ node }) {
143 const init = node.init[0];
144
145 /** @type {ImportNode} */
146 let importNode = null;
147
148 if (init.id === "get_global") {
149 const globalIdx = init.args[0].value;
150
151 if (globalIdx < importedGlobals.length) {
152 importNode = importedGlobals[globalIdx];
153 }
154 }
155
156 importedGlobals.push(importNode);
157 },
158
159 ModuleImport({ node }) {
160 /** @type {false | string} */
161 let onlyDirectImport = false;
162
163 if (t.isMemory(node.descr) === true) {
164 onlyDirectImport = "Memory";
165 } else if (t.isTable(node.descr) === true) {
166 onlyDirectImport = "Table";
167 } else if (t.isFuncImportDescr(node.descr) === true) {
168 const incompatibleType = getJsIncompatibleType(
169 /** @type {t.Signature} */
170 (node.descr.signature)
171 );
172 if (incompatibleType) {
173 onlyDirectImport = `Non-JS-compatible Func Signature (${incompatibleType})`;
174 }
175 } else if (t.isGlobalType(node.descr) === true) {
176 const type = /** @type {string} */ (node.descr.valtype);
177 if (!JS_COMPAT_TYPES.has(type)) {
178 onlyDirectImport = `Non-JS-compatible Global Type (${type})`;
179 }
180 }
181
182 const dep = new WebAssemblyImportDependency(
183 node.module,
184 node.name,
185 node.descr,
186 onlyDirectImport
187 );
188
189 state.module.addDependency(dep);
190
191 if (t.isGlobalType(node.descr)) {
192 importedGlobals.push(node);
193 }
194 }
195 });
196
197 state.module.addDependency(new StaticExportsDependency(exports, false));
198
199 return state;
200 }
201}
202
203module.exports = WebAssemblyParser;
Note: See TracBrowser for help on using the repository browser.