1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | import {
|
16 | BinaryReader,
|
17 | BinaryReaderState,
|
18 | bytesToString,
|
19 | ElementMode,
|
20 | ExternalKind,
|
21 | IDataSegmentBody,
|
22 | IElementSegment,
|
23 | IElementSegmentBody,
|
24 | IEventNameEntry,
|
25 | IEventType,
|
26 | IExportEntry,
|
27 | IFieldNameEntry,
|
28 | IFunctionEntry,
|
29 | IFunctionInformation,
|
30 | IFunctionNameEntry,
|
31 | IGlobalNameEntry,
|
32 | IGlobalType,
|
33 | IGlobalVariable,
|
34 | IImportEntry,
|
35 | ILocalNameEntry,
|
36 | IMemoryAddress,
|
37 | IMemoryNameEntry,
|
38 | IMemoryType,
|
39 | INameEntry,
|
40 | Int64,
|
41 | IOperatorInformation,
|
42 | IResizableLimits,
|
43 | ISectionInformation,
|
44 | IStartEntry,
|
45 | ITableNameEntry,
|
46 | ITableType,
|
47 | ITypeEntry,
|
48 | ITypeNameEntry,
|
49 | NameType,
|
50 | OperatorCode,
|
51 | OperatorCodeNames,
|
52 | SectionCode,
|
53 | Type,
|
54 | TypeKind,
|
55 | } from "./WasmParser.js";
|
56 |
|
57 | const NAME_SECTION_NAME = "name";
|
58 | const INVALID_NAME_SYMBOLS_REGEX = /[^0-9A-Za-z!#$%&'*+.:<=>?@^_`|~\/\-]/;
|
59 | const INVALID_NAME_SYMBOLS_REGEX_GLOBAL = new RegExp(
|
60 | INVALID_NAME_SYMBOLS_REGEX.source,
|
61 | "g"
|
62 | );
|
63 |
|
64 | function formatFloat32(n: number): string {
|
65 | if (n === 0) return 1 / n < 0 ? "-0.0" : "0.0";
|
66 | if (isFinite(n)) return n.toString();
|
67 | if (!isNaN(n)) return n < 0 ? "-inf" : "inf";
|
68 | var view = new DataView(new ArrayBuffer(8));
|
69 | view.setFloat32(0, n, true);
|
70 | var data = view.getInt32(0, true);
|
71 | var payload = data & 0x7fffff;
|
72 | const canonicalBits = 4194304;
|
73 | if (data > 0 && payload === canonicalBits) return "nan";
|
74 |
|
75 | else if (payload === canonicalBits) return "-nan";
|
76 | return (data < 0 ? "-" : "+") + "nan:0x" + payload.toString(16);
|
77 | }
|
78 |
|
79 | function formatFloat64(n: number): string {
|
80 | if (n === 0) return 1 / n < 0 ? "-0.0" : "0.0";
|
81 | if (isFinite(n)) return n.toString();
|
82 | if (!isNaN(n)) return n < 0 ? "-inf" : "inf";
|
83 | var view = new DataView(new ArrayBuffer(8));
|
84 | view.setFloat64(0, n, true);
|
85 | var data1 = view.getUint32(0, true);
|
86 | var data2 = view.getInt32(4, true);
|
87 | var payload = data1 + (data2 & 0xfffff) * 4294967296;
|
88 | const canonicalBits = 524288 * 4294967296;
|
89 | if (data2 > 0 && payload === canonicalBits) return "nan";
|
90 |
|
91 | else if (payload === canonicalBits) return "-nan";
|
92 | return (data2 < 0 ? "-" : "+") + "nan:0x" + payload.toString(16);
|
93 | }
|
94 |
|
95 | function formatI32Array(bytes, count) {
|
96 | var dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
97 | var result = [];
|
98 | for (var i = 0; i < count; i++)
|
99 | result.push(`0x${formatHex(dv.getInt32(i << 2, true), 8)}`);
|
100 | return result.join(" ");
|
101 | }
|
102 |
|
103 | function formatI8Array(bytes, count) {
|
104 | var dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
105 | var result = [];
|
106 | for (var i = 0; i < count; i++) result.push(`${dv.getInt8(i)}`);
|
107 | return result.join(" ");
|
108 | }
|
109 |
|
110 | function memoryAddressToString(
|
111 | address: IMemoryAddress,
|
112 | code: OperatorCode
|
113 | ): string {
|
114 | var defaultAlignFlags;
|
115 | switch (code) {
|
116 | case OperatorCode.v128_load:
|
117 | case OperatorCode.i16x8_load8x8_s:
|
118 | case OperatorCode.i16x8_load8x8_u:
|
119 | case OperatorCode.i32x4_load16x4_s:
|
120 | case OperatorCode.i32x4_load16x4_u:
|
121 | case OperatorCode.i64x2_load32x2_s:
|
122 | case OperatorCode.i64x2_load32x2_u:
|
123 | case OperatorCode.v8x16_load_splat:
|
124 | case OperatorCode.v16x8_load_splat:
|
125 | case OperatorCode.v32x4_load_splat:
|
126 | case OperatorCode.v64x2_load_splat:
|
127 | case OperatorCode.v128_store:
|
128 | defaultAlignFlags = 4;
|
129 | break;
|
130 | case OperatorCode.i64_load:
|
131 | case OperatorCode.i64_store:
|
132 | case OperatorCode.f64_load:
|
133 | case OperatorCode.f64_store:
|
134 | case OperatorCode.i64_atomic_wait:
|
135 | case OperatorCode.i64_atomic_load:
|
136 | case OperatorCode.i64_atomic_store:
|
137 | case OperatorCode.i64_atomic_rmw_add:
|
138 | case OperatorCode.i64_atomic_rmw_sub:
|
139 | case OperatorCode.i64_atomic_rmw_and:
|
140 | case OperatorCode.i64_atomic_rmw_or:
|
141 | case OperatorCode.i64_atomic_rmw_xor:
|
142 | case OperatorCode.i64_atomic_rmw_xchg:
|
143 | case OperatorCode.i64_atomic_rmw_cmpxchg:
|
144 | case OperatorCode.v128_load64_zero:
|
145 | defaultAlignFlags = 3;
|
146 | break;
|
147 | case OperatorCode.i32_load:
|
148 | case OperatorCode.i64_load32_s:
|
149 | case OperatorCode.i64_load32_u:
|
150 | case OperatorCode.i32_store:
|
151 | case OperatorCode.i64_store32:
|
152 | case OperatorCode.f32_load:
|
153 | case OperatorCode.f32_store:
|
154 | case OperatorCode.atomic_notify:
|
155 | case OperatorCode.i32_atomic_wait:
|
156 | case OperatorCode.i32_atomic_load:
|
157 | case OperatorCode.i64_atomic_load32_u:
|
158 | case OperatorCode.i32_atomic_store:
|
159 | case OperatorCode.i64_atomic_store32:
|
160 | case OperatorCode.i32_atomic_rmw_add:
|
161 | case OperatorCode.i64_atomic_rmw32_add_u:
|
162 | case OperatorCode.i32_atomic_rmw_sub:
|
163 | case OperatorCode.i64_atomic_rmw32_sub_u:
|
164 | case OperatorCode.i32_atomic_rmw_and:
|
165 | case OperatorCode.i64_atomic_rmw32_and_u:
|
166 | case OperatorCode.i32_atomic_rmw_or:
|
167 | case OperatorCode.i64_atomic_rmw32_or_u:
|
168 | case OperatorCode.i32_atomic_rmw_xor:
|
169 | case OperatorCode.i64_atomic_rmw32_xor_u:
|
170 | case OperatorCode.i32_atomic_rmw_xchg:
|
171 | case OperatorCode.i64_atomic_rmw32_xchg_u:
|
172 | case OperatorCode.i32_atomic_rmw_cmpxchg:
|
173 | case OperatorCode.i64_atomic_rmw32_cmpxchg_u:
|
174 | case OperatorCode.v128_load32_zero:
|
175 | defaultAlignFlags = 2;
|
176 | break;
|
177 | case OperatorCode.i32_load16_s:
|
178 | case OperatorCode.i32_load16_u:
|
179 | case OperatorCode.i64_load16_s:
|
180 | case OperatorCode.i64_load16_u:
|
181 | case OperatorCode.i32_store16:
|
182 | case OperatorCode.i64_store16:
|
183 | case OperatorCode.i32_atomic_load16_u:
|
184 | case OperatorCode.i64_atomic_load16_u:
|
185 | case OperatorCode.i32_atomic_store16:
|
186 | case OperatorCode.i64_atomic_store16:
|
187 | case OperatorCode.i32_atomic_rmw16_add_u:
|
188 | case OperatorCode.i64_atomic_rmw16_add_u:
|
189 | case OperatorCode.i32_atomic_rmw16_sub_u:
|
190 | case OperatorCode.i64_atomic_rmw16_sub_u:
|
191 | case OperatorCode.i32_atomic_rmw16_and_u:
|
192 | case OperatorCode.i64_atomic_rmw16_and_u:
|
193 | case OperatorCode.i32_atomic_rmw16_or_u:
|
194 | case OperatorCode.i64_atomic_rmw16_or_u:
|
195 | case OperatorCode.i32_atomic_rmw16_xor_u:
|
196 | case OperatorCode.i64_atomic_rmw16_xor_u:
|
197 | case OperatorCode.i32_atomic_rmw16_xchg_u:
|
198 | case OperatorCode.i64_atomic_rmw16_xchg_u:
|
199 | case OperatorCode.i32_atomic_rmw16_cmpxchg_u:
|
200 | case OperatorCode.i64_atomic_rmw16_cmpxchg_u:
|
201 | defaultAlignFlags = 1;
|
202 | break;
|
203 | case OperatorCode.i32_load8_s:
|
204 | case OperatorCode.i32_load8_u:
|
205 | case OperatorCode.i64_load8_s:
|
206 | case OperatorCode.i64_load8_u:
|
207 | case OperatorCode.i32_store8:
|
208 | case OperatorCode.i64_store8:
|
209 | case OperatorCode.i32_atomic_load8_u:
|
210 | case OperatorCode.i64_atomic_load8_u:
|
211 | case OperatorCode.i32_atomic_store8:
|
212 | case OperatorCode.i64_atomic_store8:
|
213 | case OperatorCode.i32_atomic_rmw8_add_u:
|
214 | case OperatorCode.i64_atomic_rmw8_add_u:
|
215 | case OperatorCode.i32_atomic_rmw8_sub_u:
|
216 | case OperatorCode.i64_atomic_rmw8_sub_u:
|
217 | case OperatorCode.i32_atomic_rmw8_and_u:
|
218 | case OperatorCode.i64_atomic_rmw8_and_u:
|
219 | case OperatorCode.i32_atomic_rmw8_or_u:
|
220 | case OperatorCode.i64_atomic_rmw8_or_u:
|
221 | case OperatorCode.i32_atomic_rmw8_xor_u:
|
222 | case OperatorCode.i64_atomic_rmw8_xor_u:
|
223 | case OperatorCode.i32_atomic_rmw8_xchg_u:
|
224 | case OperatorCode.i64_atomic_rmw8_xchg_u:
|
225 | case OperatorCode.i32_atomic_rmw8_cmpxchg_u:
|
226 | case OperatorCode.i64_atomic_rmw8_cmpxchg_u:
|
227 | defaultAlignFlags = 0;
|
228 | break;
|
229 | }
|
230 | if (address.flags == defaultAlignFlags)
|
231 |
|
232 | return !address.offset ? null : `offset=${address.offset}`;
|
233 | if (!address.offset)
|
234 |
|
235 | return `align=${1 << address.flags}`;
|
236 | return `offset=${address.offset | 0} align=${1 << address.flags}`;
|
237 | }
|
238 | function limitsToString(limits: IResizableLimits): string {
|
239 | return (
|
240 | limits.initial + (limits.maximum !== undefined ? " " + limits.maximum : "")
|
241 | );
|
242 | }
|
243 | var paddingCache = ["0", "00", "000"];
|
244 | function formatHex(n: number, width?: number): string {
|
245 | var s = (n >>> 0).toString(16).toUpperCase();
|
246 | if (width === undefined || s.length >= width) return s;
|
247 | var paddingIndex = width - s.length - 1;
|
248 | while (paddingIndex >= paddingCache.length)
|
249 | paddingCache.push(paddingCache[paddingCache.length - 1] + "0");
|
250 | return paddingCache[paddingIndex] + s;
|
251 | }
|
252 | const IndentIncrement = " ";
|
253 |
|
254 | function isValidName(name: string) {
|
255 | return !INVALID_NAME_SYMBOLS_REGEX.test(name);
|
256 | }
|
257 |
|
258 | export interface IExportMetadata {
|
259 | getFunctionExportNames(index: number): string[];
|
260 | getGlobalExportNames(index: number): string[];
|
261 | getMemoryExportNames(index: number): string[];
|
262 | getTableExportNames(index: number): string[];
|
263 | getEventExportNames(index: number): string[];
|
264 | }
|
265 |
|
266 | export interface INameResolver {
|
267 | getTypeName(index: number, isRef: boolean): string;
|
268 | getTableName(index: number, isRef: boolean): string;
|
269 | getMemoryName(index: number, isRef: boolean): string;
|
270 | getGlobalName(index: number, isRef: boolean): string;
|
271 | getElementName(index: number, isRef: boolean): string;
|
272 | getEventName(index: number, isRef: boolean): string;
|
273 | getFunctionName(index: number, isImport: boolean, isRef: boolean): string;
|
274 | getVariableName(funcIndex: number, index: number, isRef: boolean): string;
|
275 | getFieldName(typeIndex: number, index: number, isRef: boolean): string;
|
276 | getLabel(index: number): string;
|
277 | }
|
278 | export class DefaultNameResolver implements INameResolver {
|
279 | public getTypeName(index: number, isRef: boolean): string {
|
280 | return "$type" + index;
|
281 | }
|
282 | public getTableName(index: number, isRef: boolean): string {
|
283 | return "$table" + index;
|
284 | }
|
285 | public getMemoryName(index: number, isRef: boolean): string {
|
286 | return "$memory" + index;
|
287 | }
|
288 | public getGlobalName(index: number, isRef: boolean): string {
|
289 | return "$global" + index;
|
290 | }
|
291 | public getElementName(index: number, isRef: boolean): string {
|
292 | return `$elem${index}`;
|
293 | }
|
294 | public getEventName(index: number, isRef: boolean): string {
|
295 | return `$event${index}`;
|
296 | }
|
297 | public getFunctionName(
|
298 | index: number,
|
299 | isImport: boolean,
|
300 | isRef: boolean
|
301 | ): string {
|
302 | return (isImport ? "$import" : "$func") + index;
|
303 | }
|
304 | public getVariableName(
|
305 | funcIndex: number,
|
306 | index: number,
|
307 | isRef: boolean
|
308 | ): string {
|
309 | return "$var" + index;
|
310 | }
|
311 | public getFieldName(
|
312 | typeIndex: number,
|
313 | index: number,
|
314 | isRef: boolean
|
315 | ): string {
|
316 | return "$field" + index;
|
317 | }
|
318 | public getLabel(index: number): string {
|
319 | return "$label" + index;
|
320 | }
|
321 | }
|
322 |
|
323 | const EMPTY_STRING_ARRAY: string[] = [];
|
324 |
|
325 | class DevToolsExportMetadata implements IExportMetadata {
|
326 | private readonly _functionExportNames: string[][];
|
327 | private readonly _globalExportNames: string[][];
|
328 | private readonly _memoryExportNames: string[][];
|
329 | private readonly _tableExportNames: string[][];
|
330 | private readonly _eventExportNames: string[][];
|
331 |
|
332 | constructor(
|
333 | functionExportNames: string[][],
|
334 | globalExportNames: string[][],
|
335 | memoryExportNames: string[][],
|
336 | tableExportNames: string[][],
|
337 | eventExportNames: string[][]
|
338 | ) {
|
339 | this._functionExportNames = functionExportNames;
|
340 | this._globalExportNames = globalExportNames;
|
341 | this._memoryExportNames = memoryExportNames;
|
342 | this._tableExportNames = tableExportNames;
|
343 | this._eventExportNames = eventExportNames;
|
344 | }
|
345 |
|
346 | public getFunctionExportNames(index: number) {
|
347 | return this._functionExportNames[index] ?? EMPTY_STRING_ARRAY;
|
348 | }
|
349 |
|
350 | public getGlobalExportNames(index: number) {
|
351 | return this._globalExportNames[index] ?? EMPTY_STRING_ARRAY;
|
352 | }
|
353 |
|
354 | public getMemoryExportNames(index: number) {
|
355 | return this._memoryExportNames[index] ?? EMPTY_STRING_ARRAY;
|
356 | }
|
357 |
|
358 | public getTableExportNames(index: number) {
|
359 | return this._tableExportNames[index] ?? EMPTY_STRING_ARRAY;
|
360 | }
|
361 |
|
362 | public getEventExportNames(index: number) {
|
363 | return this._eventExportNames[index] ?? EMPTY_STRING_ARRAY;
|
364 | }
|
365 | }
|
366 |
|
367 | export class NumericNameResolver implements INameResolver {
|
368 | public getTypeName(index: number, isRef: boolean): string {
|
369 | return isRef ? "" + index : `(;${index};)`;
|
370 | }
|
371 | public getTableName(index: number, isRef: boolean): string {
|
372 | return isRef ? "" + index : `(;${index};)`;
|
373 | }
|
374 | public getMemoryName(index: number, isRef: boolean): string {
|
375 | return isRef ? "" + index : `(;${index};)`;
|
376 | }
|
377 | public getGlobalName(index: number, isRef: boolean): string {
|
378 | return isRef ? "" + index : `(;${index};)`;
|
379 | }
|
380 | public getElementName(index: number, isRef: boolean): string {
|
381 | return isRef ? "" + index : `(;${index};)`;
|
382 | }
|
383 | public getEventName(index: number, isRef: boolean): string {
|
384 | return isRef ? "" + index : `(;${index};)`;
|
385 | }
|
386 | public getFunctionName(
|
387 | index: number,
|
388 | isImport: boolean,
|
389 | isRef: boolean
|
390 | ): string {
|
391 | return isRef ? "" + index : `(;${index};)`;
|
392 | }
|
393 | public getVariableName(
|
394 | funcIndex: number,
|
395 | index: number,
|
396 | isRef: boolean
|
397 | ): string {
|
398 | return isRef ? "" + index : `(;${index};)`;
|
399 | }
|
400 | public getFieldName(
|
401 | typeIndex: number,
|
402 | index: number,
|
403 | isRef: boolean
|
404 | ): string {
|
405 | return isRef ? "" : index + `(;${index};)`;
|
406 | }
|
407 | public getLabel(index: number): string {
|
408 | return null;
|
409 | }
|
410 | }
|
411 |
|
412 | export enum LabelMode {
|
413 | Depth,
|
414 | WhenUsed,
|
415 | Always,
|
416 | }
|
417 |
|
418 |
|
419 | export interface IFunctionBodyOffset {
|
420 | start: number;
|
421 | end: number;
|
422 | }
|
423 |
|
424 | export interface IDisassemblerResult {
|
425 | lines: Array<string>;
|
426 | offsets?: Array<number>;
|
427 | done: boolean;
|
428 | functionBodyOffsets?: Array<IFunctionBodyOffset>;
|
429 | }
|
430 |
|
431 | export class WasmDisassembler {
|
432 | private _lines: Array<string>;
|
433 | private _offsets: Array<number>;
|
434 | private _buffer: string;
|
435 | private _types: Array<ITypeEntry>;
|
436 | private _funcIndex: number;
|
437 | private _funcTypes: Array<number>;
|
438 | private _importCount: number;
|
439 | private _globalCount: number;
|
440 | private _memoryCount: number;
|
441 | private _eventCount: number;
|
442 | private _tableCount: number;
|
443 | private _elementCount: number;
|
444 | private _expression: Array<IOperatorInformation>;
|
445 | private _backrefLabels: Array<{
|
446 | line: number;
|
447 | position: number;
|
448 | useLabel: boolean;
|
449 | label: string;
|
450 | }>;
|
451 | private _labelIndex: number;
|
452 | private _indent: string;
|
453 | private _indentLevel: number;
|
454 | private _addOffsets: boolean;
|
455 | private _skipTypes = true;
|
456 | private _done: boolean;
|
457 | private _currentPosition: number;
|
458 | private _nameResolver: INameResolver;
|
459 | private _exportMetadata: IExportMetadata = null;
|
460 | private _labelMode: LabelMode;
|
461 | private _functionBodyOffsets: Array<IFunctionBodyOffset>;
|
462 | private _currentFunctionBodyOffset: number;
|
463 | private _currentSectionId: SectionCode;
|
464 | private _logFirstInstruction: boolean;
|
465 | constructor() {
|
466 | this._lines = [];
|
467 | this._offsets = [];
|
468 | this._buffer = "";
|
469 | this._indent = null;
|
470 | this._indentLevel = 0;
|
471 | this._addOffsets = false;
|
472 | this._done = false;
|
473 | this._currentPosition = 0;
|
474 | this._nameResolver = new DefaultNameResolver();
|
475 | this._labelMode = LabelMode.WhenUsed;
|
476 | this._functionBodyOffsets = [];
|
477 | this._currentFunctionBodyOffset = 0;
|
478 | this._currentSectionId = SectionCode.Unknown;
|
479 | this._logFirstInstruction = false;
|
480 |
|
481 | this._reset();
|
482 | }
|
483 | private _reset(): void {
|
484 | this._types = [];
|
485 | this._funcIndex = 0;
|
486 | this._funcTypes = [];
|
487 | this._importCount = 0;
|
488 | this._globalCount = 0;
|
489 | this._memoryCount = 0;
|
490 | this._eventCount = 0;
|
491 | this._tableCount = 0;
|
492 | this._elementCount = 0;
|
493 | this._expression = [];
|
494 | this._backrefLabels = null;
|
495 | this._labelIndex = 0;
|
496 | }
|
497 | public get addOffsets(): boolean {
|
498 | return this._addOffsets;
|
499 | }
|
500 | public set addOffsets(value: boolean) {
|
501 | if (this._currentPosition)
|
502 | throw new Error("Cannot switch addOffsets during processing.");
|
503 | this._addOffsets = value;
|
504 | }
|
505 | public get skipTypes(): boolean {
|
506 | return this._skipTypes;
|
507 | }
|
508 | public set skipTypes(skipTypes: boolean) {
|
509 | if (this._currentPosition)
|
510 | throw new Error("Cannot switch skipTypes during processing.");
|
511 | this._skipTypes = skipTypes;
|
512 | }
|
513 | public get labelMode(): LabelMode {
|
514 | return this._labelMode;
|
515 | }
|
516 | public set labelMode(value: LabelMode) {
|
517 | if (this._currentPosition)
|
518 | throw new Error("Cannot switch labelMode during processing.");
|
519 | this._labelMode = value;
|
520 | }
|
521 | public get exportMetadata(): IExportMetadata {
|
522 | return this._exportMetadata;
|
523 | }
|
524 | public set exportMetadata(exportMetadata: IExportMetadata) {
|
525 | if (this._currentPosition)
|
526 | throw new Error("Cannot switch exportMetadata during processing.");
|
527 | this._exportMetadata = exportMetadata;
|
528 | }
|
529 | public get nameResolver(): INameResolver {
|
530 | return this._nameResolver;
|
531 | }
|
532 | public set nameResolver(resolver: INameResolver) {
|
533 | if (this._currentPosition)
|
534 | throw new Error("Cannot switch nameResolver during processing.");
|
535 | this._nameResolver = resolver;
|
536 | }
|
537 | private appendBuffer(s: string) {
|
538 | this._buffer += s;
|
539 | }
|
540 | private newLine() {
|
541 | if (this.addOffsets) this._offsets.push(this._currentPosition);
|
542 | this._lines.push(this._buffer);
|
543 | this._buffer = "";
|
544 | }
|
545 | private logStartOfFunctionBodyOffset() {
|
546 | if (this.addOffsets) {
|
547 | this._currentFunctionBodyOffset = this._currentPosition;
|
548 | }
|
549 | }
|
550 | private logEndOfFunctionBodyOffset() {
|
551 | if (this.addOffsets) {
|
552 | this._functionBodyOffsets.push({
|
553 | start: this._currentFunctionBodyOffset,
|
554 | end: this._currentPosition,
|
555 | });
|
556 | }
|
557 | }
|
558 | private typeIndexToString(typeIndex: number): string {
|
559 | if (typeIndex >= 0) return this._nameResolver.getTypeName(typeIndex, true);
|
560 | switch (typeIndex) {
|
561 | case TypeKind.funcref:
|
562 | return "func";
|
563 | case TypeKind.externref:
|
564 | return "extern";
|
565 | case TypeKind.anyref:
|
566 | return "any";
|
567 | case TypeKind.eqref:
|
568 | return "eq";
|
569 | case TypeKind.i31ref:
|
570 | return "i31";
|
571 | case TypeKind.dataref:
|
572 | return "data";
|
573 | }
|
574 | }
|
575 | private typeToString(type: Type): string {
|
576 | switch (type.kind) {
|
577 | case TypeKind.i32:
|
578 | return "i32";
|
579 | case TypeKind.i64:
|
580 | return "i64";
|
581 | case TypeKind.f32:
|
582 | return "f32";
|
583 | case TypeKind.f64:
|
584 | return "f64";
|
585 | case TypeKind.v128:
|
586 | return "v128";
|
587 | case TypeKind.i8:
|
588 | return "i8";
|
589 | case TypeKind.i16:
|
590 | return "i16";
|
591 | case TypeKind.funcref:
|
592 | return "funcref";
|
593 | case TypeKind.externref:
|
594 | return "externref";
|
595 | case TypeKind.anyref:
|
596 | return "anyref";
|
597 | case TypeKind.eqref:
|
598 | return "eqref";
|
599 | case TypeKind.i31ref:
|
600 | return "i31ref";
|
601 | case TypeKind.dataref:
|
602 | return "dataref";
|
603 | case TypeKind.ref:
|
604 | return `(ref ${this.typeIndexToString(type.index)})`;
|
605 | case TypeKind.optref:
|
606 | return `(ref null ${this.typeIndexToString(type.index)})`;
|
607 | case TypeKind.rtt:
|
608 | return `(rtt ${this.typeIndexToString(type.index)})`;
|
609 | case TypeKind.rtt_d:
|
610 | return `(rtt ${type.depth} ${this.typeIndexToString(type.index)})`;
|
611 | default:
|
612 | throw new Error(`Unexpected type ${JSON.stringify(type)}`);
|
613 | }
|
614 | }
|
615 | private maybeMut(type: string, mutability: boolean): string {
|
616 | return mutability ? `(mut ${type})` : type;
|
617 | }
|
618 | private globalTypeToString(type: IGlobalType): string {
|
619 | const typeStr = this.typeToString(type.contentType);
|
620 | return this.maybeMut(typeStr, !!type.mutability);
|
621 | }
|
622 | private printFuncType(typeIndex: number): void {
|
623 | var type = this._types[typeIndex];
|
624 | if (type.params.length > 0) {
|
625 | this.appendBuffer(" (param");
|
626 | for (var i = 0; i < type.params.length; i++) {
|
627 | this.appendBuffer(" ");
|
628 | this.appendBuffer(this.typeToString(type.params[i]));
|
629 | }
|
630 | this.appendBuffer(")");
|
631 | }
|
632 | if (type.returns.length > 0) {
|
633 | this.appendBuffer(" (result");
|
634 | for (var i = 0; i < type.returns.length; i++) {
|
635 | this.appendBuffer(" ");
|
636 | this.appendBuffer(this.typeToString(type.returns[i]));
|
637 | }
|
638 | this.appendBuffer(")");
|
639 | }
|
640 | }
|
641 | private printStructType(typeIndex: number): void {
|
642 | var type = this._types[typeIndex];
|
643 | if (type.fields.length === 0) return;
|
644 | for (var i = 0; i < type.fields.length; i++) {
|
645 | const fieldType = this.maybeMut(
|
646 | this.typeToString(type.fields[i]),
|
647 | type.mutabilities[i]
|
648 | );
|
649 | const fieldName = this._nameResolver.getFieldName(typeIndex, i, false);
|
650 | this.appendBuffer(` (field ${fieldName} ${fieldType})`);
|
651 | }
|
652 | }
|
653 | private printArrayType(typeIndex: number): void {
|
654 | var type = this._types[typeIndex];
|
655 | this.appendBuffer(" (field ");
|
656 | this.appendBuffer(
|
657 | this.maybeMut(this.typeToString(type.elementType), type.mutability)
|
658 | );
|
659 | }
|
660 | private printBlockType(type: Type): void {
|
661 | if (type.kind === TypeKind.empty_block_type) {
|
662 | return;
|
663 | }
|
664 | if (type.kind === TypeKind.unspecified) {
|
665 | return this.printFuncType(type.index);
|
666 | }
|
667 | this.appendBuffer(" (result ");
|
668 | this.appendBuffer(this.typeToString(type));
|
669 | this.appendBuffer(")");
|
670 | }
|
671 | private printString(b: Uint8Array): void {
|
672 | this.appendBuffer('"');
|
673 | for (var i = 0; i < b.length; i++) {
|
674 | var byte = b[i];
|
675 | if (
|
676 | byte < 0x20 ||
|
677 | byte >= 0x7f ||
|
678 | byte == 0x22 ||
|
679 | byte == 0x5c
|
680 | ) {
|
681 | this.appendBuffer(
|
682 | "\\" + (byte >> 4).toString(16) + (byte & 15).toString(16)
|
683 | );
|
684 | } else {
|
685 | this.appendBuffer(String.fromCharCode(byte));
|
686 | }
|
687 | }
|
688 | this.appendBuffer('"');
|
689 | }
|
690 | private printExpression(expression: IOperatorInformation[]): void {
|
691 | for (const operator of expression) {
|
692 | this.appendBuffer("(");
|
693 | this.printOperator(operator);
|
694 | this.appendBuffer(")");
|
695 | }
|
696 | }
|
697 |
|
698 | private useLabel(depth: number, extraDepthOffset = 0): string {
|
699 | if (!this._backrefLabels) {
|
700 | return "" + depth;
|
701 | }
|
702 | var i = this._backrefLabels.length - depth - 1 - extraDepthOffset;
|
703 | if (i < 0) {
|
704 | return "" + depth;
|
705 | }
|
706 | var backrefLabel = this._backrefLabels[i];
|
707 | if (!backrefLabel.useLabel) {
|
708 | backrefLabel.useLabel = true;
|
709 | backrefLabel.label = this._nameResolver.getLabel(this._labelIndex);
|
710 | var line = this._lines[backrefLabel.line];
|
711 | this._lines[backrefLabel.line] =
|
712 | line.substring(0, backrefLabel.position) +
|
713 | " " +
|
714 | backrefLabel.label +
|
715 | line.substring(backrefLabel.position);
|
716 | this._labelIndex++;
|
717 | }
|
718 | return backrefLabel.label || "" + depth;
|
719 | }
|
720 | private printOperator(operator: IOperatorInformation): void {
|
721 | var code = operator.code;
|
722 | this.appendBuffer(OperatorCodeNames[code]);
|
723 | switch (code) {
|
724 | case OperatorCode.block:
|
725 | case OperatorCode.loop:
|
726 | case OperatorCode.if:
|
727 | case OperatorCode.try:
|
728 | if (this._labelMode !== LabelMode.Depth) {
|
729 | const backrefLabel = {
|
730 | line: this._lines.length,
|
731 | position: this._buffer.length,
|
732 | useLabel: false,
|
733 | label: null,
|
734 | };
|
735 | if (this._labelMode === LabelMode.Always) {
|
736 | backrefLabel.useLabel = true;
|
737 | backrefLabel.label = this._nameResolver.getLabel(
|
738 | this._labelIndex++
|
739 | );
|
740 | if (backrefLabel.label) {
|
741 | this.appendBuffer(" ");
|
742 | this.appendBuffer(backrefLabel.label);
|
743 | }
|
744 | }
|
745 | this._backrefLabels.push(backrefLabel);
|
746 | }
|
747 | this.printBlockType(operator.blockType);
|
748 | break;
|
749 | case OperatorCode.end:
|
750 | if (this._labelMode === LabelMode.Depth) {
|
751 | break;
|
752 | }
|
753 | const backrefLabel = this._backrefLabels.pop();
|
754 | if (backrefLabel.label) {
|
755 | this.appendBuffer(" ");
|
756 | this.appendBuffer(backrefLabel.label);
|
757 | }
|
758 | break;
|
759 | case OperatorCode.br:
|
760 | case OperatorCode.br_if:
|
761 | case OperatorCode.br_on_null:
|
762 | case OperatorCode.br_on_non_null:
|
763 | case OperatorCode.br_on_cast:
|
764 | case OperatorCode.br_on_cast_fail:
|
765 | case OperatorCode.br_on_func:
|
766 | case OperatorCode.br_on_non_func:
|
767 | case OperatorCode.br_on_data:
|
768 | case OperatorCode.br_on_non_data:
|
769 | case OperatorCode.br_on_i31:
|
770 | case OperatorCode.br_on_non_i31:
|
771 | this.appendBuffer(" ");
|
772 | this.appendBuffer(this.useLabel(operator.brDepth));
|
773 | break;
|
774 | case OperatorCode.br_on_cast_static:
|
775 | case OperatorCode.br_on_cast_static_fail: {
|
776 | const label = this.useLabel(operator.brDepth);
|
777 | const refType = this._nameResolver.getTypeName(operator.refType, true);
|
778 | this.appendBuffer(` ${label} ${refType}`);
|
779 | break;
|
780 | }
|
781 | case OperatorCode.br_table:
|
782 | for (var i = 0; i < operator.brTable.length; i++) {
|
783 | this.appendBuffer(" ");
|
784 | this.appendBuffer(this.useLabel(operator.brTable[i]));
|
785 | }
|
786 | break;
|
787 | case OperatorCode.rethrow:
|
788 | this.appendBuffer(" ");
|
789 | this.appendBuffer(this.useLabel(operator.relativeDepth));
|
790 | break;
|
791 | case OperatorCode.delegate:
|
792 | this.appendBuffer(" ");
|
793 | this.appendBuffer(this.useLabel(operator.relativeDepth, 1));
|
794 | break;
|
795 | case OperatorCode.catch:
|
796 | case OperatorCode.throw:
|
797 | var eventName = this._nameResolver.getEventName(
|
798 | operator.eventIndex,
|
799 | true
|
800 | );
|
801 | this.appendBuffer(` ${eventName}`);
|
802 | break;
|
803 | case OperatorCode.ref_null:
|
804 | this.appendBuffer(" ");
|
805 | this.appendBuffer(this.typeIndexToString(operator.refType));
|
806 | break;
|
807 | case OperatorCode.call:
|
808 | case OperatorCode.return_call:
|
809 | case OperatorCode.ref_func:
|
810 | var funcName = this._nameResolver.getFunctionName(
|
811 | operator.funcIndex,
|
812 | operator.funcIndex < this._importCount,
|
813 | true
|
814 | );
|
815 | this.appendBuffer(` ${funcName}`);
|
816 | break;
|
817 | case OperatorCode.call_indirect:
|
818 | case OperatorCode.return_call_indirect:
|
819 | this.printFuncType(operator.typeIndex);
|
820 | break;
|
821 | case OperatorCode.select_with_type: {
|
822 | const selectType = this.typeToString(operator.selectType);
|
823 | this.appendBuffer(` ${selectType}`);
|
824 | break;
|
825 | }
|
826 | case OperatorCode.local_get:
|
827 | case OperatorCode.local_set:
|
828 | case OperatorCode.local_tee:
|
829 | var paramName = this._nameResolver.getVariableName(
|
830 | this._funcIndex,
|
831 | operator.localIndex,
|
832 | true
|
833 | );
|
834 | this.appendBuffer(` ${paramName}`);
|
835 | break;
|
836 | case OperatorCode.global_get:
|
837 | case OperatorCode.global_set:
|
838 | var globalName = this._nameResolver.getGlobalName(
|
839 | operator.globalIndex,
|
840 | true
|
841 | );
|
842 | this.appendBuffer(` ${globalName}`);
|
843 | break;
|
844 | case OperatorCode.i32_load:
|
845 | case OperatorCode.i64_load:
|
846 | case OperatorCode.f32_load:
|
847 | case OperatorCode.f64_load:
|
848 | case OperatorCode.i32_load8_s:
|
849 | case OperatorCode.i32_load8_u:
|
850 | case OperatorCode.i32_load16_s:
|
851 | case OperatorCode.i32_load16_u:
|
852 | case OperatorCode.i64_load8_s:
|
853 | case OperatorCode.i64_load8_u:
|
854 | case OperatorCode.i64_load16_s:
|
855 | case OperatorCode.i64_load16_u:
|
856 | case OperatorCode.i64_load32_s:
|
857 | case OperatorCode.i64_load32_u:
|
858 | case OperatorCode.i32_store:
|
859 | case OperatorCode.i64_store:
|
860 | case OperatorCode.f32_store:
|
861 | case OperatorCode.f64_store:
|
862 | case OperatorCode.i32_store8:
|
863 | case OperatorCode.i32_store16:
|
864 | case OperatorCode.i64_store8:
|
865 | case OperatorCode.i64_store16:
|
866 | case OperatorCode.i64_store32:
|
867 | case OperatorCode.atomic_notify:
|
868 | case OperatorCode.i32_atomic_wait:
|
869 | case OperatorCode.i64_atomic_wait:
|
870 | case OperatorCode.i32_atomic_load:
|
871 | case OperatorCode.i64_atomic_load:
|
872 | case OperatorCode.i32_atomic_load8_u:
|
873 | case OperatorCode.i32_atomic_load16_u:
|
874 | case OperatorCode.i64_atomic_load8_u:
|
875 | case OperatorCode.i64_atomic_load16_u:
|
876 | case OperatorCode.i64_atomic_load32_u:
|
877 | case OperatorCode.i32_atomic_store:
|
878 | case OperatorCode.i64_atomic_store:
|
879 | case OperatorCode.i32_atomic_store8:
|
880 | case OperatorCode.i32_atomic_store16:
|
881 | case OperatorCode.i64_atomic_store8:
|
882 | case OperatorCode.i64_atomic_store16:
|
883 | case OperatorCode.i64_atomic_store32:
|
884 | case OperatorCode.i32_atomic_rmw_add:
|
885 | case OperatorCode.i64_atomic_rmw_add:
|
886 | case OperatorCode.i32_atomic_rmw8_add_u:
|
887 | case OperatorCode.i32_atomic_rmw16_add_u:
|
888 | case OperatorCode.i64_atomic_rmw8_add_u:
|
889 | case OperatorCode.i64_atomic_rmw16_add_u:
|
890 | case OperatorCode.i64_atomic_rmw32_add_u:
|
891 | case OperatorCode.i32_atomic_rmw_sub:
|
892 | case OperatorCode.i64_atomic_rmw_sub:
|
893 | case OperatorCode.i32_atomic_rmw8_sub_u:
|
894 | case OperatorCode.i32_atomic_rmw16_sub_u:
|
895 | case OperatorCode.i64_atomic_rmw8_sub_u:
|
896 | case OperatorCode.i64_atomic_rmw16_sub_u:
|
897 | case OperatorCode.i64_atomic_rmw32_sub_u:
|
898 | case OperatorCode.i32_atomic_rmw_and:
|
899 | case OperatorCode.i64_atomic_rmw_and:
|
900 | case OperatorCode.i32_atomic_rmw8_and_u:
|
901 | case OperatorCode.i32_atomic_rmw16_and_u:
|
902 | case OperatorCode.i64_atomic_rmw8_and_u:
|
903 | case OperatorCode.i64_atomic_rmw16_and_u:
|
904 | case OperatorCode.i64_atomic_rmw32_and_u:
|
905 | case OperatorCode.i32_atomic_rmw_or:
|
906 | case OperatorCode.i64_atomic_rmw_or:
|
907 | case OperatorCode.i32_atomic_rmw8_or_u:
|
908 | case OperatorCode.i32_atomic_rmw16_or_u:
|
909 | case OperatorCode.i64_atomic_rmw8_or_u:
|
910 | case OperatorCode.i64_atomic_rmw16_or_u:
|
911 | case OperatorCode.i64_atomic_rmw32_or_u:
|
912 | case OperatorCode.i32_atomic_rmw_xor:
|
913 | case OperatorCode.i64_atomic_rmw_xor:
|
914 | case OperatorCode.i32_atomic_rmw8_xor_u:
|
915 | case OperatorCode.i32_atomic_rmw16_xor_u:
|
916 | case OperatorCode.i64_atomic_rmw8_xor_u:
|
917 | case OperatorCode.i64_atomic_rmw16_xor_u:
|
918 | case OperatorCode.i64_atomic_rmw32_xor_u:
|
919 | case OperatorCode.i32_atomic_rmw_xchg:
|
920 | case OperatorCode.i64_atomic_rmw_xchg:
|
921 | case OperatorCode.i32_atomic_rmw8_xchg_u:
|
922 | case OperatorCode.i32_atomic_rmw16_xchg_u:
|
923 | case OperatorCode.i64_atomic_rmw8_xchg_u:
|
924 | case OperatorCode.i64_atomic_rmw16_xchg_u:
|
925 | case OperatorCode.i64_atomic_rmw32_xchg_u:
|
926 | case OperatorCode.i32_atomic_rmw_cmpxchg:
|
927 | case OperatorCode.i64_atomic_rmw_cmpxchg:
|
928 | case OperatorCode.i32_atomic_rmw8_cmpxchg_u:
|
929 | case OperatorCode.i32_atomic_rmw16_cmpxchg_u:
|
930 | case OperatorCode.i64_atomic_rmw8_cmpxchg_u:
|
931 | case OperatorCode.i64_atomic_rmw16_cmpxchg_u:
|
932 | case OperatorCode.i64_atomic_rmw32_cmpxchg_u:
|
933 | case OperatorCode.v128_load:
|
934 | case OperatorCode.i16x8_load8x8_s:
|
935 | case OperatorCode.i16x8_load8x8_u:
|
936 | case OperatorCode.i32x4_load16x4_s:
|
937 | case OperatorCode.i32x4_load16x4_u:
|
938 | case OperatorCode.i64x2_load32x2_s:
|
939 | case OperatorCode.i64x2_load32x2_u:
|
940 | case OperatorCode.v8x16_load_splat:
|
941 | case OperatorCode.v16x8_load_splat:
|
942 | case OperatorCode.v32x4_load_splat:
|
943 | case OperatorCode.v64x2_load_splat:
|
944 | case OperatorCode.v128_store:
|
945 | case OperatorCode.v128_load32_zero:
|
946 | case OperatorCode.v128_load64_zero:
|
947 | var memoryAddress = memoryAddressToString(
|
948 | operator.memoryAddress,
|
949 | operator.code
|
950 | );
|
951 | if (memoryAddress !== null) {
|
952 | this.appendBuffer(" ");
|
953 | this.appendBuffer(memoryAddress);
|
954 | }
|
955 | break;
|
956 | case OperatorCode.current_memory:
|
957 | case OperatorCode.grow_memory:
|
958 | break;
|
959 | case OperatorCode.i32_const:
|
960 | this.appendBuffer(` ${(<number>operator.literal).toString()}`);
|
961 | break;
|
962 | case OperatorCode.i64_const:
|
963 | this.appendBuffer(` ${(<Int64>operator.literal).toString()}`);
|
964 | break;
|
965 | case OperatorCode.f32_const:
|
966 | this.appendBuffer(` ${formatFloat32(<number>operator.literal)}`);
|
967 | break;
|
968 | case OperatorCode.f64_const:
|
969 | this.appendBuffer(` ${formatFloat64(<number>operator.literal)}`);
|
970 | break;
|
971 | case OperatorCode.v128_const:
|
972 | this.appendBuffer(` i32x4 ${formatI32Array(operator.literal, 4)}`);
|
973 | break;
|
974 | case OperatorCode.i8x16_shuffle:
|
975 | this.appendBuffer(` ${formatI8Array(operator.lines, 16)}`);
|
976 | break;
|
977 | case OperatorCode.i8x16_extract_lane_s:
|
978 | case OperatorCode.i8x16_extract_lane_u:
|
979 | case OperatorCode.i8x16_replace_lane:
|
980 | case OperatorCode.i16x8_extract_lane_s:
|
981 | case OperatorCode.i16x8_extract_lane_u:
|
982 | case OperatorCode.i16x8_replace_lane:
|
983 | case OperatorCode.i32x4_extract_lane:
|
984 | case OperatorCode.i32x4_replace_lane:
|
985 | case OperatorCode.f32x4_extract_lane:
|
986 | case OperatorCode.f32x4_replace_lane:
|
987 | case OperatorCode.i64x2_extract_lane:
|
988 | case OperatorCode.i64x2_replace_lane:
|
989 | case OperatorCode.f64x2_extract_lane:
|
990 | case OperatorCode.f64x2_replace_lane:
|
991 | this.appendBuffer(` ${operator.lineIndex}`);
|
992 | break;
|
993 | case OperatorCode.memory_init:
|
994 | case OperatorCode.data_drop:
|
995 | this.appendBuffer(` ${operator.segmentIndex}`);
|
996 | break;
|
997 | case OperatorCode.elem_drop:
|
998 | const elementName = this._nameResolver.getElementName(
|
999 | operator.segmentIndex,
|
1000 | true
|
1001 | );
|
1002 | this.appendBuffer(` ${elementName}`);
|
1003 | break;
|
1004 | case OperatorCode.table_set:
|
1005 | case OperatorCode.table_get:
|
1006 | case OperatorCode.table_fill: {
|
1007 | const tableName = this._nameResolver.getTableName(
|
1008 | operator.tableIndex,
|
1009 | true
|
1010 | );
|
1011 | this.appendBuffer(` ${tableName}`);
|
1012 | break;
|
1013 | }
|
1014 | case OperatorCode.table_copy: {
|
1015 |
|
1016 | if (operator.tableIndex !== 0 || operator.destinationIndex !== 0) {
|
1017 | const tableName = this._nameResolver.getTableName(
|
1018 | operator.tableIndex,
|
1019 | true
|
1020 | );
|
1021 | const destinationName = this._nameResolver.getTableName(
|
1022 | operator.destinationIndex,
|
1023 | true
|
1024 | );
|
1025 | this.appendBuffer(` ${destinationName} ${tableName}`);
|
1026 | }
|
1027 | break;
|
1028 | }
|
1029 | case OperatorCode.table_init: {
|
1030 |
|
1031 | if (operator.tableIndex !== 0) {
|
1032 | const tableName = this._nameResolver.getTableName(
|
1033 | operator.tableIndex,
|
1034 | true
|
1035 | );
|
1036 | this.appendBuffer(` ${tableName}`);
|
1037 | }
|
1038 | const elementName = this._nameResolver.getElementName(
|
1039 | operator.segmentIndex,
|
1040 | true
|
1041 | );
|
1042 | this.appendBuffer(` ${elementName}`);
|
1043 | break;
|
1044 | }
|
1045 | case OperatorCode.struct_get:
|
1046 | case OperatorCode.struct_get_s:
|
1047 | case OperatorCode.struct_get_u:
|
1048 | case OperatorCode.struct_set: {
|
1049 | const refType = this._nameResolver.getTypeName(operator.refType, true);
|
1050 | const fieldName = this._nameResolver.getFieldName(
|
1051 | operator.refType,
|
1052 | operator.fieldIndex,
|
1053 | true
|
1054 | );
|
1055 | this.appendBuffer(` ${refType} ${fieldName}`);
|
1056 | break;
|
1057 | }
|
1058 | case OperatorCode.rtt_canon:
|
1059 | case OperatorCode.rtt_sub:
|
1060 | case OperatorCode.rtt_fresh_sub:
|
1061 | case OperatorCode.ref_test_static:
|
1062 | case OperatorCode.ref_cast_static:
|
1063 | case OperatorCode.struct_new_default:
|
1064 | case OperatorCode.struct_new_default_with_rtt:
|
1065 | case OperatorCode.struct_new:
|
1066 | case OperatorCode.struct_new_with_rtt:
|
1067 | case OperatorCode.array_new_default:
|
1068 | case OperatorCode.array_new_default_with_rtt:
|
1069 | case OperatorCode.array_new:
|
1070 | case OperatorCode.array_new_with_rtt:
|
1071 | case OperatorCode.array_get:
|
1072 | case OperatorCode.array_get_s:
|
1073 | case OperatorCode.array_get_u:
|
1074 | case OperatorCode.array_set:
|
1075 | case OperatorCode.array_len: {
|
1076 | const refType = this._nameResolver.getTypeName(operator.refType, true);
|
1077 | this.appendBuffer(` ${refType}`);
|
1078 | break;
|
1079 | }
|
1080 | case OperatorCode.array_copy: {
|
1081 | const dstType = this._nameResolver.getTypeName(operator.refType, true);
|
1082 | const srcType = this._nameResolver.getTypeName(operator.srcType, true);
|
1083 | this.appendBuffer(` ${dstType} ${srcType}`);
|
1084 | break;
|
1085 | }
|
1086 | case OperatorCode.array_init:
|
1087 | case OperatorCode.array_init_static: {
|
1088 | const refType = this._nameResolver.getTypeName(operator.refType, true);
|
1089 | const length = operator.brDepth;
|
1090 | this.appendBuffer(` ${refType} ${length}`);
|
1091 | break;
|
1092 | }
|
1093 | }
|
1094 | }
|
1095 | private printImportSource(info: IImportEntry): void {
|
1096 | this.printString(info.module);
|
1097 | this.appendBuffer(" ");
|
1098 | this.printString(info.field);
|
1099 | }
|
1100 | private increaseIndent(): void {
|
1101 | this._indent += IndentIncrement;
|
1102 | this._indentLevel++;
|
1103 | }
|
1104 | private decreaseIndent(): void {
|
1105 | this._indent = this._indent.slice(0, -IndentIncrement.length);
|
1106 | this._indentLevel--;
|
1107 | }
|
1108 | public disassemble(reader: BinaryReader): string {
|
1109 | const done = this.disassembleChunk(reader);
|
1110 | if (!done) return null;
|
1111 | let lines = this._lines;
|
1112 | if (this._addOffsets) {
|
1113 | lines = lines.map((line, index) => {
|
1114 | var position = formatHex(this._offsets[index], 4);
|
1115 | return line + " ;; @" + position;
|
1116 | });
|
1117 | }
|
1118 | lines.push("");
|
1119 | const result = lines.join("\n");
|
1120 | this._lines.length = 0;
|
1121 | this._offsets.length = 0;
|
1122 | this._functionBodyOffsets.length = 0;
|
1123 | return result;
|
1124 | }
|
1125 | public getResult(): IDisassemblerResult {
|
1126 | let linesReady = this._lines.length;
|
1127 | if (this._backrefLabels && this._labelMode === LabelMode.WhenUsed) {
|
1128 | this._backrefLabels.some((backrefLabel) => {
|
1129 | if (backrefLabel.useLabel) return false;
|
1130 | linesReady = backrefLabel.line;
|
1131 | return true;
|
1132 | });
|
1133 | }
|
1134 | if (linesReady === 0) {
|
1135 | return {
|
1136 | lines: [],
|
1137 | offsets: this._addOffsets ? [] : undefined,
|
1138 | done: this._done,
|
1139 | functionBodyOffsets: this._addOffsets ? [] : undefined,
|
1140 | };
|
1141 | }
|
1142 | if (linesReady === this._lines.length) {
|
1143 | const result = {
|
1144 | lines: this._lines,
|
1145 | offsets: this._addOffsets ? this._offsets : undefined,
|
1146 | done: this._done,
|
1147 | functionBodyOffsets: this._addOffsets
|
1148 | ? this._functionBodyOffsets
|
1149 | : undefined,
|
1150 | };
|
1151 | this._lines = [];
|
1152 | if (this._addOffsets) {
|
1153 | this._offsets = [];
|
1154 | this._functionBodyOffsets = [];
|
1155 | }
|
1156 | return result;
|
1157 | }
|
1158 | const result = {
|
1159 | lines: this._lines.splice(0, linesReady),
|
1160 | offsets: this._addOffsets
|
1161 | ? this._offsets.splice(0, linesReady)
|
1162 | : undefined,
|
1163 | done: false,
|
1164 | functionBodyOffsets: this._addOffsets
|
1165 | ? this._functionBodyOffsets
|
1166 | : undefined,
|
1167 | };
|
1168 | if (this._backrefLabels) {
|
1169 | this._backrefLabels.forEach((backrefLabel) => {
|
1170 | backrefLabel.line -= linesReady;
|
1171 | });
|
1172 | }
|
1173 | return result;
|
1174 | }
|
1175 | public disassembleChunk(reader: BinaryReader, offsetInModule = 0): boolean {
|
1176 | if (this._done)
|
1177 | throw new Error(
|
1178 | "Invalid state: disassembly process was already finished."
|
1179 | );
|
1180 | while (true) {
|
1181 | this._currentPosition = reader.position + offsetInModule;
|
1182 | if (!reader.read()) return false;
|
1183 | switch (reader.state) {
|
1184 | case BinaryReaderState.END_WASM:
|
1185 | this.appendBuffer(")");
|
1186 | this.newLine();
|
1187 | this._reset();
|
1188 | if (!reader.hasMoreBytes()) {
|
1189 | this._done = true;
|
1190 | return true;
|
1191 | }
|
1192 | break;
|
1193 | case BinaryReaderState.ERROR:
|
1194 | throw reader.error;
|
1195 | case BinaryReaderState.BEGIN_WASM:
|
1196 | this.appendBuffer("(module");
|
1197 | this.newLine();
|
1198 | break;
|
1199 | case BinaryReaderState.END_SECTION:
|
1200 | this._currentSectionId = SectionCode.Unknown;
|
1201 | break;
|
1202 | case BinaryReaderState.BEGIN_SECTION:
|
1203 | var sectionInfo = <ISectionInformation>reader.result;
|
1204 | switch (sectionInfo.id) {
|
1205 | case SectionCode.Type:
|
1206 | case SectionCode.Import:
|
1207 | case SectionCode.Export:
|
1208 | case SectionCode.Global:
|
1209 | case SectionCode.Function:
|
1210 | case SectionCode.Start:
|
1211 | case SectionCode.Code:
|
1212 | case SectionCode.Memory:
|
1213 | case SectionCode.Data:
|
1214 | case SectionCode.Table:
|
1215 | case SectionCode.Element:
|
1216 | case SectionCode.Event:
|
1217 | this._currentSectionId = sectionInfo.id;
|
1218 | break;
|
1219 | default:
|
1220 | reader.skipSection();
|
1221 | break;
|
1222 | }
|
1223 | break;
|
1224 | case BinaryReaderState.MEMORY_SECTION_ENTRY:
|
1225 | var memoryInfo = <IMemoryType>reader.result;
|
1226 | var memoryIndex = this._memoryCount++;
|
1227 | var memoryName = this._nameResolver.getMemoryName(memoryIndex, false);
|
1228 | this.appendBuffer(` (memory ${memoryName}`);
|
1229 | if (this._exportMetadata !== null) {
|
1230 | for (const exportName of this._exportMetadata.getMemoryExportNames(
|
1231 | memoryIndex
|
1232 | )) {
|
1233 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1234 | }
|
1235 | }
|
1236 | this.appendBuffer(` ${limitsToString(memoryInfo.limits)}`);
|
1237 | if (memoryInfo.shared) {
|
1238 | this.appendBuffer(` shared`);
|
1239 | }
|
1240 | this.appendBuffer(")");
|
1241 | this.newLine();
|
1242 | break;
|
1243 | case BinaryReaderState.EVENT_SECTION_ENTRY:
|
1244 | var eventInfo = <IEventType>reader.result;
|
1245 | var eventIndex = this._eventCount++;
|
1246 | var eventName = this._nameResolver.getEventName(eventIndex, false);
|
1247 | this.appendBuffer(` (event ${eventName}`);
|
1248 | if (this._exportMetadata !== null) {
|
1249 | for (const exportName of this._exportMetadata.getEventExportNames(
|
1250 | eventIndex
|
1251 | )) {
|
1252 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1253 | }
|
1254 | }
|
1255 | this.printFuncType(eventInfo.typeIndex);
|
1256 | this.appendBuffer(")");
|
1257 | this.newLine();
|
1258 | break;
|
1259 | case BinaryReaderState.TABLE_SECTION_ENTRY:
|
1260 | var tableInfo = <ITableType>reader.result;
|
1261 | var tableIndex = this._tableCount++;
|
1262 | var tableName = this._nameResolver.getTableName(tableIndex, false);
|
1263 | this.appendBuffer(` (table ${tableName}`);
|
1264 | if (this._exportMetadata !== null) {
|
1265 | for (const exportName of this._exportMetadata.getTableExportNames(
|
1266 | tableIndex
|
1267 | )) {
|
1268 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1269 | }
|
1270 | }
|
1271 | this.appendBuffer(
|
1272 | ` ${limitsToString(tableInfo.limits)} ${this.typeToString(
|
1273 | tableInfo.elementType
|
1274 | )})`
|
1275 | );
|
1276 | this.newLine();
|
1277 | break;
|
1278 | case BinaryReaderState.EXPORT_SECTION_ENTRY:
|
1279 |
|
1280 |
|
1281 | if (this._exportMetadata === null) {
|
1282 | var exportInfo = <IExportEntry>reader.result;
|
1283 | this.appendBuffer(" (export ");
|
1284 | this.printString(exportInfo.field);
|
1285 | this.appendBuffer(" ");
|
1286 | switch (exportInfo.kind) {
|
1287 | case ExternalKind.Function:
|
1288 | var funcName = this._nameResolver.getFunctionName(
|
1289 | exportInfo.index,
|
1290 | exportInfo.index < this._importCount,
|
1291 | true
|
1292 | );
|
1293 | this.appendBuffer(`(func ${funcName})`);
|
1294 | break;
|
1295 | case ExternalKind.Table:
|
1296 | var tableName = this._nameResolver.getTableName(
|
1297 | exportInfo.index,
|
1298 | true
|
1299 | );
|
1300 | this.appendBuffer(`(table ${tableName})`);
|
1301 | break;
|
1302 | case ExternalKind.Memory:
|
1303 | var memoryName = this._nameResolver.getMemoryName(
|
1304 | exportInfo.index,
|
1305 | true
|
1306 | );
|
1307 | this.appendBuffer(`(memory ${memoryName})`);
|
1308 | break;
|
1309 | case ExternalKind.Global:
|
1310 | var globalName = this._nameResolver.getGlobalName(
|
1311 | exportInfo.index,
|
1312 | true
|
1313 | );
|
1314 | this.appendBuffer(`(global ${globalName})`);
|
1315 | break;
|
1316 | case ExternalKind.Event:
|
1317 | var eventName = this._nameResolver.getEventName(
|
1318 | exportInfo.index,
|
1319 | true
|
1320 | );
|
1321 | this.appendBuffer(`(event ${eventName})`);
|
1322 | break;
|
1323 | default:
|
1324 | throw new Error(`Unsupported export ${exportInfo.kind}`);
|
1325 | }
|
1326 | this.appendBuffer(")");
|
1327 | this.newLine();
|
1328 | }
|
1329 | break;
|
1330 | case BinaryReaderState.IMPORT_SECTION_ENTRY:
|
1331 | var importInfo = <IImportEntry>reader.result;
|
1332 | switch (importInfo.kind) {
|
1333 | case ExternalKind.Function:
|
1334 | this._importCount++;
|
1335 | var funcIndex = this._funcIndex++;
|
1336 | var funcName = this._nameResolver.getFunctionName(
|
1337 | funcIndex,
|
1338 | true,
|
1339 | false
|
1340 | );
|
1341 | this.appendBuffer(` (func ${funcName}`);
|
1342 | if (this._exportMetadata !== null) {
|
1343 | for (const exportName of this._exportMetadata.getFunctionExportNames(
|
1344 | funcIndex
|
1345 | )) {
|
1346 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1347 | }
|
1348 | }
|
1349 | this.appendBuffer(` (import `);
|
1350 | this.printImportSource(importInfo);
|
1351 | this.appendBuffer(")");
|
1352 | this.printFuncType(importInfo.funcTypeIndex);
|
1353 | this.appendBuffer(")");
|
1354 | break;
|
1355 | case ExternalKind.Global:
|
1356 | var globalImportInfo = <IGlobalType>importInfo.type;
|
1357 | var globalIndex = this._globalCount++;
|
1358 | var globalName = this._nameResolver.getGlobalName(
|
1359 | globalIndex,
|
1360 | false
|
1361 | );
|
1362 | this.appendBuffer(` (global ${globalName}`);
|
1363 | if (this._exportMetadata !== null) {
|
1364 | for (const exportName of this._exportMetadata.getGlobalExportNames(
|
1365 | globalIndex
|
1366 | )) {
|
1367 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1368 | }
|
1369 | }
|
1370 | this.appendBuffer(` (import `);
|
1371 | this.printImportSource(importInfo);
|
1372 | this.appendBuffer(
|
1373 | `) ${this.globalTypeToString(globalImportInfo)})`
|
1374 | );
|
1375 | break;
|
1376 | case ExternalKind.Memory:
|
1377 | var memoryImportInfo = <IMemoryType>importInfo.type;
|
1378 | var memoryIndex = this._memoryCount++;
|
1379 | var memoryName = this._nameResolver.getMemoryName(
|
1380 | memoryIndex,
|
1381 | false
|
1382 | );
|
1383 | this.appendBuffer(` (memory ${memoryName}`);
|
1384 | if (this._exportMetadata !== null) {
|
1385 | for (const exportName of this._exportMetadata.getMemoryExportNames(
|
1386 | memoryIndex
|
1387 | )) {
|
1388 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1389 | }
|
1390 | }
|
1391 | this.appendBuffer(` (import `);
|
1392 | this.printImportSource(importInfo);
|
1393 | this.appendBuffer(`) ${limitsToString(memoryImportInfo.limits)}`);
|
1394 | if (memoryImportInfo.shared) {
|
1395 | this.appendBuffer(` shared`);
|
1396 | }
|
1397 | this.appendBuffer(")");
|
1398 | break;
|
1399 | case ExternalKind.Table:
|
1400 | var tableImportInfo = <ITableType>importInfo.type;
|
1401 | var tableIndex = this._tableCount++;
|
1402 | var tableName = this._nameResolver.getTableName(
|
1403 | tableIndex,
|
1404 | false
|
1405 | );
|
1406 | this.appendBuffer(` (table ${tableName}`);
|
1407 | if (this._exportMetadata !== null) {
|
1408 | for (const exportName of this._exportMetadata.getTableExportNames(
|
1409 | tableIndex
|
1410 | )) {
|
1411 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1412 | }
|
1413 | }
|
1414 | this.appendBuffer(` (import `);
|
1415 | this.printImportSource(importInfo);
|
1416 | this.appendBuffer(
|
1417 | `) ${limitsToString(
|
1418 | tableImportInfo.limits
|
1419 | )} ${this.typeToString(tableImportInfo.elementType)})`
|
1420 | );
|
1421 | break;
|
1422 | case ExternalKind.Event:
|
1423 | var eventImportInfo = <IEventType>importInfo.type;
|
1424 | var eventIndex = this._eventCount++;
|
1425 | var eventName = this._nameResolver.getEventName(
|
1426 | eventIndex,
|
1427 | false
|
1428 | );
|
1429 | this.appendBuffer(` (event ${eventName}`);
|
1430 | if (this._exportMetadata !== null) {
|
1431 | for (const exportName of this._exportMetadata.getEventExportNames(
|
1432 | eventIndex
|
1433 | )) {
|
1434 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1435 | }
|
1436 | }
|
1437 | this.appendBuffer(` (import `);
|
1438 | this.printImportSource(importInfo);
|
1439 | this.appendBuffer(")");
|
1440 | this.printFuncType(eventImportInfo.typeIndex);
|
1441 | this.appendBuffer(")");
|
1442 | break;
|
1443 | default:
|
1444 | throw new Error(`NYI other import types: ${importInfo.kind}`);
|
1445 | }
|
1446 | this.newLine();
|
1447 | break;
|
1448 | case BinaryReaderState.BEGIN_ELEMENT_SECTION_ENTRY:
|
1449 | var elementSegment = <IElementSegment>reader.result;
|
1450 | var elementIndex = this._elementCount++;
|
1451 | var elementName = this._nameResolver.getElementName(
|
1452 | elementIndex,
|
1453 | false
|
1454 | );
|
1455 | this.appendBuffer(` (elem ${elementName}`);
|
1456 | switch (elementSegment.mode) {
|
1457 | case ElementMode.Active:
|
1458 | if (elementSegment.tableIndex !== 0) {
|
1459 | const tableName = this._nameResolver.getTableName(
|
1460 | elementSegment.tableIndex,
|
1461 | false
|
1462 | );
|
1463 | this.appendBuffer(` (table ${tableName})`);
|
1464 | }
|
1465 | break;
|
1466 | case ElementMode.Passive:
|
1467 | break;
|
1468 | case ElementMode.Declarative:
|
1469 | this.appendBuffer(" declare");
|
1470 | break;
|
1471 | }
|
1472 | break;
|
1473 | case BinaryReaderState.END_ELEMENT_SECTION_ENTRY:
|
1474 | this.appendBuffer(")");
|
1475 | this.newLine();
|
1476 | break;
|
1477 | case BinaryReaderState.ELEMENT_SECTION_ENTRY_BODY:
|
1478 | const elementSegmentBody = <IElementSegmentBody>reader.result;
|
1479 | this.appendBuffer(
|
1480 | ` ${this.typeToString(elementSegmentBody.elementType)}`
|
1481 | );
|
1482 | break;
|
1483 | case BinaryReaderState.BEGIN_GLOBAL_SECTION_ENTRY:
|
1484 | var globalInfo = <IGlobalVariable>reader.result;
|
1485 | var globalIndex = this._globalCount++;
|
1486 | var globalName = this._nameResolver.getGlobalName(globalIndex, false);
|
1487 | this.appendBuffer(` (global ${globalName}`);
|
1488 | if (this._exportMetadata !== null) {
|
1489 | for (const exportName of this._exportMetadata.getGlobalExportNames(
|
1490 | globalIndex
|
1491 | )) {
|
1492 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1493 | }
|
1494 | }
|
1495 | this.appendBuffer(` ${this.globalTypeToString(globalInfo.type)}`);
|
1496 | break;
|
1497 | case BinaryReaderState.END_GLOBAL_SECTION_ENTRY:
|
1498 | this.appendBuffer(")");
|
1499 | this.newLine();
|
1500 | break;
|
1501 | case BinaryReaderState.TYPE_SECTION_ENTRY:
|
1502 | var typeEntry = <ITypeEntry>reader.result;
|
1503 | var typeIndex = this._types.length;
|
1504 | this._types.push(typeEntry);
|
1505 | if (!this._skipTypes) {
|
1506 | var typeName = this._nameResolver.getTypeName(typeIndex, false);
|
1507 | var superTypeName = undefined;
|
1508 | if (typeEntry.supertype !== undefined) {
|
1509 | superTypeName = this.typeIndexToString(typeEntry.supertype);
|
1510 | }
|
1511 | if (typeEntry.form === TypeKind.func) {
|
1512 | this.appendBuffer(` (type ${typeName} (func`);
|
1513 | this.printFuncType(typeIndex);
|
1514 | this.appendBuffer("))");
|
1515 | } else if (typeEntry.form === TypeKind.func_subtype) {
|
1516 | this.appendBuffer(` (type ${typeName} (func_subtype`);
|
1517 | this.printFuncType(typeIndex);
|
1518 | this.appendBuffer(` (supertype ${superTypeName})))`);
|
1519 | } else if (typeEntry.form === TypeKind.struct) {
|
1520 | this.appendBuffer(` (type ${typeName} (struct`);
|
1521 | this.printStructType(typeIndex);
|
1522 | this.appendBuffer("))");
|
1523 | } else if (typeEntry.form === TypeKind.struct_subtype) {
|
1524 | this.appendBuffer(` (type ${typeName} (struct_subtype`);
|
1525 | this.printStructType(typeIndex);
|
1526 | this.appendBuffer(` (supertype ${superTypeName})))`);
|
1527 | } else if (typeEntry.form === TypeKind.array) {
|
1528 | this.appendBuffer(` (type ${typeName} (array`);
|
1529 | this.printArrayType(typeIndex);
|
1530 | this.appendBuffer("))");
|
1531 | } else if (typeEntry.form === TypeKind.array_subtype) {
|
1532 | this.appendBuffer(` (type ${typeName} (array_subtype`);
|
1533 | this.printArrayType(typeIndex);
|
1534 | this.appendBuffer(`) (supertype ${superTypeName})))`);
|
1535 | } else {
|
1536 | throw new Error(`Unknown type form: ${typeEntry.form}`);
|
1537 | }
|
1538 | this.newLine();
|
1539 | }
|
1540 | break;
|
1541 | case BinaryReaderState.START_SECTION_ENTRY:
|
1542 | var startEntry = <IStartEntry>reader.result;
|
1543 | var funcName = this._nameResolver.getFunctionName(
|
1544 | startEntry.index,
|
1545 | startEntry.index < this._importCount,
|
1546 | true
|
1547 | );
|
1548 | this.appendBuffer(` (start ${funcName})`);
|
1549 | this.newLine();
|
1550 | break;
|
1551 | case BinaryReaderState.BEGIN_DATA_SECTION_ENTRY:
|
1552 | this.appendBuffer(" (data");
|
1553 | break;
|
1554 | case BinaryReaderState.DATA_SECTION_ENTRY_BODY:
|
1555 | var body = <IDataSegmentBody>reader.result;
|
1556 | this.appendBuffer(" ");
|
1557 | this.printString(body.data);
|
1558 | break;
|
1559 | case BinaryReaderState.END_DATA_SECTION_ENTRY:
|
1560 | this.appendBuffer(")");
|
1561 | this.newLine();
|
1562 | break;
|
1563 | case BinaryReaderState.BEGIN_INIT_EXPRESSION_BODY:
|
1564 | case BinaryReaderState.BEGIN_OFFSET_EXPRESSION_BODY:
|
1565 | this._expression = [];
|
1566 | break;
|
1567 | case BinaryReaderState.INIT_EXPRESSION_OPERATOR:
|
1568 | case BinaryReaderState.OFFSET_EXPRESSION_OPERATOR:
|
1569 | var operator = <IOperatorInformation>reader.result;
|
1570 | if (operator.code !== OperatorCode.end) {
|
1571 | this._expression.push(operator);
|
1572 | }
|
1573 | break;
|
1574 | case BinaryReaderState.END_OFFSET_EXPRESSION_BODY:
|
1575 | if (this._expression.length > 1) {
|
1576 | this.appendBuffer(" (offset ");
|
1577 | this.printExpression(this._expression);
|
1578 | this.appendBuffer(")");
|
1579 | } else {
|
1580 | this.appendBuffer(" ");
|
1581 | this.printExpression(this._expression);
|
1582 | }
|
1583 | this._expression = [];
|
1584 | break;
|
1585 | case BinaryReaderState.END_INIT_EXPRESSION_BODY:
|
1586 | if (
|
1587 | this._expression.length > 1 &&
|
1588 | this._currentSectionId === SectionCode.Element
|
1589 | ) {
|
1590 | this.appendBuffer(" (item ");
|
1591 | this.printExpression(this._expression);
|
1592 | this.appendBuffer(")");
|
1593 | } else {
|
1594 | this.appendBuffer(" ");
|
1595 | this.printExpression(this._expression);
|
1596 | }
|
1597 | this._expression = [];
|
1598 | break;
|
1599 | case BinaryReaderState.FUNCTION_SECTION_ENTRY:
|
1600 | this._funcTypes.push((<IFunctionEntry>reader.result).typeIndex);
|
1601 | break;
|
1602 | case BinaryReaderState.BEGIN_FUNCTION_BODY:
|
1603 | var func = <IFunctionInformation>reader.result;
|
1604 | var type = this._types[
|
1605 | this._funcTypes[this._funcIndex - this._importCount]
|
1606 | ];
|
1607 | this.appendBuffer(" (func ");
|
1608 | this.appendBuffer(
|
1609 | this._nameResolver.getFunctionName(this._funcIndex, false, false)
|
1610 | );
|
1611 | if (this._exportMetadata !== null) {
|
1612 | for (const exportName of this._exportMetadata.getFunctionExportNames(
|
1613 | this._funcIndex
|
1614 | )) {
|
1615 | this.appendBuffer(` (export ${JSON.stringify(exportName)})`);
|
1616 | }
|
1617 | }
|
1618 | for (var i = 0; i < type.params.length; i++) {
|
1619 | var paramName = this._nameResolver.getVariableName(
|
1620 | this._funcIndex,
|
1621 | i,
|
1622 | false
|
1623 | );
|
1624 | this.appendBuffer(
|
1625 | ` (param ${paramName} ${this.typeToString(type.params[i])})`
|
1626 | );
|
1627 | }
|
1628 | for (var i = 0; i < type.returns.length; i++) {
|
1629 | this.appendBuffer(
|
1630 | ` (result ${this.typeToString(type.returns[i])})`
|
1631 | );
|
1632 | }
|
1633 | this.newLine();
|
1634 | var localIndex = type.params.length;
|
1635 | if (func.locals.length > 0) {
|
1636 | this.appendBuffer(" ");
|
1637 | for (var l of func.locals) {
|
1638 | for (var i = 0; i < l.count; i++) {
|
1639 | var paramName = this._nameResolver.getVariableName(
|
1640 | this._funcIndex,
|
1641 | localIndex++,
|
1642 | false
|
1643 | );
|
1644 | this.appendBuffer(
|
1645 | ` (local ${paramName} ${this.typeToString(l.type)})`
|
1646 | );
|
1647 | }
|
1648 | }
|
1649 | this.newLine();
|
1650 | }
|
1651 | this._indent = " ";
|
1652 | this._indentLevel = 0;
|
1653 | this._labelIndex = 0;
|
1654 | this._backrefLabels = this._labelMode === LabelMode.Depth ? null : [];
|
1655 | this._logFirstInstruction = true;
|
1656 | break;
|
1657 | case BinaryReaderState.CODE_OPERATOR:
|
1658 | if (this._logFirstInstruction) {
|
1659 | this.logStartOfFunctionBodyOffset();
|
1660 | this._logFirstInstruction = false;
|
1661 | }
|
1662 | var operator = <IOperatorInformation>reader.result;
|
1663 | if (operator.code == OperatorCode.end && this._indentLevel == 0) {
|
1664 |
|
1665 | this.appendBuffer(` )`);
|
1666 | this.newLine();
|
1667 | break;
|
1668 | }
|
1669 | switch (operator.code) {
|
1670 | case OperatorCode.end:
|
1671 | case OperatorCode.else:
|
1672 | case OperatorCode.catch:
|
1673 | case OperatorCode.catch_all:
|
1674 | case OperatorCode.unwind:
|
1675 | case OperatorCode.delegate:
|
1676 | this.decreaseIndent();
|
1677 | break;
|
1678 | }
|
1679 | this.appendBuffer(this._indent);
|
1680 | this.printOperator(operator);
|
1681 | this.newLine();
|
1682 | switch (operator.code) {
|
1683 | case OperatorCode.if:
|
1684 | case OperatorCode.block:
|
1685 | case OperatorCode.loop:
|
1686 | case OperatorCode.else:
|
1687 | case OperatorCode.try:
|
1688 | case OperatorCode.catch:
|
1689 | case OperatorCode.catch_all:
|
1690 | case OperatorCode.unwind:
|
1691 | this.increaseIndent();
|
1692 | break;
|
1693 | }
|
1694 | break;
|
1695 | case BinaryReaderState.END_FUNCTION_BODY:
|
1696 | this._funcIndex++;
|
1697 | this._backrefLabels = null;
|
1698 | this.logEndOfFunctionBodyOffset();
|
1699 |
|
1700 | break;
|
1701 | default:
|
1702 | throw new Error(`Expectected state: ${reader.state}`);
|
1703 | }
|
1704 | }
|
1705 | }
|
1706 | }
|
1707 |
|
1708 | const UNKNOWN_FUNCTION_PREFIX = "unknown";
|
1709 |
|
1710 | class NameSectionNameResolver extends DefaultNameResolver {
|
1711 | protected readonly _functionNames: string[];
|
1712 | protected readonly _localNames: string[][];
|
1713 | protected readonly _eventNames: string[];
|
1714 | protected readonly _typeNames: string[];
|
1715 | protected readonly _tableNames: string[];
|
1716 | protected readonly _memoryNames: string[];
|
1717 | protected readonly _globalNames: string[];
|
1718 | protected readonly _fieldNames: string[][];
|
1719 |
|
1720 | constructor(
|
1721 | functionNames: string[],
|
1722 | localNames: string[][],
|
1723 | eventNames: string[],
|
1724 | typeNames: string[],
|
1725 | tableNames: string[],
|
1726 | memoryNames: string[],
|
1727 | globalNames: string[],
|
1728 | fieldNames: string[][]
|
1729 | ) {
|
1730 | super();
|
1731 | this._functionNames = functionNames;
|
1732 | this._localNames = localNames;
|
1733 | this._eventNames = eventNames;
|
1734 | this._typeNames = typeNames;
|
1735 | this._tableNames = tableNames;
|
1736 | this._memoryNames = memoryNames;
|
1737 | this._globalNames = globalNames;
|
1738 | this._fieldNames = fieldNames;
|
1739 | }
|
1740 |
|
1741 | public override getTypeName(index: number, isRef: boolean): string {
|
1742 | const name = this._typeNames[index];
|
1743 | if (!name) return super.getTypeName(index, isRef);
|
1744 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1745 | }
|
1746 |
|
1747 | public override getTableName(index: number, isRef: boolean): string {
|
1748 | const name = this._tableNames[index];
|
1749 | if (!name) return super.getTableName(index, isRef);
|
1750 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1751 | }
|
1752 |
|
1753 | public override getMemoryName(index: number, isRef: boolean): string {
|
1754 | const name = this._memoryNames[index];
|
1755 | if (!name) return super.getMemoryName(index, isRef);
|
1756 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1757 | }
|
1758 |
|
1759 | public override getGlobalName(index: number, isRef: boolean): string {
|
1760 | const name = this._globalNames[index];
|
1761 | if (!name) return super.getGlobalName(index, isRef);
|
1762 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1763 | }
|
1764 |
|
1765 | public override getEventName(index: number, isRef: boolean): string {
|
1766 | const name = this._eventNames[index];
|
1767 | if (!name) return super.getEventName(index, isRef);
|
1768 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1769 | }
|
1770 |
|
1771 | public override getFunctionName(
|
1772 | index: number,
|
1773 | isImport: boolean,
|
1774 | isRef: boolean
|
1775 | ): string {
|
1776 | const name = this._functionNames[index];
|
1777 | if (!name) return `$${UNKNOWN_FUNCTION_PREFIX}${index}`;
|
1778 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1779 | }
|
1780 |
|
1781 | public override getVariableName(
|
1782 | funcIndex: number,
|
1783 | index: number,
|
1784 | isRef: boolean
|
1785 | ): string {
|
1786 | const name =
|
1787 | this._localNames[funcIndex] && this._localNames[funcIndex][index];
|
1788 | if (!name) return super.getVariableName(funcIndex, index, isRef);
|
1789 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1790 | }
|
1791 |
|
1792 | public override getFieldName(
|
1793 | typeIndex: number,
|
1794 | index: number,
|
1795 | isRef: boolean
|
1796 | ): string {
|
1797 | const name =
|
1798 | this._fieldNames[typeIndex] && this._fieldNames[typeIndex][index];
|
1799 | if (!name) return super.getFieldName(typeIndex, index, isRef);
|
1800 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
1801 | }
|
1802 | }
|
1803 |
|
1804 | export class NameSectionReader {
|
1805 | private _done = false;
|
1806 | private _functionsCount = 0;
|
1807 | private _functionImportsCount = 0;
|
1808 | private _functionNames: string[] = null;
|
1809 | private _functionLocalNames: string[][] = null;
|
1810 | private _eventNames: string[] = null;
|
1811 | private _typeNames: string[] = null;
|
1812 | private _tableNames: string[] = null;
|
1813 | private _memoryNames: string[] = null;
|
1814 | private _globalNames: string[] = null;
|
1815 | private _fieldNames: string[][] = null;
|
1816 | private _hasNames = false;
|
1817 |
|
1818 | public read(reader: BinaryReader): boolean {
|
1819 | if (this._done)
|
1820 | throw new Error(
|
1821 | "Invalid state: disassembly process was already finished."
|
1822 | );
|
1823 | while (true) {
|
1824 | if (!reader.read()) return false;
|
1825 | switch (reader.state) {
|
1826 | case BinaryReaderState.END_WASM:
|
1827 | if (!reader.hasMoreBytes()) {
|
1828 | this._done = true;
|
1829 | return true;
|
1830 | }
|
1831 | break;
|
1832 | case BinaryReaderState.ERROR:
|
1833 | throw reader.error;
|
1834 | case BinaryReaderState.BEGIN_WASM:
|
1835 | this._functionsCount = 0;
|
1836 | this._functionImportsCount = 0;
|
1837 | this._functionNames = [];
|
1838 | this._functionLocalNames = [];
|
1839 | this._eventNames = [];
|
1840 | this._typeNames = [];
|
1841 | this._tableNames = [];
|
1842 | this._memoryNames = [];
|
1843 | this._globalNames = [];
|
1844 | this._fieldNames = [];
|
1845 | this._hasNames = false;
|
1846 | break;
|
1847 | case BinaryReaderState.END_SECTION:
|
1848 | break;
|
1849 | case BinaryReaderState.BEGIN_SECTION:
|
1850 | var sectionInfo = <ISectionInformation>reader.result;
|
1851 | if (
|
1852 | sectionInfo.id === SectionCode.Custom &&
|
1853 | bytesToString(sectionInfo.name) === NAME_SECTION_NAME
|
1854 | ) {
|
1855 | break;
|
1856 | }
|
1857 | if (
|
1858 | sectionInfo.id === SectionCode.Function ||
|
1859 | sectionInfo.id === SectionCode.Import
|
1860 | ) {
|
1861 | break;
|
1862 | }
|
1863 | reader.skipSection();
|
1864 | break;
|
1865 | case BinaryReaderState.IMPORT_SECTION_ENTRY:
|
1866 | var importInfo = <IImportEntry>reader.result;
|
1867 | if (importInfo.kind === ExternalKind.Function)
|
1868 | this._functionImportsCount++;
|
1869 | break;
|
1870 | case BinaryReaderState.FUNCTION_SECTION_ENTRY:
|
1871 | this._functionsCount++;
|
1872 | break;
|
1873 | case BinaryReaderState.NAME_SECTION_ENTRY:
|
1874 | const nameInfo = <INameEntry>reader.result;
|
1875 | if (nameInfo.type === NameType.Function) {
|
1876 | const { names } = <IFunctionNameEntry>nameInfo;
|
1877 | names.forEach(({ index, name }) => {
|
1878 | this._functionNames[index] = bytesToString(name);
|
1879 | });
|
1880 | this._hasNames = true;
|
1881 | } else if (nameInfo.type === NameType.Local) {
|
1882 | const { funcs } = <ILocalNameEntry>nameInfo;
|
1883 | funcs.forEach(({ index, locals }) => {
|
1884 | const localNames = (this._functionLocalNames[index] = []);
|
1885 | locals.forEach(({ index, name }) => {
|
1886 | localNames[index] = bytesToString(name);
|
1887 | });
|
1888 | });
|
1889 | this._hasNames = true;
|
1890 | } else if (nameInfo.type === NameType.Event) {
|
1891 | const { names } = <IEventNameEntry>nameInfo;
|
1892 | names.forEach(({ index, name }) => {
|
1893 | this._eventNames[index] = bytesToString(name);
|
1894 | });
|
1895 | this._hasNames = true;
|
1896 | } else if (nameInfo.type === NameType.Type) {
|
1897 | const { names } = <ITypeNameEntry>nameInfo;
|
1898 | names.forEach(({ index, name }) => {
|
1899 | this._typeNames[index] = bytesToString(name);
|
1900 | });
|
1901 | this._hasNames = true;
|
1902 | } else if (nameInfo.type === NameType.Table) {
|
1903 | const { names } = <ITableNameEntry>nameInfo;
|
1904 | names.forEach(({ index, name }) => {
|
1905 | this._tableNames[index] = bytesToString(name);
|
1906 | });
|
1907 | this._hasNames = true;
|
1908 | } else if (nameInfo.type === NameType.Memory) {
|
1909 | const { names } = <IMemoryNameEntry>nameInfo;
|
1910 | names.forEach(({ index, name }) => {
|
1911 | this._memoryNames[index] = bytesToString(name);
|
1912 | });
|
1913 | this._hasNames = true;
|
1914 | } else if (nameInfo.type === NameType.Global) {
|
1915 | const { names } = <IGlobalNameEntry>nameInfo;
|
1916 | names.forEach(({ index, name }) => {
|
1917 | this._globalNames[index] = bytesToString(name);
|
1918 | });
|
1919 | this._hasNames = true;
|
1920 | } else if (nameInfo.type === NameType.Field) {
|
1921 | const { types } = <IFieldNameEntry>nameInfo;
|
1922 | types.forEach(({ index, fields }) => {
|
1923 | const fieldNames = (this._fieldNames[index] = []);
|
1924 | fields.forEach(({ index, name }) => {
|
1925 | fieldNames[index] = bytesToString(name);
|
1926 | });
|
1927 | });
|
1928 | }
|
1929 | break;
|
1930 | default:
|
1931 | throw new Error(`Expectected state: ${reader.state}`);
|
1932 | }
|
1933 | }
|
1934 | }
|
1935 |
|
1936 | public hasValidNames(): boolean {
|
1937 | return this._hasNames;
|
1938 | }
|
1939 |
|
1940 | public getNameResolver(): INameResolver {
|
1941 | if (!this.hasValidNames()) throw new Error("Has no valid name section");
|
1942 |
|
1943 |
|
1944 | const functionNamesLength =
|
1945 | this._functionImportsCount + this._functionsCount;
|
1946 | const functionNames = this._functionNames.slice(0, functionNamesLength);
|
1947 | const usedNameAt = Object.create(null);
|
1948 | for (let i = 0; i < functionNames.length; i++) {
|
1949 | const name = functionNames[i];
|
1950 | if (!name) continue;
|
1951 | const goodName =
|
1952 | !(name in usedNameAt) &&
|
1953 | isValidName(name) &&
|
1954 | name.indexOf(UNKNOWN_FUNCTION_PREFIX) !== 0;
|
1955 | if (!goodName) {
|
1956 | if (usedNameAt[name] >= 0) {
|
1957 |
|
1958 | functionNames[usedNameAt[name]] = null;
|
1959 | usedNameAt[name] = -1;
|
1960 | }
|
1961 | functionNames[i] = null;
|
1962 | continue;
|
1963 | }
|
1964 | usedNameAt[name] = i;
|
1965 | }
|
1966 |
|
1967 | return new NameSectionNameResolver(
|
1968 | functionNames,
|
1969 | this._functionLocalNames,
|
1970 | this._eventNames,
|
1971 | this._typeNames,
|
1972 | this._tableNames,
|
1973 | this._memoryNames,
|
1974 | this._globalNames,
|
1975 | this._fieldNames
|
1976 | );
|
1977 | }
|
1978 | }
|
1979 |
|
1980 | export class DevToolsNameResolver extends NameSectionNameResolver {
|
1981 | constructor(
|
1982 | functionNames: string[],
|
1983 | localNames: string[][],
|
1984 | eventNames: string[],
|
1985 | typeNames: string[],
|
1986 | tableNames: string[],
|
1987 | memoryNames: string[],
|
1988 | globalNames: string[],
|
1989 | fieldNames: string[][]
|
1990 | ) {
|
1991 | super(
|
1992 | functionNames,
|
1993 | localNames,
|
1994 | eventNames,
|
1995 | typeNames,
|
1996 | tableNames,
|
1997 | memoryNames,
|
1998 | globalNames,
|
1999 | fieldNames
|
2000 | );
|
2001 | }
|
2002 |
|
2003 | public override getFunctionName(
|
2004 | index: number,
|
2005 | isImport: boolean,
|
2006 | isRef: boolean
|
2007 | ): string {
|
2008 | const name = this._functionNames[index];
|
2009 | if (!name) return isImport ? `$import${index}` : `$func${index}`;
|
2010 | return isRef ? `$${name}` : `$${name} (;${index};)`;
|
2011 | }
|
2012 | }
|
2013 |
|
2014 | export class DevToolsNameGenerator {
|
2015 | private _done = false;
|
2016 | private _functionImportsCount = 0;
|
2017 | private _memoryImportsCount = 0;
|
2018 | private _tableImportsCount = 0;
|
2019 | private _globalImportsCount = 0;
|
2020 | private _eventImportsCount = 0;
|
2021 |
|
2022 | private _functionNames: string[] = null;
|
2023 | private _functionLocalNames: string[][] = null;
|
2024 | private _eventNames: string[] = null;
|
2025 | private _memoryNames: string[] = null;
|
2026 | private _typeNames: string[] = null;
|
2027 | private _tableNames: string[] = null;
|
2028 | private _globalNames: string[] = null;
|
2029 | private _fieldNames: string[][] = null;
|
2030 |
|
2031 | private _functionExportNames: string[][] = null;
|
2032 | private _globalExportNames: string[][] = null;
|
2033 | private _memoryExportNames: string[][] = null;
|
2034 | private _tableExportNames: string[][] = null;
|
2035 | private _eventExportNames: string[][] = null;
|
2036 |
|
2037 | private _addExportName(exportNames: string[][], index: number, name: string) {
|
2038 | const names = exportNames[index];
|
2039 | if (names) {
|
2040 | names.push(name);
|
2041 | } else {
|
2042 | exportNames[index] = [name];
|
2043 | }
|
2044 | }
|
2045 |
|
2046 | private _setName(
|
2047 | names: string[],
|
2048 | index: number,
|
2049 | name: string,
|
2050 | isNameSectionName: boolean
|
2051 | ) {
|
2052 | if (!name) return;
|
2053 | if (isNameSectionName) {
|
2054 | if (!isValidName(name)) return;
|
2055 | names[index] = name;
|
2056 | } else if (!names[index]) {
|
2057 | names[index] = name.replace(INVALID_NAME_SYMBOLS_REGEX_GLOBAL, "_");
|
2058 | }
|
2059 | }
|
2060 |
|
2061 | public read(reader: BinaryReader): boolean {
|
2062 | if (this._done)
|
2063 | throw new Error(
|
2064 | "Invalid state: disassembly process was already finished."
|
2065 | );
|
2066 | while (true) {
|
2067 | if (!reader.read()) return false;
|
2068 | switch (reader.state) {
|
2069 | case BinaryReaderState.END_WASM:
|
2070 | if (!reader.hasMoreBytes()) {
|
2071 | this._done = true;
|
2072 | return true;
|
2073 | }
|
2074 | break;
|
2075 | case BinaryReaderState.ERROR:
|
2076 | throw reader.error;
|
2077 | case BinaryReaderState.BEGIN_WASM:
|
2078 | this._functionImportsCount = 0;
|
2079 | this._memoryImportsCount = 0;
|
2080 | this._tableImportsCount = 0;
|
2081 | this._globalImportsCount = 0;
|
2082 | this._eventImportsCount = 0;
|
2083 |
|
2084 | this._functionNames = [];
|
2085 | this._functionLocalNames = [];
|
2086 | this._eventNames = [];
|
2087 | this._memoryNames = [];
|
2088 | this._typeNames = [];
|
2089 | this._tableNames = [];
|
2090 | this._globalNames = [];
|
2091 | this._fieldNames = [];
|
2092 | this._functionExportNames = [];
|
2093 | this._globalExportNames = [];
|
2094 | this._memoryExportNames = [];
|
2095 | this._tableExportNames = [];
|
2096 | this._eventExportNames = [];
|
2097 | break;
|
2098 | case BinaryReaderState.END_SECTION:
|
2099 | break;
|
2100 | case BinaryReaderState.BEGIN_SECTION:
|
2101 | var sectionInfo = <ISectionInformation>reader.result;
|
2102 |
|
2103 | if (
|
2104 | sectionInfo.id === SectionCode.Custom &&
|
2105 | bytesToString(sectionInfo.name) === NAME_SECTION_NAME
|
2106 | ) {
|
2107 | break;
|
2108 | }
|
2109 | switch (sectionInfo.id) {
|
2110 | case SectionCode.Import:
|
2111 | case SectionCode.Export:
|
2112 | break;
|
2113 | default:
|
2114 | reader.skipSection();
|
2115 | break;
|
2116 | }
|
2117 | break;
|
2118 | case BinaryReaderState.IMPORT_SECTION_ENTRY:
|
2119 | var importInfo = <IImportEntry>reader.result;
|
2120 | const importName = `${bytesToString(
|
2121 | importInfo.module
|
2122 | )}.${bytesToString(importInfo.field)}`;
|
2123 | switch (importInfo.kind) {
|
2124 | case ExternalKind.Function:
|
2125 | this._setName(
|
2126 | this._functionNames,
|
2127 | this._functionImportsCount++,
|
2128 | importName,
|
2129 | false
|
2130 | );
|
2131 | break;
|
2132 | case ExternalKind.Table:
|
2133 | this._setName(
|
2134 | this._tableNames,
|
2135 | this._tableImportsCount++,
|
2136 | importName,
|
2137 | false
|
2138 | );
|
2139 | break;
|
2140 | case ExternalKind.Memory:
|
2141 | this._setName(
|
2142 | this._memoryNames,
|
2143 | this._memoryImportsCount++,
|
2144 | importName,
|
2145 | false
|
2146 | );
|
2147 | break;
|
2148 | case ExternalKind.Global:
|
2149 | this._setName(
|
2150 | this._globalNames,
|
2151 | this._globalImportsCount++,
|
2152 | importName,
|
2153 | false
|
2154 | );
|
2155 | break;
|
2156 | case ExternalKind.Event:
|
2157 | this._setName(
|
2158 | this._eventNames,
|
2159 | this._eventImportsCount++,
|
2160 | importName,
|
2161 | false
|
2162 | );
|
2163 | default:
|
2164 | throw new Error(`Unsupported export ${importInfo.kind}`);
|
2165 | }
|
2166 | break;
|
2167 | case BinaryReaderState.NAME_SECTION_ENTRY:
|
2168 | const nameInfo = <INameEntry>reader.result;
|
2169 | if (nameInfo.type === NameType.Function) {
|
2170 | const { names } = <IFunctionNameEntry>nameInfo;
|
2171 | names.forEach(({ index, name }) => {
|
2172 | this._setName(
|
2173 | this._functionNames,
|
2174 | index,
|
2175 | bytesToString(name),
|
2176 | true
|
2177 | );
|
2178 | });
|
2179 | } else if (nameInfo.type === NameType.Local) {
|
2180 | const { funcs } = <ILocalNameEntry>nameInfo;
|
2181 | funcs.forEach(({ index, locals }) => {
|
2182 | const localNames = (this._functionLocalNames[index] = []);
|
2183 | locals.forEach(({ index, name }) => {
|
2184 | localNames[index] = bytesToString(name);
|
2185 | });
|
2186 | });
|
2187 | } else if (nameInfo.type === NameType.Event) {
|
2188 | const { names } = <IEventNameEntry>nameInfo;
|
2189 | names.forEach(({ index, name }) => {
|
2190 | this._setName(this._eventNames, index, bytesToString(name), true);
|
2191 | });
|
2192 | } else if (nameInfo.type === NameType.Type) {
|
2193 | const { names } = <ITypeNameEntry>nameInfo;
|
2194 | names.forEach(({ index, name }) => {
|
2195 | this._setName(this._typeNames, index, bytesToString(name), true);
|
2196 | });
|
2197 | } else if (nameInfo.type === NameType.Table) {
|
2198 | const { names } = <ITableNameEntry>nameInfo;
|
2199 | names.forEach(({ index, name }) => {
|
2200 | this._setName(this._tableNames, index, bytesToString(name), true);
|
2201 | });
|
2202 | } else if (nameInfo.type === NameType.Memory) {
|
2203 | const { names } = <IMemoryNameEntry>nameInfo;
|
2204 | names.forEach(({ index, name }) => {
|
2205 | this._setName(
|
2206 | this._memoryNames,
|
2207 | index,
|
2208 | bytesToString(name),
|
2209 | true
|
2210 | );
|
2211 | });
|
2212 | } else if (nameInfo.type === NameType.Global) {
|
2213 | const { names } = <IGlobalNameEntry>nameInfo;
|
2214 | names.forEach(({ index, name }) => {
|
2215 | this._setName(
|
2216 | this._globalNames,
|
2217 | index,
|
2218 | bytesToString(name),
|
2219 | true
|
2220 | );
|
2221 | });
|
2222 | } else if (nameInfo.type === NameType.Field) {
|
2223 | const { types } = <IFieldNameEntry>nameInfo;
|
2224 | types.forEach(({ index, fields }) => {
|
2225 | const fieldNames = (this._fieldNames[index] = []);
|
2226 | fields.forEach(({ index, name }) => {
|
2227 | fieldNames[index] = bytesToString(name);
|
2228 | });
|
2229 | });
|
2230 | }
|
2231 | break;
|
2232 | case BinaryReaderState.EXPORT_SECTION_ENTRY:
|
2233 | var exportInfo = <IExportEntry>reader.result;
|
2234 | const exportName = bytesToString(exportInfo.field);
|
2235 | switch (exportInfo.kind) {
|
2236 | case ExternalKind.Function:
|
2237 | this._addExportName(
|
2238 | this._functionExportNames,
|
2239 | exportInfo.index,
|
2240 | exportName
|
2241 | );
|
2242 | this._setName(
|
2243 | this._functionNames,
|
2244 | exportInfo.index,
|
2245 | exportName,
|
2246 | false
|
2247 | );
|
2248 | break;
|
2249 | case ExternalKind.Global:
|
2250 | this._addExportName(
|
2251 | this._globalExportNames,
|
2252 | exportInfo.index,
|
2253 | exportName
|
2254 | );
|
2255 | this._setName(
|
2256 | this._globalNames,
|
2257 | exportInfo.index,
|
2258 | exportName,
|
2259 | false
|
2260 | );
|
2261 | break;
|
2262 | case ExternalKind.Memory:
|
2263 | this._addExportName(
|
2264 | this._memoryExportNames,
|
2265 | exportInfo.index,
|
2266 | exportName
|
2267 | );
|
2268 | this._setName(
|
2269 | this._memoryNames,
|
2270 | exportInfo.index,
|
2271 | exportName,
|
2272 | false
|
2273 | );
|
2274 | break;
|
2275 | case ExternalKind.Table:
|
2276 | this._addExportName(
|
2277 | this._tableExportNames,
|
2278 | exportInfo.index,
|
2279 | exportName
|
2280 | );
|
2281 | this._setName(
|
2282 | this._tableNames,
|
2283 | exportInfo.index,
|
2284 | exportName,
|
2285 | false
|
2286 | );
|
2287 | break;
|
2288 | case ExternalKind.Event:
|
2289 | this._addExportName(
|
2290 | this._eventExportNames,
|
2291 | exportInfo.index,
|
2292 | exportName
|
2293 | );
|
2294 | this._setName(
|
2295 | this._eventNames,
|
2296 | exportInfo.index,
|
2297 | exportName,
|
2298 | false
|
2299 | );
|
2300 | break;
|
2301 | default:
|
2302 | throw new Error(`Unsupported export ${exportInfo.kind}`);
|
2303 | }
|
2304 | break;
|
2305 | default:
|
2306 | throw new Error(`Expectected state: ${reader.state}`);
|
2307 | }
|
2308 | }
|
2309 | }
|
2310 |
|
2311 | public getExportMetadata(): IExportMetadata {
|
2312 | return new DevToolsExportMetadata(
|
2313 | this._functionExportNames,
|
2314 | this._globalExportNames,
|
2315 | this._memoryExportNames,
|
2316 | this._tableExportNames,
|
2317 | this._eventExportNames
|
2318 | );
|
2319 | }
|
2320 |
|
2321 | public getNameResolver(): INameResolver {
|
2322 | return new DevToolsNameResolver(
|
2323 | this._functionNames,
|
2324 | this._functionLocalNames,
|
2325 | this._eventNames,
|
2326 | this._typeNames,
|
2327 | this._tableNames,
|
2328 | this._memoryNames,
|
2329 | this._globalNames,
|
2330 | this._fieldNames
|
2331 | );
|
2332 | }
|
2333 | }
|