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

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

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