porffor 0.37.24 → 0.37.25

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.
@@ -357,6 +357,13 @@ const generateIdent = (scope, decl) => {
357
357
  }
358
358
 
359
359
  if (local?.idx === undefined) {
360
+ if (name === 'arguments' && scope.name !== 'main' && !scope.arrow) {
361
+ // todo: stub arguments as [] for now :)
362
+ return generateArray(scope, {
363
+ elements: []
364
+ }, false, '#arguments');
365
+ }
366
+
360
367
  // no local var with name
361
368
  if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name].idx ] ];
362
369
 
@@ -559,7 +566,8 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
559
566
  const useTmp = knownType(scope, type) == null;
560
567
  const tmp = useTmp && localTmp(scope, `#logicinner_tmp${intIn ? '_int' : ''}`, intIn ? Valtype.i32 : valtypeBinary);
561
568
 
562
- const def = (truthyMode => {
569
+ const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
570
+ const def = (() => {
563
571
  if (truthyMode === 'full') return [
564
572
  // if value != 0 or NaN
565
573
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
@@ -584,7 +592,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
584
592
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
585
593
  ...(!intOut || (intIn && intOut) ? [] : [ Opcodes.i32_to_u ])
586
594
  ];
587
- })(forceTruthyMode ?? Prefs.truthy ?? 'full');
595
+ })();
588
596
 
589
597
  return [
590
598
  ...wasm,
@@ -603,6 +611,17 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
603
611
  [ Opcodes.i32_eqz ], */
604
612
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
605
613
  ] ],
614
+ // [ [ TYPES.boolean, TYPES.number, TYPES.object, TYPES.undefined, TYPES.empty ], def ],
615
+ // [ 'default', [
616
+ // // other types are always truthy
617
+ // ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
618
+ // ...number(1, intOut ? Valtype.i32 : valtypeBinary)
619
+ // ] ]
620
+ ...(truthyMode === 'full' ? [ [ [ TYPES.booleanobject, TYPES.numberobject ], [
621
+ // always truthy :))
622
+ ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
623
+ ...number(1, intOut ? Valtype.i32 : valtypeBinary)
624
+ ] ] ] : []),
606
625
  [ 'default', def ]
607
626
  ], intOut ? Valtype.i32 : valtypeBinary)
608
627
  ];
@@ -612,7 +631,8 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode
612
631
  const useTmp = knownType(scope, type) == null;
613
632
  const tmp = useTmp && localTmp(scope, `#logicinner_tmp${intIn ? '_int' : ''}`, intIn ? Valtype.i32 : valtypeBinary);
614
633
 
615
- const def = (truthyMode => {
634
+ const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
635
+ const def = (() => {
616
636
  if (truthyMode === 'full') return [
617
637
  // if value == 0 or NaN
618
638
  ...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
@@ -638,7 +658,7 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode
638
658
  ...(intIn ? [ [ Opcodes.i32_eqz ] ] : [ ...Opcodes.eqz ]),
639
659
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
640
660
  ];
641
- })(forceTruthyMode ?? Prefs.truthy ?? 'full');
661
+ })();
642
662
 
643
663
  return [
644
664
  ...wasm,
@@ -656,6 +676,17 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode
656
676
  [ Opcodes.i32_eqz ],
657
677
  ...(intOut ? [] : [ Opcodes.i32_from_u ])
658
678
  ] ],
679
+ // [ [ TYPES.boolean, TYPES.number, TYPES.object, TYPES.undefined, TYPES.empty ], def ],
680
+ // [ 'default', [
681
+ // // other types are always truthy
682
+ // ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
683
+ // ...number(0, intOut ? Valtype.i32 : valtypeBinary)
684
+ // ] ]
685
+ ...(truthyMode === 'full' ? [ [ [ TYPES.booleanobject, TYPES.numberobject ], [
686
+ // always truthy :))
687
+ ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
688
+ ...number(0, intOut ? Valtype.i32 : valtypeBinary)
689
+ ] ] ] : []),
659
690
  [ 'default', def ]
660
691
  ], intOut ? Valtype.i32 : valtypeBinary)
661
692
  ];
@@ -1680,6 +1711,20 @@ const setObjProp = (obj, prop, value) => {
1680
1711
  });
1681
1712
  };
1682
1713
 
1714
+ const aliasPrimObjsBC = bc => {
1715
+ const add = (x, y) => {
1716
+ if (bc[x] == null) return;
1717
+
1718
+ // bc[`${x},${y}`] = original;
1719
+
1720
+ // intentionally duplicate to avoid extra bc for prim objs as rarely used
1721
+ bc[y] = bc[x];
1722
+ };
1723
+
1724
+ add(TYPES.boolean, TYPES.booleanobject);
1725
+ add(TYPES.number, TYPES.numberobject);
1726
+ };
1727
+
1683
1728
  const createThisArg = (scope, decl) => {
1684
1729
  const name = mapName(decl.callee?.name);
1685
1730
  if (decl._new) {
@@ -2075,6 +2120,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2075
2120
  // fallback to object prototype impl as a basic prototype chain hack
2076
2121
  if (protoBC[TYPES.object]) def = protoBC[TYPES.object];
2077
2122
 
2123
+ // alias primitive prototype with primitive object types
2124
+ aliasPrimObjsBC(protoBC);
2125
+
2078
2126
  return [
2079
2127
  ...out,
2080
2128
 
@@ -2718,27 +2766,40 @@ const typeUsed = (scope, x) => {
2718
2766
  scope.usedTypes ??= new Set();
2719
2767
  scope.usedTypes.add(x);
2720
2768
  };
2769
+
2721
2770
  const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = false) => {
2771
+ if (typeof bc === 'function') bc = bc();
2772
+
2773
+ let def;
2774
+ if (!Array.isArray(bc)) {
2775
+ def = bc.default;
2776
+ bc = Object.entries(bc);
2777
+
2778
+ // turn keys back into numbers from keys
2779
+ for (const x of bc) {
2780
+ const k = x[0];
2781
+ if (k === 'default') continue;
2782
+
2783
+ // uncomment if needed/used again
2784
+ // x[0] = k.split(',').map(x => +x);
2785
+ x[0] = +k;
2786
+ }
2787
+ }
2788
+
2722
2789
  const known = knownType(scope, type);
2723
2790
  if (known != null) {
2724
- if (Array.isArray(bc)) {
2725
- let def;
2726
- for (const [ type, wasm ] of bc) {
2727
- if (type === 'default') {
2728
- def = wasm;
2729
- continue;
2730
- }
2731
-
2732
- if (Array.isArray(type)) {
2733
- if (type.includes(known)) return typeof wasm === 'function' ? wasm() : wasm;
2734
- } else if (type === known) return typeof wasm === 'function' ? wasm() : wasm;
2791
+ for (const [ type, wasm ] of bc) {
2792
+ if (type === 'default') {
2793
+ def = wasm;
2794
+ continue;
2735
2795
  }
2736
2796
 
2737
- return typeof def === 'function' ? def() : def;
2738
- } else {
2739
- const wasm = bc[known] ?? bc.default;
2740
- return typeof wasm === 'function' ? wasm() : wasm;
2797
+ if (type === known || (Array.isArray(type) && type.includes(known))) {
2798
+ return typeof wasm === 'function' ? wasm() : wasm;
2799
+ }
2741
2800
  }
2801
+
2802
+ return typeof def === 'function' ? def() : def;
2742
2803
  }
2743
2804
 
2744
2805
  if (Prefs.typeswitchBrtable) {
@@ -2753,19 +2814,6 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
2753
2814
  [ Opcodes.block, returns ]
2754
2815
  ];
2755
2816
 
2756
- if (typeof bc === 'function') bc = bc();
2757
-
2758
- let def;
2759
- if (!Array.isArray(bc)) {
2760
- def = bc.default;
2761
- bc = Object.entries(bc);
2762
-
2763
- // turn keys back into numbers from keys
2764
- for (const x of bc) {
2765
- if (x[0] !== 'default') x[0] = +x[0];
2766
- }
2767
- }
2768
-
2769
2817
  for (let i = 0; i < bc.length; i++) {
2770
2818
  let [ types, wasm ] = bc[i];
2771
2819
  if (types === 'default') {
@@ -2837,6 +2885,17 @@ const typeIsOneOf = (type, types, valtype = Valtype.i32) => {
2837
2885
  return out;
2838
2886
  };
2839
2887
 
2888
+ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
2889
+ const out = [];
2890
+
2891
+ for (let i = 0; i < types.length; i++) {
2892
+ out.push(...type, ...number(types[i], valtype), valtype === Valtype.f64 ? [ Opcodes.f64_ne ] : [ Opcodes.i32_ne ]);
2893
+ if (i !== 0) out.push([ Opcodes.i32_and ]);
2894
+ }
2895
+
2896
+ return out;
2897
+ };
2898
+
2840
2899
  const allocVar = (scope, name, global = false, type = true) => {
2841
2900
  const target = global ? globals : scope.locals;
2842
2901
 
@@ -5411,7 +5470,10 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5411
5470
  if (type === known) return bc[type]();
5412
5471
  }
5413
5472
 
5414
- if (known == null) extraBC = bc;
5473
+ if (known == null) {
5474
+ aliasPrimObjsBC(bc);
5475
+ extraBC = bc;
5476
+ }
5415
5477
  }
5416
5478
 
5417
5479
  // todo/perf: use i32 object (and prop?) locals
@@ -5892,6 +5954,7 @@ const generateFunc = (scope, decl) => {
5892
5954
  const params = decl.params ?? [];
5893
5955
 
5894
5956
  // TODO: share scope/locals between !!!
5957
+ const arrow = decl.type === 'ArrowFunctionExpression' || decl.type === 'Program';
5895
5958
  const func = {
5896
5959
  locals: {},
5897
5960
  localInd: 0,
@@ -5899,11 +5962,8 @@ const generateFunc = (scope, decl) => {
5899
5962
  returns: [ valtypeBinary, Valtype.i32 ],
5900
5963
  name,
5901
5964
  index: currentFuncIndex++,
5902
- constr:
5903
- // not arrow function or main
5904
- (decl.type && decl.type !== 'ArrowFunctionExpression' && decl.type !== 'Program') &&
5905
- // not async or generator
5906
- !decl.async && !decl.generator,
5965
+ arrow,
5966
+ constr: !arrow && !decl.generator && !decl.async,
5907
5967
  _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
5908
5968
  strict: scope.strict || decl.strict,
5909
5969
 
@@ -6097,10 +6157,11 @@ const generateFunc = (scope, decl) => {
6097
6157
  TYPES.weakref, TYPES.weakset, TYPES.weakmap,
6098
6158
  TYPES.arraybuffer, TYPES.sharedarraybuffer, TYPES.dataview
6099
6159
  ].includes(typeAnno.type)) {
6160
+ let types = [ typeAnno.type ];
6161
+ if (typeAnno.type === TYPES.number) types.push(TYPES.numberobject);
6162
+
6100
6163
  prelude.push(
6101
- [ Opcodes.local_get, func.locals[name].idx + 1 ],
6102
- ...number(typeAnno.type, Valtype.i32),
6103
- [ Opcodes.i32_ne ],
6164
+ ...typeIsNotOneOf([ [ Opcodes.local_get, func.locals[name].idx + 1 ] ], types),
6104
6165
  [ Opcodes.if, Blocktype.void ],
6105
6166
  ...internalThrow(func, 'TypeError', `${unhackName(func.name)} expects 'this' to be a ${TYPE_NAMES[typeAnno.type]}`),
6106
6167
  [ Opcodes.end ]
package/compiler/types.js CHANGED
@@ -74,6 +74,9 @@ registerInternalType('WeakMap');
74
74
 
75
75
  registerInternalType('Promise');
76
76
 
77
+ registerInternalType('BooleanObject');
78
+ registerInternalType('NumberObject');
79
+
77
80
  if (Prefs.largestTypes) {
78
81
  const typeKeys = Object.keys(TYPES);
79
82
  const typeVals = Object.values(TYPES);
package/compiler/wrap.js CHANGED
@@ -41,7 +41,12 @@ const porfToJSValue = ({ memory, funcs, pages }, value, type, override = undefin
41
41
  case TYPES.undefined:
42
42
  return undefined;
43
43
 
44
+ case TYPES.number: return value;
45
+ case TYPES.numberobject: return new Number(value);
46
+
44
47
  case TYPES.boolean: return Boolean(value);
48
+ case TYPES.booleanobject: return new Boolean(value);
49
+
45
50
  case TYPES.object: {
46
51
  if (value === 0 || checkOOB(memory, value)) return null;
47
52
 
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.37.24+5dd7ec92f",
4
+ "version": "0.37.25+8558a306e",
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.37.24+5dd7ec92f';
3
+ globalThis.version = '0.37.25+8558a306e';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {