porffor 0.17.0-55999d22b → 0.17.0-589ace465
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/builtins/array.ts +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 +14 -0
- package/compiler/codegen.js +392 -38
- package/compiler/generated_builtins.js +304 -122
- package/compiler/types.js +31 -5
- package/compiler/wasmSpec.js +2 -0
- package/compiler/wrap.js +64 -9
- package/package.json +1 -1
- package/runner/index.js +4 -2
- package/runner/repl.js +11 -6
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
|
}
|
@@ -973,6 +979,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
973
979
|
};
|
974
980
|
|
975
981
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
982
|
+
if (decl.operator === 'instanceof') {
|
983
|
+
// very hacky basic instanceof
|
984
|
+
// todo: support dynamic right-hand side
|
985
|
+
|
986
|
+
const out = generate(scope, decl.left);
|
987
|
+
disposeLeftover(out);
|
988
|
+
|
989
|
+
const rightName = decl.right.name;
|
990
|
+
if (!rightName) return todo(scope, 'instanceof dynamic right-hand side is not supported yet', true);
|
991
|
+
|
992
|
+
const checkType = TYPES[rightName.toLowerCase()];
|
993
|
+
if (checkType == null || rightName !== TYPE_NAMES[checkType] || checkType === TYPES.undefined) return todo(scope, 'instanceof right-hand side type unsupported', true);
|
994
|
+
|
995
|
+
if ([TYPES.number, TYPES.boolean, TYPES.string, TYPES.symbol, TYPES.object].includes(checkType)) {
|
996
|
+
out.push(...number(0));
|
997
|
+
} else {
|
998
|
+
out.push(
|
999
|
+
...getNodeType(scope, decl.left),
|
1000
|
+
...number(checkType, Valtype.i32),
|
1001
|
+
[ Opcodes.i32_eq ],
|
1002
|
+
Opcodes.i32_from_u
|
1003
|
+
);
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
return out;
|
1007
|
+
}
|
1008
|
+
|
976
1009
|
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
1010
|
|
978
1011
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1279,7 +1312,7 @@ const getNodeType = (scope, node) => {
|
|
1279
1312
|
}
|
1280
1313
|
|
1281
1314
|
if (node.type === 'BinaryExpression') {
|
1282
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1315
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1283
1316
|
if (node.operator !== '+') return TYPES.number;
|
1284
1317
|
|
1285
1318
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -1312,7 +1345,7 @@ const getNodeType = (scope, node) => {
|
|
1312
1345
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1313
1346
|
if (objectKnownType != null) {
|
1314
1347
|
if (name === 'length') {
|
1315
|
-
if (
|
1348
|
+
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1316
1349
|
else return TYPES.undefined;
|
1317
1350
|
}
|
1318
1351
|
|
@@ -1424,6 +1457,18 @@ const generateExp = (scope, decl) => {
|
|
1424
1457
|
return out;
|
1425
1458
|
};
|
1426
1459
|
|
1460
|
+
const generateSequence = (scope, decl) => {
|
1461
|
+
let out = [];
|
1462
|
+
|
1463
|
+
const exprs = decl.expressions;
|
1464
|
+
for (let i = 0; i < exprs.length; i++) {
|
1465
|
+
if (i > 0) disposeLeftover(out);
|
1466
|
+
out.push(...generate(scope, exprs[i]));
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
return out;
|
1470
|
+
};
|
1471
|
+
|
1427
1472
|
const CTArrayUtil = {
|
1428
1473
|
getLengthI32: pointer => [
|
1429
1474
|
...number(0, Valtype.i32),
|
@@ -2012,7 +2057,7 @@ const unhackName = name => {
|
|
2012
2057
|
|
2013
2058
|
const knownType = (scope, type) => {
|
2014
2059
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2015
|
-
return type[0]
|
2060
|
+
return read_signedLEB128(type[0].slice(1));
|
2016
2061
|
}
|
2017
2062
|
|
2018
2063
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -2299,11 +2344,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2299
2344
|
const { type, name } = decl.left;
|
2300
2345
|
const [ local, isGlobal ] = lookupName(scope, name);
|
2301
2346
|
|
2302
|
-
if (type === 'ObjectPattern') {
|
2303
|
-
// hack: ignore object parts of `var a = {} = 2`
|
2304
|
-
return generate(scope, decl.right);
|
2305
|
-
}
|
2306
|
-
|
2307
2347
|
if (isFuncType(decl.right.type)) {
|
2308
2348
|
// hack for a = function () { ... }
|
2309
2349
|
decl.right.id = { name };
|
@@ -2376,10 +2416,160 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2376
2416
|
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
|
2377
2417
|
], getNodeType(scope, decl.right), false, name, true)),
|
2378
2418
|
[ Opcodes.local_tee, newValueTmp ],
|
2379
|
-
|
2380
2419
|
[ Opcodes.store, 0, ValtypeSize.i32 ]
|
2381
2420
|
],
|
2382
2421
|
|
2422
|
+
...wrapBC({
|
2423
|
+
[TYPES.uint8array]: [
|
2424
|
+
[ Opcodes.i32_add ],
|
2425
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2426
|
+
|
2427
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2428
|
+
[ Opcodes.local_get, pointerTmp ],
|
2429
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2430
|
+
Opcodes.i32_from_u
|
2431
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2432
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2433
|
+
|
2434
|
+
Opcodes.i32_to_u,
|
2435
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2436
|
+
],
|
2437
|
+
[TYPES.uint8clampedarray]: [
|
2438
|
+
[ Opcodes.i32_add ],
|
2439
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2440
|
+
|
2441
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2442
|
+
[ Opcodes.local_get, pointerTmp ],
|
2443
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
2444
|
+
Opcodes.i32_from_u
|
2445
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2446
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2447
|
+
|
2448
|
+
...number(0),
|
2449
|
+
[ Opcodes.f64_max ],
|
2450
|
+
...number(255),
|
2451
|
+
[ Opcodes.f64_min ],
|
2452
|
+
Opcodes.i32_to_u,
|
2453
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2454
|
+
],
|
2455
|
+
[TYPES.int8array]: [
|
2456
|
+
[ Opcodes.i32_add ],
|
2457
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2458
|
+
|
2459
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2460
|
+
[ Opcodes.local_get, pointerTmp ],
|
2461
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
2462
|
+
Opcodes.i32_from
|
2463
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2464
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2465
|
+
|
2466
|
+
Opcodes.i32_to,
|
2467
|
+
[ Opcodes.i32_store8, 0, 4 ]
|
2468
|
+
],
|
2469
|
+
[TYPES.uint16array]: [
|
2470
|
+
...number(2, Valtype.i32),
|
2471
|
+
[ Opcodes.i32_mul ],
|
2472
|
+
[ Opcodes.i32_add ],
|
2473
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2474
|
+
|
2475
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2476
|
+
[ Opcodes.local_get, pointerTmp ],
|
2477
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
2478
|
+
Opcodes.i32_from_u
|
2479
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2480
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2481
|
+
|
2482
|
+
Opcodes.i32_to_u,
|
2483
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2484
|
+
],
|
2485
|
+
[TYPES.int16array]: [
|
2486
|
+
...number(2, Valtype.i32),
|
2487
|
+
[ Opcodes.i32_mul ],
|
2488
|
+
[ Opcodes.i32_add ],
|
2489
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2490
|
+
|
2491
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2492
|
+
[ Opcodes.local_get, pointerTmp ],
|
2493
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
2494
|
+
Opcodes.i32_from
|
2495
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2496
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2497
|
+
|
2498
|
+
Opcodes.i32_to,
|
2499
|
+
[ Opcodes.i32_store16, 0, 4 ]
|
2500
|
+
],
|
2501
|
+
[TYPES.uint32array]: [
|
2502
|
+
...number(4, Valtype.i32),
|
2503
|
+
[ Opcodes.i32_mul ],
|
2504
|
+
[ Opcodes.i32_add ],
|
2505
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2506
|
+
|
2507
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2508
|
+
[ Opcodes.local_get, pointerTmp ],
|
2509
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2510
|
+
Opcodes.i32_from_u
|
2511
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2512
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2513
|
+
|
2514
|
+
Opcodes.i32_to_u,
|
2515
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2516
|
+
],
|
2517
|
+
[TYPES.int32array]: [
|
2518
|
+
...number(4, Valtype.i32),
|
2519
|
+
[ Opcodes.i32_mul ],
|
2520
|
+
[ Opcodes.i32_add ],
|
2521
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2522
|
+
|
2523
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2524
|
+
[ Opcodes.local_get, pointerTmp ],
|
2525
|
+
[ Opcodes.i32_load, 0, 4 ],
|
2526
|
+
Opcodes.i32_from
|
2527
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2528
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2529
|
+
|
2530
|
+
Opcodes.i32_to,
|
2531
|
+
[ Opcodes.i32_store, 0, 4 ]
|
2532
|
+
],
|
2533
|
+
[TYPES.float32array]: [
|
2534
|
+
...number(4, Valtype.i32),
|
2535
|
+
[ Opcodes.i32_mul ],
|
2536
|
+
[ Opcodes.i32_add ],
|
2537
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2538
|
+
|
2539
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2540
|
+
[ Opcodes.local_get, pointerTmp ],
|
2541
|
+
[ Opcodes.f32_load, 0, 4 ],
|
2542
|
+
[ Opcodes.f64_promote_f32 ]
|
2543
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2544
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2545
|
+
|
2546
|
+
[ Opcodes.f32_demote_f64 ],
|
2547
|
+
[ Opcodes.f32_store, 0, 4 ]
|
2548
|
+
],
|
2549
|
+
[TYPES.float64array]: [
|
2550
|
+
...number(8, Valtype.i32),
|
2551
|
+
[ Opcodes.i32_mul ],
|
2552
|
+
[ Opcodes.i32_add ],
|
2553
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
2554
|
+
|
2555
|
+
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2556
|
+
[ Opcodes.local_get, pointerTmp ],
|
2557
|
+
[ Opcodes.f64_load, 0, 4 ]
|
2558
|
+
], generate(scope, decl.right), number(TYPES.number, Valtype.i32), getNodeType(scope, decl.right), false, name, true)),
|
2559
|
+
[ Opcodes.local_tee, newValueTmp ],
|
2560
|
+
|
2561
|
+
[ Opcodes.f64_store, 0, 4 ]
|
2562
|
+
],
|
2563
|
+
}, {
|
2564
|
+
prelude: [
|
2565
|
+
...generate(scope, decl.left.object),
|
2566
|
+
Opcodes.i32_to_u,
|
2567
|
+
...generate(scope, decl.left.property),
|
2568
|
+
Opcodes.i32_to_u,
|
2569
|
+
],
|
2570
|
+
postlude: setLastType(scope, TYPES.number)
|
2571
|
+
}),
|
2572
|
+
|
2383
2573
|
default: internalThrow(scope, 'TypeError', `Cannot assign member with non-array`)
|
2384
2574
|
}, Blocktype.void),
|
2385
2575
|
|
@@ -2957,6 +3147,7 @@ const generateForOf = (scope, decl) => {
|
|
2957
3147
|
[ Opcodes.end ],
|
2958
3148
|
[ Opcodes.end ]
|
2959
3149
|
],
|
3150
|
+
// todo: typed arrays
|
2960
3151
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
2961
3152
|
}, Blocktype.void));
|
2962
3153
|
|
@@ -3029,32 +3220,102 @@ const generateLabel = (scope, decl) => {
|
|
3029
3220
|
const generateThrow = (scope, decl) => {
|
3030
3221
|
scope.throws = true;
|
3031
3222
|
|
3032
|
-
|
3223
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
3224
|
+
if (exceptionMode === 'lut') {
|
3225
|
+
let message = decl.argument.value, constructor = null;
|
3226
|
+
|
3227
|
+
// support `throw (new)? Error(...)`
|
3228
|
+
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
3229
|
+
constructor = decl.argument.callee.name;
|
3230
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
3231
|
+
}
|
3232
|
+
|
3233
|
+
if (tags.length === 0) tags.push({
|
3234
|
+
params: [ Valtype.i32 ],
|
3235
|
+
results: [],
|
3236
|
+
idx: tags.length
|
3237
|
+
});
|
3238
|
+
|
3239
|
+
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
3240
|
+
if (exceptId === -1) exceptId = exceptions.push({ constructor, message }) - 1;
|
3241
|
+
|
3242
|
+
scope.exceptions ??= [];
|
3243
|
+
scope.exceptions.push(exceptId);
|
3033
3244
|
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3245
|
+
return [
|
3246
|
+
...number(exceptId, Valtype.i32),
|
3247
|
+
[ Opcodes.throw, tags[0].idx ]
|
3248
|
+
];
|
3038
3249
|
}
|
3039
3250
|
|
3040
|
-
if (
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3251
|
+
if (exceptionMode === 'stack') {
|
3252
|
+
if (tags.length === 0) tags.push({
|
3253
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
3254
|
+
results: [],
|
3255
|
+
idx: tags.length
|
3256
|
+
});
|
3045
3257
|
|
3046
|
-
|
3047
|
-
|
3258
|
+
return [
|
3259
|
+
...generate(scope, decl.argument),
|
3260
|
+
...getNodeType(scope, decl.argument),
|
3261
|
+
[ Opcodes.throw, tags[0].idx ]
|
3262
|
+
];
|
3263
|
+
}
|
3048
3264
|
|
3049
|
-
|
3050
|
-
|
3265
|
+
if (exceptionMode === 'stackest') {
|
3266
|
+
let message = decl.argument, constructor = null;
|
3051
3267
|
|
3052
|
-
|
3268
|
+
// support `throw (new)? Error(...)`
|
3269
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3270
|
+
constructor = decl.argument.callee;
|
3271
|
+
message = decl.argument.arguments[0];
|
3272
|
+
}
|
3053
3273
|
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3274
|
+
message ??= DEFAULT_VALUE;
|
3275
|
+
|
3276
|
+
if (tags.length === 0) tags.push({
|
3277
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3278
|
+
results: [],
|
3279
|
+
idx: tags.length
|
3280
|
+
});
|
3281
|
+
|
3282
|
+
return [
|
3283
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3284
|
+
...generate(scope, message),
|
3285
|
+
...getNodeType(scope, message),
|
3286
|
+
[ Opcodes.throw, tags[0].idx ]
|
3287
|
+
];
|
3288
|
+
}
|
3289
|
+
|
3290
|
+
if (exceptionMode === 'partial') {
|
3291
|
+
let message = decl.argument, constructor = null;
|
3292
|
+
|
3293
|
+
// support `throw (new)? Error(...)`
|
3294
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3295
|
+
constructor = decl.argument.callee.name;
|
3296
|
+
message = decl.argument.arguments[0];
|
3297
|
+
}
|
3298
|
+
|
3299
|
+
message ??= DEFAULT_VALUE;
|
3300
|
+
|
3301
|
+
if (tags.length === 0) tags.push({
|
3302
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3303
|
+
results: [],
|
3304
|
+
idx: tags.length
|
3305
|
+
});
|
3306
|
+
|
3307
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3308
|
+
|
3309
|
+
scope.exceptions ??= [];
|
3310
|
+
scope.exceptions.push(exceptId);
|
3311
|
+
|
3312
|
+
return [
|
3313
|
+
...number(exceptId, Valtype.i32),
|
3314
|
+
...generate(scope, message),
|
3315
|
+
...getNodeType(scope, message),
|
3316
|
+
[ Opcodes.throw, tags[0].idx ]
|
3317
|
+
];
|
3318
|
+
}
|
3058
3319
|
};
|
3059
3320
|
|
3060
3321
|
const generateTry = (scope, decl) => {
|
@@ -3407,6 +3668,19 @@ const withType = (scope, wasm, type) => [
|
|
3407
3668
|
...setLastType(scope, type)
|
3408
3669
|
];
|
3409
3670
|
|
3671
|
+
const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
|
3672
|
+
const out = {};
|
3673
|
+
for (const x in bc) {
|
3674
|
+
out[x] = [
|
3675
|
+
...prelude,
|
3676
|
+
...bc[x],
|
3677
|
+
...postlude
|
3678
|
+
];
|
3679
|
+
}
|
3680
|
+
|
3681
|
+
return out;
|
3682
|
+
};
|
3683
|
+
|
3410
3684
|
const generateMember = (scope, decl, _global, _name) => {
|
3411
3685
|
const name = decl.object.name;
|
3412
3686
|
|
@@ -3460,7 +3734,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3460
3734
|
const type = getNodeType(scope, decl.object);
|
3461
3735
|
const known = knownType(scope, type);
|
3462
3736
|
if (known != null) {
|
3463
|
-
if (
|
3737
|
+
if (typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3464
3738
|
...generate(scope, decl.object),
|
3465
3739
|
Opcodes.i32_to_u,
|
3466
3740
|
|
@@ -3472,7 +3746,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3472
3746
|
}
|
3473
3747
|
|
3474
3748
|
return [
|
3475
|
-
...
|
3749
|
+
...getNodeType(scope, decl.object),
|
3750
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3751
|
+
[ Opcodes.i32_and ],
|
3476
3752
|
[ Opcodes.if, valtypeBinary ],
|
3477
3753
|
...generate(scope, decl.object),
|
3478
3754
|
Opcodes.i32_to_u,
|
@@ -3521,7 +3797,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3521
3797
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3522
3798
|
// hack: this is naughty and will break things!
|
3523
3799
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
3524
|
-
|
3800
|
+
|
3801
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
3802
|
+
if ((known === TYPES.string || known === TYPES.bytestring) || (pages.hasAnyString && known == null)) {
|
3525
3803
|
// todo: we use i16 even for bytestrings which should not make a bad thing happen, just be confusing for debugging?
|
3526
3804
|
0, [ newOut, newPointer ] = makeArray(scope, {
|
3527
3805
|
rawElements: new Array(0)
|
@@ -3595,6 +3873,82 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3595
3873
|
...setLastType(scope, TYPES.bytestring)
|
3596
3874
|
],
|
3597
3875
|
|
3876
|
+
...wrapBC({
|
3877
|
+
[TYPES.uint8array]: [
|
3878
|
+
[ Opcodes.i32_add ],
|
3879
|
+
|
3880
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3881
|
+
Opcodes.i32_from_u
|
3882
|
+
],
|
3883
|
+
[TYPES.uint8clampedarray]: [
|
3884
|
+
[ Opcodes.i32_add ],
|
3885
|
+
|
3886
|
+
[ Opcodes.i32_load8_u, 0, 4 ],
|
3887
|
+
Opcodes.i32_from_u
|
3888
|
+
],
|
3889
|
+
[TYPES.int8array]: [
|
3890
|
+
[ Opcodes.i32_add ],
|
3891
|
+
|
3892
|
+
[ Opcodes.i32_load8_s, 0, 4 ],
|
3893
|
+
Opcodes.i32_from
|
3894
|
+
],
|
3895
|
+
[TYPES.uint16array]: [
|
3896
|
+
...number(2, Valtype.i32),
|
3897
|
+
[ Opcodes.i32_mul ],
|
3898
|
+
[ Opcodes.i32_add ],
|
3899
|
+
|
3900
|
+
[ Opcodes.i32_load16_u, 0, 4 ],
|
3901
|
+
Opcodes.i32_from_u
|
3902
|
+
],
|
3903
|
+
[TYPES.int16array]: [
|
3904
|
+
...number(2, Valtype.i32),
|
3905
|
+
[ Opcodes.i32_mul ],
|
3906
|
+
[ Opcodes.i32_add ],
|
3907
|
+
|
3908
|
+
[ Opcodes.i32_load16_s, 0, 4 ],
|
3909
|
+
Opcodes.i32_from
|
3910
|
+
],
|
3911
|
+
[TYPES.uint32array]: [
|
3912
|
+
...number(4, Valtype.i32),
|
3913
|
+
[ Opcodes.i32_mul ],
|
3914
|
+
[ Opcodes.i32_add ],
|
3915
|
+
|
3916
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3917
|
+
Opcodes.i32_from_u
|
3918
|
+
],
|
3919
|
+
[TYPES.int32array]: [
|
3920
|
+
...number(4, Valtype.i32),
|
3921
|
+
[ Opcodes.i32_mul ],
|
3922
|
+
[ Opcodes.i32_add ],
|
3923
|
+
|
3924
|
+
[ Opcodes.i32_load, 0, 4 ],
|
3925
|
+
Opcodes.i32_from
|
3926
|
+
],
|
3927
|
+
[TYPES.float32array]: [
|
3928
|
+
...number(4, Valtype.i32),
|
3929
|
+
[ Opcodes.i32_mul ],
|
3930
|
+
[ Opcodes.i32_add ],
|
3931
|
+
|
3932
|
+
[ Opcodes.f32_load, 0, 4 ],
|
3933
|
+
[ Opcodes.f64_promote_f32 ]
|
3934
|
+
],
|
3935
|
+
[TYPES.float64array]: [
|
3936
|
+
...number(8, Valtype.i32),
|
3937
|
+
[ Opcodes.i32_mul ],
|
3938
|
+
[ Opcodes.i32_add ],
|
3939
|
+
|
3940
|
+
[ Opcodes.f64_load, 0, 4 ]
|
3941
|
+
],
|
3942
|
+
}, {
|
3943
|
+
prelude: [
|
3944
|
+
...object,
|
3945
|
+
Opcodes.i32_to_u,
|
3946
|
+
...property,
|
3947
|
+
Opcodes.i32_to_u
|
3948
|
+
],
|
3949
|
+
postlude: setLastType(scope, TYPES.number)
|
3950
|
+
}),
|
3951
|
+
|
3598
3952
|
default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
|
3599
3953
|
});
|
3600
3954
|
};
|
@@ -3772,7 +4126,7 @@ const internalConstrs = {
|
|
3772
4126
|
|
3773
4127
|
// todo: check in wasm instead of here
|
3774
4128
|
const literalValue = arg.value ?? 0;
|
3775
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
4129
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3776
4130
|
|
3777
4131
|
return [
|
3778
4132
|
...out,
|