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.
@@ -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 ?? 6;
59
- if (func.returns.length === 2 && countParams(func) < wrapperArgc && !func.wrapperFunc) {
59
+ const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
60
+ if (!func.wrapperFunc) {
60
61
  const locals = {}, params = [];
61
- for (let i = 0; i < wrapperArgc + (func.constr ? 2 : 0); i++) {
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 + (func.constr ? 2 : 0)) * 2;
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
- wasm.push(
71
- [ Opcodes.local_get, i ],
72
- ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
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
- const localIdx = localInd++;
80
- locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
117
+ if (func.returns.length === 2) {
118
+ const localIdx = localInd++;
119
+ locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
81
120
 
82
- wasm.push(
83
- [ Opcodes.local_set, localIdx ],
84
- Opcodes.i32_from,
85
- [ Opcodes.local_get, localIdx ]
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: func.constr,
143
+ constr: true,
97
144
  internal: true,
98
- index: currentFuncIndex++
145
+ indirect: true
99
146
  };
100
147
 
101
- funcs.push(wrapperFunc);
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
- // ignore return value and return this if being constructed
407
- // todo: only do this when trying to return a primitive?
408
- out.push(
409
- // ...truthy(scope, [ [ Opcodes.local_get, scope.locals['#newtarget'].idx ] ], [ [ Opcodes.local_get, scope.locals['#newtarget#type'].idx ] ], false, true),
410
- [ Opcodes.local_get, scope.locals['#newtarget'].idx ],
411
- Opcodes.i32_to_u,
412
- [ Opcodes.if, Blocktype.void ],
413
- [ Opcodes.local_get, scope.locals['#this'].idx ],
414
- ...(scope.returnType != null ? [] : [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ]),
415
- [ Opcodes.return ],
416
- [ Opcodes.end ]
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
- out.push(
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 ?? 6;
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
- // get if func we are calling is a constructor or not
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
- ...number(48, Valtype.i32),
2300
- [ Opcodes.i32_mul ],
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 && !func.hasRestArgument && args.length < paramCount) {
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 generateThrow = (scope, decl) => {
4600
- scope.throws = true;
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
- if (exceptionMode === 'stack') {
4635
- if (tags.length === 0) tags.push({
4636
- params: [ valtypeBinary, Valtype.i32 ],
4637
- results: [],
4638
- idx: tags.length
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(getObjProp(root, 'prototype'), '__proto__', getObjProp(decl.superClass, 'prototype')))
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
- delete globals['#ind'];
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
- // console.log([...usedTypes].map(x => TYPE_NAMES[x]));
6530
+ delete globals['#ind'];
6456
6531
 
6457
6532
  return { funcs, globals, tags, exceptions, pages, data };
6458
6533
  };
@@ -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
- if (exceptionMode === 'stack') {
524
- const value = e.getArg(exceptTag, 0);
525
- const type = e.getArg(exceptTag, 1);
523
+ const value = e.getArg(exceptTag, 0);
524
+ const type = e.getArg(exceptTag, 1);
526
525
 
527
- throw porfToJSValue({ memory, funcs, pages }, value, type);
528
- }
526
+ throw porfToJSValue({ memory, funcs, pages }, value, type);
529
527
  }
530
528
 
531
529
  if (e instanceof WebAssembly.RuntimeError) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.41.7+89be416c1",
4
+ "version": "0.42.1+240c1785e",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.41.7+89be416c1';
3
+ globalThis.version = '0.42.1+240c1785e';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {