porffor 0.50.18 → 0.50.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/builtins/array.ts +0 -1
- package/compiler/builtins.js +0 -6
- package/compiler/builtins_precompiled.js +443 -443
- package/compiler/codegen.js +263 -246
- package/compiler/wrap.js +0 -3
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -219,7 +219,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
219
219
|
return cacheAst(decl, generateFunc(scope, decl)[1]);
|
220
220
|
|
221
221
|
case 'BlockStatement':
|
222
|
-
return cacheAst(decl,
|
222
|
+
return cacheAst(decl, generateBlock(scope, decl));
|
223
223
|
|
224
224
|
case 'ReturnStatement':
|
225
225
|
return cacheAst(decl, generateReturn(scope, decl));
|
@@ -304,7 +304,10 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
304
304
|
return cacheAst(decl, generateTry(scope, decl));
|
305
305
|
|
306
306
|
case 'DebuggerStatement':
|
307
|
-
return cacheAst(decl, [
|
307
|
+
return cacheAst(decl, [
|
308
|
+
// [ Opcodes.call, importedFuncs.debugger ],
|
309
|
+
number(UNDEFINED)
|
310
|
+
]);
|
308
311
|
|
309
312
|
case 'ArrayExpression':
|
310
313
|
return cacheAst(decl, generateArray(scope, decl, global, name, globalThis.precompile));
|
@@ -329,10 +332,10 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
329
332
|
return cacheAst(decl, generateTemplate(scope, decl));
|
330
333
|
|
331
334
|
case 'TaggedTemplateExpression':
|
332
|
-
return cacheAst(decl, generateTaggedTemplate(scope, decl, global, name));
|
335
|
+
return cacheAst(decl, generateTaggedTemplate(scope, decl, global, name, valueUnused));
|
333
336
|
|
334
337
|
case 'ExportNamedDeclaration':
|
335
|
-
if (!decl.declaration) return todo(scope, 'unsupported export declaration');
|
338
|
+
if (!decl.declaration) return todo(scope, 'unsupported export declaration', true);
|
336
339
|
|
337
340
|
const funcsBefore = funcs.map(x => x.name);
|
338
341
|
generate(scope, decl.declaration);
|
@@ -349,16 +352,16 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
349
352
|
}
|
350
353
|
}
|
351
354
|
|
352
|
-
return cacheAst(decl, []);
|
355
|
+
return cacheAst(decl, [ number(UNDEFINED) ]);
|
353
356
|
|
354
357
|
default:
|
355
358
|
// ignore typescript nodes
|
356
359
|
if (decl.type.startsWith('TS') ||
|
357
360
|
decl.type === 'ImportDeclaration' && decl.importKind === 'type') {
|
358
|
-
return cacheAst(decl, []);
|
361
|
+
return cacheAst(decl, [ number(UNDEFINED) ]);
|
359
362
|
}
|
360
363
|
|
361
|
-
return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`,
|
364
|
+
return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`, true));
|
362
365
|
}
|
363
366
|
};
|
364
367
|
|
@@ -1110,7 +1113,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
|
|
1110
1113
|
let checkType = TYPES[rightName.toLowerCase()];
|
1111
1114
|
if (checkType != null && rightName === TYPE_NAMES[checkType] && !rightName.endsWith('Error')) {
|
1112
1115
|
const out = generate(scope, decl.left);
|
1113
|
-
|
1116
|
+
out.push([ Opcodes.drop ]);
|
1114
1117
|
|
1115
1118
|
// switch primitive types to primitive object types
|
1116
1119
|
if (checkType === TYPES.number) checkType = TYPES.numberobject;
|
@@ -1532,6 +1535,7 @@ const getNodeType = (scope, node) => {
|
|
1532
1535
|
}
|
1533
1536
|
|
1534
1537
|
if (isFuncType(node.type)) {
|
1538
|
+
if (node.type.endsWith('Declaration')) return TYPES.undefined;
|
1535
1539
|
return TYPES.function;
|
1536
1540
|
}
|
1537
1541
|
|
@@ -1711,6 +1715,18 @@ const getNodeType = (scope, node) => {
|
|
1711
1715
|
return getNodeType(scope, node.expression);
|
1712
1716
|
}
|
1713
1717
|
|
1718
|
+
if (node.type === 'BlockStatement') {
|
1719
|
+
return getNodeType(scope, getLastNode(node.body));
|
1720
|
+
}
|
1721
|
+
|
1722
|
+
if (node.type === 'LabeledStatement') {
|
1723
|
+
return getNodeType(scope, node.body);
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
if (node.type.endsWith('Statement') || node.type.endsWith('Declaration')) {
|
1727
|
+
return TYPES.undefined;
|
1728
|
+
}
|
1729
|
+
|
1714
1730
|
return getLastType(scope);
|
1715
1731
|
})();
|
1716
1732
|
|
@@ -1745,68 +1761,13 @@ const generateLiteral = (scope, decl, global, name) => {
|
|
1745
1761
|
}
|
1746
1762
|
};
|
1747
1763
|
|
1748
|
-
const countLeftover = wasm => {
|
1749
|
-
let count = 0, depth = 0;
|
1750
|
-
|
1751
|
-
for (let i = 0; i < wasm.length; i++) {
|
1752
|
-
const inst = wasm[i];
|
1753
|
-
if (depth === 0 && inst[0] == null) {
|
1754
|
-
if (typeof inst[1] === 'function' && typeof inst[2] === 'number') count += inst[2];
|
1755
|
-
continue;
|
1756
|
-
}
|
1757
|
-
|
1758
|
-
if (depth === 0 && (inst[0] === Opcodes.if || inst[0] === Opcodes.block || inst[0] === Opcodes.loop)) {
|
1759
|
-
if (inst[0] === Opcodes.if) count--;
|
1760
|
-
if (inst[1] !== Blocktype.void) count++;
|
1761
|
-
}
|
1762
|
-
if ([Opcodes.if, Opcodes.try, Opcodes.loop, Opcodes.block].includes(inst[0])) depth++;
|
1763
|
-
if (inst[0] === Opcodes.end) depth--;
|
1764
|
-
|
1765
|
-
if (depth === 0)
|
1766
|
-
if ([Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1767
|
-
else if ([Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_abs, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.f32_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
|
1768
|
-
else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const, Opcodes.memory_size].includes(inst[0])) count++;
|
1769
|
-
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.f32_store, Opcodes.i32_store16, Opcodes.i32_store8, Opcodes.select].includes(inst[0])) count -= 2;
|
1770
|
-
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1771
|
-
else if (inst[0] === Opcodes.return) count = 0;
|
1772
|
-
else if (inst[0] === Opcodes.catch) count += 2;
|
1773
|
-
else if (inst[0] === Opcodes.throw) {
|
1774
|
-
count--;
|
1775
|
-
if ((Prefs.exceptionMode ?? 'stack') === 'stack' || (globalThis.precompile && inst[1] === 1)) count--;
|
1776
|
-
} else if (inst[0] === Opcodes.call) {
|
1777
|
-
if (inst[1] < importedFuncs.length) {
|
1778
|
-
const func = importedFuncs[inst[1]];
|
1779
|
-
count = count - func.params + func.returns;
|
1780
|
-
} else {
|
1781
|
-
const func = funcByIndex(inst[1]);
|
1782
|
-
count = count - func.params.length + func.returns.length;
|
1783
|
-
}
|
1784
|
-
} else if (inst[0] === Opcodes.call_indirect) {
|
1785
|
-
count--; // funcidx
|
1786
|
-
count -= inst[1] * 2; // params * 2 (typed)
|
1787
|
-
count += 2; // fixed return (value, type)
|
1788
|
-
} else count--;
|
1789
|
-
|
1790
|
-
// console.log(count, depth, decompile([ inst ], undefined, undefined, undefined, undefined, undefined, funcs).slice(0, -1));
|
1791
|
-
}
|
1792
|
-
|
1793
|
-
return count;
|
1794
|
-
};
|
1795
|
-
|
1796
|
-
const disposeLeftover = wasm => {
|
1797
|
-
const leftover = countLeftover(wasm);
|
1798
|
-
for (let i = 0; i < leftover; i++) wasm.push([ Opcodes.drop ]);
|
1799
|
-
};
|
1800
|
-
|
1801
1764
|
const generateExp = (scope, decl) => {
|
1802
1765
|
if (decl.directive === 'use strict') {
|
1803
1766
|
scope.strict = true;
|
1767
|
+
return [ number(UNDEFINED) ];
|
1804
1768
|
}
|
1805
1769
|
|
1806
|
-
|
1807
|
-
disposeLeftover(out);
|
1808
|
-
|
1809
|
-
return out;
|
1770
|
+
return generate(scope, decl.expression, undefined, undefined, !scope.inEval);
|
1810
1771
|
};
|
1811
1772
|
|
1812
1773
|
const generateSequence = (scope, decl) => {
|
@@ -1814,8 +1775,8 @@ const generateSequence = (scope, decl) => {
|
|
1814
1775
|
|
1815
1776
|
const exprs = decl.expressions;
|
1816
1777
|
for (let i = 0; i < exprs.length; i++) {
|
1817
|
-
if (i > 0) disposeLeftover(out);
|
1818
1778
|
out.push(...generate(scope, exprs[i]));
|
1779
|
+
if (i !== exprs.length - 1) out.push([ Opcodes.drop ]);
|
1819
1780
|
}
|
1820
1781
|
|
1821
1782
|
return out;
|
@@ -1932,19 +1893,16 @@ const setObjProp = (obj, prop, value) => {
|
|
1932
1893
|
};
|
1933
1894
|
|
1934
1895
|
return objectHack({
|
1935
|
-
type: '
|
1936
|
-
|
1937
|
-
|
1938
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
},
|
1946
|
-
right: value
|
1947
|
-
}
|
1896
|
+
type: 'AssignmentExpression',
|
1897
|
+
operator: '=',
|
1898
|
+
left: {
|
1899
|
+
type: 'MemberExpression',
|
1900
|
+
object: obj,
|
1901
|
+
property: prop,
|
1902
|
+
computed: false,
|
1903
|
+
optional: false
|
1904
|
+
},
|
1905
|
+
right: value
|
1948
1906
|
});
|
1949
1907
|
};
|
1950
1908
|
|
@@ -2058,6 +2016,14 @@ const createThisArg = (scope, decl) => {
|
|
2058
2016
|
}
|
2059
2017
|
};
|
2060
2018
|
|
2019
|
+
const isEmptyNode = x => x && (x.type === 'EmptyStatement' || (x.type === 'BlockStatement' && x.body.length === 0));
|
2020
|
+
const getLastNode = body => {
|
2021
|
+
let offset = 1, node = body[body.length - offset];
|
2022
|
+
while (isEmptyNode(node)) node = body[body.length - ++offset];
|
2023
|
+
|
2024
|
+
return node ?? { type: 'EmptyStatement' };
|
2025
|
+
};
|
2026
|
+
|
2061
2027
|
const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
2062
2028
|
if (decl.type === 'NewExpression') decl._new = true;
|
2063
2029
|
|
@@ -2095,17 +2061,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2095
2061
|
});
|
2096
2062
|
scope.inEval = false;
|
2097
2063
|
|
2098
|
-
|
2099
|
-
if (lastInst && lastInst[0] === Opcodes.drop) {
|
2100
|
-
out.splice(out.length - 1, 1);
|
2101
|
-
|
2102
|
-
const finalStatement = parsed.body[parsed.body.length - 1];
|
2103
|
-
out.push(...setLastType(scope, getNodeType(scope, finalStatement)));
|
2104
|
-
} else if (countLeftover(out) === 0) {
|
2105
|
-
out.push(number(UNDEFINED));
|
2106
|
-
out.push(...setLastType(scope, TYPES.undefined));
|
2107
|
-
}
|
2108
|
-
|
2064
|
+
out.push(...setLastType(scope, getNodeType(scope, getLastNode(parsed.body))));
|
2109
2065
|
return out;
|
2110
2066
|
}
|
2111
2067
|
}
|
@@ -2406,6 +2362,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2406
2362
|
// TODO: error better
|
2407
2363
|
default: internalThrow(scope, 'TypeError', `'${protoName}' proto func tried to be called on a type without an impl`, !unusedValue)
|
2408
2364
|
}, unusedValue ? Blocktype.void : valtypeBinary),
|
2365
|
+
...(unusedValue ? [ number(UNDEFINED) ] : [])
|
2409
2366
|
];
|
2410
2367
|
}
|
2411
2368
|
|
@@ -2481,26 +2438,26 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2481
2438
|
// pointer, align, offset
|
2482
2439
|
i32_load: { imms: 2, args: [ true ], returns: 1 },
|
2483
2440
|
// pointer, value, align, offset
|
2484
|
-
i32_store: { imms: 2, args: [ true, true ], returns: 0 },
|
2441
|
+
i32_store: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2485
2442
|
// pointer, align, offset
|
2486
2443
|
i32_load8_u: { imms: 2, args: [ true ], returns: 1 },
|
2487
2444
|
// pointer, value, align, offset
|
2488
|
-
i32_store8: { imms: 2, args: [ true, true ], returns: 0 },
|
2445
|
+
i32_store8: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2489
2446
|
// pointer, align, offset
|
2490
2447
|
i32_load16_u: { imms: 2, args: [ true ], returns: 1 },
|
2491
2448
|
// pointer, value, align, offset
|
2492
|
-
i32_store16: { imms: 2, args: [ true, true ], returns: 0 },
|
2449
|
+
i32_store16: { imms: 2, args: [ true, true ], returns: 0, addValue: true },
|
2493
2450
|
|
2494
2451
|
// pointer, align, offset
|
2495
2452
|
f64_load: { imms: 2, args: [ true ], returns: 0 }, // 0 due to not i32
|
2496
2453
|
// pointer, value, align, offset
|
2497
|
-
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
2454
|
+
f64_store: { imms: 2, args: [ true, false ], returns: 0, addValue: true },
|
2498
2455
|
|
2499
2456
|
// value
|
2500
2457
|
i32_const: { imms: 1, args: [], returns: 0 },
|
2501
2458
|
|
2502
2459
|
// dst, src, size, _, _
|
2503
|
-
memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
|
2460
|
+
memory_copy: { imms: 2, args: [ true, true, true ], returns: 0, addValue: true }
|
2504
2461
|
};
|
2505
2462
|
|
2506
2463
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -2529,7 +2486,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2529
2486
|
return [
|
2530
2487
|
...argOut,
|
2531
2488
|
[ ...opcode, ...imms ],
|
2532
|
-
...(new Array(op.returns).fill(Opcodes.i32_from))
|
2489
|
+
...(new Array(op.returns).fill(Opcodes.i32_from)),
|
2490
|
+
...(op.addValue ? [ number(UNDEFINED) ] : [])
|
2533
2491
|
];
|
2534
2492
|
}
|
2535
2493
|
} else {
|
@@ -2732,6 +2690,11 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2732
2690
|
out.push(Opcodes.i32_trunc_sat_f64_s);
|
2733
2691
|
}
|
2734
2692
|
|
2693
|
+
if ((builtinFuncs[name] && builtinFuncs[name].returns?.length === 0) ||
|
2694
|
+
(importedFuncs[name] != null && importedFuncs[importedFuncs[name]]?.returns === 0)) {
|
2695
|
+
out.push(number(UNDEFINED));
|
2696
|
+
}
|
2697
|
+
|
2735
2698
|
return out;
|
2736
2699
|
};
|
2737
2700
|
|
@@ -3060,6 +3023,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
|
|
3060
3023
|
|
3061
3024
|
out.push([ Opcodes.end ]);
|
3062
3025
|
|
3026
|
+
// todo: sometimes gets stuck?
|
3063
3027
|
if (depth.at(-1) === 'typeswitch') {
|
3064
3028
|
depth.pop();
|
3065
3029
|
}
|
@@ -3091,15 +3055,18 @@ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
|
|
3091
3055
|
return out;
|
3092
3056
|
};
|
3093
3057
|
|
3094
|
-
const allocVar = (scope, name, global = false, type = true) => {
|
3058
|
+
const allocVar = (scope, name, global = false, type = true, redecl = false) => {
|
3095
3059
|
const target = global ? globals : scope.locals;
|
3096
3060
|
|
3097
3061
|
// already declared
|
3098
3062
|
if (Object.hasOwn(target, name)) {
|
3099
|
-
|
3100
|
-
|
3101
|
-
|
3102
|
-
|
3063
|
+
if (redecl) {
|
3064
|
+
// force change old local name(s)
|
3065
|
+
target['#redecl_' + name + uniqId()] = target[name];
|
3066
|
+
if (type) target['#redecl_' + name + '#type' + uniqId()] = target[name + '#type'];
|
3067
|
+
} else {
|
3068
|
+
return target[name].idx;
|
3069
|
+
}
|
3103
3070
|
}
|
3104
3071
|
|
3105
3072
|
let idx = global ? globals['#ind']++ : scope.localInd++;
|
@@ -3524,6 +3491,7 @@ const generateVar = (scope, decl) => {
|
|
3524
3491
|
out = out.concat(generateVarDstr(scope, decl.kind, x.id, x.init, undefined, global));
|
3525
3492
|
}
|
3526
3493
|
|
3494
|
+
out.push(number(UNDEFINED));
|
3527
3495
|
return out;
|
3528
3496
|
};
|
3529
3497
|
|
@@ -3704,7 +3672,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3704
3672
|
...decl,
|
3705
3673
|
_internalAssign: true
|
3706
3674
|
});
|
3707
|
-
if (valueUnused)
|
3675
|
+
if (valueUnused) slow.push([ Opcodes.drop ]);
|
3708
3676
|
|
3709
3677
|
return [
|
3710
3678
|
...out,
|
@@ -4053,7 +4021,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
4053
4021
|
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
4054
4022
|
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
|
4055
4023
|
], getType(scope, name), getNodeType(scope, decl.right), isGlobal, name, true),
|
4056
|
-
[ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
|
4057
4024
|
|
4058
4025
|
...setType(scope, name, getLastType(scope), true)
|
4059
4026
|
];
|
@@ -4148,7 +4115,7 @@ const generateUnary = (scope, decl) => {
|
|
4148
4115
|
case 'void': {
|
4149
4116
|
// drop current expression value after running, give undefined
|
4150
4117
|
const out = generate(scope, decl.argument);
|
4151
|
-
|
4118
|
+
out.push([ Opcodes.drop ]);
|
4152
4119
|
|
4153
4120
|
out.push(number(UNDEFINED));
|
4154
4121
|
return out;
|
@@ -4215,7 +4182,7 @@ const generateUnary = (scope, decl) => {
|
|
4215
4182
|
}
|
4216
4183
|
|
4217
4184
|
const out = toGenerate ? generate(scope, decl.argument) : [];
|
4218
|
-
|
4185
|
+
if (toGenerate) out.push([ Opcodes.drop ]);
|
4219
4186
|
|
4220
4187
|
out.push(number(toReturn ? 1 : 0));
|
4221
4188
|
return out;
|
@@ -4229,7 +4196,7 @@ const generateUnary = (scope, decl) => {
|
|
4229
4196
|
}
|
4230
4197
|
|
4231
4198
|
const out = toGenerate ? generate(scope, decl.argument) : [];
|
4232
|
-
|
4199
|
+
if (toGenerate) out.push([ Opcodes.drop ]);
|
4233
4200
|
|
4234
4201
|
out.push(...typeSwitch(scope, overrideType ?? getNodeType(scope, decl.argument), [
|
4235
4202
|
[ TYPES.number, () => makeString(scope, 'number') ],
|
@@ -4308,8 +4275,7 @@ const generateUpdate = (scope, decl, _global, _name, valueUnused = false) => {
|
|
4308
4275
|
right: { type: 'Literal', value: 1 }
|
4309
4276
|
}
|
4310
4277
|
}, _global, _name, valueUnused),
|
4311
|
-
...(decl.prefix || valueUnused ? [] : [ [ Opcodes.drop ] ])
|
4312
|
-
...optional([ number(UNDEFINED) ], valueUnused)
|
4278
|
+
...(decl.prefix || valueUnused ? [] : [ [ Opcodes.drop ] ])
|
4313
4279
|
];
|
4314
4280
|
};
|
4315
4281
|
|
@@ -4343,7 +4309,10 @@ const inferLoopEnd = scope => {
|
|
4343
4309
|
const generateIf = (scope, decl) => {
|
4344
4310
|
if (globalThis.precompile && decl.test?.tag?.name === '__Porffor_comptime_flag') {
|
4345
4311
|
const flag = decl.test.quasi.quasis[0].value.raw;
|
4346
|
-
return [
|
4312
|
+
return [
|
4313
|
+
[ null, 'comptime_flag', flag, decl.consequent, '#', Prefs ],
|
4314
|
+
number(UNDEFINED)
|
4315
|
+
];
|
4347
4316
|
}
|
4348
4317
|
|
4349
4318
|
const out = truthy(scope, generate(scope, decl.test), getNodeType(scope, decl.test), false, true);
|
@@ -4351,22 +4320,26 @@ const generateIf = (scope, decl) => {
|
|
4351
4320
|
depth.push('if');
|
4352
4321
|
inferBranchStart(scope, decl.consequent);
|
4353
4322
|
|
4354
|
-
|
4355
|
-
|
4356
|
-
|
4323
|
+
out.push(
|
4324
|
+
...generate(scope, decl.consequent),
|
4325
|
+
[ Opcodes.drop ]
|
4326
|
+
);
|
4357
4327
|
|
4358
4328
|
inferBranchEnd(scope);
|
4359
4329
|
if (decl.alternate) {
|
4360
|
-
out.push([ Opcodes.else ]);
|
4361
4330
|
inferBranchStart(scope, decl.alternate);
|
4362
|
-
|
4363
|
-
|
4364
|
-
|
4365
|
-
|
4331
|
+
out.push(
|
4332
|
+
[ Opcodes.else ],
|
4333
|
+
...generate(scope, decl.alternate),
|
4334
|
+
[ Opcodes.drop ]
|
4335
|
+
);
|
4366
4336
|
inferBranchEnd(scope);
|
4367
4337
|
}
|
4368
4338
|
|
4369
|
-
out.push(
|
4339
|
+
out.push(
|
4340
|
+
[ Opcodes.end ],
|
4341
|
+
number(UNDEFINED)
|
4342
|
+
);
|
4370
4343
|
depth.pop();
|
4371
4344
|
|
4372
4345
|
return out;
|
@@ -4402,10 +4375,10 @@ let depth = [];
|
|
4402
4375
|
const generateFor = (scope, decl) => {
|
4403
4376
|
const out = [];
|
4404
4377
|
|
4405
|
-
if (decl.init)
|
4406
|
-
|
4407
|
-
|
4408
|
-
|
4378
|
+
if (decl.init) out.push(
|
4379
|
+
...generate(scope, decl.init, false, undefined, true),
|
4380
|
+
[ Opcodes.drop ]
|
4381
|
+
);
|
4409
4382
|
|
4410
4383
|
inferLoopStart(scope, decl);
|
4411
4384
|
out.push([ Opcodes.loop, Blocktype.void ]);
|
@@ -4414,19 +4387,31 @@ const generateFor = (scope, decl) => {
|
|
4414
4387
|
if (decl.test) out.push(...generate(scope, decl.test), Opcodes.i32_to);
|
4415
4388
|
else out.push(number(1, Valtype.i32));
|
4416
4389
|
|
4417
|
-
out.push(
|
4418
|
-
|
4390
|
+
out.push(
|
4391
|
+
[ Opcodes.if, Blocktype.void ],
|
4392
|
+
[ Opcodes.block, Blocktype.void ]
|
4393
|
+
);
|
4394
|
+
depth.push('if', 'block');
|
4419
4395
|
|
4420
|
-
out.push(
|
4421
|
-
|
4422
|
-
|
4423
|
-
|
4396
|
+
out.push(
|
4397
|
+
...generate(scope, decl.body),
|
4398
|
+
[ Opcodes.drop ],
|
4399
|
+
[ Opcodes.end ]
|
4400
|
+
);
|
4401
|
+
depth.pop();
|
4424
4402
|
|
4425
|
-
if (decl.update) out.push(
|
4403
|
+
if (decl.update) out.push(
|
4404
|
+
...generate(scope, decl.update, false, undefined, true),
|
4405
|
+
[ Opcodes.drop ]
|
4406
|
+
);
|
4426
4407
|
|
4427
|
-
out.push(
|
4428
|
-
|
4429
|
-
|
4408
|
+
out.push(
|
4409
|
+
[ Opcodes.br, 1 ],
|
4410
|
+
[ Opcodes.end ],
|
4411
|
+
[ Opcodes.end ],
|
4412
|
+
number(UNDEFINED)
|
4413
|
+
);
|
4414
|
+
depth.pop(); depth.pop();
|
4430
4415
|
|
4431
4416
|
inferLoopEnd(scope);
|
4432
4417
|
return out;
|
@@ -4439,14 +4424,21 @@ const generateWhile = (scope, decl) => {
|
|
4439
4424
|
out.push([ Opcodes.loop, Blocktype.void ]);
|
4440
4425
|
depth.push('while');
|
4441
4426
|
|
4442
|
-
out.push(
|
4443
|
-
|
4427
|
+
out.push(
|
4428
|
+
...generate(scope, decl.test),
|
4429
|
+
Opcodes.i32_to,
|
4430
|
+
[ Opcodes.if, Blocktype.void ]
|
4431
|
+
);
|
4444
4432
|
depth.push('if');
|
4445
4433
|
|
4446
|
-
out.push(
|
4447
|
-
|
4448
|
-
|
4449
|
-
|
4434
|
+
out.push(
|
4435
|
+
...generate(scope, decl.body),
|
4436
|
+
[ Opcodes.drop ],
|
4437
|
+
[ Opcodes.br, 1 ],
|
4438
|
+
[ Opcodes.end ],
|
4439
|
+
[ Opcodes.end ],
|
4440
|
+
number(UNDEFINED)
|
4441
|
+
);
|
4450
4442
|
depth.pop(); depth.pop();
|
4451
4443
|
|
4452
4444
|
inferLoopEnd(scope);
|
@@ -4458,27 +4450,31 @@ const generateDoWhile = (scope, decl) => {
|
|
4458
4450
|
inferLoopStart(scope, decl);
|
4459
4451
|
|
4460
4452
|
out.push([ Opcodes.loop, Blocktype.void ]);
|
4461
|
-
depth.push('dowhile');
|
4462
4453
|
|
4463
4454
|
// block for break (includes all)
|
4464
4455
|
out.push([ Opcodes.block, Blocktype.void ]);
|
4465
|
-
depth.push('block');
|
4466
4456
|
|
4467
4457
|
// block for continue
|
4468
4458
|
// includes body but not test+loop so we can exit body at anytime
|
4469
4459
|
// and still test+loop after
|
4470
4460
|
out.push([ Opcodes.block, Blocktype.void ]);
|
4471
|
-
depth.push('block');
|
4461
|
+
depth.push('dowhile', 'block', 'block');
|
4472
4462
|
|
4473
|
-
out.push(
|
4474
|
-
|
4475
|
-
|
4463
|
+
out.push(
|
4464
|
+
...generate(scope, decl.body),
|
4465
|
+
[ Opcodes.drop ],
|
4466
|
+
[ Opcodes.end ]
|
4467
|
+
);
|
4476
4468
|
depth.pop();
|
4477
4469
|
|
4478
|
-
out.push(
|
4479
|
-
|
4480
|
-
|
4481
|
-
|
4470
|
+
out.push(
|
4471
|
+
...generate(scope, decl.test),
|
4472
|
+
Opcodes.i32_to,
|
4473
|
+
[ Opcodes.br_if, 1 ],
|
4474
|
+
[ Opcodes.end ],
|
4475
|
+
[ Opcodes.end ],
|
4476
|
+
number(UNDEFINED)
|
4477
|
+
);
|
4482
4478
|
depth.pop(); depth.pop();
|
4483
4479
|
|
4484
4480
|
inferLoopEnd(scope);
|
@@ -4811,17 +4807,17 @@ const generateForOf = (scope, decl) => {
|
|
4811
4807
|
}
|
4812
4808
|
|
4813
4809
|
// next and set local
|
4814
|
-
out.push(
|
4815
|
-
|
4816
|
-
|
4817
|
-
|
4818
|
-
|
4819
|
-
|
4820
|
-
|
4821
|
-
|
4810
|
+
out.push(
|
4811
|
+
...setVar,
|
4812
|
+
...generate(scope, decl.body),
|
4813
|
+
[ Opcodes.drop ],
|
4814
|
+
[ Opcodes.br, 1 ], // continue
|
4815
|
+
[ Opcodes.end ], // end block
|
4816
|
+
[ Opcodes.end ], // end loop
|
4817
|
+
number(UNDEFINED)
|
4818
|
+
);
|
4822
4819
|
|
4823
|
-
depth.pop();
|
4824
|
-
depth.pop();
|
4820
|
+
depth.pop(); depth.pop();
|
4825
4821
|
|
4826
4822
|
inferLoopEnd(scope);
|
4827
4823
|
return out;
|
@@ -4921,6 +4917,7 @@ const generateForIn = (scope, decl) => {
|
|
4921
4917
|
[ Opcodes.i32_and ],
|
4922
4918
|
[ Opcodes.if, Blocktype.void ],
|
4923
4919
|
...generate(scope, decl.body),
|
4920
|
+
[ Opcodes.drop ],
|
4924
4921
|
[ Opcodes.end ],
|
4925
4922
|
|
4926
4923
|
// increment pointer by 14
|
@@ -4953,33 +4950,41 @@ const generateForIn = (scope, decl) => {
|
|
4953
4950
|
|
4954
4951
|
inferLoopEnd(scope);
|
4955
4952
|
|
4956
|
-
|
4953
|
+
const final = typeSwitch(scope, getNodeType(scope, decl.right), {
|
4957
4954
|
// fast path for objects
|
4958
4955
|
[TYPES.object]: out,
|
4959
4956
|
|
4960
4957
|
// wrap for of object.keys
|
4961
|
-
default: () =>
|
4962
|
-
|
4963
|
-
|
4964
|
-
|
4965
|
-
|
4966
|
-
|
4967
|
-
|
4968
|
-
|
4969
|
-
|
4970
|
-
|
4971
|
-
|
4972
|
-
|
4973
|
-
|
4974
|
-
|
4975
|
-
|
4976
|
-
|
4977
|
-
|
4978
|
-
|
4979
|
-
|
4980
|
-
|
4981
|
-
|
4958
|
+
default: () => {
|
4959
|
+
const out = generate(scope, {
|
4960
|
+
type: 'ForOfStatement',
|
4961
|
+
left: decl.left,
|
4962
|
+
body: decl.body,
|
4963
|
+
right: {
|
4964
|
+
type: 'CallExpression',
|
4965
|
+
callee: {
|
4966
|
+
type: 'Identifier',
|
4967
|
+
name: '__Object_keys'
|
4968
|
+
},
|
4969
|
+
arguments: [ {
|
4970
|
+
type: 'LogicalExpression',
|
4971
|
+
left: decl.right,
|
4972
|
+
operator: '??',
|
4973
|
+
right: {
|
4974
|
+
type: 'Literal',
|
4975
|
+
value: 0
|
4976
|
+
}
|
4977
|
+
} ]
|
4978
|
+
}
|
4979
|
+
});
|
4980
|
+
|
4981
|
+
out.push([ Opcodes.drop ]);
|
4982
|
+
return out;
|
4983
|
+
}
|
4982
4984
|
}, Blocktype.void);
|
4985
|
+
|
4986
|
+
final.push(number(UNDEFINED));
|
4987
|
+
return final;
|
4983
4988
|
};
|
4984
4989
|
|
4985
4990
|
const generateSwitch = (scope, decl) => {
|
@@ -5024,6 +5029,7 @@ const generateSwitch = (scope, decl) => {
|
|
5024
5029
|
}, Blocktype.void, true);
|
5025
5030
|
|
5026
5031
|
depth.pop();
|
5032
|
+
out.push(number(UNDEFINED));
|
5027
5033
|
return out;
|
5028
5034
|
}
|
5029
5035
|
}
|
@@ -5082,13 +5088,15 @@ const generateSwitch = (scope, decl) => {
|
|
5082
5088
|
depth.pop();
|
5083
5089
|
out.push(
|
5084
5090
|
[ Opcodes.end ],
|
5085
|
-
...generate(scope, { type: 'BlockStatement', body: cases[i].consequent })
|
5091
|
+
...generate(scope, { type: 'BlockStatement', body: cases[i].consequent }),
|
5092
|
+
[ Opcodes.drop ]
|
5086
5093
|
);
|
5087
5094
|
}
|
5088
5095
|
|
5089
5096
|
out.push([ Opcodes.end ]);
|
5090
5097
|
depth.pop();
|
5091
5098
|
|
5099
|
+
out.push(number(UNDEFINED));
|
5092
5100
|
return out;
|
5093
5101
|
};
|
5094
5102
|
|
@@ -5152,7 +5160,19 @@ const generateLabel = (scope, decl) => {
|
|
5152
5160
|
const name = decl.label.name;
|
5153
5161
|
scope.labels.set(name, depth.length);
|
5154
5162
|
|
5155
|
-
|
5163
|
+
const out = generate(scope, decl.body);
|
5164
|
+
|
5165
|
+
// if block statement, wrap in block to allow for breaking
|
5166
|
+
if (decl.body.type === 'BlockStatement') {
|
5167
|
+
out.unshift([ Opcodes.block, Blocktype.void ]);
|
5168
|
+
out.push(
|
5169
|
+
[ Opcodes.drop ],
|
5170
|
+
[ Opcodes.end ],
|
5171
|
+
number(UNDEFINED)
|
5172
|
+
);
|
5173
|
+
}
|
5174
|
+
|
5175
|
+
return out;
|
5156
5176
|
};
|
5157
5177
|
|
5158
5178
|
const ensureTag = (exceptionMode = Prefs.exceptionMode ?? 'stack') => {
|
@@ -5211,13 +5231,19 @@ const generateTry = (scope, decl) => {
|
|
5211
5231
|
|
5212
5232
|
const out = [];
|
5213
5233
|
|
5214
|
-
const finalizer = decl.finalizer ?
|
5234
|
+
const finalizer = decl.finalizer ? [
|
5235
|
+
...generate(scope, decl.finalizer),
|
5236
|
+
[ Opcodes.drop ]
|
5237
|
+
]: [];
|
5215
5238
|
|
5216
5239
|
out.push([ Opcodes.try, Blocktype.void ]);
|
5217
5240
|
depth.push('try');
|
5218
5241
|
|
5219
|
-
out.push(
|
5220
|
-
|
5242
|
+
out.push(
|
5243
|
+
...generate(scope, decl.block),
|
5244
|
+
[ Opcodes.drop ],
|
5245
|
+
...finalizer
|
5246
|
+
);
|
5221
5247
|
|
5222
5248
|
if (decl.handler) {
|
5223
5249
|
depth.pop();
|
@@ -5252,6 +5278,7 @@ const generateTry = (scope, decl) => {
|
|
5252
5278
|
|
5253
5279
|
out.push(
|
5254
5280
|
...generate(scope, decl.handler.body),
|
5281
|
+
[ Opcodes.drop ],
|
5255
5282
|
...finalizer
|
5256
5283
|
);
|
5257
5284
|
}
|
@@ -5259,11 +5286,12 @@ const generateTry = (scope, decl) => {
|
|
5259
5286
|
out.push([ Opcodes.end ]);
|
5260
5287
|
depth.pop();
|
5261
5288
|
|
5289
|
+
out.push(number(UNDEFINED));
|
5262
5290
|
return out;
|
5263
5291
|
};
|
5264
5292
|
|
5265
5293
|
const generateEmpty = (scope, decl) => {
|
5266
|
-
return [];
|
5294
|
+
return [ number(UNDEFINED) ];
|
5267
5295
|
};
|
5268
5296
|
|
5269
5297
|
const generateMeta = (scope, decl) => {
|
@@ -6143,13 +6171,15 @@ const generateClass = (scope, decl) => {
|
|
6143
6171
|
// Bar.__proto__ = Foo
|
6144
6172
|
// Bar.prototype.__proto__ = Foo.prototype
|
6145
6173
|
...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
|
6146
|
-
|
6174
|
+
[ Opcodes.drop ],
|
6175
|
+
...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype'))),
|
6176
|
+
[ Opcodes.drop ]
|
6147
6177
|
);
|
6148
6178
|
}
|
6149
6179
|
|
6150
6180
|
for (const x of body) {
|
6151
6181
|
let { type, key, value, kind, static: _static, computed } = x;
|
6152
|
-
if (type !== 'MethodDefinition' && type !== 'PropertyDefinition') return todo(scope, `class body type ${type} is not supported yet`,
|
6182
|
+
if (type !== 'MethodDefinition' && type !== 'PropertyDefinition') return todo(scope, `class body type ${type} is not supported yet`, true);
|
6153
6183
|
|
6154
6184
|
if (kind === 'constructor') continue;
|
6155
6185
|
|
@@ -6254,7 +6284,7 @@ export const generateTemplate = (scope, decl) => {
|
|
6254
6284
|
return generate(scope, current);
|
6255
6285
|
};
|
6256
6286
|
|
6257
|
-
const generateTaggedTemplate = (scope, decl, global = false, name = undefined) => {
|
6287
|
+
const generateTaggedTemplate = (scope, decl, global = false, name = undefined, valueUnused = false) => {
|
6258
6288
|
const intrinsics = {
|
6259
6289
|
__Porffor_wasm: str => {
|
6260
6290
|
let out = [];
|
@@ -6301,6 +6331,11 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined) =
|
|
6301
6331
|
out.push([ ...inst, ...immediates.flatMap(x => encodeFunc(x)) ]);
|
6302
6332
|
}
|
6303
6333
|
|
6334
|
+
// add value to stack if value unused as 99% typically means
|
6335
|
+
// no value on stack at end of wasm
|
6336
|
+
// unless final op is return
|
6337
|
+
if (valueUnused && out.at(-1)[0] !== Opcodes.return) out.push(number(UNDEFINED));
|
6338
|
+
|
6304
6339
|
return out;
|
6305
6340
|
},
|
6306
6341
|
|
@@ -6483,7 +6518,7 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6483
6518
|
const { name, def, destr, type } = args[i];
|
6484
6519
|
|
6485
6520
|
func.localInd = i * 2;
|
6486
|
-
allocVar(func, name, false);
|
6521
|
+
allocVar(func, name, false, true, true);
|
6487
6522
|
|
6488
6523
|
func.localInd = localInd;
|
6489
6524
|
if (type) {
|
@@ -6584,6 +6619,30 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6584
6619
|
wasm = generate(func, body);
|
6585
6620
|
wasm.unshift(...preface);
|
6586
6621
|
|
6622
|
+
if (name === '#main') {
|
6623
|
+
func.gotLastType = true;
|
6624
|
+
func.export = true;
|
6625
|
+
|
6626
|
+
wasm.push(...getNodeType(func, getLastNode(decl.body.body)));
|
6627
|
+
|
6628
|
+
// inject promise job runner func at the end of main if promises are made
|
6629
|
+
if (Object.hasOwn(funcIndex, 'Promise') || Object.hasOwn(funcIndex, '__Promise_resolve') || Object.hasOwn(funcIndex, '__Promise_reject')) {
|
6630
|
+
wasm.push(
|
6631
|
+
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ],
|
6632
|
+
[ Opcodes.drop ],
|
6633
|
+
[ Opcodes.drop ]
|
6634
|
+
);
|
6635
|
+
}
|
6636
|
+
} else {
|
6637
|
+
// add end empty return if not found
|
6638
|
+
if (wasm[wasm.length - 1]?.[0] !== Opcodes.return) {
|
6639
|
+
wasm.push(
|
6640
|
+
[ Opcodes.drop ],
|
6641
|
+
...generateReturn(func, {})
|
6642
|
+
);
|
6643
|
+
}
|
6644
|
+
}
|
6645
|
+
|
6587
6646
|
if (func.generator) {
|
6588
6647
|
// make generator at the start
|
6589
6648
|
wasm.unshift(
|
@@ -6628,57 +6687,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6628
6687
|
ensureTag();
|
6629
6688
|
}
|
6630
6689
|
|
6631
|
-
if (name === '#main') {
|
6632
|
-
func.gotLastType = true;
|
6633
|
-
func.export = true;
|
6634
|
-
|
6635
|
-
let finalStatement = decl.body.body[decl.body.body.length - 1];
|
6636
|
-
if (finalStatement?.type === 'EmptyStatement') finalStatement = decl.body.body[decl.body.body.length - 2];
|
6637
|
-
|
6638
|
-
const lastInst = getLastInst(wasm) ?? [ Opcodes.end ];
|
6639
|
-
if (lastInst[0] === Opcodes.drop || lastInst[0] === Opcodes.f64_const) {
|
6640
|
-
if (finalStatement.type.endsWith('Declaration')) {
|
6641
|
-
// final statement is decl, force undefined
|
6642
|
-
disposeLeftover(wasm);
|
6643
|
-
wasm.push(
|
6644
|
-
number(UNDEFINED),
|
6645
|
-
number(TYPES.undefined, Valtype.i32)
|
6646
|
-
);
|
6647
|
-
} else {
|
6648
|
-
wasm.splice(wasm.length - 1, 1);
|
6649
|
-
wasm.push(...getNodeType(func, finalStatement));
|
6650
|
-
}
|
6651
|
-
}
|
6652
|
-
|
6653
|
-
if (lastInst[0] === Opcodes.end || lastInst[0] === Opcodes.local_set || lastInst[0] === Opcodes.global_set) {
|
6654
|
-
if (lastInst[0] === Opcodes.local_set && lastInst[1] === func.locals['#last_type'].idx) {
|
6655
|
-
wasm.splice(wasm.length - 1, 1);
|
6656
|
-
} else {
|
6657
|
-
func.returns = [];
|
6658
|
-
}
|
6659
|
-
}
|
6660
|
-
|
6661
|
-
if (lastInst[0] === Opcodes.call) {
|
6662
|
-
const callee = funcByIndex(lastInst[1]);
|
6663
|
-
if (callee) func.returns = callee.returns.slice();
|
6664
|
-
else func.returns = [];
|
6665
|
-
}
|
6666
|
-
|
6667
|
-
// inject promise job runner func at the end of main if promises are made
|
6668
|
-
if (Object.hasOwn(funcIndex, 'Promise') || Object.hasOwn(funcIndex, '__Promise_resolve') || Object.hasOwn(funcIndex, '__Promise_reject')) {
|
6669
|
-
wasm.push(
|
6670
|
-
[ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ],
|
6671
|
-
[ Opcodes.drop ],
|
6672
|
-
[ Opcodes.drop ]
|
6673
|
-
);
|
6674
|
-
}
|
6675
|
-
} else {
|
6676
|
-
// add end return if not found
|
6677
|
-
if (wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) < func.returns.length) {
|
6678
|
-
wasm.push(...generateReturn(func, {}));
|
6679
|
-
}
|
6680
|
-
}
|
6681
|
-
|
6682
6690
|
return func.wasm = wasm;
|
6683
6691
|
}
|
6684
6692
|
};
|
@@ -6747,24 +6755,31 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6747
6755
|
if (globalThis.precompile) func.generate();
|
6748
6756
|
|
6749
6757
|
if (decl._doNotMarkFuncRef) doNotMarkFuncRef = true;
|
6750
|
-
const out = decl.type.endsWith('Expression') && !forceNoExpr ? funcRef(func) : [];
|
6758
|
+
const out = decl.type.endsWith('Expression') && !forceNoExpr ? funcRef(func) : [ number(UNDEFINED) ];
|
6751
6759
|
doNotMarkFuncRef = false;
|
6752
6760
|
|
6753
6761
|
astCache.set(decl, out);
|
6754
6762
|
return [ func, out ];
|
6755
6763
|
};
|
6756
6764
|
|
6757
|
-
const
|
6765
|
+
const generateBlock = (scope, decl) => {
|
6758
6766
|
let out = [];
|
6759
6767
|
|
6760
6768
|
scope.inferTree ??= [];
|
6761
6769
|
scope.inferTree.push(decl);
|
6762
6770
|
|
6763
|
-
|
6771
|
+
let j = 0;
|
6772
|
+
for (let i = 0; i < decl.body.length; i++) {
|
6773
|
+
const x = decl.body[i];
|
6774
|
+
if (isEmptyNode(x)) continue;
|
6775
|
+
|
6776
|
+
if (j++ > 0) out.push([ Opcodes.drop ]);
|
6764
6777
|
out = out.concat(generate(scope, x));
|
6765
6778
|
}
|
6766
6779
|
|
6767
6780
|
scope.inferTree.pop();
|
6781
|
+
|
6782
|
+
if (out.length === 0) out.push(number(UNDEFINED));
|
6768
6783
|
return out;
|
6769
6784
|
};
|
6770
6785
|
|
@@ -6867,7 +6882,9 @@ const internalConstrs = {
|
|
6867
6882
|
scope.usesImports = true;
|
6868
6883
|
|
6869
6884
|
const str = decl.arguments[0].value;
|
6870
|
-
|
6885
|
+
const out = printStaticStr(str);
|
6886
|
+
out.push(number(UNDEFINED));
|
6887
|
+
return out;
|
6871
6888
|
},
|
6872
6889
|
type: TYPES.undefined,
|
6873
6890
|
notConstr: true,
|
@@ -7046,4 +7063,4 @@ export default program => {
|
|
7046
7063
|
delete globals['#ind'];
|
7047
7064
|
|
7048
7065
|
return { funcs, globals, tags, exceptions, pages, data };
|
7049
|
-
};
|
7066
|
+
};
|