porffor 0.17.0-bf4206d7b → 0.17.0-f43ba190c
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 +7 -9
- package/compiler/builtins/typedarray.js +42 -0
- package/compiler/builtins.js +14 -0
- package/compiler/codegen.js +400 -43
- package/compiler/generated_builtins.js +313 -121
- 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/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
|
|
@@ -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),
|
@@ -2012,7 +2060,7 @@ const unhackName = name => {
|
|
2012
2060
|
|
2013
2061
|
const knownType = (scope, type) => {
|
2014
2062
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2015
|
-
return type[0]
|
2063
|
+
return read_signedLEB128(type[0].slice(1));
|
2016
2064
|
}
|
2017
2065
|
|
2018
2066
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2299,11 +2347,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2299
2347
|
const { type, name } = decl.left;
|
2300
2348
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2301
2349
|
|
2302
|
-
if (type === 'ObjectPattern') {
|
2303
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2304
|
-
return generate(scope, decl.right);
|
2305
|
-
}
|
2306
|
-
|
2307
2350
|
if (isFuncType(decl.right.type)) {
|
2308
2351
|
// hack for a = function () { ... }
|
2309
2352
|
decl.right.id = { name };
|
@@ -2376,10 +2419,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2376
2419
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2377
2420
|
], getNodeType(scope, decl.right), false, name, true)),
|
2378
2421
|
[ Opcodes.local_tee, newValueTmp ],
|
2379
|
-
|
2380
2422
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2381
2423
|
],
|
2382
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
|
+
|
2383
2576
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2384
2577
|
}, Blocktype.void),
|
2385
2578
|
|
@@ -2957,6 +3150,7 @@ const generateForOf = (scope, decl) => {
|
|
2957
3150
|
[ Opcodes.end ],
|
2958
3151
|
[ Opcodes.end ]
|
2959
3152
|
],
|
3153
|
+
// todo: typed arrays
|
2960
3154
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2961
3155
|
}, Blocktype.void));
|
2962
3156
|
|
@@ -3029,32 +3223,102 @@ const generateLabel = (scope, decl) => {
|
|
3029
3223
|
const generateThrow = (scope, decl) => {
|
3030
3224
|
scope.throws = true;
|
3031
3225
|
|
3032
|
-
|
3226
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
3227
|
+
if (exceptionMode === 'lut') {
|
3228
|
+
let message = decl.argument.value, constructor = null;
|
3229
|
+
|
3230
|
+
// support `throw (new)? Error(...)`
|
3231
|
+
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
3232
|
+
constructor = decl.argument.callee.name;
|
3233
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
3234
|
+
}
|
3235
|
+
|
3236
|
+
if (tags.length === 0) tags.push({
|
3237
|
+
params: [ Valtype.i32 ],
|
3238
|
+
results: [],
|
3239
|
+
idx: tags.length
|
3240
|
+
});
|
3033
3241
|
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3242
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3243
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3244
|
+
|
3245
|
+
scope.exceptions ??= [];
|
3246
|
+
scope.exceptions.push(exceptId);
|
3247
|
+
|
3248
|
+
return [
|
3249
|
+
...number(exceptId, Valtype.i32),
|
3250
|
+
[ Opcodes.throw, tags[0].idx ]
|
3251
|
+
];
|
3038
3252
|
}
|
3039
3253
|
|
3040
|
-
if (
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3254
|
+
if (exceptionMode === 'stack') {
|
3255
|
+
if (tags.length === 0) tags.push({
|
3256
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
3257
|
+
results: [],
|
3258
|
+
idx: tags.length
|
3259
|
+
});
|
3260
|
+
|
3261
|
+
return [
|
3262
|
+
...generate(scope, decl.argument),
|
3263
|
+
...getNodeType(scope, decl.argument),
|
3264
|
+
[ Opcodes.throw, tags[0].idx ]
|
3265
|
+
];
|
3266
|
+
}
|
3045
3267
|
|
3046
|
-
|
3047
|
-
|
3268
|
+
if (exceptionMode === 'stackest') {
|
3269
|
+
let message = decl.argument, constructor = null;
|
3048
3270
|
|
3049
|
-
|
3050
|
-
|
3271
|
+
// support `throw (new)? Error(...)`
|
3272
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3273
|
+
constructor = decl.argument.callee;
|
3274
|
+
message = decl.argument.arguments[0];
|
3275
|
+
}
|
3051
3276
|
|
3052
|
-
|
3277
|
+
message ??= DEFAULT_VALUE;
|
3053
3278
|
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3279
|
+
if (tags.length === 0) tags.push({
|
3280
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3281
|
+
results: [],
|
3282
|
+
idx: tags.length
|
3283
|
+
});
|
3284
|
+
|
3285
|
+
return [
|
3286
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3287
|
+
...generate(scope, message),
|
3288
|
+
...getNodeType(scope, message),
|
3289
|
+
[ Opcodes.throw, tags[0].idx ]
|
3290
|
+
];
|
3291
|
+
}
|
3292
|
+
|
3293
|
+
if (exceptionMode === 'partial') {
|
3294
|
+
let message = decl.argument, constructor = null;
|
3295
|
+
|
3296
|
+
// support `throw (new)? Error(...)`
|
3297
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3298
|
+
constructor = decl.argument.callee.name;
|
3299
|
+
message = decl.argument.arguments[0];
|
3300
|
+
}
|
3301
|
+
|
3302
|
+
message ??= DEFAULT_VALUE;
|
3303
|
+
|
3304
|
+
if (tags.length === 0) tags.push({
|
3305
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3306
|
+
results: [],
|
3307
|
+
idx: tags.length
|
3308
|
+
});
|
3309
|
+
|
3310
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3311
|
+
|
3312
|
+
scope.exceptions ??= [];
|
3313
|
+
scope.exceptions.push(exceptId);
|
3314
|
+
|
3315
|
+
return [
|
3316
|
+
...number(exceptId, Valtype.i32),
|
3317
|
+
...generate(scope, message),
|
3318
|
+
...getNodeType(scope, message),
|
3319
|
+
[ Opcodes.throw, tags[0].idx ]
|
3320
|
+
];
|
3321
|
+
}
|
3058
3322
|
};
|
3059
3323
|
|
3060
3324
|
const generateTry = (scope, decl) => {
|
@@ -3407,6 +3671,19 @@ const withType = (scope, wasm, type) => [
|
|
3407
3671
|
...setLastType(scope, type)
|
3408
3672
|
];
|
3409
3673
|
|
3674
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3675
|
+
const out = {};
|
3676
|
+
for (const x in bc) {
|
3677
|
+
out[x] = [
|
3678
|
+
...prelude,
|
3679
|
+
...bc[x],
|
3680
|
+
...postlude
|
3681
|
+
];
|
3682
|
+
}
|
3683
|
+
|
3684
|
+
return out;
|
3685
|
+
};
|
3686
|
+
|
3410
3687
|
const generateMember = (scope, decl, _global, _name) => {
|
3411
3688
|
const name = decl.object.name;
|
3412
3689
|
|
@@ -3460,7 +3737,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3460
3737
|
const type = getNodeType(scope, decl.object);
|
3461
3738
|
const known = knownType(scope, type);
|
3462
3739
|
if (known != null) {
|
3463
|
-
if (
|
3740
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3464
3741
|
...generate(scope, decl.object),
|
3465
3742
|
Opcodes.i32_to_u,
|
3466
3743
|
|
@@ -3472,7 +3749,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3472
3749
|
}
|
3473
3750
|
|
3474
3751
|
return [
|
3475
|
-
...
|
3752
|
+
...getNodeType(scope, decl.object),
|
3753
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3754
|
+
[ Opcodes.i32_and ],
|
3476
3755
|
[ Opcodes.if, valtypeBinary ],
|
3477
3756
|
...generate(scope, decl.object),
|
3478
3757
|
Opcodes.i32_to_u,
|
@@ -3521,7 +3800,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3521
3800
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3522
3801
|
// hack: this is naughty and will break things!
|
3523
3802
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3524
|
-
|
3803
|
+
|
3804
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3805
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3525
3806
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3526
3807
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3527
3808
|
rawElements: new Array(0)
|
@@ -3595,6 +3876,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3595
3876
|
...setLastType(scope, TYPES.bytestring)
|
3596
3877
|
],
|
3597
3878
|
|
3879
|
+
...wrapBC({
|
3880
|
+
[TYPES.uint8array]: [
|
3881
|
+
[ Opcodes.i32_add ],
|
3882
|
+
|
3883
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3884
|
+
Opcodes.i32_from_u
|
3885
|
+
],
|
3886
|
+
[TYPES.uint8clampedarray]: [
|
3887
|
+
[ Opcodes.i32_add ],
|
3888
|
+
|
3889
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3890
|
+
Opcodes.i32_from_u
|
3891
|
+
],
|
3892
|
+
[TYPES.int8array]: [
|
3893
|
+
[ Opcodes.i32_add ],
|
3894
|
+
|
3895
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3896
|
+
Opcodes.i32_from
|
3897
|
+
],
|
3898
|
+
[TYPES.uint16array]: [
|
3899
|
+
...number(2, Valtype.i32),
|
3900
|
+
[ Opcodes.i32_mul ],
|
3901
|
+
[ Opcodes.i32_add ],
|
3902
|
+
|
3903
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3904
|
+
Opcodes.i32_from_u
|
3905
|
+
],
|
3906
|
+
[TYPES.int16array]: [
|
3907
|
+
...number(2, Valtype.i32),
|
3908
|
+
[ Opcodes.i32_mul ],
|
3909
|
+
[ Opcodes.i32_add ],
|
3910
|
+
|
3911
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3912
|
+
Opcodes.i32_from
|
3913
|
+
],
|
3914
|
+
[TYPES.uint32array]: [
|
3915
|
+
...number(4, Valtype.i32),
|
3916
|
+
[ Opcodes.i32_mul ],
|
3917
|
+
[ Opcodes.i32_add ],
|
3918
|
+
|
3919
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3920
|
+
Opcodes.i32_from_u
|
3921
|
+
],
|
3922
|
+
[TYPES.int32array]: [
|
3923
|
+
...number(4, Valtype.i32),
|
3924
|
+
[ Opcodes.i32_mul ],
|
3925
|
+
[ Opcodes.i32_add ],
|
3926
|
+
|
3927
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3928
|
+
Opcodes.i32_from
|
3929
|
+
],
|
3930
|
+
[TYPES.float32array]: [
|
3931
|
+
...number(4, Valtype.i32),
|
3932
|
+
[ Opcodes.i32_mul ],
|
3933
|
+
[ Opcodes.i32_add ],
|
3934
|
+
|
3935
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3936
|
+
[ Opcodes.f64_promote_f32 ]
|
3937
|
+
],
|
3938
|
+
[TYPES.float64array]: [
|
3939
|
+
...number(8, Valtype.i32),
|
3940
|
+
[ Opcodes.i32_mul ],
|
3941
|
+
[ Opcodes.i32_add ],
|
3942
|
+
|
3943
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3944
|
+
],
|
3945
|
+
}, {
|
3946
|
+
prelude: [
|
3947
|
+
...object,
|
3948
|
+
Opcodes.i32_to_u,
|
3949
|
+
...property,
|
3950
|
+
Opcodes.i32_to_u
|
3951
|
+
],
|
3952
|
+
postlude: setLastType(scope, TYPES.number)
|
3953
|
+
}),
|
3954
|
+
|
3598
3955
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3599
3956
|
});
|
3600
3957
|
};
|
@@ -3772,7 +4129,7 @@ const internalConstrs = {
|
|
3772
4129
|
|
3773
4130
|
// todo: check in wasm instead of here
|
3774
4131
|
const literalValue = arg.value ?? 0;
|
3775
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
4132
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3776
4133
|
|
3777
4134
|
return [
|
3778
4135
|
...out,
|