porffor 0.41.7 → 0.42.1
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/assemble.js +6 -5
- package/compiler/builtins_precompiled.js +563 -364
- package/compiler/codegen.js +197 -122
- package/compiler/precompile.js +6 -1
- package/compiler/wrap.js +3 -5
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -48,6 +48,7 @@ const cacheAst = (decl, wasm) => {
|
|
48
48
|
return wasm;
|
49
49
|
};
|
50
50
|
|
51
|
+
let indirectFuncs = [];
|
51
52
|
const funcRef = func => {
|
52
53
|
func.generate?.();
|
53
54
|
|
@@ -55,35 +56,81 @@ const funcRef = func => {
|
|
55
56
|
[ Opcodes.const, 'funcref', func.name ]
|
56
57
|
];
|
57
58
|
|
58
|
-
const wrapperArgc = Prefs.indirectWrapperArgc ??
|
59
|
-
if (
|
59
|
+
const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
|
60
|
+
if (!func.wrapperFunc) {
|
60
61
|
const locals = {}, params = [];
|
61
|
-
for (let i = 0; i < wrapperArgc +
|
62
|
+
for (let i = 0; i < wrapperArgc + 2; i++) {
|
62
63
|
params.push(valtypeBinary, Valtype.i32);
|
63
64
|
locals[i * 2] = { idx: i * 2, type: valtypeBinary };
|
64
65
|
locals[i * 2 + 1] = { idx: i * 2 + 1, type: Valtype.i32 };
|
65
66
|
}
|
66
|
-
let localInd = (wrapperArgc +
|
67
|
+
let localInd = (wrapperArgc + 2) * 2;
|
68
|
+
|
69
|
+
if (indirectFuncs.length === 0) {
|
70
|
+
// add empty indirect func
|
71
|
+
const emptyFunc = {
|
72
|
+
name: '#indirect#empty',
|
73
|
+
params,
|
74
|
+
locals: { ...locals }, localInd,
|
75
|
+
returns: [ valtypeBinary, Valtype.i32 ],
|
76
|
+
wasm: [
|
77
|
+
...number(0),
|
78
|
+
...number(0, Valtype.i32)
|
79
|
+
],
|
80
|
+
constr: true,
|
81
|
+
internal: true,
|
82
|
+
indirect: true
|
83
|
+
};
|
84
|
+
|
85
|
+
// check not being constructed
|
86
|
+
emptyFunc.wasm.unshift(
|
87
|
+
[ Opcodes.local_get, 0 ], // new.target value
|
88
|
+
Opcodes.i32_to_u,
|
89
|
+
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
90
|
+
...internalThrow(emptyFunc, 'TypeError', `Function is not a constructor`), // throw type error
|
91
|
+
[ Opcodes.end ]
|
92
|
+
);
|
93
|
+
|
94
|
+
indirectFuncs.push(emptyFunc);
|
95
|
+
}
|
67
96
|
|
68
97
|
const wasm = [];
|
98
|
+
const offset = func.constr ? 0 : 4;
|
69
99
|
for (let i = 0; i < func.params.length; i++) {
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
100
|
+
if (func.internal && func.name.includes('_prototype_') && i < 2) {
|
101
|
+
// special case: use real this for prototype internals
|
102
|
+
wasm.push(
|
103
|
+
[ Opcodes.local_get, 2 + i ],
|
104
|
+
...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
|
105
|
+
);
|
106
|
+
} else {
|
107
|
+
wasm.push(
|
108
|
+
[ Opcodes.local_get, offset + (!func.internal || func.typedParams ? i : i * 2) ],
|
109
|
+
...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
|
110
|
+
);
|
111
|
+
}
|
74
112
|
}
|
75
113
|
|
76
114
|
wasm.push([ Opcodes.call, func.index ]);
|
77
115
|
|
78
116
|
if (func.returns[0] === Valtype.i32) {
|
79
|
-
|
80
|
-
|
117
|
+
if (func.returns.length === 2) {
|
118
|
+
const localIdx = localInd++;
|
119
|
+
locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
|
81
120
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
121
|
+
wasm.push(
|
122
|
+
[ Opcodes.local_set, localIdx ],
|
123
|
+
Opcodes.i32_from,
|
124
|
+
[ Opcodes.local_get, localIdx ]
|
125
|
+
);
|
126
|
+
} else {
|
127
|
+
wasm.push(Opcodes.i32_from);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
if (func.returns.length === 1) {
|
132
|
+
// add built-in returnType if only returns a value
|
133
|
+
wasm.push(...number(func.returnType ?? TYPES.number, Valtype.i32));
|
87
134
|
}
|
88
135
|
|
89
136
|
const name = '#indirect_' + func.name;
|
@@ -93,16 +140,26 @@ const funcRef = func => {
|
|
93
140
|
locals, localInd,
|
94
141
|
returns: [ valtypeBinary, Valtype.i32 ],
|
95
142
|
wasm,
|
96
|
-
constr:
|
143
|
+
constr: true,
|
97
144
|
internal: true,
|
98
|
-
|
145
|
+
indirect: true
|
99
146
|
};
|
100
147
|
|
101
|
-
|
102
|
-
funcIndex[name] = wrapperFunc.index;
|
148
|
+
indirectFuncs.push(wrapperFunc);
|
103
149
|
|
104
150
|
wrapperFunc.jsLength = countLength(func);
|
105
151
|
func.wrapperFunc = wrapperFunc;
|
152
|
+
|
153
|
+
if (!func.constr) {
|
154
|
+
// check not being constructed
|
155
|
+
wasm.unshift(
|
156
|
+
[ Opcodes.local_get, 0 ], // new.target value
|
157
|
+
Opcodes.i32_to_u,
|
158
|
+
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
159
|
+
...internalThrow(wrapperFunc, 'TypeError', `${unhackName(func.name)} is not a constructor`), // throw type error
|
160
|
+
[ Opcodes.end ]
|
161
|
+
);
|
162
|
+
}
|
106
163
|
}
|
107
164
|
|
108
165
|
return [
|
@@ -398,32 +455,75 @@ const generateReturn = (scope, decl) => {
|
|
398
455
|
];
|
399
456
|
}
|
400
457
|
|
401
|
-
const out = [];
|
402
458
|
if (
|
403
459
|
scope.constr && // only do this in constructors
|
404
460
|
!globalThis.precompile // skip in precompiled built-ins, we should not require this and handle it ourselves
|
405
461
|
) {
|
406
|
-
//
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
Opcodes.
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
462
|
+
// perform return value checks for constructors and (sub)classes
|
463
|
+
return [
|
464
|
+
...generate(scope, arg),
|
465
|
+
[ Opcodes.local_set, localTmp(scope, '#return') ],
|
466
|
+
...(scope.returnType != null ? [] : getNodeType(scope, arg)),
|
467
|
+
[ Opcodes.local_set, localTmp(scope, '#return#type', Valtype.i32) ],
|
468
|
+
|
469
|
+
...(scope._onlyConstr ? [] : [
|
470
|
+
[ Opcodes.local_get, scope.locals['#newtarget'].idx ],
|
471
|
+
Opcodes.i32_to_u,
|
472
|
+
[ Opcodes.if, Blocktype.void ]
|
473
|
+
]),
|
474
|
+
...(scope.subclass ? [
|
475
|
+
// if subclass and returning undefined, return this
|
476
|
+
[ Opcodes.local_get, localTmp(scope, '#return#type') ],
|
477
|
+
...number(TYPE_FLAGS.parity, Valtype.i32),
|
478
|
+
[ Opcodes.i32_or ],
|
479
|
+
...number(TYPES.undefined, Valtype.i32),
|
480
|
+
[ Opcodes.i32_eq ],
|
481
|
+
[ Opcodes.if, Blocktype.void ],
|
482
|
+
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
483
|
+
...(scope.returnType != null ? [] : [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ]),
|
484
|
+
[ Opcodes.return ],
|
485
|
+
[ Opcodes.end ]
|
486
|
+
] : []),
|
487
|
+
|
488
|
+
// if not object, then...
|
489
|
+
...generate(scope, {
|
490
|
+
type: 'CallExpression',
|
491
|
+
callee: {
|
492
|
+
type: 'Identifier',
|
493
|
+
name: '__Porffor_object_isObject'
|
494
|
+
},
|
495
|
+
arguments: [
|
496
|
+
{ type: 'Identifier', name: '#return' }
|
497
|
+
]
|
498
|
+
}),
|
499
|
+
Opcodes.i32_to_u,
|
500
|
+
[ Opcodes.i32_eqz ],
|
501
|
+
[ Opcodes.if, Blocktype.void ],
|
502
|
+
...(scope.subclass ? [
|
503
|
+
// throw if subclass
|
504
|
+
...internalThrow(scope, 'TypeError', 'Subclass can only return an object or undefined'),
|
505
|
+
] : [
|
506
|
+
// return this if not subclass
|
507
|
+
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
508
|
+
...(scope.returnType != null ? [] : [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ]),
|
509
|
+
[ Opcodes.return ],
|
510
|
+
]),
|
511
|
+
[ Opcodes.end ],
|
512
|
+
...(scope._onlyConstr ? [] : [
|
513
|
+
[ Opcodes.end ]
|
514
|
+
]),
|
515
|
+
|
516
|
+
[ Opcodes.local_get, localTmp(scope, '#return') ],
|
517
|
+
[ Opcodes.local_get, localTmp(scope, '#return#type') ],
|
518
|
+
[ Opcodes.return ]
|
519
|
+
];
|
418
520
|
}
|
419
521
|
|
420
|
-
|
522
|
+
return [
|
421
523
|
...generate(scope, arg),
|
422
524
|
...(scope.returnType != null ? [] : getNodeType(scope, arg)),
|
423
525
|
[ Opcodes.return ]
|
424
|
-
|
425
|
-
|
426
|
-
return out;
|
526
|
+
];
|
427
527
|
};
|
428
528
|
|
429
529
|
const localTmp = (scope, name, type = valtypeBinary) => {
|
@@ -1032,7 +1132,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1032
1132
|
});
|
1033
1133
|
};
|
1034
1134
|
|
1035
|
-
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usedTypes = [] } = {}) => {
|
1135
|
+
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usedTypes = [] } = {}) => {
|
1036
1136
|
if (wasm == null) { // called with no builtin
|
1037
1137
|
log.warning('codegen', `${name} has no built-in!`);
|
1038
1138
|
wasm = [];
|
@@ -1105,6 +1205,7 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1105
1205
|
}
|
1106
1206
|
|
1107
1207
|
if (hasRestArgument) func.hasRestArgument = true;
|
1208
|
+
if (usesTag) ensureTag();
|
1108
1209
|
|
1109
1210
|
for (const x of usedTypes) typeUsed(func, x);
|
1110
1211
|
|
@@ -2233,7 +2334,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2233
2334
|
scope.table = true;
|
2234
2335
|
|
2235
2336
|
let args = decl.arguments;
|
2236
|
-
const wrapperArgc = Prefs.indirectWrapperArgc ??
|
2337
|
+
const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
|
2237
2338
|
if (args.length < wrapperArgc) {
|
2238
2339
|
args = args.concat(new Array(wrapperArgc - args.length).fill(DEFAULT_VALUE()));
|
2239
2340
|
}
|
@@ -2293,39 +2394,14 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2293
2394
|
|
2294
2395
|
...typeSwitch(scope, getNodeType(scope, callee), {
|
2295
2396
|
[TYPES.function]: () => [
|
2296
|
-
|
2397
|
+
...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
|
2398
|
+
...forceDuoValtype(scope, thisWasm, Valtype.f64),
|
2399
|
+
...out,
|
2400
|
+
|
2297
2401
|
[ Opcodes.local_get, calleeLocal ],
|
2298
2402
|
Opcodes.i32_to_u,
|
2299
|
-
|
2300
|
-
|
2301
|
-
...number(2, Valtype.i32),
|
2302
|
-
[ Opcodes.i32_add ],
|
2303
|
-
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(allocPage(scope, 'func lut')), 'read func lut' ],
|
2304
|
-
|
2305
|
-
...number(0b10, Valtype.i32),
|
2306
|
-
[ Opcodes.i32_and ],
|
2307
|
-
[ Opcodes.if, Valtype.f64 ],
|
2308
|
-
...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
|
2309
|
-
...forceDuoValtype(scope, thisWasm, Valtype.f64),
|
2310
|
-
...out,
|
2311
|
-
|
2312
|
-
[ Opcodes.local_get, calleeLocal ],
|
2313
|
-
Opcodes.i32_to_u,
|
2314
|
-
[ Opcodes.call_indirect, args.length + 2, 0 ],
|
2315
|
-
...setLastType(scope),
|
2316
|
-
[ Opcodes.else ],
|
2317
|
-
// throw if non-constructor called with new
|
2318
|
-
...(callAsNew ? [
|
2319
|
-
...internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, Valtype.f64)
|
2320
|
-
] : [
|
2321
|
-
...out,
|
2322
|
-
|
2323
|
-
[ Opcodes.local_get, calleeLocal ],
|
2324
|
-
Opcodes.i32_to_u,
|
2325
|
-
[ Opcodes.call_indirect, args.length, 0 ],
|
2326
|
-
...setLastType(scope)
|
2327
|
-
]),
|
2328
|
-
[ Opcodes.end ]
|
2403
|
+
[ Opcodes.call_indirect, args.length + 2, 0 ],
|
2404
|
+
...setLastType(scope)
|
2329
2405
|
],
|
2330
2406
|
|
2331
2407
|
default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
|
@@ -2362,16 +2438,12 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2362
2438
|
paramOffset += 4;
|
2363
2439
|
}
|
2364
2440
|
|
2365
|
-
if (func &&
|
2441
|
+
if (func && args.length < paramCount) {
|
2366
2442
|
// too little args, push undefineds
|
2367
|
-
args = args.concat(new Array(paramCount - args.length).fill(DEFAULT_VALUE()));
|
2443
|
+
args = args.concat(new Array(paramCount - (func.hasRestArgument ? 1 : 0) - args.length).fill(DEFAULT_VALUE()));
|
2368
2444
|
}
|
2369
2445
|
|
2370
2446
|
if (func && func.hasRestArgument) {
|
2371
|
-
if (args.length < paramCount) {
|
2372
|
-
args = args.concat(new Array(paramCount - 1 - args.length).fill(DEFAULT_VALUE()));
|
2373
|
-
}
|
2374
|
-
|
2375
2447
|
const restArgs = args.slice(paramCount - 1);
|
2376
2448
|
args = args.slice(0, paramCount - 1);
|
2377
2449
|
args.push({
|
@@ -2385,13 +2457,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2385
2457
|
args = args.slice(0, paramCount);
|
2386
2458
|
}
|
2387
2459
|
|
2388
|
-
if (func && func.throws) scope.throws = true;
|
2389
|
-
|
2390
2460
|
for (let i = 0; i < args.length; i++) {
|
2391
2461
|
const arg = args[i];
|
2392
2462
|
if (Array.isArray(arg)) {
|
2393
2463
|
// if wasm, just append it
|
2394
2464
|
out = out.concat(arg);
|
2465
|
+
|
2466
|
+
if (valtypeBinary !== Valtype.i32 &&
|
2467
|
+
(func && func.params[paramOffset + i * (typedParams ? 2 : 1)] === Valtype.i32)
|
2468
|
+
) {
|
2469
|
+
out.push(...forceDuoValtype(scope, [], Valtype.i32));
|
2470
|
+
}
|
2471
|
+
|
2395
2472
|
continue;
|
2396
2473
|
}
|
2397
2474
|
|
@@ -3662,8 +3739,11 @@ const generateUnary = (scope, decl) => {
|
|
3662
3739
|
case 'delete': {
|
3663
3740
|
if (decl.argument.type === 'MemberExpression') {
|
3664
3741
|
const object = decl.argument.object;
|
3665
|
-
const property = getProperty(decl.argument);
|
3666
3742
|
|
3743
|
+
// disallow `delete super.*`
|
3744
|
+
if (object.type === 'Super') return internalThrow(scope, 'ReferenceError', 'Cannot delete super property', true);
|
3745
|
+
|
3746
|
+
const property = getProperty(decl.argument);
|
3667
3747
|
if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
|
3668
3748
|
|
3669
3749
|
return [
|
@@ -4596,11 +4676,20 @@ const generateLabel = (scope, decl) => {
|
|
4596
4676
|
return generate(scope, decl.body);
|
4597
4677
|
};
|
4598
4678
|
|
4599
|
-
const
|
4600
|
-
|
4679
|
+
const ensureTag = (exceptionMode = Prefs.exceptionMode ?? 'stack') => {
|
4680
|
+
if (tags.length !== 0) return;
|
4681
|
+
|
4682
|
+
tags.push({
|
4683
|
+
params: exceptionMode === 'lut' ? [ Valtype.i32 ] : [ valtypeBinary, Valtype.i32 ],
|
4684
|
+
results: [],
|
4685
|
+
idx: tags.length
|
4686
|
+
});
|
4687
|
+
};
|
4601
4688
|
|
4689
|
+
const generateThrow = (scope, decl) => {
|
4602
4690
|
let exceptionMode = Prefs.exceptionMode ?? 'stack';
|
4603
4691
|
if (globalThis.precompile) exceptionMode = decl.argument.callee != null ? 'lut' : 'stack';
|
4692
|
+
ensureTag(exceptionMode);
|
4604
4693
|
|
4605
4694
|
if (exceptionMode === 'lut') {
|
4606
4695
|
let message = decl.argument.value, constructor = null;
|
@@ -4611,12 +4700,6 @@ const generateThrow = (scope, decl) => {
|
|
4611
4700
|
message = decl.argument.arguments[0]?.value ?? '';
|
4612
4701
|
}
|
4613
4702
|
|
4614
|
-
if (tags.length === 0) tags.push({
|
4615
|
-
params: [ Valtype.i32 ],
|
4616
|
-
results: [],
|
4617
|
-
idx: tags.length
|
4618
|
-
});
|
4619
|
-
|
4620
4703
|
if (constructor && constructor.startsWith('__')) constructor = constructor.split('_').pop();
|
4621
4704
|
|
4622
4705
|
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
@@ -4631,19 +4714,11 @@ const generateThrow = (scope, decl) => {
|
|
4631
4714
|
];
|
4632
4715
|
}
|
4633
4716
|
|
4634
|
-
|
4635
|
-
|
4636
|
-
|
4637
|
-
|
4638
|
-
|
4639
|
-
});
|
4640
|
-
|
4641
|
-
return [
|
4642
|
-
...generate(scope, decl.argument),
|
4643
|
-
...getNodeType(scope, decl.argument),
|
4644
|
-
[ Opcodes.throw, globalThis.precompile ? 1 : 0 ]
|
4645
|
-
];
|
4646
|
-
}
|
4717
|
+
return [
|
4718
|
+
...generate(scope, decl.argument),
|
4719
|
+
...getNodeType(scope, decl.argument),
|
4720
|
+
[ Opcodes.throw, globalThis.precompile ? 1 : 0 ]
|
4721
|
+
];
|
4647
4722
|
};
|
4648
4723
|
|
4649
4724
|
const generateTry = (scope, decl) => {
|
@@ -4686,6 +4761,9 @@ const generateTry = (scope, decl) => {
|
|
4686
4761
|
|
4687
4762
|
...generateVarDstr(scope, 'let', param, { type: 'Identifier', name: tmpName }, undefined, false)
|
4688
4763
|
);
|
4764
|
+
|
4765
|
+
// ensure tag exists for specific catch
|
4766
|
+
ensureTag();
|
4689
4767
|
} else {
|
4690
4768
|
out.push([ Opcodes.catch_all ]);
|
4691
4769
|
}
|
@@ -5056,11 +5134,7 @@ const toPropertyKey = (scope, wasm, type, computed = false, i32Conv = false) =>
|
|
5056
5134
|
...wasm,
|
5057
5135
|
...type,
|
5058
5136
|
[ Opcodes.call, includeBuiltin(scope, '__ecma262_ToPropertyKey').index ],
|
5059
|
-
...(i32Conv ? [
|
5060
|
-
[ Opcodes.local_set, localTmp(scope, '#swap', Valtype.i32) ],
|
5061
|
-
Opcodes.i32_to_u,
|
5062
|
-
[ Opcodes.local_get, localTmp(scope, '#swap', Valtype.i32) ]
|
5063
|
-
] : [])
|
5137
|
+
...(i32Conv ? forceDuoValtype(scope, [], Valtype.i32) : [])
|
5064
5138
|
] : [
|
5065
5139
|
...wasm,
|
5066
5140
|
...(i32Conv ? [ Opcodes.i32_to_u ] : []),
|
@@ -5203,7 +5277,6 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5203
5277
|
if (decl.property.name === 'name' && hasFuncWithName(name) && !scope.noFastFuncMembers) {
|
5204
5278
|
// eg: __String_prototype_toLowerCase -> toLowerCase
|
5205
5279
|
if (name.startsWith('__')) name = name.split('_').pop();
|
5206
|
-
if (name.startsWith('#indirect_')) name = name.slice(10);
|
5207
5280
|
if (name.startsWith('#')) name = '';
|
5208
5281
|
|
5209
5282
|
return withType(scope, makeString(scope, name, _global, _name, true), TYPES.bytestring);
|
@@ -5620,16 +5693,7 @@ const generateClass = (scope, decl) => {
|
|
5620
5693
|
type: 'Identifier',
|
5621
5694
|
name
|
5622
5695
|
};
|
5623
|
-
const proto =
|
5624
|
-
type: 'MemberExpression',
|
5625
|
-
object: root,
|
5626
|
-
property: {
|
5627
|
-
type: 'Identifier',
|
5628
|
-
name: 'prototype'
|
5629
|
-
},
|
5630
|
-
computed: false,
|
5631
|
-
optional: false
|
5632
|
-
};
|
5696
|
+
const proto = getObjProp(root, 'prototype');
|
5633
5697
|
|
5634
5698
|
const [ func, out ] = generateFunc(scope, {
|
5635
5699
|
...(body.find(x => x.kind === 'constructor')?.value ?? {
|
@@ -5641,9 +5705,10 @@ const generateClass = (scope, decl) => {
|
|
5641
5705
|
}
|
5642
5706
|
}),
|
5643
5707
|
id: root,
|
5644
|
-
_onlyConstr: true,
|
5645
5708
|
strict: true,
|
5646
|
-
type: expr ? 'FunctionExpression' : 'FunctionDeclaration'
|
5709
|
+
type: expr ? 'FunctionExpression' : 'FunctionDeclaration',
|
5710
|
+
_onlyConstr: true,
|
5711
|
+
_subclass: !!decl.superClass
|
5647
5712
|
});
|
5648
5713
|
|
5649
5714
|
// always generate class constructor funcs
|
@@ -5656,7 +5721,7 @@ const generateClass = (scope, decl) => {
|
|
5656
5721
|
// Bar.__proto__ = Foo
|
5657
5722
|
// Bar.prototype.__proto__ = Foo.prototype
|
5658
5723
|
...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
|
5659
|
-
...generate(scope, setObjProp(
|
5724
|
+
...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype')))
|
5660
5725
|
);
|
5661
5726
|
}
|
5662
5727
|
|
@@ -5951,7 +6016,7 @@ const generateFunc = (scope, decl) => {
|
|
5951
6016
|
index: currentFuncIndex++,
|
5952
6017
|
arrow,
|
5953
6018
|
constr: !arrow && !decl.generator && !decl.async,
|
5954
|
-
_onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
6019
|
+
subclass: decl._subclass, _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
5955
6020
|
strict: scope.strict || decl.strict,
|
5956
6021
|
|
5957
6022
|
generate() {
|
@@ -6039,6 +6104,9 @@ const generateFunc = (scope, decl) => {
|
|
6039
6104
|
...number(TYPES.promise, Valtype.i32),
|
6040
6105
|
[ Opcodes.return ]
|
6041
6106
|
);
|
6107
|
+
|
6108
|
+
// ensure tag exists for specific catch
|
6109
|
+
ensureTag();
|
6042
6110
|
}
|
6043
6111
|
|
6044
6112
|
if (name === 'main') {
|
@@ -6339,7 +6407,7 @@ export default program => {
|
|
6339
6407
|
};
|
6340
6408
|
tags = [];
|
6341
6409
|
exceptions = [];
|
6342
|
-
funcs = [];
|
6410
|
+
funcs = []; indirectFuncs = [];
|
6343
6411
|
funcIndex = {};
|
6344
6412
|
depth = [];
|
6345
6413
|
pages = new Map();
|
@@ -6394,6 +6462,7 @@ export default program => {
|
|
6394
6462
|
// todo: these should just be deleted once able
|
6395
6463
|
for (let i = 0; i < funcs.length; i++) {
|
6396
6464
|
const f = funcs[i];
|
6465
|
+
|
6397
6466
|
if (f.wasm) {
|
6398
6467
|
// run callbacks
|
6399
6468
|
const wasm = f.wasm;
|
@@ -6450,9 +6519,15 @@ export default program => {
|
|
6450
6519
|
// }
|
6451
6520
|
// }
|
6452
6521
|
|
6453
|
-
|
6522
|
+
// add indirect funcs to end of funcs
|
6523
|
+
for (let i = 0; i < indirectFuncs.length; i++) {
|
6524
|
+
const f = indirectFuncs[i];
|
6525
|
+
f.index = currentFuncIndex++;
|
6526
|
+
}
|
6527
|
+
|
6528
|
+
funcs.push(...indirectFuncs);
|
6454
6529
|
|
6455
|
-
|
6530
|
+
delete globals['#ind'];
|
6456
6531
|
|
6457
6532
|
return { funcs, globals, tags, exceptions, pages, data };
|
6458
6533
|
};
|
package/compiler/precompile.js
CHANGED
@@ -153,6 +153,7 @@ const compile = async (file, _funcs) => {
|
|
153
153
|
}
|
154
154
|
|
155
155
|
if (n[0] === Opcodes.throw) {
|
156
|
+
x.usesTag = true;
|
156
157
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
157
158
|
const id = read_signedLEB128(y.slice(1));
|
158
159
|
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
@@ -163,6 +164,10 @@ const compile = async (file, _funcs) => {
|
|
163
164
|
n[1]--;
|
164
165
|
}
|
165
166
|
}
|
167
|
+
|
168
|
+
if (n[0] === Opcodes.catch) {
|
169
|
+
x.usesTag = true;
|
170
|
+
}
|
166
171
|
}
|
167
172
|
};
|
168
173
|
|
@@ -251,7 +256,7 @@ params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.retu
|
|
251
256
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
252
257
|
${usedTypes.length > 0 ? `usedTypes:${JSON.stringify(usedTypes)},` : ''}
|
253
258
|
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && Object.keys(x.data).length > 0 ? `data:${JSON.stringify(x.data)},` : ''}
|
254
|
-
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}
|
259
|
+
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}${x.usesTag ? `usesTag:1,` : ''}
|
255
260
|
}`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
256
261
|
}).join('\n')}
|
257
262
|
}`;
|
package/compiler/wrap.js
CHANGED
@@ -520,12 +520,10 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
520
520
|
throw new constructor(exception.message);
|
521
521
|
}
|
522
522
|
|
523
|
-
|
524
|
-
|
525
|
-
const type = e.getArg(exceptTag, 1);
|
523
|
+
const value = e.getArg(exceptTag, 0);
|
524
|
+
const type = e.getArg(exceptTag, 1);
|
526
525
|
|
527
|
-
|
528
|
-
}
|
526
|
+
throw porfToJSValue({ memory, funcs, pages }, value, type);
|
529
527
|
}
|
530
528
|
|
531
529
|
if (e instanceof WebAssembly.RuntimeError) {
|
package/package.json
CHANGED