porffor 0.17.0-048c6f2ee → 0.17.0-05070e1f0
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 +42 -0
- package/compiler/builtins.js +25 -0
- package/compiler/codegen.js +473 -29
- package/compiler/generated_builtins.js +316 -134
- package/compiler/pgo.js +9 -1
- package/compiler/types.js +31 -5
- package/compiler/wasmSpec.js +2 -0
- package/compiler/wrap.js +52 -5
- package/package.json +1 -1
- package/rhemyn/README.md +7 -4
- package/rhemyn/compile.js +138 -66
- 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
|
|
@@ -291,12 +294,13 @@ const generateIdent = (scope, decl) => {
|
|
291
294
|
return wasm.slice();
|
292
295
|
}
|
293
296
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
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
|
+
// }
|
298
302
|
|
299
|
-
if (isExistingProtoFunc(name)) {
|
303
|
+
if (isExistingProtoFunc(name) || Object.hasOwn(internalConstrs, name) || Object.hasOwn(builtinFuncs, name)) {
|
300
304
|
// todo: return an actual something
|
301
305
|
return number(1);
|
302
306
|
}
|
@@ -615,11 +619,14 @@ const compareStrings = (scope, left, right, bytestrings = false) => {
|
|
615
619
|
};
|
616
620
|
|
617
621
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
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
|
+
];
|
623
630
|
|
624
631
|
// todo/perf: use knownType and custom bytecode here instead of typeSwitch
|
625
632
|
|
@@ -975,6 +982,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
975
982
|
};
|
976
983
|
|
977
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
|
+
|
978
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);
|
979
1013
|
|
980
1014
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1281,7 +1315,7 @@ const getNodeType = (scope, node) => {
|
|
1281
1315
|
}
|
1282
1316
|
|
1283
1317
|
if (node.type === 'BinaryExpression') {
|
1284
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1318
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1285
1319
|
if (node.operator !== '+') return TYPES.number;
|
1286
1320
|
|
1287
1321
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1314,7 +1348,7 @@ const getNodeType = (scope, node) => {
|
|
1314
1348
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1315
1349
|
if (objectKnownType != null) {
|
1316
1350
|
if (name === 'length') {
|
1317
|
-
if (
|
1351
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1318
1352
|
else return TYPES.undefined;
|
1319
1353
|
}
|
1320
1354
|
|
@@ -1386,9 +1420,9 @@ const countLeftover = wasm => {
|
|
1386
1420
|
|
1387
1421
|
if (depth === 0)
|
1388
1422
|
if ([Opcodes.throw, Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
|
1389
|
-
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)) {}
|
1390
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++;
|
1391
|
-
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;
|
1392
1426
|
else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
|
1393
1427
|
else if (inst[0] === Opcodes.return) count = 0;
|
1394
1428
|
else if (inst[0] === Opcodes.call) {
|
@@ -1426,6 +1460,18 @@ const generateExp = (scope, decl) => {
|
|
1426
1460
|
return out;
|
1427
1461
|
};
|
1428
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
|
+
|
1429
1475
|
const CTArrayUtil = {
|
1430
1476
|
getLengthI32: pointer => [
|
1431
1477
|
...number(0, Valtype.i32),
|
@@ -2014,7 +2060,7 @@ const unhackName = name => {
|
|
2014
2060
|
|
2015
2061
|
const knownType = (scope, type) => {
|
2016
2062
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2017
|
-
return type[0]
|
2063
|
+
return read_signedLEB128(type[0].slice(1));
|
2018
2064
|
}
|
2019
2065
|
|
2020
2066
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2301,11 +2347,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2301
2347
|
const { type, name } = decl.left;
|
2302
2348
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2303
2349
|
|
2304
|
-
if (type === 'ObjectPattern') {
|
2305
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2306
|
-
return generate(scope, decl.right);
|
2307
|
-
}
|
2308
|
-
|
2309
2350
|
if (isFuncType(decl.right.type)) {
|
2310
2351
|
// hack for a = function () { ... }
|
2311
2352
|
decl.right.id = { name };
|
@@ -2378,10 +2419,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2378
2419
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2379
2420
|
], getNodeType(scope, decl.right), false, name, true)),
|
2380
2421
|
[ Opcodes.local_tee, newValueTmp ],
|
2381
|
-
|
2382
2422
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2383
2423
|
],
|
2384
2424
|
|
2425
|
+
...wrapBC({
|
2426
|
+
[TYPES.uint8array]: [
|
2427
|
+
[ Opcodes.i32_add ],
|
2428
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2429
|
+
|
2430
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2431
|
+
[ Opcodes.local_get, pointerTmp ],
|
2432
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2433
|
+
Opcodes.i32_from_u
|
2434
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2435
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2436
|
+
|
2437
|
+
Opcodes.i32_to_u,
|
2438
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2439
|
+
],
|
2440
|
+
[TYPES.uint8clampedarray]: [
|
2441
|
+
[ Opcodes.i32_add ],
|
2442
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2443
|
+
|
2444
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2445
|
+
[ Opcodes.local_get, pointerTmp ],
|
2446
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2447
|
+
Opcodes.i32_from_u
|
2448
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2449
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2450
|
+
|
2451
|
+
...number(0),
|
2452
|
+
[ Opcodes.f64_max ],
|
2453
|
+
...number(255),
|
2454
|
+
[ Opcodes.f64_min ],
|
2455
|
+
Opcodes.i32_to_u,
|
2456
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2457
|
+
],
|
2458
|
+
[TYPES.int8array]: [
|
2459
|
+
[ Opcodes.i32_add ],
|
2460
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2461
|
+
|
2462
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2463
|
+
[ Opcodes.local_get, pointerTmp ],
|
2464
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2465
|
+
Opcodes.i32_from
|
2466
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2467
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2468
|
+
|
2469
|
+
Opcodes.i32_to,
|
2470
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2471
|
+
],
|
2472
|
+
[TYPES.uint16array]: [
|
2473
|
+
...number(2, Valtype.i32),
|
2474
|
+
[ Opcodes.i32_mul ],
|
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_load16_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
|
+
Opcodes.i32_to_u,
|
2486
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2487
|
+
],
|
2488
|
+
[TYPES.int16array]: [
|
2489
|
+
...number(2, Valtype.i32),
|
2490
|
+
[ Opcodes.i32_mul ],
|
2491
|
+
[ Opcodes.i32_add ],
|
2492
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2493
|
+
|
2494
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2495
|
+
[ Opcodes.local_get, pointerTmp ],
|
2496
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2497
|
+
Opcodes.i32_from
|
2498
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2499
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2500
|
+
|
2501
|
+
Opcodes.i32_to,
|
2502
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2503
|
+
],
|
2504
|
+
[TYPES.uint32array]: [
|
2505
|
+
...number(4, Valtype.i32),
|
2506
|
+
[ Opcodes.i32_mul ],
|
2507
|
+
[ Opcodes.i32_add ],
|
2508
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2509
|
+
|
2510
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2511
|
+
[ Opcodes.local_get, pointerTmp ],
|
2512
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2513
|
+
Opcodes.i32_from_u
|
2514
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2515
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2516
|
+
|
2517
|
+
Opcodes.i32_to_u,
|
2518
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2519
|
+
],
|
2520
|
+
[TYPES.int32array]: [
|
2521
|
+
...number(4, Valtype.i32),
|
2522
|
+
[ Opcodes.i32_mul ],
|
2523
|
+
[ Opcodes.i32_add ],
|
2524
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2525
|
+
|
2526
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2527
|
+
[ Opcodes.local_get, pointerTmp ],
|
2528
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2529
|
+
Opcodes.i32_from
|
2530
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2531
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2532
|
+
|
2533
|
+
Opcodes.i32_to,
|
2534
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2535
|
+
],
|
2536
|
+
[TYPES.float32array]: [
|
2537
|
+
...number(4, Valtype.i32),
|
2538
|
+
[ Opcodes.i32_mul ],
|
2539
|
+
[ Opcodes.i32_add ],
|
2540
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2541
|
+
|
2542
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2543
|
+
[ Opcodes.local_get, pointerTmp ],
|
2544
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2545
|
+
[ Opcodes.f64_promote_f32 ]
|
2546
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2547
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2548
|
+
|
2549
|
+
[ Opcodes.f32_demote_f64 ],
|
2550
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2551
|
+
],
|
2552
|
+
[TYPES.float64array]: [
|
2553
|
+
...number(8, Valtype.i32),
|
2554
|
+
[ Opcodes.i32_mul ],
|
2555
|
+
[ Opcodes.i32_add ],
|
2556
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2557
|
+
|
2558
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2559
|
+
[ Opcodes.local_get, pointerTmp ],
|
2560
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2561
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2562
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2563
|
+
|
2564
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2565
|
+
],
|
2566
|
+
}, {
|
2567
|
+
prelude: [
|
2568
|
+
...generate(scope, decl.left.object),
|
2569
|
+
Opcodes.i32_to_u,
|
2570
|
+
...generate(scope, decl.left.property),
|
2571
|
+
Opcodes.i32_to_u,
|
2572
|
+
],
|
2573
|
+
postlude: setLastType(scope, TYPES.number)
|
2574
|
+
}),
|
2575
|
+
|
2385
2576
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2386
2577
|
}, Blocktype.void),
|
2387
2578
|
|
@@ -2765,7 +2956,9 @@ const generateForOf = (scope, decl) => {
|
|
2765
2956
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
2766
2957
|
// hack: this is naughty and will break things!
|
2767
2958
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
2768
|
-
|
2959
|
+
|
2960
|
+
const known = knownType(scope, getNodeType(scope, decl.right));
|
2961
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
2769
2962
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
2770
2963
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
2771
2964
|
rawElements: new Array(0)
|
@@ -2813,6 +3006,7 @@ const generateForOf = (scope, decl) => {
|
|
2813
3006
|
[ Opcodes.end ],
|
2814
3007
|
[ Opcodes.end ]
|
2815
3008
|
],
|
3009
|
+
|
2816
3010
|
[TYPES.string]: [
|
2817
3011
|
...setType(scope, leftName, TYPES.string),
|
2818
3012
|
|
@@ -2921,6 +3115,7 @@ const generateForOf = (scope, decl) => {
|
|
2921
3115
|
[ Opcodes.end ],
|
2922
3116
|
[ Opcodes.end ]
|
2923
3117
|
],
|
3118
|
+
|
2924
3119
|
[TYPES.set]: [
|
2925
3120
|
[ Opcodes.loop, Blocktype.void ],
|
2926
3121
|
|
@@ -2959,6 +3154,106 @@ const generateForOf = (scope, decl) => {
|
|
2959
3154
|
[ Opcodes.end ],
|
2960
3155
|
[ Opcodes.end ]
|
2961
3156
|
],
|
3157
|
+
|
3158
|
+
...wrapBC({
|
3159
|
+
[TYPES.uint8array]: [
|
3160
|
+
[ Opcodes.i32_add ],
|
3161
|
+
|
3162
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3163
|
+
Opcodes.i32_from_u
|
3164
|
+
],
|
3165
|
+
[TYPES.uint8clampedarray]: [
|
3166
|
+
[ Opcodes.i32_add ],
|
3167
|
+
|
3168
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3169
|
+
Opcodes.i32_from_u
|
3170
|
+
],
|
3171
|
+
[TYPES.int8array]: [
|
3172
|
+
[ Opcodes.i32_add ],
|
3173
|
+
|
3174
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3175
|
+
Opcodes.i32_from
|
3176
|
+
],
|
3177
|
+
[TYPES.uint16array]: [
|
3178
|
+
...number(2, Valtype.i32),
|
3179
|
+
[ Opcodes.i32_mul ],
|
3180
|
+
[ Opcodes.i32_add ],
|
3181
|
+
|
3182
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3183
|
+
Opcodes.i32_from_u
|
3184
|
+
],
|
3185
|
+
[TYPES.int16array]: [
|
3186
|
+
...number(2, Valtype.i32),
|
3187
|
+
[ Opcodes.i32_mul ],
|
3188
|
+
[ Opcodes.i32_add ],
|
3189
|
+
|
3190
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3191
|
+
Opcodes.i32_from
|
3192
|
+
],
|
3193
|
+
[TYPES.uint32array]: [
|
3194
|
+
...number(4, Valtype.i32),
|
3195
|
+
[ Opcodes.i32_mul ],
|
3196
|
+
[ Opcodes.i32_add ],
|
3197
|
+
|
3198
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3199
|
+
Opcodes.i32_from_u
|
3200
|
+
],
|
3201
|
+
[TYPES.int32array]: [
|
3202
|
+
...number(4, Valtype.i32),
|
3203
|
+
[ Opcodes.i32_mul ],
|
3204
|
+
[ Opcodes.i32_add ],
|
3205
|
+
|
3206
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3207
|
+
Opcodes.i32_from
|
3208
|
+
],
|
3209
|
+
[TYPES.float32array]: [
|
3210
|
+
...number(4, Valtype.i32),
|
3211
|
+
[ Opcodes.i32_mul ],
|
3212
|
+
[ Opcodes.i32_add ],
|
3213
|
+
|
3214
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3215
|
+
[ Opcodes.f64_promote_f32 ]
|
3216
|
+
],
|
3217
|
+
[TYPES.float64array]: [
|
3218
|
+
...number(8, Valtype.i32),
|
3219
|
+
[ Opcodes.i32_mul ],
|
3220
|
+
[ Opcodes.i32_add ],
|
3221
|
+
|
3222
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3223
|
+
],
|
3224
|
+
}, {
|
3225
|
+
prelude: [
|
3226
|
+
...setType(scope, leftName, TYPES.number),
|
3227
|
+
|
3228
|
+
[ Opcodes.loop, Blocktype.void ],
|
3229
|
+
|
3230
|
+
[ Opcodes.local_get, pointer ],
|
3231
|
+
[ Opcodes.local_get, counter ]
|
3232
|
+
],
|
3233
|
+
postlude: [
|
3234
|
+
[ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
|
3235
|
+
|
3236
|
+
[ Opcodes.block, Blocktype.void ],
|
3237
|
+
[ Opcodes.block, Blocktype.void ],
|
3238
|
+
...generate(scope, decl.body),
|
3239
|
+
[ Opcodes.end ],
|
3240
|
+
|
3241
|
+
// increment counter by 1
|
3242
|
+
[ Opcodes.local_get, counter ],
|
3243
|
+
...number(1, Valtype.i32),
|
3244
|
+
[ Opcodes.i32_add ],
|
3245
|
+
[ Opcodes.local_tee, counter ],
|
3246
|
+
|
3247
|
+
// loop if counter != length
|
3248
|
+
[ Opcodes.local_get, length ],
|
3249
|
+
[ Opcodes.i32_ne ],
|
3250
|
+
[ Opcodes.br_if, 1 ],
|
3251
|
+
|
3252
|
+
[ Opcodes.end ],
|
3253
|
+
[ Opcodes.end ]
|
3254
|
+
]
|
3255
|
+
}),
|
3256
|
+
|
2962
3257
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2963
3258
|
}, Blocktype.void));
|
2964
3259
|
|
@@ -3047,13 +3342,14 @@ const generateThrow = (scope, decl) => {
|
|
3047
3342
|
idx: tags.length
|
3048
3343
|
});
|
3049
3344
|
|
3050
|
-
let exceptId = exceptions.
|
3345
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3346
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3051
3347
|
|
3052
3348
|
scope.exceptions ??= [];
|
3053
3349
|
scope.exceptions.push(exceptId);
|
3054
3350
|
|
3055
3351
|
return [
|
3056
|
-
|
3352
|
+
...number(exceptId, Valtype.i32),
|
3057
3353
|
[ Opcodes.throw, tags[0].idx ]
|
3058
3354
|
];
|
3059
3355
|
}
|
@@ -3071,6 +3367,61 @@ const generateThrow = (scope, decl) => {
|
|
3071
3367
|
[ Opcodes.throw, tags[0].idx ]
|
3072
3368
|
];
|
3073
3369
|
}
|
3370
|
+
|
3371
|
+
if (exceptionMode === 'stackest') {
|
3372
|
+
let message = decl.argument, constructor = null;
|
3373
|
+
|
3374
|
+
// support `throw (new)? Error(...)`
|
3375
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3376
|
+
constructor = decl.argument.callee;
|
3377
|
+
message = decl.argument.arguments[0];
|
3378
|
+
}
|
3379
|
+
|
3380
|
+
message ??= DEFAULT_VALUE;
|
3381
|
+
|
3382
|
+
if (tags.length === 0) tags.push({
|
3383
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3384
|
+
results: [],
|
3385
|
+
idx: tags.length
|
3386
|
+
});
|
3387
|
+
|
3388
|
+
return [
|
3389
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3390
|
+
...generate(scope, message),
|
3391
|
+
...getNodeType(scope, message),
|
3392
|
+
[ Opcodes.throw, tags[0].idx ]
|
3393
|
+
];
|
3394
|
+
}
|
3395
|
+
|
3396
|
+
if (exceptionMode === 'partial') {
|
3397
|
+
let message = decl.argument, constructor = null;
|
3398
|
+
|
3399
|
+
// support `throw (new)? Error(...)`
|
3400
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3401
|
+
constructor = decl.argument.callee.name;
|
3402
|
+
message = decl.argument.arguments[0];
|
3403
|
+
}
|
3404
|
+
|
3405
|
+
message ??= DEFAULT_VALUE;
|
3406
|
+
|
3407
|
+
if (tags.length === 0) tags.push({
|
3408
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3409
|
+
results: [],
|
3410
|
+
idx: tags.length
|
3411
|
+
});
|
3412
|
+
|
3413
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3414
|
+
|
3415
|
+
scope.exceptions ??= [];
|
3416
|
+
scope.exceptions.push(exceptId);
|
3417
|
+
|
3418
|
+
return [
|
3419
|
+
...number(exceptId, Valtype.i32),
|
3420
|
+
...generate(scope, message),
|
3421
|
+
...getNodeType(scope, message),
|
3422
|
+
[ Opcodes.throw, tags[0].idx ]
|
3423
|
+
];
|
3424
|
+
}
|
3074
3425
|
};
|
3075
3426
|
|
3076
3427
|
const generateTry = (scope, decl) => {
|
@@ -3423,6 +3774,19 @@ const withType = (scope, wasm, type) => [
|
|
3423
3774
|
...setLastType(scope, type)
|
3424
3775
|
];
|
3425
3776
|
|
3777
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3778
|
+
const out = {};
|
3779
|
+
for (const x in bc) {
|
3780
|
+
out[x] = [
|
3781
|
+
...prelude,
|
3782
|
+
...bc[x],
|
3783
|
+
...postlude
|
3784
|
+
];
|
3785
|
+
}
|
3786
|
+
|
3787
|
+
return out;
|
3788
|
+
};
|
3789
|
+
|
3426
3790
|
const generateMember = (scope, decl, _global, _name) => {
|
3427
3791
|
const name = decl.object.name;
|
3428
3792
|
|
@@ -3476,7 +3840,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3476
3840
|
const type = getNodeType(scope, decl.object);
|
3477
3841
|
const known = knownType(scope, type);
|
3478
3842
|
if (known != null) {
|
3479
|
-
if (
|
3843
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3480
3844
|
...generate(scope, decl.object),
|
3481
3845
|
Opcodes.i32_to_u,
|
3482
3846
|
|
@@ -3488,7 +3852,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3488
3852
|
}
|
3489
3853
|
|
3490
3854
|
return [
|
3491
|
-
...
|
3855
|
+
...getNodeType(scope, decl.object),
|
3856
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3857
|
+
[ Opcodes.i32_and ],
|
3492
3858
|
[ Opcodes.if, valtypeBinary ],
|
3493
3859
|
...generate(scope, decl.object),
|
3494
3860
|
Opcodes.i32_to_u,
|
@@ -3537,7 +3903,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3537
3903
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3538
3904
|
// hack: this is naughty and will break things!
|
3539
3905
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3540
|
-
|
3906
|
+
|
3907
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3908
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3541
3909
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3542
3910
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3543
3911
|
rawElements: new Array(0)
|
@@ -3611,6 +3979,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3611
3979
|
...setLastType(scope, TYPES.bytestring)
|
3612
3980
|
],
|
3613
3981
|
|
3982
|
+
...wrapBC({
|
3983
|
+
[TYPES.uint8array]: [
|
3984
|
+
[ Opcodes.i32_add ],
|
3985
|
+
|
3986
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3987
|
+
Opcodes.i32_from_u
|
3988
|
+
],
|
3989
|
+
[TYPES.uint8clampedarray]: [
|
3990
|
+
[ Opcodes.i32_add ],
|
3991
|
+
|
3992
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3993
|
+
Opcodes.i32_from_u
|
3994
|
+
],
|
3995
|
+
[TYPES.int8array]: [
|
3996
|
+
[ Opcodes.i32_add ],
|
3997
|
+
|
3998
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3999
|
+
Opcodes.i32_from
|
4000
|
+
],
|
4001
|
+
[TYPES.uint16array]: [
|
4002
|
+
...number(2, Valtype.i32),
|
4003
|
+
[ Opcodes.i32_mul ],
|
4004
|
+
[ Opcodes.i32_add ],
|
4005
|
+
|
4006
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
4007
|
+
Opcodes.i32_from_u
|
4008
|
+
],
|
4009
|
+
[TYPES.int16array]: [
|
4010
|
+
...number(2, Valtype.i32),
|
4011
|
+
[ Opcodes.i32_mul ],
|
4012
|
+
[ Opcodes.i32_add ],
|
4013
|
+
|
4014
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
4015
|
+
Opcodes.i32_from
|
4016
|
+
],
|
4017
|
+
[TYPES.uint32array]: [
|
4018
|
+
...number(4, Valtype.i32),
|
4019
|
+
[ Opcodes.i32_mul ],
|
4020
|
+
[ Opcodes.i32_add ],
|
4021
|
+
|
4022
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4023
|
+
Opcodes.i32_from_u
|
4024
|
+
],
|
4025
|
+
[TYPES.int32array]: [
|
4026
|
+
...number(4, Valtype.i32),
|
4027
|
+
[ Opcodes.i32_mul ],
|
4028
|
+
[ Opcodes.i32_add ],
|
4029
|
+
|
4030
|
+
[ Opcodes.i32_load, 0, 4 ],
|
4031
|
+
Opcodes.i32_from
|
4032
|
+
],
|
4033
|
+
[TYPES.float32array]: [
|
4034
|
+
...number(4, Valtype.i32),
|
4035
|
+
[ Opcodes.i32_mul ],
|
4036
|
+
[ Opcodes.i32_add ],
|
4037
|
+
|
4038
|
+
[ Opcodes.f32_load, 0, 4 ],
|
4039
|
+
[ Opcodes.f64_promote_f32 ]
|
4040
|
+
],
|
4041
|
+
[TYPES.float64array]: [
|
4042
|
+
...number(8, Valtype.i32),
|
4043
|
+
[ Opcodes.i32_mul ],
|
4044
|
+
[ Opcodes.i32_add ],
|
4045
|
+
|
4046
|
+
[ Opcodes.f64_load, 0, 4 ]
|
4047
|
+
],
|
4048
|
+
}, {
|
4049
|
+
prelude: [
|
4050
|
+
...object,
|
4051
|
+
Opcodes.i32_to_u,
|
4052
|
+
...property,
|
4053
|
+
Opcodes.i32_to_u
|
4054
|
+
],
|
4055
|
+
postlude: setLastType(scope, TYPES.number)
|
4056
|
+
}),
|
4057
|
+
|
3614
4058
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3615
4059
|
});
|
3616
4060
|
};
|
@@ -3788,7 +4232,7 @@ const internalConstrs = {
|
|
3788
4232
|
|
3789
4233
|
// todo: check in wasm instead of here
|
3790
4234
|
const literalValue = arg.value ?? 0;
|
3791
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
4235
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3792
4236
|
|
3793
4237
|
return [
|
3794
4238
|
...out,
|