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.
@@ -45,17 +45,23 @@ const funcRef = func => {
45
45
 
46
46
  const wrapperArgc = Prefs.indirectWrapperArgc ?? 10;
47
47
  if (!func.wrapperFunc) {
48
- const locals = {}, params = [];
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 * 2] = { idx: i * 2, type: valtypeBinary };
52
- locals[i * 2 + 1] = { idx: i * 2 + 1, type: Valtype.i32 };
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, 0 ], // new.target value
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 offset = func.constr ? 0 : (func.method ? 2 : 4);
92
- for (let i = 0; i < func.params.length; i++) {
93
- if (func.internal && func.name.includes('_prototype_') && i < 2) {
94
- // special case: use real this for prototype internals
95
- wasm.push(
96
- [ Opcodes.local_get, 2 + i ],
97
- ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
98
- );
99
- } else {
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, offset + (!func.internal || func.typedParams ? i : i * 2) ],
102
- ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
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([ Opcodes.call, func.index ]);
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, 0 ], // new.target value
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
- [ [ TYPES.empty, TYPES.undefined ], [
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
- // TODO: long-term, prototypes should be their individual separate funcs
2241
-
2242
- const rawPointer = [
2243
- ...generate(scope, target),
2244
- Opcodes.i32_to_u
2245
- ];
2246
-
2247
- const usePointerCache = !Object.values(protoCands).every(x => x.noPointerCache === true);
2248
- const getPointer = usePointerCache ? [ [ Opcodes.local_get, pointerLocal ] ] : rawPointer;
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
- [ Opcodes.block, unusedValue ? Blocktype.void : valtypeBinary ],
2346
+ ...ArrayUtil.getLengthI32(getPointer),
2347
+ [ Opcodes.local_set, lengthLocal ],
2348
+
2349
+ [ Opcodes.block, unusedValue && optUnused ? Blocktype.void : valtypeBinary ],
2293
2350
  ...protoOut,
2294
- ...(unusedValue && !optUnused ? [ [ Opcodes.drop ] ] : []),
2295
- [ Opcodes.end ]
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 (Object.hasOwn(funcIndex, name)) {
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
- return [
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, TYPES.empty ]),
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, TYPES.empty ]),
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
- [ [ TYPES.undefined, TYPES.empty ], () => makeString(scope, 'undefined') ],
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
- func.wasm.unshift(
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.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
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
- 0, { parse } = (await import((globalThis.document || globalThis.Deno ? 'https://esm.sh/' : '') + parser));
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 ast = parse(input, {
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
- if (ast.type === 'File') return ast.program;
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) {
@@ -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.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ].includes(x));
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)},` : ''}
@@ -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
- empty: 0x00,
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
@@ -33,7 +33,6 @@ const writeByteStr = (memory, ptr, str) => {
33
33
 
34
34
  const porfToJSValue = ({ memory, funcs, pages }, value, type, override = undefined) => {
35
35
  switch (type) {
36
- case TYPES.empty:
37
36
  case TYPES.undefined:
38
37
  return undefined;
39
38
 
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honk/porffor",
3
- "version": "0.58.3",
3
+ "version": "0.58.5",
4
4
  "exports": "./compiler/wrap.js",
5
5
  "publish": {
6
6
  "exclude": [
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.3",
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"
package/runtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.58.3';
3
+ globalThis.version = '0.58.5';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {