porffor 0.41.7 → 0.42.0
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 +5 -5
- package/compiler/builtins_precompiled.js +180 -180
- package/compiler/codegen.js +81 -82
- 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,53 @@ 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;
|
67
68
|
|
68
69
|
const wasm = [];
|
70
|
+
const offset = func.constr ? 0 : 4;
|
69
71
|
for (let i = 0; i < func.params.length; i++) {
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
if (func.internal && func.name.includes('_prototype_') && i < 2) {
|
73
|
+
// special case: use real this for prototype internals
|
74
|
+
wasm.push(
|
75
|
+
[ Opcodes.local_get, 2 + i ],
|
76
|
+
...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
|
77
|
+
);
|
78
|
+
} else {
|
79
|
+
wasm.push(
|
80
|
+
[ Opcodes.local_get, offset + (!func.internal || func.typedParams ? i : i * 2) ],
|
81
|
+
...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
|
82
|
+
);
|
83
|
+
}
|
74
84
|
}
|
75
85
|
|
76
86
|
wasm.push([ Opcodes.call, func.index ]);
|
77
87
|
|
78
88
|
if (func.returns[0] === Valtype.i32) {
|
79
|
-
|
80
|
-
|
89
|
+
if (func.returns.length === 2) {
|
90
|
+
const localIdx = localInd++;
|
91
|
+
locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
|
81
92
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
93
|
+
wasm.push(
|
94
|
+
[ Opcodes.local_set, localIdx ],
|
95
|
+
Opcodes.i32_from,
|
96
|
+
[ Opcodes.local_get, localIdx ]
|
97
|
+
);
|
98
|
+
} else {
|
99
|
+
wasm.push(Opcodes.i32_from);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
if (func.returns.length === 1) {
|
104
|
+
// add built-in returnType if only returns a value
|
105
|
+
wasm.push(...number(func.returnType ?? TYPES.number, Valtype.i32));
|
87
106
|
}
|
88
107
|
|
89
108
|
const name = '#indirect_' + func.name;
|
@@ -93,16 +112,26 @@ const funcRef = func => {
|
|
93
112
|
locals, localInd,
|
94
113
|
returns: [ valtypeBinary, Valtype.i32 ],
|
95
114
|
wasm,
|
96
|
-
constr:
|
115
|
+
constr: true,
|
97
116
|
internal: true,
|
98
|
-
|
117
|
+
indirect: true
|
99
118
|
};
|
100
119
|
|
101
|
-
|
102
|
-
funcIndex[name] = wrapperFunc.index;
|
120
|
+
indirectFuncs.push(wrapperFunc);
|
103
121
|
|
104
122
|
wrapperFunc.jsLength = countLength(func);
|
105
123
|
func.wrapperFunc = wrapperFunc;
|
124
|
+
|
125
|
+
if (!func.constr) {
|
126
|
+
// check not being constructed
|
127
|
+
wasm.unshift(
|
128
|
+
[ Opcodes.local_get, 0 ], // new.target value
|
129
|
+
Opcodes.i32_to_u,
|
130
|
+
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
131
|
+
...internalThrow(wrapperFunc, 'TypeError', `${unhackName(func.name)} is not a constructor`), // throw type error
|
132
|
+
[ Opcodes.end ]
|
133
|
+
);
|
134
|
+
}
|
106
135
|
}
|
107
136
|
|
108
137
|
return [
|
@@ -2233,7 +2262,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2233
2262
|
scope.table = true;
|
2234
2263
|
|
2235
2264
|
let args = decl.arguments;
|
2236
|
-
const wrapperArgc = Prefs.indirectWrapperArgc ??
|
2265
|
+
const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
|
2237
2266
|
if (args.length < wrapperArgc) {
|
2238
2267
|
args = args.concat(new Array(wrapperArgc - args.length).fill(DEFAULT_VALUE()));
|
2239
2268
|
}
|
@@ -2293,39 +2322,14 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2293
2322
|
|
2294
2323
|
...typeSwitch(scope, getNodeType(scope, callee), {
|
2295
2324
|
[TYPES.function]: () => [
|
2296
|
-
|
2325
|
+
...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
|
2326
|
+
...forceDuoValtype(scope, thisWasm, Valtype.f64),
|
2327
|
+
...out,
|
2328
|
+
|
2297
2329
|
[ Opcodes.local_get, calleeLocal ],
|
2298
2330
|
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 ]
|
2331
|
+
[ Opcodes.call_indirect, args.length + 2, 0 ],
|
2332
|
+
...setLastType(scope)
|
2329
2333
|
],
|
2330
2334
|
|
2331
2335
|
default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
|
@@ -2362,16 +2366,12 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2362
2366
|
paramOffset += 4;
|
2363
2367
|
}
|
2364
2368
|
|
2365
|
-
if (func &&
|
2369
|
+
if (func && args.length < paramCount) {
|
2366
2370
|
// too little args, push undefineds
|
2367
|
-
args = args.concat(new Array(paramCount - args.length).fill(DEFAULT_VALUE()));
|
2371
|
+
args = args.concat(new Array(paramCount - (func.hasRestArgument ? 1 : 0) - args.length).fill(DEFAULT_VALUE()));
|
2368
2372
|
}
|
2369
2373
|
|
2370
2374
|
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
2375
|
const restArgs = args.slice(paramCount - 1);
|
2376
2376
|
args = args.slice(0, paramCount - 1);
|
2377
2377
|
args.push({
|
@@ -2385,13 +2385,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2385
2385
|
args = args.slice(0, paramCount);
|
2386
2386
|
}
|
2387
2387
|
|
2388
|
-
if (func && func.throws) scope.throws = true;
|
2389
|
-
|
2390
2388
|
for (let i = 0; i < args.length; i++) {
|
2391
2389
|
const arg = args[i];
|
2392
2390
|
if (Array.isArray(arg)) {
|
2393
2391
|
// if wasm, just append it
|
2394
2392
|
out = out.concat(arg);
|
2393
|
+
|
2394
|
+
if (valtypeBinary !== Valtype.i32 &&
|
2395
|
+
(func && func.params[paramOffset + i * (typedParams ? 2 : 1)] === Valtype.i32)
|
2396
|
+
) {
|
2397
|
+
out.push(...forceDuoValtype(scope, [], Valtype.i32));
|
2398
|
+
}
|
2399
|
+
|
2395
2400
|
continue;
|
2396
2401
|
}
|
2397
2402
|
|
@@ -3662,8 +3667,11 @@ const generateUnary = (scope, decl) => {
|
|
3662
3667
|
case 'delete': {
|
3663
3668
|
if (decl.argument.type === 'MemberExpression') {
|
3664
3669
|
const object = decl.argument.object;
|
3665
|
-
const property = getProperty(decl.argument);
|
3666
3670
|
|
3671
|
+
// disallow `delete super.*`
|
3672
|
+
if (object.type === 'Super') return internalThrow(scope, 'ReferenceError', 'Cannot delete super property', true);
|
3673
|
+
|
3674
|
+
const property = getProperty(decl.argument);
|
3667
3675
|
if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
|
3668
3676
|
|
3669
3677
|
return [
|
@@ -4597,8 +4605,6 @@ const generateLabel = (scope, decl) => {
|
|
4597
4605
|
};
|
4598
4606
|
|
4599
4607
|
const generateThrow = (scope, decl) => {
|
4600
|
-
scope.throws = true;
|
4601
|
-
|
4602
4608
|
let exceptionMode = Prefs.exceptionMode ?? 'stack';
|
4603
4609
|
if (globalThis.precompile) exceptionMode = decl.argument.callee != null ? 'lut' : 'stack';
|
4604
4610
|
|
@@ -5056,11 +5062,7 @@ const toPropertyKey = (scope, wasm, type, computed = false, i32Conv = false) =>
|
|
5056
5062
|
...wasm,
|
5057
5063
|
...type,
|
5058
5064
|
[ 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
|
-
] : [])
|
5065
|
+
...(i32Conv ? forceDuoValtype(scope, [], Valtype.i32) : [])
|
5064
5066
|
] : [
|
5065
5067
|
...wasm,
|
5066
5068
|
...(i32Conv ? [ Opcodes.i32_to_u ] : []),
|
@@ -5203,7 +5205,6 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5203
5205
|
if (decl.property.name === 'name' && hasFuncWithName(name) && !scope.noFastFuncMembers) {
|
5204
5206
|
// eg: __String_prototype_toLowerCase -> toLowerCase
|
5205
5207
|
if (name.startsWith('__')) name = name.split('_').pop();
|
5206
|
-
if (name.startsWith('#indirect_')) name = name.slice(10);
|
5207
5208
|
if (name.startsWith('#')) name = '';
|
5208
5209
|
|
5209
5210
|
return withType(scope, makeString(scope, name, _global, _name, true), TYPES.bytestring);
|
@@ -5620,16 +5621,7 @@ const generateClass = (scope, decl) => {
|
|
5620
5621
|
type: 'Identifier',
|
5621
5622
|
name
|
5622
5623
|
};
|
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
|
-
};
|
5624
|
+
const proto = getObjProp(root, 'prototype');
|
5633
5625
|
|
5634
5626
|
const [ func, out ] = generateFunc(scope, {
|
5635
5627
|
...(body.find(x => x.kind === 'constructor')?.value ?? {
|
@@ -5656,7 +5648,7 @@ const generateClass = (scope, decl) => {
|
|
5656
5648
|
// Bar.__proto__ = Foo
|
5657
5649
|
// Bar.prototype.__proto__ = Foo.prototype
|
5658
5650
|
...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
|
5659
|
-
...generate(scope, setObjProp(
|
5651
|
+
...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype')))
|
5660
5652
|
);
|
5661
5653
|
}
|
5662
5654
|
|
@@ -6339,7 +6331,7 @@ export default program => {
|
|
6339
6331
|
};
|
6340
6332
|
tags = [];
|
6341
6333
|
exceptions = [];
|
6342
|
-
funcs = [];
|
6334
|
+
funcs = []; indirectFuncs = [];
|
6343
6335
|
funcIndex = {};
|
6344
6336
|
depth = [];
|
6345
6337
|
pages = new Map();
|
@@ -6394,6 +6386,7 @@ export default program => {
|
|
6394
6386
|
// todo: these should just be deleted once able
|
6395
6387
|
for (let i = 0; i < funcs.length; i++) {
|
6396
6388
|
const f = funcs[i];
|
6389
|
+
|
6397
6390
|
if (f.wasm) {
|
6398
6391
|
// run callbacks
|
6399
6392
|
const wasm = f.wasm;
|
@@ -6450,9 +6443,15 @@ export default program => {
|
|
6450
6443
|
// }
|
6451
6444
|
// }
|
6452
6445
|
|
6453
|
-
|
6446
|
+
// add indirect funcs to end of funcs
|
6447
|
+
for (let i = 0; i < indirectFuncs.length; i++) {
|
6448
|
+
const f = indirectFuncs[i];
|
6449
|
+
f.index = currentFuncIndex++;
|
6450
|
+
}
|
6451
|
+
|
6452
|
+
funcs.push(...indirectFuncs);
|
6454
6453
|
|
6455
|
-
|
6454
|
+
delete globals['#ind'];
|
6456
6455
|
|
6457
6456
|
return { funcs, globals, tags, exceptions, pages, data };
|
6458
6457
|
};
|
package/package.json
CHANGED