porffor 0.58.3 → 0.58.5
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/bun.lock +45 -0
- package/compiler/assemble.js +1 -1
- package/compiler/builtins/_internal_object.ts +7 -10
- package/compiler/builtins/console.ts +0 -2
- package/compiler/builtins/date.ts +4 -1
- package/compiler/builtins/error.js +1 -1
- package/compiler/builtins/object_hiddenPrototype.js +1 -1
- package/compiler/builtins/z_ecma262.ts +2 -6
- package/compiler/builtins_precompiled.js +555 -554
- package/compiler/codegen.js +170 -101
- package/compiler/parse.js +13 -5
- package/compiler/precompile.js +1 -1
- package/compiler/prototype.js +0 -2
- package/compiler/types.js +2 -5
- package/compiler/wrap.js +0 -1
- package/jsr.json +1 -1
- package/package.json +3 -2
- package/runtime/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -45,17 +45,23 @@ const funcRef = func => {
|
|
45
45
|
|
46
46
|
const wrapperArgc = Prefs.indirectWrapperArgc ?? 10;
|
47
47
|
if (!func.wrapperFunc) {
|
48
|
-
const locals = {
|
48
|
+
const locals = {
|
49
|
+
['#length']: { idx: 0, type: Valtype.i32 }
|
50
|
+
}, params = [
|
51
|
+
Valtype.i32
|
52
|
+
];
|
53
|
+
|
49
54
|
for (let i = 0; i < wrapperArgc + 2; i++) {
|
50
55
|
params.push(valtypeBinary, Valtype.i32);
|
51
|
-
locals[i
|
52
|
-
locals[i
|
56
|
+
locals[`#${i}`] = { idx: 1 + i * 2, type: valtypeBinary };
|
57
|
+
locals[`#${i}#type`] = { idx: 2 + i * 2, type: Valtype.i32 };
|
53
58
|
}
|
54
|
-
let localInd = (wrapperArgc + 2) * 2;
|
59
|
+
let localInd = 1 + (wrapperArgc + 2) * 2;
|
55
60
|
|
56
61
|
if (indirectFuncs.length === 0) {
|
57
62
|
// add empty indirect func
|
58
63
|
const emptyFunc = {
|
64
|
+
constr: true, internal: true, indirect: true,
|
59
65
|
name: '#indirect#empty',
|
60
66
|
params,
|
61
67
|
locals: { ...locals }, localInd,
|
@@ -64,9 +70,6 @@ const funcRef = func => {
|
|
64
70
|
number(0),
|
65
71
|
number(0, Valtype.i32)
|
66
72
|
],
|
67
|
-
constr: true,
|
68
|
-
internal: true,
|
69
|
-
indirect: true,
|
70
73
|
wrapperOf: {
|
71
74
|
name: '',
|
72
75
|
jsLength: 0
|
@@ -76,7 +79,7 @@ const funcRef = func => {
|
|
76
79
|
|
77
80
|
// check not being constructed
|
78
81
|
emptyFunc.wasm.unshift(
|
79
|
-
[ Opcodes.local_get,
|
82
|
+
[ Opcodes.local_get, 1 ], // new.target value
|
80
83
|
Opcodes.i32_to_u,
|
81
84
|
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
82
85
|
...internalThrow(emptyFunc, 'TypeError', `Function is not a constructor`), // throw type error
|
@@ -88,27 +91,94 @@ const funcRef = func => {
|
|
88
91
|
}
|
89
92
|
|
90
93
|
const wasm = [];
|
91
|
-
const
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
94
|
+
const name = '#indirect_' + func.name;
|
95
|
+
const wrapperFunc = {
|
96
|
+
constr: true, internal: true, indirect: true,
|
97
|
+
name, params, locals, localInd,
|
98
|
+
returns: [ valtypeBinary, Valtype.i32 ],
|
99
|
+
wasm,
|
100
|
+
wrapperOf: func,
|
101
|
+
indirectIndex: indirectFuncs.length
|
102
|
+
};
|
103
|
+
|
104
|
+
indirectFuncs.push(wrapperFunc);
|
105
|
+
|
106
|
+
wrapperFunc.jsLength = countLength(func);
|
107
|
+
func.wrapperFunc = wrapperFunc;
|
108
|
+
|
109
|
+
const paramCount = countParams(func, name);
|
110
|
+
const args = [];
|
111
|
+
for (let i = 0; i < paramCount - (func.hasRestArgument ? 1 : 0); i++) {
|
112
|
+
args.push({
|
113
|
+
type: 'Identifier',
|
114
|
+
name: `#${i + 2}`
|
115
|
+
});
|
116
|
+
}
|
117
|
+
|
118
|
+
if (func.hasRestArgument) {
|
119
|
+
const array = (wrapperFunc.localInd += 2) - 2;
|
120
|
+
locals['#array#i32'] = { idx: array, type: Valtype.i32 };
|
121
|
+
locals['#array'] = { idx: array + 1, type: valtypeBinary };
|
122
|
+
|
123
|
+
wasm.push(
|
124
|
+
[ Opcodes.call, includeBuiltin(wrapperFunc, '__Porffor_allocate').index ],
|
125
|
+
[ Opcodes.local_tee, array ],
|
126
|
+
Opcodes.i32_from_u,
|
127
|
+
[ Opcodes.local_set, array + 1 ],
|
128
|
+
|
129
|
+
[ Opcodes.local_get, array ],
|
130
|
+
[ Opcodes.local_get, 0 ],
|
131
|
+
number(paramCount - 1, Valtype.i32),
|
132
|
+
[ Opcodes.i32_sub ],
|
133
|
+
[ Opcodes.i32_store, 0, 0 ]
|
134
|
+
);
|
135
|
+
|
136
|
+
let offset = 4;
|
137
|
+
for (let i = paramCount - 1; i < wrapperArgc; i++) {
|
100
138
|
wasm.push(
|
101
|
-
[ Opcodes.local_get,
|
102
|
-
|
139
|
+
[ Opcodes.local_get, array ],
|
140
|
+
[ Opcodes.local_get, 5 + i * 2 ],
|
141
|
+
[ Opcodes.f64_store, 0, offset ],
|
142
|
+
|
143
|
+
[ Opcodes.local_get, array ],
|
144
|
+
[ Opcodes.local_get, 6 + i * 2 ],
|
145
|
+
[ Opcodes.i32_store8, 0, offset + 8 ],
|
103
146
|
);
|
147
|
+
offset += 9;
|
104
148
|
}
|
149
|
+
|
150
|
+
args.push({
|
151
|
+
type: 'SpreadElement',
|
152
|
+
argument: {
|
153
|
+
type: 'Identifier',
|
154
|
+
name: '#array',
|
155
|
+
_type: TYPES.array
|
156
|
+
}
|
157
|
+
});
|
105
158
|
}
|
106
159
|
|
107
|
-
wasm.push(
|
160
|
+
wasm.push(...generate(wrapperFunc, {
|
161
|
+
type: 'CallExpression',
|
162
|
+
callee: {
|
163
|
+
type: 'Identifier',
|
164
|
+
name: func.name
|
165
|
+
},
|
166
|
+
_funcIdx: func.index,
|
167
|
+
arguments: args,
|
168
|
+
_insideIndirect: true,
|
169
|
+
_newTargetWasm: [
|
170
|
+
[ Opcodes.local_get, 1 ],
|
171
|
+
[ Opcodes.local_get, 2 ]
|
172
|
+
],
|
173
|
+
_thisWasm: [
|
174
|
+
[ Opcodes.local_get, 3 ],
|
175
|
+
[ Opcodes.local_get, 4 ]
|
176
|
+
]
|
177
|
+
}));
|
108
178
|
|
109
179
|
if (func.returns[0] === Valtype.i32) {
|
110
180
|
if (func.returns.length === 2) {
|
111
|
-
const localIdx = localInd++;
|
181
|
+
const localIdx = wrapperFunc.localInd++;
|
112
182
|
locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
|
113
183
|
|
114
184
|
wasm.push(
|
@@ -131,29 +201,10 @@ const funcRef = func => {
|
|
131
201
|
wasm.push(number(func.returnType ?? TYPES.number, Valtype.i32));
|
132
202
|
}
|
133
203
|
|
134
|
-
const name = '#indirect_' + func.name;
|
135
|
-
const wrapperFunc = {
|
136
|
-
name,
|
137
|
-
params,
|
138
|
-
locals, localInd,
|
139
|
-
returns: [ valtypeBinary, Valtype.i32 ],
|
140
|
-
wasm,
|
141
|
-
constr: true,
|
142
|
-
internal: true,
|
143
|
-
indirect: true,
|
144
|
-
wrapperOf: func,
|
145
|
-
indirectIndex: indirectFuncs.length
|
146
|
-
};
|
147
|
-
|
148
|
-
indirectFuncs.push(wrapperFunc);
|
149
|
-
|
150
|
-
wrapperFunc.jsLength = countLength(func);
|
151
|
-
func.wrapperFunc = wrapperFunc;
|
152
|
-
|
153
204
|
if (!func.constr) {
|
154
205
|
// check not being constructed
|
155
206
|
wasm.unshift(
|
156
|
-
[ Opcodes.local_get,
|
207
|
+
[ Opcodes.local_get, 1 ], // new.target value
|
157
208
|
Opcodes.i32_to_u,
|
158
209
|
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
159
210
|
// ...internalThrow(wrapperFunc, 'TypeError', `${unhackName(func.name)} is not a constructor`), // throw type error
|
@@ -662,8 +713,6 @@ const generateReturn = (scope, decl) => {
|
|
662
713
|
...(scope.subclass ? [
|
663
714
|
// if subclass and returning undefined, return this
|
664
715
|
[ Opcodes.local_get, localTmp(scope, '#return#type', Valtype.i32) ],
|
665
|
-
number(TYPE_FLAGS.parity, Valtype.i32),
|
666
|
-
[ Opcodes.i32_or ],
|
667
716
|
number(TYPES.undefined, Valtype.i32),
|
668
717
|
[ Opcodes.i32_eq ],
|
669
718
|
[ Opcodes.if, Blocktype.void ],
|
@@ -989,7 +1038,7 @@ const nullish = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
989
1038
|
...(!useTmp ? [] : [ [ Opcodes.local_set, tmp ] ]),
|
990
1039
|
|
991
1040
|
...typeSwitch(scope, type, [
|
992
|
-
[
|
1041
|
+
[ TYPES.undefined, [
|
993
1042
|
// empty
|
994
1043
|
...(!useTmp ? [ [ Opcodes.drop ] ] : []),
|
995
1044
|
number(1, intOut ? Valtype.i32 : valtypeBinary)
|
@@ -2055,7 +2104,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2055
2104
|
name = func.name;
|
2056
2105
|
}
|
2057
2106
|
|
2058
|
-
if (!decl._new && (name === 'eval' || (decl.callee.type === 'SequenceExpression' && decl.callee.expressions.at(-1)?.name === 'eval'))) {
|
2107
|
+
if (!decl._funcIdx && !decl._new && (name === 'eval' || (decl.callee.type === 'SequenceExpression' && decl.callee.expressions.at(-1)?.name === 'eval'))) {
|
2059
2108
|
const known = knownValue(scope, decl.arguments[0]);
|
2060
2109
|
if (known !== unknownValue) {
|
2061
2110
|
// eval('with known/literal string')
|
@@ -2101,7 +2150,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2101
2150
|
}
|
2102
2151
|
}
|
2103
2152
|
|
2104
|
-
if (name === 'Function') {
|
2153
|
+
if (!decl._funcIdx && name === 'Function') {
|
2105
2154
|
const knowns = decl.arguments.map(x => knownValue(scope, x));
|
2106
2155
|
if (knowns.every(x => x !== unknownValue)) {
|
2107
2156
|
// new Function('with known/literal strings')
|
@@ -2237,19 +2286,24 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2237
2286
|
const lengthLocal = localTmp(scope, '__proto_length_cache', Valtype.i32);
|
2238
2287
|
const pointerLocal = localTmp(scope, '__proto_pointer_cache', Valtype.i32);
|
2239
2288
|
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2289
|
+
if (out.length === 0) {
|
2290
|
+
out.push(
|
2291
|
+
...generate(scope, target),
|
2292
|
+
Opcodes.i32_to_u,
|
2293
|
+
[ Opcodes.local_set, pointerLocal ]
|
2294
|
+
);
|
2295
|
+
} else {
|
2296
|
+
out.push(
|
2297
|
+
[ Opcodes.local_get, localTmp(scope, '#proto_target') ],
|
2298
|
+
Opcodes.i32_to_u,
|
2299
|
+
[ Opcodes.local_set, pointerLocal ]
|
2300
|
+
);
|
2301
|
+
}
|
2249
2302
|
|
2250
|
-
const useLengthCache = true; // basically every prototype uses it
|
2251
2303
|
for (const x in protoCands) {
|
2252
2304
|
const protoFunc = protoCands[x];
|
2305
|
+
const getPointer = [ [ Opcodes.local_get, pointerLocal ] ];
|
2306
|
+
|
2253
2307
|
if (protoFunc.noArgRetLength && decl.arguments.length === 0) {
|
2254
2308
|
protoBC[x] = [
|
2255
2309
|
...ArrayUtil.getLength(getPointer),
|
@@ -2289,37 +2343,16 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2289
2343
|
});
|
2290
2344
|
|
2291
2345
|
return [
|
2292
|
-
|
2346
|
+
...ArrayUtil.getLengthI32(getPointer),
|
2347
|
+
[ Opcodes.local_set, lengthLocal ],
|
2348
|
+
|
2349
|
+
[ Opcodes.block, unusedValue && optUnused ? Blocktype.void : valtypeBinary ],
|
2293
2350
|
...protoOut,
|
2294
|
-
|
2295
|
-
[
|
2351
|
+
[ Opcodes.end ],
|
2352
|
+
...(unusedValue && optUnused ? [ number(UNDEFINED) ] : [])
|
2296
2353
|
];
|
2297
2354
|
};
|
2298
2355
|
}
|
2299
|
-
|
2300
|
-
// alias primitive prototype with primitive object types
|
2301
|
-
aliasPrimObjsBC(protoBC);
|
2302
|
-
|
2303
|
-
return [
|
2304
|
-
...(usePointerCache ? [
|
2305
|
-
...rawPointer,
|
2306
|
-
[ Opcodes.local_set, pointerLocal ],
|
2307
|
-
] : []),
|
2308
|
-
|
2309
|
-
...(useLengthCache ? [
|
2310
|
-
...ArrayUtil.getLengthI32(getPointer),
|
2311
|
-
[ Opcodes.local_set, lengthLocal ],
|
2312
|
-
] : []),
|
2313
|
-
|
2314
|
-
...typeSwitch(scope, getNodeType(scope, target), {
|
2315
|
-
...protoBC,
|
2316
|
-
|
2317
|
-
// TODO: error better
|
2318
|
-
default: decl.optional ? withType(scope, [ number(UNDEFINED) ], TYPES.undefined)
|
2319
|
-
: internalThrow(scope, 'TypeError', `'${protoName}' proto func tried to be called on a type without an impl`, !unusedValue)
|
2320
|
-
}, unusedValue ? Blocktype.void : valtypeBinary),
|
2321
|
-
...(unusedValue ? [ number(UNDEFINED) ] : [])
|
2322
|
-
];
|
2323
2356
|
}
|
2324
2357
|
|
2325
2358
|
if (Object.keys(protoBC).length > 0) {
|
@@ -2374,7 +2407,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2374
2407
|
}
|
2375
2408
|
|
2376
2409
|
let idx;
|
2377
|
-
if (
|
2410
|
+
if (decl._funcIdx) {
|
2411
|
+
idx = decl._funcIdx;
|
2412
|
+
} else if (Object.hasOwn(funcIndex, name)) {
|
2378
2413
|
idx = funcIndex[name];
|
2379
2414
|
} else if (scope.name === name) {
|
2380
2415
|
// fallback for own func but with a different var/id name
|
@@ -2503,7 +2538,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2503
2538
|
}
|
2504
2539
|
}
|
2505
2540
|
|
2506
|
-
let callee = decl.callee, callAsNew = decl._new;
|
2541
|
+
let callee = decl.callee, callAsNew = decl._new, sup = false;
|
2507
2542
|
if (callee.type === 'Super') {
|
2508
2543
|
// call super constructor with direct super() call
|
2509
2544
|
callee = getObjProp(callee, 'constructor');
|
@@ -2512,6 +2547,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2512
2547
|
...generate(scope, { type: 'ThisExpression' }),
|
2513
2548
|
...getNodeType(scope, { type: 'ThisExpression' })
|
2514
2549
|
];
|
2550
|
+
sup = true;
|
2515
2551
|
}
|
2516
2552
|
|
2517
2553
|
const newTargetWasm = decl._newTargetWasm ?? createNewTarget(scope, decl, [
|
@@ -2519,32 +2555,35 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2519
2555
|
], callAsNew);
|
2520
2556
|
const thisWasm = decl._thisWasm ?? knownThis ?? createThisArg(scope, decl);
|
2521
2557
|
|
2522
|
-
|
2558
|
+
out = [
|
2523
2559
|
...(getCallee ? getCallee : generate(scope, callee)),
|
2524
2560
|
[ Opcodes.local_set, calleeLocal ],
|
2525
2561
|
|
2526
2562
|
...typeSwitch(scope, getNodeType(scope, callee), {
|
2527
2563
|
[TYPES.function]: () => [
|
2564
|
+
number(10 - underflow, Valtype.i32),
|
2528
2565
|
...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
|
2529
2566
|
...forceDuoValtype(scope, thisWasm, Valtype.f64),
|
2530
2567
|
...out,
|
2531
2568
|
|
2532
2569
|
[ Opcodes.local_get, calleeLocal ],
|
2533
2570
|
Opcodes.i32_to_u,
|
2534
|
-
[ Opcodes.call_indirect, args.length + 2, 0
|
2571
|
+
[ Opcodes.call_indirect, args.length + 2, 0, ],
|
2535
2572
|
...setLastType(scope)
|
2536
2573
|
],
|
2537
2574
|
|
2538
2575
|
default: decl.optional ? withType(scope, [ number(UNDEFINED, Valtype.f64) ], TYPES.undefined)
|
2539
2576
|
: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
|
2540
|
-
}, Valtype.f64)
|
2541
|
-
...(valtypeBinary === Valtype.i32 ? [ Opcodes.i32_trunc_sat_f64_s ] : [])
|
2577
|
+
}, Valtype.f64)
|
2542
2578
|
];
|
2579
|
+
|
2580
|
+
if (valtypeBinary === Valtype.i32) out.push(Opcodes.i32_trunc_sat_f64_s);
|
2581
|
+
if (sup) out.push([ null, 'super marker' ]);
|
2582
|
+
return out;
|
2543
2583
|
}
|
2544
2584
|
|
2545
2585
|
const func = funcByIndex(idx);
|
2546
|
-
|
2547
|
-
if (func && !decl._new) func.onlyNew = false;
|
2586
|
+
if (func && !decl._new && !decl._insideIndirect) func.onlyNew = false;
|
2548
2587
|
|
2549
2588
|
// generate func
|
2550
2589
|
if (func) func.generate?.();
|
@@ -2640,6 +2679,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2640
2679
|
}
|
2641
2680
|
|
2642
2681
|
out.push([ Opcodes.call, idx ]);
|
2682
|
+
if (decl._insideIndirect) return out;
|
2683
|
+
|
2643
2684
|
if (typedReturns) out.push(...setLastType(scope));
|
2644
2685
|
|
2645
2686
|
if (
|
@@ -3270,7 +3311,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
3270
3311
|
|
3271
3312
|
if (defaultValue) {
|
3272
3313
|
out.push(
|
3273
|
-
...typeIsOneOf(getType(scope, name), [ TYPES.undefined
|
3314
|
+
...typeIsOneOf(getType(scope, name), [ TYPES.undefined ]),
|
3274
3315
|
[ Opcodes.if, Blocktype.void ],
|
3275
3316
|
...generate(scope, defaultValue, global, name),
|
3276
3317
|
[ global ? Opcodes.global_set : Opcodes.local_set, idx ],
|
@@ -3418,7 +3459,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
3418
3459
|
out = out.concat([
|
3419
3460
|
// check tmp is valid object
|
3420
3461
|
// not undefined or empty type
|
3421
|
-
...typeIsOneOf(getType(scope, tmpName), [ TYPES.undefined
|
3462
|
+
...typeIsOneOf(getType(scope, tmpName), [ TYPES.undefined ]),
|
3422
3463
|
|
3423
3464
|
// not null
|
3424
3465
|
...getType(scope, tmpName),
|
@@ -4313,7 +4354,7 @@ const generateUnary = (scope, decl) => {
|
|
4313
4354
|
[ TYPES.number, () => makeString(scope, 'number') ],
|
4314
4355
|
[ TYPES.boolean, () => makeString(scope, 'boolean') ],
|
4315
4356
|
[ [ TYPES.string, TYPES.bytestring ], () => makeString(scope, 'string') ],
|
4316
|
-
[
|
4357
|
+
[ TYPES.undefined, () => makeString(scope, 'undefined') ],
|
4317
4358
|
[ TYPES.function, () => makeString(scope, 'function') ],
|
4318
4359
|
[ TYPES.symbol, () => makeString(scope, 'symbol') ],
|
4319
4360
|
|
@@ -6207,14 +6248,33 @@ const generateClass = (scope, decl) => {
|
|
6207
6248
|
const proto = getObjProp(root, 'prototype');
|
6208
6249
|
|
6209
6250
|
const [ func, out ] = generateFunc(scope, {
|
6210
|
-
...(body.find(x => x.kind === 'constructor')?.value ?? {
|
6251
|
+
...(body.find(x => x.kind === 'constructor')?.value ?? (decl.superClass ? {
|
6252
|
+
type: 'FunctionExpression',
|
6253
|
+
params: [
|
6254
|
+
{
|
6255
|
+
type: 'RestElement',
|
6256
|
+
argument: { type: 'Identifier', name: 'args' }
|
6257
|
+
}
|
6258
|
+
],
|
6259
|
+
body: {
|
6260
|
+
type: 'ExpressionStatement',
|
6261
|
+
expression: {
|
6262
|
+
type: 'CallExpression',
|
6263
|
+
callee: { type: 'Super' },
|
6264
|
+
arguments: [ {
|
6265
|
+
type: 'SpreadElement',
|
6266
|
+
argument: { type: 'Identifier', name: 'args' }
|
6267
|
+
} ]
|
6268
|
+
}
|
6269
|
+
}
|
6270
|
+
}: {
|
6211
6271
|
type: 'FunctionExpression',
|
6212
6272
|
params: [],
|
6213
6273
|
body: {
|
6214
6274
|
type: 'BlockStatement',
|
6215
6275
|
body: []
|
6216
6276
|
}
|
6217
|
-
}),
|
6277
|
+
})),
|
6218
6278
|
id: root,
|
6219
6279
|
strict: true,
|
6220
6280
|
type: expr ? 'FunctionExpression' : 'FunctionDeclaration',
|
@@ -6225,6 +6285,13 @@ const generateClass = (scope, decl) => {
|
|
6225
6285
|
// always generate class constructor funcs
|
6226
6286
|
func.generate();
|
6227
6287
|
|
6288
|
+
let constrInsertIndex = func.wasm.findIndex(x => x.at(-1) === 'super marker');
|
6289
|
+
if (constrInsertIndex != -1) {
|
6290
|
+
func.wasm.splice(constrInsertIndex, 1);
|
6291
|
+
} else {
|
6292
|
+
constrInsertIndex = 0;
|
6293
|
+
}
|
6294
|
+
|
6228
6295
|
if (decl.superClass) {
|
6229
6296
|
const superTmp = localTmp(scope, '#superclass');
|
6230
6297
|
const superTypeTmp = localTmp(scope, '#superclass#type', Valtype.i32);
|
@@ -6287,6 +6354,7 @@ const generateClass = (scope, decl) => {
|
|
6287
6354
|
scope.overrideThis = generate(scope, root);
|
6288
6355
|
scope.overrideThisType = TYPES.function;
|
6289
6356
|
|
6357
|
+
let constrAdd = [];
|
6290
6358
|
for (const x of body) {
|
6291
6359
|
let { type, value, kind, static: _static, computed } = x;
|
6292
6360
|
if (kind === 'constructor') continue;
|
@@ -6351,7 +6419,7 @@ const generateClass = (scope, decl) => {
|
|
6351
6419
|
);
|
6352
6420
|
}
|
6353
6421
|
|
6354
|
-
|
6422
|
+
const constrWasm = [
|
6355
6423
|
...generate(func, object),
|
6356
6424
|
Opcodes.i32_to_u,
|
6357
6425
|
...getNodeType(func, object),
|
@@ -6370,7 +6438,10 @@ const generateClass = (scope, decl) => {
|
|
6370
6438
|
...getNodeType(func, value),
|
6371
6439
|
|
6372
6440
|
[ Opcodes.call, includeBuiltin(func, `__Porffor_object_class_${initKind}`).index ]
|
6373
|
-
|
6441
|
+
];
|
6442
|
+
|
6443
|
+
func.wasm.splice(constrInsertIndex, 0, ...constrWasm);
|
6444
|
+
constrInsertIndex += constrWasm.length;
|
6374
6445
|
} else {
|
6375
6446
|
out.push(
|
6376
6447
|
...generate(scope, object),
|
@@ -6727,8 +6798,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
|
|
6727
6798
|
[ Opcodes.i32_ne ],
|
6728
6799
|
[ Opcodes.if, Blocktype.void ],
|
6729
6800
|
[ Opcodes.local_get, func.locals[name].idx + 1 ],
|
6730
|
-
number(TYPE_FLAGS.parity, Valtype.i32),
|
6731
|
-
[ Opcodes.i32_or ],
|
6732
6801
|
number(TYPES.undefined, Valtype.i32),
|
6733
6802
|
[ Opcodes.i32_eq ],
|
6734
6803
|
|
@@ -7161,7 +7230,7 @@ export default program => {
|
|
7161
7230
|
data = [];
|
7162
7231
|
currentFuncIndex = importedFuncs.length;
|
7163
7232
|
typeswitchDepth = 0;
|
7164
|
-
usedTypes = new Set([ TYPES.
|
7233
|
+
usedTypes = new Set([ TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
|
7165
7234
|
coctc = new Map();
|
7166
7235
|
globalInfer = new Map();
|
7167
7236
|
|
package/compiler/parse.js
CHANGED
@@ -11,21 +11,24 @@ globalThis.typedInput = types && Prefs.optTypes;
|
|
11
11
|
// - meriyah
|
12
12
|
// - hermes-parser
|
13
13
|
// - @babel/parser
|
14
|
+
// - oxc-parser
|
14
15
|
|
15
16
|
globalThis.parser = '';
|
16
17
|
let parse;
|
17
18
|
const loadParser = async (fallbackParser = 'acorn', forceParser) => {
|
18
19
|
parser = forceParser ?? Prefs.parser ?? fallbackParser;
|
19
|
-
|
20
|
+
const mod = (await import((globalThis.document || globalThis.Deno ? 'https://esm.sh/' : '') + parser));
|
21
|
+
if (mod.parseSync) parse = mod.parseSync;
|
22
|
+
else parse = mod.parse;
|
20
23
|
};
|
21
24
|
globalThis._porf_loadParser = loadParser;
|
22
25
|
await loadParser(types ? '@babel/parser' : undefined);
|
23
26
|
|
24
|
-
if (types && !['@babel/parser', 'hermes-parser'].includes(parser)) log.warning('parse', `passed -parse-types with a parser (${parser}) which does not support`);
|
27
|
+
if (types && !['@babel/parser', 'hermes-parser', 'oxc-parser'].includes(parser)) log.warning('parse', `passed -parse-types with a parser (${parser}) which does not support`);
|
25
28
|
|
26
29
|
export default input => {
|
27
30
|
try {
|
28
|
-
const
|
31
|
+
const options = {
|
29
32
|
// acorn
|
30
33
|
ecmaVersion: 'latest',
|
31
34
|
|
@@ -43,9 +46,14 @@ export default input => {
|
|
43
46
|
ranges: false,
|
44
47
|
tokens: false,
|
45
48
|
comments: false,
|
46
|
-
});
|
47
49
|
|
48
|
-
|
50
|
+
// oxc
|
51
|
+
lang: types ? 'ts' : 'js',
|
52
|
+
showSemanticErrors: true // sorry oxc pals but this default is bad
|
53
|
+
};
|
54
|
+
|
55
|
+
let ast = parser === 'oxc-parser' ? parse('js', input, options) : parse(input, options);
|
56
|
+
if (ast.program) ast = ast.program;
|
49
57
|
|
50
58
|
return ast;
|
51
59
|
} catch (e) {
|
package/compiler/precompile.js
CHANGED
@@ -277,7 +277,7 @@ ${funcs.map(x => {
|
|
277
277
|
// todo: check for other identifier unsafe characters
|
278
278
|
const name = x.name.includes('#') ? `['${x.name}']` : `.${x.name}`;
|
279
279
|
|
280
|
-
const returnTypes = [...(x.returnTypes ?? [])].filter(x => ![ TYPES.
|
280
|
+
const returnTypes = [...(x.returnTypes ?? [])].filter(x => ![ TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ].includes(x));
|
281
281
|
return `this${name} = {
|
282
282
|
wasm:${rewriteWasm(x.wasm)},
|
283
283
|
params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)},` : ''}${returnTypes.length > 0 ? `returnTypes:${JSON.stringify(returnTypes)},` : ''}
|
package/compiler/prototype.js
CHANGED
@@ -320,7 +320,6 @@ export const PrototypeFuncs = function() {
|
|
320
320
|
this[TYPES.string].at.local2 = Valtype.i32;
|
321
321
|
this[TYPES.string].charAt.local = Valtype.i32;
|
322
322
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
323
|
-
this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
324
323
|
|
325
324
|
this[TYPES.bytestring] = {
|
326
325
|
at: ({ pointer, length, arg, iTmp, iTmp2, alloc, setType }) => [
|
@@ -454,5 +453,4 @@ export const PrototypeFuncs = function() {
|
|
454
453
|
this[TYPES.bytestring].at.local2 = Valtype.i32;
|
455
454
|
this[TYPES.bytestring].charAt.local = Valtype.i32;
|
456
455
|
this[TYPES.bytestring].charCodeAt.local = Valtype.i32;
|
457
|
-
this[TYPES.bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
458
456
|
};
|
package/compiler/types.js
CHANGED
@@ -6,20 +6,17 @@ export const TYPE_FLAGS = {
|
|
6
6
|
};
|
7
7
|
|
8
8
|
export const TYPES = {
|
9
|
-
|
9
|
+
undefined: 0x00,
|
10
10
|
number: 0x01,
|
11
11
|
boolean: 0x02,
|
12
12
|
string: 0x03 | TYPE_FLAGS.length,
|
13
13
|
bigint: 0x04,
|
14
14
|
symbol: 0x05,
|
15
15
|
function: 0x06,
|
16
|
-
object: 0x07
|
17
|
-
|
18
|
-
undefined: 0x00 | TYPE_FLAGS.parity,
|
16
|
+
object: 0x07
|
19
17
|
};
|
20
18
|
|
21
19
|
export const TYPE_NAMES = {
|
22
|
-
[TYPES.empty]: 'empty',
|
23
20
|
[TYPES.number]: 'Number',
|
24
21
|
[TYPES.boolean]: 'Boolean',
|
25
22
|
[TYPES.string]: 'String',
|
package/compiler/wrap.js
CHANGED
package/jsr.json
CHANGED
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "An ahead-of-time JavaScript compiler",
|
4
|
-
"version": "0.58.
|
4
|
+
"version": "0.58.5",
|
5
5
|
"author": "Oliver Medhurst <honk@goose.icu>",
|
6
6
|
"license": "MIT",
|
7
7
|
"scripts": {},
|
@@ -12,7 +12,8 @@
|
|
12
12
|
"optionalDependencies": {
|
13
13
|
"@babel/parser": "^7.24.4",
|
14
14
|
"hermes-parser": "^0.18.2",
|
15
|
-
"meriyah": "^4.3.9"
|
15
|
+
"meriyah": "^4.3.9",
|
16
|
+
"oxc-parser": "^0.72.2"
|
16
17
|
},
|
17
18
|
"bin": {
|
18
19
|
"porf": "./runtime/index.js"
|