porffor 0.17.0-b7ba5b83d → 0.17.0-b92c546cf
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/2c.js +28 -11
- package/compiler/builtins/array.ts +22 -0
- package/compiler/builtins/math.ts +6 -2
- package/compiler/builtins/set.ts +2 -9
- package/compiler/builtins/typedarray.js +47 -0
- package/compiler/builtins.js +25 -0
- package/compiler/codegen.js +554 -64
- package/compiler/generated_builtins.js +397 -134
- package/compiler/pgo.js +9 -1
- package/compiler/types.js +31 -5
- package/compiler/wasmSpec.js +2 -0
- package/compiler/wrap.js +69 -12
- package/package.json +1 -1
- package/rhemyn/README.md +7 -4
- package/rhemyn/compile.js +139 -73
- package/runner/debug.js +1 -1
- package/runner/index.js +5 -3
- package/runner/profile.js +1 -1
- package/runner/repl.js +16 -11
package/compiler/codegen.js
CHANGED
@@ -4,7 +4,7 @@ import { operatorOpcode } from './expression.js';
|
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
5
|
import { PrototypeFuncs } from './prototype.js';
|
6
6
|
import { number } from './embedding.js';
|
7
|
-
import { TYPES, TYPE_NAMES } from './types.js';
|
7
|
+
import { TYPES, TYPE_FLAGS, TYPE_NAMES, typeHasFlag } from './types.js';
|
8
8
|
import * as Rhemyn from '../rhemyn/compile.js';
|
9
9
|
import parse from './parse.js';
|
10
10
|
import { log } from './log.js';
|
@@ -72,6 +72,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
72
72
|
case 'ExpressionStatement':
|
73
73
|
return generateExp(scope, decl);
|
74
74
|
|
75
|
+
case 'SequenceExpression':
|
76
|
+
return generateSequence(scope, decl);
|
77
|
+
|
75
78
|
case 'CallExpression':
|
76
79
|
return generateCall(scope, decl, global, name, valueUnused);
|
77
80
|
|
@@ -264,10 +267,12 @@ const internalThrow = (scope, constructor, message, expectsValue = Prefs.alwaysV
|
|
264
267
|
argument: {
|
265
268
|
type: 'NewExpression',
|
266
269
|
callee: {
|
270
|
+
type: 'Identifier',
|
267
271
|
name: constructor
|
268
272
|
},
|
269
273
|
arguments: [
|
270
274
|
{
|
275
|
+
type: 'Literal',
|
271
276
|
value: message
|
272
277
|
}
|
273
278
|
]
|
@@ -289,12 +294,13 @@ const generateIdent = (scope, decl) => {
|
|
289
294
|
return wasm.slice();
|
290
295
|
}
|
291
296
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
297
|
+
// todo: enable this by default in future
|
298
|
+
// if (!Object.hasOwn(funcIndex, name) && Object.hasOwn(builtinFuncs, name)) {
|
299
|
+
// includeBuiltin(scope, name);
|
300
|
+
// return number(funcIndex[name] - importedFuncs.length);
|
301
|
+
// }
|
296
302
|
|
297
|
-
if (isExistingProtoFunc(name)) {
|
303
|
+
if (isExistingProtoFunc(name) || Object.hasOwn(internalConstrs, name) || Object.hasOwn(builtinFuncs, name)) {
|
298
304
|
// todo: return an actual something
|
299
305
|
return number(1);
|
300
306
|
}
|
@@ -613,11 +619,14 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
613
619
|
};
|
614
620
|
|
615
621
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
622
|
+
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
623
|
+
...wasm,
|
624
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
625
|
+
];
|
626
|
+
if (isIntOp(wasm[wasm.length - 1])) return [
|
627
|
+
...wasm,
|
628
|
+
...(intOut ? [] : [ Opcodes.i32_from ]),
|
629
|
+
];
|
621
630
|
|
622
631
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
623
632
|
|
@@ -973,6 +982,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
973
982
|
};
|
974
983
|
|
975
984
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
985
|
+
if (decl.operator === 'instanceof') {
|
986
|
+
// very hacky basic instanceof
|
987
|
+
// todo: support dynamic right-hand side
|
988
|
+
|
989
|
+
const out = generate(scope, decl.left);
|
990
|
+
disposeLeftover(out);
|
991
|
+
|
992
|
+
const rightName = decl.right.name;
|
993
|
+
if (!rightName) return todo(scope, 'instanceof dynamic right-hand side is not supported yet', true);
|
994
|
+
|
995
|
+
const checkType = TYPES[rightName.toLowerCase()];
|
996
|
+
if (checkType == null || rightName !== TYPE_NAMES[checkType] || checkType === TYPES.undefined) return todo(scope, 'instanceof right-hand side type unsupported', true);
|
997
|
+
|
998
|
+
if ([TYPES.number, TYPES.boolean, TYPES.string, TYPES.symbol, TYPES.object].includes(checkType)) {
|
999
|
+
out.push(...number(0));
|
1000
|
+
} else {
|
1001
|
+
out.push(
|
1002
|
+
...getNodeType(scope, decl.left),
|
1003
|
+
...number(checkType, Valtype.i32),
|
1004
|
+
[ Opcodes.i32_eq ],
|
1005
|
+
Opcodes.i32_from_u
|
1006
|
+
);
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
return out;
|
1010
|
+
}
|
1011
|
+
|
976
1012
|
const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
|
977
1013
|
|
978
1014
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1279,7 +1315,7 @@ const getNodeType = (scope, node) => {
|
|
1279
1315
|
}
|
1280
1316
|
|
1281
1317
|
if (node.type === 'BinaryExpression') {
|
1282
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1318
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1283
1319
|
if (node.operator !== '+') return TYPES.number;
|
1284
1320
|
|
1285
1321
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1312,7 +1348,7 @@ const getNodeType = (scope, node) => {
|
|
1312
1348
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1313
1349
|
if (objectKnownType != null) {
|
1314
1350
|
if (name === 'length') {
|
1315
|
-
if (
|
1351
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1316
1352
|
else return TYPES.undefined;
|
1317
1353
|
}
|
1318
1354
|
|
@@ -1384,9 +1420,9 @@ const countLeftover = wasm => {
|
|
1384
1420
|
|
1385
1421
|
if (depth === 0)
|
1386
1422
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1387
|
-
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, 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.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)) {}
|
1423
|
+
else if ([null, Opcodes.i32_eqz, Opcodes.i64_eqz, 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)) {}
|
1388
1424
|
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++;
|
1389
|
-
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1425
|
+
else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.f32_store, Opcodes.i32_store16, Opcodes.i32_store8].includes(inst[0])) count -= 2;
|
1390
1426
|
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1391
1427
|
else if (inst[0] === Opcodes.return) count = 0;
|
1392
1428
|
else if (inst[0] === Opcodes.call) {
|
@@ -1424,6 +1460,18 @@ const generateExp = (scope, decl) => {
|
|
1424
1460
|
return out;
|
1425
1461
|
};
|
1426
1462
|
|
1463
|
+
const generateSequence = (scope, decl) => {
|
1464
|
+
let out = [];
|
1465
|
+
|
1466
|
+
const exprs = decl.expressions;
|
1467
|
+
for (let i = 0; i < exprs.length; i++) {
|
1468
|
+
if (i > 0) disposeLeftover(out);
|
1469
|
+
out.push(...generate(scope, exprs[i]));
|
1470
|
+
}
|
1471
|
+
|
1472
|
+
return out;
|
1473
|
+
};
|
1474
|
+
|
1427
1475
|
const CTArrayUtil = {
|
1428
1476
|
getLengthI32: pointer => [
|
1429
1477
|
...number(0, Valtype.i32),
|
@@ -1542,9 +1590,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1542
1590
|
if (!name && decl.callee.type === 'MemberExpression') {
|
1543
1591
|
// megahack for /regex/.func()
|
1544
1592
|
const funcName = decl.callee.property.name;
|
1545
|
-
if (decl.callee.object.regex &&
|
1593
|
+
if (decl.callee.object.regex && ['test'].includes(funcName)) {
|
1546
1594
|
const regex = decl.callee.object.regex.pattern;
|
1547
|
-
const rhemynName = `regex_${funcName}_${regex}`;
|
1595
|
+
const rhemynName = `regex_${funcName}_${sanitize(regex)}`;
|
1548
1596
|
|
1549
1597
|
if (!funcIndex[rhemynName]) {
|
1550
1598
|
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
@@ -1565,7 +1613,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1565
1613
|
[ Opcodes.call, idx ],
|
1566
1614
|
Opcodes.i32_from_u,
|
1567
1615
|
|
1568
|
-
...setLastType(scope,
|
1616
|
+
...setLastType(scope, Rhemyn.types[funcName])
|
1569
1617
|
];
|
1570
1618
|
}
|
1571
1619
|
|
@@ -1574,24 +1622,44 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1574
1622
|
target = decl.callee.object;
|
1575
1623
|
}
|
1576
1624
|
|
1577
|
-
|
1578
|
-
|
1625
|
+
if (protoName) {
|
1626
|
+
if (['search'].includes(protoName)) {
|
1627
|
+
const regex = decl.arguments[0]?.regex?.pattern;
|
1628
|
+
if (!regex) return [
|
1629
|
+
// no/bad regex arg, return -1/0 for now
|
1630
|
+
...generate(scope, target),
|
1631
|
+
[ Opcodes.drop ],
|
1579
1632
|
|
1580
|
-
|
1581
|
-
|
1633
|
+
...number(Rhemyn.types[protoName] === TYPES.number ? -1 : 0),
|
1634
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1635
|
+
];
|
1582
1636
|
|
1583
|
-
|
1584
|
-
// generate(scope, decl.callee.object)
|
1637
|
+
const rhemynName = `regex_${protoName}_${sanitize(regex)}`;
|
1585
1638
|
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
// ];
|
1590
|
-
// }
|
1639
|
+
if (!funcIndex[rhemynName]) {
|
1640
|
+
const func = Rhemyn[protoName](regex, currentFuncIndex++, rhemynName);
|
1641
|
+
func.internal = true;
|
1591
1642
|
|
1592
|
-
|
1593
|
-
|
1643
|
+
funcIndex[func.name] = func.index;
|
1644
|
+
funcs.push(func);
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
const idx = funcIndex[rhemynName];
|
1648
|
+
return [
|
1649
|
+
// make string arg
|
1650
|
+
...generate(scope, target),
|
1651
|
+
Opcodes.i32_to_u,
|
1652
|
+
...getNodeType(scope, target),
|
1653
|
+
|
1654
|
+
// call regex func
|
1655
|
+
[ Opcodes.call, idx ],
|
1656
|
+
Opcodes.i32_from,
|
1657
|
+
|
1658
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1659
|
+
];
|
1660
|
+
}
|
1594
1661
|
|
1662
|
+
const protoBC = {};
|
1595
1663
|
const builtinProtoCands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + protoName));
|
1596
1664
|
|
1597
1665
|
if (!decl._protoInternalCall && builtinProtoCands.length > 0) {
|
@@ -2005,6 +2073,16 @@ const DEFAULT_VALUE = {
|
|
2005
2073
|
name: 'undefined'
|
2006
2074
|
};
|
2007
2075
|
|
2076
|
+
const codeToSanitizedStr = code => {
|
2077
|
+
let out = '';
|
2078
|
+
while (code > 0) {
|
2079
|
+
out += String.fromCharCode(97 + code % 26);
|
2080
|
+
code -= 26;
|
2081
|
+
}
|
2082
|
+
return out;
|
2083
|
+
};
|
2084
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
|
2085
|
+
|
2008
2086
|
const unhackName = name => {
|
2009
2087
|
if (name.startsWith('__')) return name.slice(2).replaceAll('_', '.');
|
2010
2088
|
return name;
|
@@ -2012,7 +2090,7 @@ const unhackName = name => {
|
|
2012
2090
|
|
2013
2091
|
const knownType = (scope, type) => {
|
2014
2092
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2015
|
-
return type[0]
|
2093
|
+
return read_signedLEB128(type[0].slice(1));
|
2016
2094
|
}
|
2017
2095
|
|
2018
2096
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2299,11 +2377,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2299
2377
|
const { type, name } = decl.left;
|
2300
2378
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2301
2379
|
|
2302
|
-
if (type === 'ObjectPattern') {
|
2303
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2304
|
-
return generate(scope, decl.right);
|
2305
|
-
}
|
2306
|
-
|
2307
2380
|
if (isFuncType(decl.right.type)) {
|
2308
2381
|
// hack for a = function () { ... }
|
2309
2382
|
decl.right.id = { name };
|
@@ -2376,10 +2449,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2376
2449
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2377
2450
|
], getNodeType(scope, decl.right), false, name, true)),
|
2378
2451
|
[ Opcodes.local_tee, newValueTmp ],
|
2379
|
-
|
2380
2452
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2381
2453
|
],
|
2382
2454
|
|
2455
|
+
...wrapBC({
|
2456
|
+
[TYPES.uint8array]: [
|
2457
|
+
[ Opcodes.i32_add ],
|
2458
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2459
|
+
|
2460
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2461
|
+
[ Opcodes.local_get, pointerTmp ],
|
2462
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2463
|
+
Opcodes.i32_from_u
|
2464
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2465
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2466
|
+
|
2467
|
+
Opcodes.i32_to_u,
|
2468
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2469
|
+
],
|
2470
|
+
[TYPES.uint8clampedarray]: [
|
2471
|
+
[ Opcodes.i32_add ],
|
2472
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2473
|
+
|
2474
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2475
|
+
[ Opcodes.local_get, pointerTmp ],
|
2476
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2477
|
+
Opcodes.i32_from_u
|
2478
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2479
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2480
|
+
|
2481
|
+
...number(0),
|
2482
|
+
[ Opcodes.f64_max ],
|
2483
|
+
...number(255),
|
2484
|
+
[ Opcodes.f64_min ],
|
2485
|
+
Opcodes.i32_to_u,
|
2486
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2487
|
+
],
|
2488
|
+
[TYPES.int8array]: [
|
2489
|
+
[ Opcodes.i32_add ],
|
2490
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2491
|
+
|
2492
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2493
|
+
[ Opcodes.local_get, pointerTmp ],
|
2494
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2495
|
+
Opcodes.i32_from
|
2496
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2497
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2498
|
+
|
2499
|
+
Opcodes.i32_to,
|
2500
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2501
|
+
],
|
2502
|
+
[TYPES.uint16array]: [
|
2503
|
+
...number(2, Valtype.i32),
|
2504
|
+
[ Opcodes.i32_mul ],
|
2505
|
+
[ Opcodes.i32_add ],
|
2506
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2507
|
+
|
2508
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2509
|
+
[ Opcodes.local_get, pointerTmp ],
|
2510
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
2511
|
+
Opcodes.i32_from_u
|
2512
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2513
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2514
|
+
|
2515
|
+
Opcodes.i32_to_u,
|
2516
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2517
|
+
],
|
2518
|
+
[TYPES.int16array]: [
|
2519
|
+
...number(2, Valtype.i32),
|
2520
|
+
[ Opcodes.i32_mul ],
|
2521
|
+
[ Opcodes.i32_add ],
|
2522
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2523
|
+
|
2524
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2525
|
+
[ Opcodes.local_get, pointerTmp ],
|
2526
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2527
|
+
Opcodes.i32_from
|
2528
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2529
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2530
|
+
|
2531
|
+
Opcodes.i32_to,
|
2532
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2533
|
+
],
|
2534
|
+
[TYPES.uint32array]: [
|
2535
|
+
...number(4, Valtype.i32),
|
2536
|
+
[ Opcodes.i32_mul ],
|
2537
|
+
[ Opcodes.i32_add ],
|
2538
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2539
|
+
|
2540
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2541
|
+
[ Opcodes.local_get, pointerTmp ],
|
2542
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2543
|
+
Opcodes.i32_from_u
|
2544
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2545
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2546
|
+
|
2547
|
+
Opcodes.i32_to_u,
|
2548
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2549
|
+
],
|
2550
|
+
[TYPES.int32array]: [
|
2551
|
+
...number(4, Valtype.i32),
|
2552
|
+
[ Opcodes.i32_mul ],
|
2553
|
+
[ Opcodes.i32_add ],
|
2554
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2555
|
+
|
2556
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2557
|
+
[ Opcodes.local_get, pointerTmp ],
|
2558
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2559
|
+
Opcodes.i32_from
|
2560
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2561
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2562
|
+
|
2563
|
+
Opcodes.i32_to,
|
2564
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2565
|
+
],
|
2566
|
+
[TYPES.float32array]: [
|
2567
|
+
...number(4, Valtype.i32),
|
2568
|
+
[ Opcodes.i32_mul ],
|
2569
|
+
[ Opcodes.i32_add ],
|
2570
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2571
|
+
|
2572
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2573
|
+
[ Opcodes.local_get, pointerTmp ],
|
2574
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2575
|
+
[ Opcodes.f64_promote_f32 ]
|
2576
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2577
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2578
|
+
|
2579
|
+
[ Opcodes.f32_demote_f64 ],
|
2580
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2581
|
+
],
|
2582
|
+
[TYPES.float64array]: [
|
2583
|
+
...number(8, Valtype.i32),
|
2584
|
+
[ Opcodes.i32_mul ],
|
2585
|
+
[ Opcodes.i32_add ],
|
2586
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2587
|
+
|
2588
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2589
|
+
[ Opcodes.local_get, pointerTmp ],
|
2590
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2591
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2592
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2593
|
+
|
2594
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2595
|
+
],
|
2596
|
+
}, {
|
2597
|
+
prelude: [
|
2598
|
+
...generate(scope, decl.left.object),
|
2599
|
+
Opcodes.i32_to_u,
|
2600
|
+
...generate(scope, decl.left.property),
|
2601
|
+
Opcodes.i32_to_u,
|
2602
|
+
],
|
2603
|
+
postlude: setLastType(scope, TYPES.number)
|
2604
|
+
}),
|
2605
|
+
|
2383
2606
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2384
2607
|
}, Blocktype.void),
|
2385
2608
|
|
@@ -2763,7 +2986,9 @@ const generateForOf = (scope, decl) => {
|
|
2763
2986
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2764
2987
|
// hack: this is naughty and will break things!
|
2765
2988
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2766
|
-
|
2989
|
+
|
2990
|
+
const known = knownType(scope, getNodeType(scope, decl.right));
|
2991
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
2767
2992
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2768
2993
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2769
2994
|
rawElements: new Array(0)
|
@@ -2811,6 +3036,7 @@ const generateForOf = (scope, decl) => {
|
|
2811
3036
|
[ Opcodes.end ],
|
2812
3037
|
[ Opcodes.end ]
|
2813
3038
|
],
|
3039
|
+
|
2814
3040
|
[TYPES.string]: [
|
2815
3041
|
...setType(scope, leftName, TYPES.string),
|
2816
3042
|
|
@@ -2919,6 +3145,7 @@ const generateForOf = (scope, decl) => {
|
|
2919
3145
|
[ Opcodes.end ],
|
2920
3146
|
[ Opcodes.end ]
|
2921
3147
|
],
|
3148
|
+
|
2922
3149
|
[TYPES.set]: [
|
2923
3150
|
[ Opcodes.loop, Blocktype.void ],
|
2924
3151
|
|
@@ -2957,6 +3184,106 @@ const generateForOf = (scope, decl) => {
|
|
2957
3184
|
[ Opcodes.end ],
|
2958
3185
|
[ Opcodes.end ]
|
2959
3186
|
],
|
3187
|
+
|
3188
|
+
...wrapBC({
|
3189
|
+
[TYPES.uint8array]: [
|
3190
|
+
[ Opcodes.i32_add ],
|
3191
|
+
|
3192
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3193
|
+
Opcodes.i32_from_u
|
3194
|
+
],
|
3195
|
+
[TYPES.uint8clampedarray]: [
|
3196
|
+
[ Opcodes.i32_add ],
|
3197
|
+
|
3198
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3199
|
+
Opcodes.i32_from_u
|
3200
|
+
],
|
3201
|
+
[TYPES.int8array]: [
|
3202
|
+
[ Opcodes.i32_add ],
|
3203
|
+
|
3204
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3205
|
+
Opcodes.i32_from
|
3206
|
+
],
|
3207
|
+
[TYPES.uint16array]: [
|
3208
|
+
...number(2, Valtype.i32),
|
3209
|
+
[ Opcodes.i32_mul ],
|
3210
|
+
[ Opcodes.i32_add ],
|
3211
|
+
|
3212
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3213
|
+
Opcodes.i32_from_u
|
3214
|
+
],
|
3215
|
+
[TYPES.int16array]: [
|
3216
|
+
...number(2, Valtype.i32),
|
3217
|
+
[ Opcodes.i32_mul ],
|
3218
|
+
[ Opcodes.i32_add ],
|
3219
|
+
|
3220
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3221
|
+
Opcodes.i32_from
|
3222
|
+
],
|
3223
|
+
[TYPES.uint32array]: [
|
3224
|
+
...number(4, Valtype.i32),
|
3225
|
+
[ Opcodes.i32_mul ],
|
3226
|
+
[ Opcodes.i32_add ],
|
3227
|
+
|
3228
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3229
|
+
Opcodes.i32_from_u
|
3230
|
+
],
|
3231
|
+
[TYPES.int32array]: [
|
3232
|
+
...number(4, Valtype.i32),
|
3233
|
+
[ Opcodes.i32_mul ],
|
3234
|
+
[ Opcodes.i32_add ],
|
3235
|
+
|
3236
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3237
|
+
Opcodes.i32_from
|
3238
|
+
],
|
3239
|
+
[TYPES.float32array]: [
|
3240
|
+
...number(4, Valtype.i32),
|
3241
|
+
[ Opcodes.i32_mul ],
|
3242
|
+
[ Opcodes.i32_add ],
|
3243
|
+
|
3244
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3245
|
+
[ Opcodes.f64_promote_f32 ]
|
3246
|
+
],
|
3247
|
+
[TYPES.float64array]: [
|
3248
|
+
...number(8, Valtype.i32),
|
3249
|
+
[ Opcodes.i32_mul ],
|
3250
|
+
[ Opcodes.i32_add ],
|
3251
|
+
|
3252
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3253
|
+
],
|
3254
|
+
}, {
|
3255
|
+
prelude: [
|
3256
|
+
...setType(scope, leftName, TYPES.number),
|
3257
|
+
|
3258
|
+
[ Opcodes.loop, Blocktype.void ],
|
3259
|
+
|
3260
|
+
[ Opcodes.local_get, pointer ],
|
3261
|
+
[ Opcodes.local_get, counter ]
|
3262
|
+
],
|
3263
|
+
postlude: [
|
3264
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3265
|
+
|
3266
|
+
[ Opcodes.block, Blocktype.void ],
|
3267
|
+
[ Opcodes.block, Blocktype.void ],
|
3268
|
+
...generate(scope, decl.body),
|
3269
|
+
[ Opcodes.end ],
|
3270
|
+
|
3271
|
+
// increment counter by 1
|
3272
|
+
[ Opcodes.local_get, counter ],
|
3273
|
+
...number(1, Valtype.i32),
|
3274
|
+
[ Opcodes.i32_add ],
|
3275
|
+
[ Opcodes.local_tee, counter ],
|
3276
|
+
|
3277
|
+
// loop if counter != length
|
3278
|
+
[ Opcodes.local_get, length ],
|
3279
|
+
[ Opcodes.i32_ne ],
|
3280
|
+
[ Opcodes.br_if, 1 ],
|
3281
|
+
|
3282
|
+
[ Opcodes.end ],
|
3283
|
+
[ Opcodes.end ]
|
3284
|
+
]
|
3285
|
+
}),
|
3286
|
+
|
2960
3287
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2961
3288
|
}, Blocktype.void));
|
2962
3289
|
|
@@ -3029,32 +3356,102 @@ const generateLabel = (scope, decl) => {
|
|
3029
3356
|
const generateThrow = (scope, decl) => {
|
3030
3357
|
scope.throws = true;
|
3031
3358
|
|
3032
|
-
|
3359
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
3360
|
+
if (exceptionMode === 'lut') {
|
3361
|
+
let message = decl.argument.value, constructor = null;
|
3033
3362
|
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3363
|
+
// support `throw (new)? Error(...)`
|
3364
|
+
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
3365
|
+
constructor = decl.argument.callee.name;
|
3366
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
3367
|
+
}
|
3368
|
+
|
3369
|
+
if (tags.length === 0) tags.push({
|
3370
|
+
params: [ Valtype.i32 ],
|
3371
|
+
results: [],
|
3372
|
+
idx: tags.length
|
3373
|
+
});
|
3374
|
+
|
3375
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3376
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3377
|
+
|
3378
|
+
scope.exceptions ??= [];
|
3379
|
+
scope.exceptions.push(exceptId);
|
3380
|
+
|
3381
|
+
return [
|
3382
|
+
...number(exceptId, Valtype.i32),
|
3383
|
+
[ Opcodes.throw, tags[0].idx ]
|
3384
|
+
];
|
3038
3385
|
}
|
3039
3386
|
|
3040
|
-
if (
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3387
|
+
if (exceptionMode === 'stack') {
|
3388
|
+
if (tags.length === 0) tags.push({
|
3389
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
3390
|
+
results: [],
|
3391
|
+
idx: tags.length
|
3392
|
+
});
|
3045
3393
|
|
3046
|
-
|
3047
|
-
|
3394
|
+
return [
|
3395
|
+
...generate(scope, decl.argument),
|
3396
|
+
...getNodeType(scope, decl.argument),
|
3397
|
+
[ Opcodes.throw, tags[0].idx ]
|
3398
|
+
];
|
3399
|
+
}
|
3048
3400
|
|
3049
|
-
|
3050
|
-
|
3401
|
+
if (exceptionMode === 'stackest') {
|
3402
|
+
let message = decl.argument, constructor = null;
|
3051
3403
|
|
3052
|
-
|
3404
|
+
// support `throw (new)? Error(...)`
|
3405
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3406
|
+
constructor = decl.argument.callee;
|
3407
|
+
message = decl.argument.arguments[0];
|
3408
|
+
}
|
3053
3409
|
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3410
|
+
message ??= DEFAULT_VALUE;
|
3411
|
+
|
3412
|
+
if (tags.length === 0) tags.push({
|
3413
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3414
|
+
results: [],
|
3415
|
+
idx: tags.length
|
3416
|
+
});
|
3417
|
+
|
3418
|
+
return [
|
3419
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3420
|
+
...generate(scope, message),
|
3421
|
+
...getNodeType(scope, message),
|
3422
|
+
[ Opcodes.throw, tags[0].idx ]
|
3423
|
+
];
|
3424
|
+
}
|
3425
|
+
|
3426
|
+
if (exceptionMode === 'partial') {
|
3427
|
+
let message = decl.argument, constructor = null;
|
3428
|
+
|
3429
|
+
// support `throw (new)? Error(...)`
|
3430
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3431
|
+
constructor = decl.argument.callee.name;
|
3432
|
+
message = decl.argument.arguments[0];
|
3433
|
+
}
|
3434
|
+
|
3435
|
+
message ??= DEFAULT_VALUE;
|
3436
|
+
|
3437
|
+
if (tags.length === 0) tags.push({
|
3438
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3439
|
+
results: [],
|
3440
|
+
idx: tags.length
|
3441
|
+
});
|
3442
|
+
|
3443
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3444
|
+
|
3445
|
+
scope.exceptions ??= [];
|
3446
|
+
scope.exceptions.push(exceptId);
|
3447
|
+
|
3448
|
+
return [
|
3449
|
+
...number(exceptId, Valtype.i32),
|
3450
|
+
...generate(scope, message),
|
3451
|
+
...getNodeType(scope, message),
|
3452
|
+
[ Opcodes.throw, tags[0].idx ]
|
3453
|
+
];
|
3454
|
+
}
|
3058
3455
|
};
|
3059
3456
|
|
3060
3457
|
const generateTry = (scope, decl) => {
|
@@ -3407,6 +3804,19 @@ const withType = (scope, wasm, type) => [
|
|
3407
3804
|
...setLastType(scope, type)
|
3408
3805
|
];
|
3409
3806
|
|
3807
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3808
|
+
const out = {};
|
3809
|
+
for (const x in bc) {
|
3810
|
+
out[x] = [
|
3811
|
+
...prelude,
|
3812
|
+
...bc[x],
|
3813
|
+
...postlude
|
3814
|
+
];
|
3815
|
+
}
|
3816
|
+
|
3817
|
+
return out;
|
3818
|
+
};
|
3819
|
+
|
3410
3820
|
const generateMember = (scope, decl, _global, _name) => {
|
3411
3821
|
const name = decl.object.name;
|
3412
3822
|
|
@@ -3460,7 +3870,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3460
3870
|
const type = getNodeType(scope, decl.object);
|
3461
3871
|
const known = knownType(scope, type);
|
3462
3872
|
if (known != null) {
|
3463
|
-
if (
|
3873
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3464
3874
|
...generate(scope, decl.object),
|
3465
3875
|
Opcodes.i32_to_u,
|
3466
3876
|
|
@@ -3472,7 +3882,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3472
3882
|
}
|
3473
3883
|
|
3474
3884
|
return [
|
3475
|
-
...
|
3885
|
+
...getNodeType(scope, decl.object),
|
3886
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3887
|
+
[ Opcodes.i32_and ],
|
3476
3888
|
[ Opcodes.if, valtypeBinary ],
|
3477
3889
|
...generate(scope, decl.object),
|
3478
3890
|
Opcodes.i32_to_u,
|
@@ -3489,7 +3901,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3489
3901
|
}
|
3490
3902
|
|
3491
3903
|
// todo: generate this array procedurally during builtinFuncs creation
|
3492
|
-
if (['size', 'description'].includes(decl.property.name)) {
|
3904
|
+
if (['size', 'description', 'byteLength'].includes(decl.property.name)) {
|
3493
3905
|
const bc = {};
|
3494
3906
|
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
3495
3907
|
|
@@ -3521,7 +3933,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3521
3933
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3522
3934
|
// hack: this is naughty and will break things!
|
3523
3935
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3524
|
-
|
3936
|
+
|
3937
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3938
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3525
3939
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3526
3940
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3527
3941
|
rawElements: new Array(0)
|
@@ -3595,6 +4009,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3595
4009
|
...setLastType(scope, TYPES.bytestring)
|
3596
4010
|
],
|
3597
4011
|
|
4012
|
+
...wrapBC({
|
4013
|
+
[TYPES.uint8array]: [
|
4014
|
+
[ Opcodes.i32_add ],
|
4015
|
+
|
4016
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
4017
|
+
Opcodes.i32_from_u
|
4018
|
+
],
|
4019
|
+
[TYPES.uint8clampedarray]: [
|
4020
|
+
[ Opcodes.i32_add ],
|
4021
|
+
|
4022
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
4023
|
+
Opcodes.i32_from_u
|
4024
|
+
],
|
4025
|
+
[TYPES.int8array]: [
|
4026
|
+
[ Opcodes.i32_add ],
|
4027
|
+
|
4028
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
4029
|
+
Opcodes.i32_from
|
4030
|
+
],
|
4031
|
+
[TYPES.uint16array]: [
|
4032
|
+
...number(2, Valtype.i32),
|
4033
|
+
[ Opcodes.i32_mul ],
|
4034
|
+
[ Opcodes.i32_add ],
|
4035
|
+
|
4036
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
4037
|
+
Opcodes.i32_from_u
|
4038
|
+
],
|
4039
|
+
[TYPES.int16array]: [
|
4040
|
+
...number(2, Valtype.i32),
|
4041
|
+
[ Opcodes.i32_mul ],
|
4042
|
+
[ Opcodes.i32_add ],
|
4043
|
+
|
4044
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
4045
|
+
Opcodes.i32_from
|
4046
|
+
],
|
4047
|
+
[TYPES.uint32array]: [
|
4048
|
+
...number(4, Valtype.i32),
|
4049
|
+
[ Opcodes.i32_mul ],
|
4050
|
+
[ Opcodes.i32_add ],
|
4051
|
+
|
4052
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4053
|
+
Opcodes.i32_from_u
|
4054
|
+
],
|
4055
|
+
[TYPES.int32array]: [
|
4056
|
+
...number(4, Valtype.i32),
|
4057
|
+
[ Opcodes.i32_mul ],
|
4058
|
+
[ Opcodes.i32_add ],
|
4059
|
+
|
4060
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4061
|
+
Opcodes.i32_from
|
4062
|
+
],
|
4063
|
+
[TYPES.float32array]: [
|
4064
|
+
...number(4, Valtype.i32),
|
4065
|
+
[ Opcodes.i32_mul ],
|
4066
|
+
[ Opcodes.i32_add ],
|
4067
|
+
|
4068
|
+
[ Opcodes.f32_load, 0, 4 ],
|
4069
|
+
[ Opcodes.f64_promote_f32 ]
|
4070
|
+
],
|
4071
|
+
[TYPES.float64array]: [
|
4072
|
+
...number(8, Valtype.i32),
|
4073
|
+
[ Opcodes.i32_mul ],
|
4074
|
+
[ Opcodes.i32_add ],
|
4075
|
+
|
4076
|
+
[ Opcodes.f64_load, 0, 4 ]
|
4077
|
+
],
|
4078
|
+
}, {
|
4079
|
+
prelude: [
|
4080
|
+
...object,
|
4081
|
+
Opcodes.i32_to_u,
|
4082
|
+
...property,
|
4083
|
+
Opcodes.i32_to_u
|
4084
|
+
],
|
4085
|
+
postlude: setLastType(scope, TYPES.number)
|
4086
|
+
}),
|
4087
|
+
|
3598
4088
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3599
4089
|
});
|
3600
4090
|
};
|
@@ -3617,7 +4107,7 @@ const objectHack = node => {
|
|
3617
4107
|
if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
|
3618
4108
|
|
3619
4109
|
// if .name or .length, give up (hack within a hack!)
|
3620
|
-
if (['name', 'length', 'size', 'description'].includes(node.property.name)) {
|
4110
|
+
if (['name', 'length', 'size', 'description', 'byteLength'].includes(node.property.name)) {
|
3621
4111
|
node.object = objectHack(node.object);
|
3622
4112
|
return;
|
3623
4113
|
}
|
@@ -3772,7 +4262,7 @@ const internalConstrs = {
|
|
3772
4262
|
|
3773
4263
|
// todo: check in wasm instead of here
|
3774
4264
|
const literalValue = arg.value ?? 0;
|
3775
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
4265
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3776
4266
|
|
3777
4267
|
return [
|
3778
4268
|
...out,
|