porffor 0.17.0-93ba20045 → 0.17.0-99a1a1851
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/README.md +6 -4
- package/compiler/2c.js +28 -11
- package/compiler/builtins/array.ts +51 -9
- package/compiler/builtins/base64.ts +28 -24
- package/compiler/builtins/math.ts +6 -2
- package/compiler/builtins/set.ts +7 -9
- package/compiler/builtins/typedarray.js +96 -0
- package/compiler/builtins.js +25 -0
- package/compiler/codegen.js +559 -65
- package/compiler/generated_builtins.js +2315 -142
- package/compiler/pgo.js +9 -1
- package/compiler/precompile.js +3 -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);
|
@@ -990,6 +1026,7 @@ const asmFuncToAsm = (func, scope) => {
|
|
990
1026
|
idx = funcIndex[n];
|
991
1027
|
}
|
992
1028
|
|
1029
|
+
if (idx == null) throw new Error(`builtin('${n}') failed to find a func (inside ${scope.name})`);
|
993
1030
|
return idx;
|
994
1031
|
}
|
995
1032
|
});
|
@@ -1028,7 +1065,10 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
|
|
1028
1065
|
funcs.push(func);
|
1029
1066
|
funcIndex[name] = func.index;
|
1030
1067
|
|
1031
|
-
if (typeof wasm === 'function')
|
1068
|
+
if (typeof wasm === 'function') {
|
1069
|
+
if (globalThis.precompile) wasm = [];
|
1070
|
+
else wasm = asmFuncToAsm(wasm, func);
|
1071
|
+
}
|
1032
1072
|
|
1033
1073
|
let baseGlobalIdx, i = 0;
|
1034
1074
|
for (const type of globalTypes) {
|
@@ -1279,7 +1319,7 @@ const getNodeType = (scope, node) => {
|
|
1279
1319
|
}
|
1280
1320
|
|
1281
1321
|
if (node.type === 'BinaryExpression') {
|
1282
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1322
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1283
1323
|
if (node.operator !== '+') return TYPES.number;
|
1284
1324
|
|
1285
1325
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1312,7 +1352,7 @@ const getNodeType = (scope, node) => {
|
|
1312
1352
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1313
1353
|
if (objectKnownType != null) {
|
1314
1354
|
if (name === 'length') {
|
1315
|
-
if (
|
1355
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1316
1356
|
else return TYPES.undefined;
|
1317
1357
|
}
|
1318
1358
|
|
@@ -1384,9 +1424,9 @@ const countLeftover = wasm => {
|
|
1384
1424
|
|
1385
1425
|
if (depth === 0)
|
1386
1426
|
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)) {}
|
1427
|
+
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
1428
|
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;
|
1429
|
+
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
1430
|
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1391
1431
|
else if (inst[0] === Opcodes.return) count = 0;
|
1392
1432
|
else if (inst[0] === Opcodes.call) {
|
@@ -1424,6 +1464,18 @@ const generateExp = (scope, decl) => {
|
|
1424
1464
|
return out;
|
1425
1465
|
};
|
1426
1466
|
|
1467
|
+
const generateSequence = (scope, decl) => {
|
1468
|
+
let out = [];
|
1469
|
+
|
1470
|
+
const exprs = decl.expressions;
|
1471
|
+
for (let i = 0; i < exprs.length; i++) {
|
1472
|
+
if (i > 0) disposeLeftover(out);
|
1473
|
+
out.push(...generate(scope, exprs[i]));
|
1474
|
+
}
|
1475
|
+
|
1476
|
+
return out;
|
1477
|
+
};
|
1478
|
+
|
1427
1479
|
const CTArrayUtil = {
|
1428
1480
|
getLengthI32: pointer => [
|
1429
1481
|
...number(0, Valtype.i32),
|
@@ -1542,9 +1594,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1542
1594
|
if (!name && decl.callee.type === 'MemberExpression') {
|
1543
1595
|
// megahack for /regex/.func()
|
1544
1596
|
const funcName = decl.callee.property.name;
|
1545
|
-
if (decl.callee.object.regex &&
|
1597
|
+
if (decl.callee.object.regex && ['test'].includes(funcName)) {
|
1546
1598
|
const regex = decl.callee.object.regex.pattern;
|
1547
|
-
const rhemynName = `regex_${funcName}_${regex}`;
|
1599
|
+
const rhemynName = `regex_${funcName}_${sanitize(regex)}`;
|
1548
1600
|
|
1549
1601
|
if (!funcIndex[rhemynName]) {
|
1550
1602
|
const func = Rhemyn[funcName](regex, currentFuncIndex++, rhemynName);
|
@@ -1565,7 +1617,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1565
1617
|
[ Opcodes.call, idx ],
|
1566
1618
|
Opcodes.i32_from_u,
|
1567
1619
|
|
1568
|
-
...setLastType(scope,
|
1620
|
+
...setLastType(scope, Rhemyn.types[funcName])
|
1569
1621
|
];
|
1570
1622
|
}
|
1571
1623
|
|
@@ -1574,24 +1626,44 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1574
1626
|
target = decl.callee.object;
|
1575
1627
|
}
|
1576
1628
|
|
1577
|
-
|
1578
|
-
|
1629
|
+
if (protoName) {
|
1630
|
+
if (['search'].includes(protoName)) {
|
1631
|
+
const regex = decl.arguments[0]?.regex?.pattern;
|
1632
|
+
if (!regex) return [
|
1633
|
+
// no/bad regex arg, return -1/0 for now
|
1634
|
+
...generate(scope, target),
|
1635
|
+
[ Opcodes.drop ],
|
1579
1636
|
|
1580
|
-
|
1581
|
-
|
1637
|
+
...number(Rhemyn.types[protoName] === TYPES.number ? -1 : 0),
|
1638
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1639
|
+
];
|
1582
1640
|
|
1583
|
-
|
1584
|
-
// generate(scope, decl.callee.object)
|
1641
|
+
const rhemynName = `regex_${protoName}_${sanitize(regex)}`;
|
1585
1642
|
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
// ];
|
1590
|
-
// }
|
1643
|
+
if (!funcIndex[rhemynName]) {
|
1644
|
+
const func = Rhemyn[protoName](regex, currentFuncIndex++, rhemynName);
|
1645
|
+
func.internal = true;
|
1591
1646
|
|
1592
|
-
|
1593
|
-
|
1647
|
+
funcIndex[func.name] = func.index;
|
1648
|
+
funcs.push(func);
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
const idx = funcIndex[rhemynName];
|
1652
|
+
return [
|
1653
|
+
// make string arg
|
1654
|
+
...generate(scope, target),
|
1655
|
+
Opcodes.i32_to_u,
|
1656
|
+
...getNodeType(scope, target),
|
1657
|
+
|
1658
|
+
// call regex func
|
1659
|
+
[ Opcodes.call, idx ],
|
1660
|
+
Opcodes.i32_from,
|
1594
1661
|
|
1662
|
+
...setLastType(scope, Rhemyn.types[protoName])
|
1663
|
+
];
|
1664
|
+
}
|
1665
|
+
|
1666
|
+
const protoBC = {};
|
1595
1667
|
const builtinProtoCands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + protoName));
|
1596
1668
|
|
1597
1669
|
if (!decl._protoInternalCall && builtinProtoCands.length > 0) {
|
@@ -2005,6 +2077,16 @@ const DEFAULT_VALUE = {
|
|
2005
2077
|
name: 'undefined'
|
2006
2078
|
};
|
2007
2079
|
|
2080
|
+
const codeToSanitizedStr = code => {
|
2081
|
+
let out = '';
|
2082
|
+
while (code > 0) {
|
2083
|
+
out += String.fromCharCode(97 + code % 26);
|
2084
|
+
code -= 26;
|
2085
|
+
}
|
2086
|
+
return out;
|
2087
|
+
};
|
2088
|
+
const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
|
2089
|
+
|
2008
2090
|
const unhackName = name => {
|
2009
2091
|
if (name.startsWith('__')) return name.slice(2).replaceAll('_', '.');
|
2010
2092
|
return name;
|
@@ -2012,7 +2094,7 @@ const unhackName = name => {
|
|
2012
2094
|
|
2013
2095
|
const knownType = (scope, type) => {
|
2014
2096
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2015
|
-
return type[0]
|
2097
|
+
return read_signedLEB128(type[0].slice(1));
|
2016
2098
|
}
|
2017
2099
|
|
2018
2100
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2299,11 +2381,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2299
2381
|
const { type, name } = decl.left;
|
2300
2382
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2301
2383
|
|
2302
|
-
if (type === 'ObjectPattern') {
|
2303
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2304
|
-
return generate(scope, decl.right);
|
2305
|
-
}
|
2306
|
-
|
2307
2384
|
if (isFuncType(decl.right.type)) {
|
2308
2385
|
// hack for a = function () { ... }
|
2309
2386
|
decl.right.id = { name };
|
@@ -2376,10 +2453,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2376
2453
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2377
2454
|
], getNodeType(scope, decl.right), false, name, true)),
|
2378
2455
|
[ Opcodes.local_tee, newValueTmp ],
|
2379
|
-
|
2380
2456
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2381
2457
|
],
|
2382
2458
|
|
2459
|
+
...wrapBC({
|
2460
|
+
[TYPES.uint8array]: [
|
2461
|
+
[ Opcodes.i32_add ],
|
2462
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2463
|
+
|
2464
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2465
|
+
[ Opcodes.local_get, pointerTmp ],
|
2466
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2467
|
+
Opcodes.i32_from_u
|
2468
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2469
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2470
|
+
|
2471
|
+
Opcodes.i32_to_u,
|
2472
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2473
|
+
],
|
2474
|
+
[TYPES.uint8clampedarray]: [
|
2475
|
+
[ Opcodes.i32_add ],
|
2476
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2477
|
+
|
2478
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2479
|
+
[ Opcodes.local_get, pointerTmp ],
|
2480
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2481
|
+
Opcodes.i32_from_u
|
2482
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2483
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2484
|
+
|
2485
|
+
...number(0),
|
2486
|
+
[ Opcodes.f64_max ],
|
2487
|
+
...number(255),
|
2488
|
+
[ Opcodes.f64_min ],
|
2489
|
+
Opcodes.i32_to_u,
|
2490
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2491
|
+
],
|
2492
|
+
[TYPES.int8array]: [
|
2493
|
+
[ Opcodes.i32_add ],
|
2494
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2495
|
+
|
2496
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2497
|
+
[ Opcodes.local_get, pointerTmp ],
|
2498
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2499
|
+
Opcodes.i32_from
|
2500
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2501
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2502
|
+
|
2503
|
+
Opcodes.i32_to,
|
2504
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2505
|
+
],
|
2506
|
+
[TYPES.uint16array]: [
|
2507
|
+
...number(2, Valtype.i32),
|
2508
|
+
[ Opcodes.i32_mul ],
|
2509
|
+
[ Opcodes.i32_add ],
|
2510
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2511
|
+
|
2512
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2513
|
+
[ Opcodes.local_get, pointerTmp ],
|
2514
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
2515
|
+
Opcodes.i32_from_u
|
2516
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2517
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2518
|
+
|
2519
|
+
Opcodes.i32_to_u,
|
2520
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2521
|
+
],
|
2522
|
+
[TYPES.int16array]: [
|
2523
|
+
...number(2, Valtype.i32),
|
2524
|
+
[ Opcodes.i32_mul ],
|
2525
|
+
[ Opcodes.i32_add ],
|
2526
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2527
|
+
|
2528
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2529
|
+
[ Opcodes.local_get, pointerTmp ],
|
2530
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2531
|
+
Opcodes.i32_from
|
2532
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2533
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2534
|
+
|
2535
|
+
Opcodes.i32_to,
|
2536
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2537
|
+
],
|
2538
|
+
[TYPES.uint32array]: [
|
2539
|
+
...number(4, Valtype.i32),
|
2540
|
+
[ Opcodes.i32_mul ],
|
2541
|
+
[ Opcodes.i32_add ],
|
2542
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2543
|
+
|
2544
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2545
|
+
[ Opcodes.local_get, pointerTmp ],
|
2546
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2547
|
+
Opcodes.i32_from_u
|
2548
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2549
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2550
|
+
|
2551
|
+
Opcodes.i32_to_u,
|
2552
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2553
|
+
],
|
2554
|
+
[TYPES.int32array]: [
|
2555
|
+
...number(4, Valtype.i32),
|
2556
|
+
[ Opcodes.i32_mul ],
|
2557
|
+
[ Opcodes.i32_add ],
|
2558
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2559
|
+
|
2560
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2561
|
+
[ Opcodes.local_get, pointerTmp ],
|
2562
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2563
|
+
Opcodes.i32_from
|
2564
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2565
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2566
|
+
|
2567
|
+
Opcodes.i32_to,
|
2568
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2569
|
+
],
|
2570
|
+
[TYPES.float32array]: [
|
2571
|
+
...number(4, Valtype.i32),
|
2572
|
+
[ Opcodes.i32_mul ],
|
2573
|
+
[ Opcodes.i32_add ],
|
2574
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2575
|
+
|
2576
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2577
|
+
[ Opcodes.local_get, pointerTmp ],
|
2578
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2579
|
+
[ Opcodes.f64_promote_f32 ]
|
2580
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2581
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2582
|
+
|
2583
|
+
[ Opcodes.f32_demote_f64 ],
|
2584
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2585
|
+
],
|
2586
|
+
[TYPES.float64array]: [
|
2587
|
+
...number(8, Valtype.i32),
|
2588
|
+
[ Opcodes.i32_mul ],
|
2589
|
+
[ Opcodes.i32_add ],
|
2590
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2591
|
+
|
2592
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2593
|
+
[ Opcodes.local_get, pointerTmp ],
|
2594
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2595
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2596
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2597
|
+
|
2598
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2599
|
+
],
|
2600
|
+
}, {
|
2601
|
+
prelude: [
|
2602
|
+
...generate(scope, decl.left.object),
|
2603
|
+
Opcodes.i32_to_u,
|
2604
|
+
...generate(scope, decl.left.property),
|
2605
|
+
Opcodes.i32_to_u,
|
2606
|
+
],
|
2607
|
+
postlude: setLastType(scope, TYPES.number)
|
2608
|
+
}),
|
2609
|
+
|
2383
2610
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2384
2611
|
}, Blocktype.void),
|
2385
2612
|
|
@@ -2763,7 +2990,9 @@ const generateForOf = (scope, decl) => {
|
|
2763
2990
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2764
2991
|
// hack: this is naughty and will break things!
|
2765
2992
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2766
|
-
|
2993
|
+
|
2994
|
+
const known = knownType(scope, getNodeType(scope, decl.right));
|
2995
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
2767
2996
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2768
2997
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2769
2998
|
rawElements: new Array(0)
|
@@ -2811,6 +3040,7 @@ const generateForOf = (scope, decl) => {
|
|
2811
3040
|
[ Opcodes.end ],
|
2812
3041
|
[ Opcodes.end ]
|
2813
3042
|
],
|
3043
|
+
|
2814
3044
|
[TYPES.string]: [
|
2815
3045
|
...setType(scope, leftName, TYPES.string),
|
2816
3046
|
|
@@ -2919,6 +3149,7 @@ const generateForOf = (scope, decl) => {
|
|
2919
3149
|
[ Opcodes.end ],
|
2920
3150
|
[ Opcodes.end ]
|
2921
3151
|
],
|
3152
|
+
|
2922
3153
|
[TYPES.set]: [
|
2923
3154
|
[ Opcodes.loop, Blocktype.void ],
|
2924
3155
|
|
@@ -2957,6 +3188,106 @@ const generateForOf = (scope, decl) => {
|
|
2957
3188
|
[ Opcodes.end ],
|
2958
3189
|
[ Opcodes.end ]
|
2959
3190
|
],
|
3191
|
+
|
3192
|
+
...wrapBC({
|
3193
|
+
[TYPES.uint8array]: [
|
3194
|
+
[ Opcodes.i32_add ],
|
3195
|
+
|
3196
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3197
|
+
Opcodes.i32_from_u
|
3198
|
+
],
|
3199
|
+
[TYPES.uint8clampedarray]: [
|
3200
|
+
[ Opcodes.i32_add ],
|
3201
|
+
|
3202
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3203
|
+
Opcodes.i32_from_u
|
3204
|
+
],
|
3205
|
+
[TYPES.int8array]: [
|
3206
|
+
[ Opcodes.i32_add ],
|
3207
|
+
|
3208
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3209
|
+
Opcodes.i32_from
|
3210
|
+
],
|
3211
|
+
[TYPES.uint16array]: [
|
3212
|
+
...number(2, Valtype.i32),
|
3213
|
+
[ Opcodes.i32_mul ],
|
3214
|
+
[ Opcodes.i32_add ],
|
3215
|
+
|
3216
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3217
|
+
Opcodes.i32_from_u
|
3218
|
+
],
|
3219
|
+
[TYPES.int16array]: [
|
3220
|
+
...number(2, Valtype.i32),
|
3221
|
+
[ Opcodes.i32_mul ],
|
3222
|
+
[ Opcodes.i32_add ],
|
3223
|
+
|
3224
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3225
|
+
Opcodes.i32_from
|
3226
|
+
],
|
3227
|
+
[TYPES.uint32array]: [
|
3228
|
+
...number(4, Valtype.i32),
|
3229
|
+
[ Opcodes.i32_mul ],
|
3230
|
+
[ Opcodes.i32_add ],
|
3231
|
+
|
3232
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3233
|
+
Opcodes.i32_from_u
|
3234
|
+
],
|
3235
|
+
[TYPES.int32array]: [
|
3236
|
+
...number(4, Valtype.i32),
|
3237
|
+
[ Opcodes.i32_mul ],
|
3238
|
+
[ Opcodes.i32_add ],
|
3239
|
+
|
3240
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3241
|
+
Opcodes.i32_from
|
3242
|
+
],
|
3243
|
+
[TYPES.float32array]: [
|
3244
|
+
...number(4, Valtype.i32),
|
3245
|
+
[ Opcodes.i32_mul ],
|
3246
|
+
[ Opcodes.i32_add ],
|
3247
|
+
|
3248
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3249
|
+
[ Opcodes.f64_promote_f32 ]
|
3250
|
+
],
|
3251
|
+
[TYPES.float64array]: [
|
3252
|
+
...number(8, Valtype.i32),
|
3253
|
+
[ Opcodes.i32_mul ],
|
3254
|
+
[ Opcodes.i32_add ],
|
3255
|
+
|
3256
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3257
|
+
],
|
3258
|
+
}, {
|
3259
|
+
prelude: [
|
3260
|
+
...setType(scope, leftName, TYPES.number),
|
3261
|
+
|
3262
|
+
[ Opcodes.loop, Blocktype.void ],
|
3263
|
+
|
3264
|
+
[ Opcodes.local_get, pointer ],
|
3265
|
+
[ Opcodes.local_get, counter ]
|
3266
|
+
],
|
3267
|
+
postlude: [
|
3268
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3269
|
+
|
3270
|
+
[ Opcodes.block, Blocktype.void ],
|
3271
|
+
[ Opcodes.block, Blocktype.void ],
|
3272
|
+
...generate(scope, decl.body),
|
3273
|
+
[ Opcodes.end ],
|
3274
|
+
|
3275
|
+
// increment counter by 1
|
3276
|
+
[ Opcodes.local_get, counter ],
|
3277
|
+
...number(1, Valtype.i32),
|
3278
|
+
[ Opcodes.i32_add ],
|
3279
|
+
[ Opcodes.local_tee, counter ],
|
3280
|
+
|
3281
|
+
// loop if counter != length
|
3282
|
+
[ Opcodes.local_get, length ],
|
3283
|
+
[ Opcodes.i32_ne ],
|
3284
|
+
[ Opcodes.br_if, 1 ],
|
3285
|
+
|
3286
|
+
[ Opcodes.end ],
|
3287
|
+
[ Opcodes.end ]
|
3288
|
+
]
|
3289
|
+
}),
|
3290
|
+
|
2960
3291
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2961
3292
|
}, Blocktype.void));
|
2962
3293
|
|
@@ -3029,32 +3360,102 @@ const generateLabel = (scope, decl) => {
|
|
3029
3360
|
const generateThrow = (scope, decl) => {
|
3030
3361
|
scope.throws = true;
|
3031
3362
|
|
3032
|
-
|
3363
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
3364
|
+
if (exceptionMode === 'lut') {
|
3365
|
+
let message = decl.argument.value, constructor = null;
|
3366
|
+
|
3367
|
+
// support `throw (new)? Error(...)`
|
3368
|
+
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
3369
|
+
constructor = decl.argument.callee.name;
|
3370
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
3371
|
+
}
|
3372
|
+
|
3373
|
+
if (tags.length === 0) tags.push({
|
3374
|
+
params: [ Valtype.i32 ],
|
3375
|
+
results: [],
|
3376
|
+
idx: tags.length
|
3377
|
+
});
|
3378
|
+
|
3379
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3380
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3381
|
+
|
3382
|
+
scope.exceptions ??= [];
|
3383
|
+
scope.exceptions.push(exceptId);
|
3384
|
+
|
3385
|
+
return [
|
3386
|
+
...number(exceptId, Valtype.i32),
|
3387
|
+
[ Opcodes.throw, tags[0].idx ]
|
3388
|
+
];
|
3389
|
+
}
|
3390
|
+
|
3391
|
+
if (exceptionMode === 'stack') {
|
3392
|
+
if (tags.length === 0) tags.push({
|
3393
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
3394
|
+
results: [],
|
3395
|
+
idx: tags.length
|
3396
|
+
});
|
3033
3397
|
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3398
|
+
return [
|
3399
|
+
...generate(scope, decl.argument),
|
3400
|
+
...getNodeType(scope, decl.argument),
|
3401
|
+
[ Opcodes.throw, tags[0].idx ]
|
3402
|
+
];
|
3038
3403
|
}
|
3039
3404
|
|
3040
|
-
if (
|
3041
|
-
|
3042
|
-
results: [],
|
3043
|
-
idx: tags.length
|
3044
|
-
});
|
3405
|
+
if (exceptionMode === 'stackest') {
|
3406
|
+
let message = decl.argument, constructor = null;
|
3045
3407
|
|
3046
|
-
|
3047
|
-
|
3408
|
+
// support `throw (new)? Error(...)`
|
3409
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3410
|
+
constructor = decl.argument.callee;
|
3411
|
+
message = decl.argument.arguments[0];
|
3412
|
+
}
|
3048
3413
|
|
3049
|
-
|
3050
|
-
scope.exceptions.push(exceptId);
|
3414
|
+
message ??= DEFAULT_VALUE;
|
3051
3415
|
|
3052
|
-
|
3416
|
+
if (tags.length === 0) tags.push({
|
3417
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3418
|
+
results: [],
|
3419
|
+
idx: tags.length
|
3420
|
+
});
|
3053
3421
|
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3422
|
+
return [
|
3423
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3424
|
+
...generate(scope, message),
|
3425
|
+
...getNodeType(scope, message),
|
3426
|
+
[ Opcodes.throw, tags[0].idx ]
|
3427
|
+
];
|
3428
|
+
}
|
3429
|
+
|
3430
|
+
if (exceptionMode === 'partial') {
|
3431
|
+
let message = decl.argument, constructor = null;
|
3432
|
+
|
3433
|
+
// support `throw (new)? Error(...)`
|
3434
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3435
|
+
constructor = decl.argument.callee.name;
|
3436
|
+
message = decl.argument.arguments[0];
|
3437
|
+
}
|
3438
|
+
|
3439
|
+
message ??= DEFAULT_VALUE;
|
3440
|
+
|
3441
|
+
if (tags.length === 0) tags.push({
|
3442
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3443
|
+
results: [],
|
3444
|
+
idx: tags.length
|
3445
|
+
});
|
3446
|
+
|
3447
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3448
|
+
|
3449
|
+
scope.exceptions ??= [];
|
3450
|
+
scope.exceptions.push(exceptId);
|
3451
|
+
|
3452
|
+
return [
|
3453
|
+
...number(exceptId, Valtype.i32),
|
3454
|
+
...generate(scope, message),
|
3455
|
+
...getNodeType(scope, message),
|
3456
|
+
[ Opcodes.throw, tags[0].idx ]
|
3457
|
+
];
|
3458
|
+
}
|
3058
3459
|
};
|
3059
3460
|
|
3060
3461
|
const generateTry = (scope, decl) => {
|
@@ -3407,6 +3808,19 @@ const withType = (scope, wasm, type) => [
|
|
3407
3808
|
...setLastType(scope, type)
|
3408
3809
|
];
|
3409
3810
|
|
3811
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3812
|
+
const out = {};
|
3813
|
+
for (const x in bc) {
|
3814
|
+
out[x] = [
|
3815
|
+
...prelude,
|
3816
|
+
...bc[x],
|
3817
|
+
...postlude
|
3818
|
+
];
|
3819
|
+
}
|
3820
|
+
|
3821
|
+
return out;
|
3822
|
+
};
|
3823
|
+
|
3410
3824
|
const generateMember = (scope, decl, _global, _name) => {
|
3411
3825
|
const name = decl.object.name;
|
3412
3826
|
|
@@ -3460,7 +3874,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3460
3874
|
const type = getNodeType(scope, decl.object);
|
3461
3875
|
const known = knownType(scope, type);
|
3462
3876
|
if (known != null) {
|
3463
|
-
if (
|
3877
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3464
3878
|
...generate(scope, decl.object),
|
3465
3879
|
Opcodes.i32_to_u,
|
3466
3880
|
|
@@ -3472,7 +3886,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3472
3886
|
}
|
3473
3887
|
|
3474
3888
|
return [
|
3475
|
-
...
|
3889
|
+
...getNodeType(scope, decl.object),
|
3890
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3891
|
+
[ Opcodes.i32_and ],
|
3476
3892
|
[ Opcodes.if, valtypeBinary ],
|
3477
3893
|
...generate(scope, decl.object),
|
3478
3894
|
Opcodes.i32_to_u,
|
@@ -3489,7 +3905,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3489
3905
|
}
|
3490
3906
|
|
3491
3907
|
// todo: generate this array procedurally during builtinFuncs creation
|
3492
|
-
if (['size', 'description'].includes(decl.property.name)) {
|
3908
|
+
if (['size', 'description', 'byteLength'].includes(decl.property.name)) {
|
3493
3909
|
const bc = {};
|
3494
3910
|
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
3495
3911
|
|
@@ -3521,7 +3937,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3521
3937
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3522
3938
|
// hack: this is naughty and will break things!
|
3523
3939
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3524
|
-
|
3940
|
+
|
3941
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3942
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3525
3943
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3526
3944
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3527
3945
|
rawElements: new Array(0)
|
@@ -3595,6 +4013,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3595
4013
|
...setLastType(scope, TYPES.bytestring)
|
3596
4014
|
],
|
3597
4015
|
|
4016
|
+
...wrapBC({
|
4017
|
+
[TYPES.uint8array]: [
|
4018
|
+
[ Opcodes.i32_add ],
|
4019
|
+
|
4020
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
4021
|
+
Opcodes.i32_from_u
|
4022
|
+
],
|
4023
|
+
[TYPES.uint8clampedarray]: [
|
4024
|
+
[ Opcodes.i32_add ],
|
4025
|
+
|
4026
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
4027
|
+
Opcodes.i32_from_u
|
4028
|
+
],
|
4029
|
+
[TYPES.int8array]: [
|
4030
|
+
[ Opcodes.i32_add ],
|
4031
|
+
|
4032
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
4033
|
+
Opcodes.i32_from
|
4034
|
+
],
|
4035
|
+
[TYPES.uint16array]: [
|
4036
|
+
...number(2, Valtype.i32),
|
4037
|
+
[ Opcodes.i32_mul ],
|
4038
|
+
[ Opcodes.i32_add ],
|
4039
|
+
|
4040
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
4041
|
+
Opcodes.i32_from_u
|
4042
|
+
],
|
4043
|
+
[TYPES.int16array]: [
|
4044
|
+
...number(2, Valtype.i32),
|
4045
|
+
[ Opcodes.i32_mul ],
|
4046
|
+
[ Opcodes.i32_add ],
|
4047
|
+
|
4048
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
4049
|
+
Opcodes.i32_from
|
4050
|
+
],
|
4051
|
+
[TYPES.uint32array]: [
|
4052
|
+
...number(4, Valtype.i32),
|
4053
|
+
[ Opcodes.i32_mul ],
|
4054
|
+
[ Opcodes.i32_add ],
|
4055
|
+
|
4056
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4057
|
+
Opcodes.i32_from_u
|
4058
|
+
],
|
4059
|
+
[TYPES.int32array]: [
|
4060
|
+
...number(4, Valtype.i32),
|
4061
|
+
[ Opcodes.i32_mul ],
|
4062
|
+
[ Opcodes.i32_add ],
|
4063
|
+
|
4064
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4065
|
+
Opcodes.i32_from
|
4066
|
+
],
|
4067
|
+
[TYPES.float32array]: [
|
4068
|
+
...number(4, Valtype.i32),
|
4069
|
+
[ Opcodes.i32_mul ],
|
4070
|
+
[ Opcodes.i32_add ],
|
4071
|
+
|
4072
|
+
[ Opcodes.f32_load, 0, 4 ],
|
4073
|
+
[ Opcodes.f64_promote_f32 ]
|
4074
|
+
],
|
4075
|
+
[TYPES.float64array]: [
|
4076
|
+
...number(8, Valtype.i32),
|
4077
|
+
[ Opcodes.i32_mul ],
|
4078
|
+
[ Opcodes.i32_add ],
|
4079
|
+
|
4080
|
+
[ Opcodes.f64_load, 0, 4 ]
|
4081
|
+
],
|
4082
|
+
}, {
|
4083
|
+
prelude: [
|
4084
|
+
...object,
|
4085
|
+
Opcodes.i32_to_u,
|
4086
|
+
...property,
|
4087
|
+
Opcodes.i32_to_u
|
4088
|
+
],
|
4089
|
+
postlude: setLastType(scope, TYPES.number)
|
4090
|
+
}),
|
4091
|
+
|
3598
4092
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3599
4093
|
});
|
3600
4094
|
};
|
@@ -3617,7 +4111,7 @@ const objectHack = node => {
|
|
3617
4111
|
if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
|
3618
4112
|
|
3619
4113
|
// if .name or .length, give up (hack within a hack!)
|
3620
|
-
if (['name', 'length', 'size', 'description'].includes(node.property.name)) {
|
4114
|
+
if (['name', 'length', 'size', 'description', 'byteLength'].includes(node.property.name)) {
|
3621
4115
|
node.object = objectHack(node.object);
|
3622
4116
|
return;
|
3623
4117
|
}
|
@@ -3772,7 +4266,7 @@ const internalConstrs = {
|
|
3772
4266
|
|
3773
4267
|
// todo: check in wasm instead of here
|
3774
4268
|
const literalValue = arg.value ?? 0;
|
3775
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
4269
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3776
4270
|
|
3777
4271
|
return [
|
3778
4272
|
...out,
|