porffor 0.37.24 → 0.37.26

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
  ];
@@ -1143,6 +1174,10 @@ const getType = (scope, _name) => {
1143
1174
  return number(TYPES.undefined, Valtype.i32);
1144
1175
  }
1145
1176
 
1177
+ if (name === 'arguments' && scope.name !== 'main' && !scope.arrow) {
1178
+ return number(TYPES.array, Valtype.i32);
1179
+ }
1180
+
1146
1181
  if (Object.hasOwn(globals, name)) {
1147
1182
  if (globals[name]?.metadata?.type != null) return number(globals[name].metadata.type, Valtype.i32);
1148
1183
 
@@ -1680,6 +1715,20 @@ const setObjProp = (obj, prop, value) => {
1680
1715
  });
1681
1716
  };
1682
1717
 
1718
+ const aliasPrimObjsBC = bc => {
1719
+ const add = (x, y) => {
1720
+ if (bc[x] == null) return;
1721
+
1722
+ // bc[`${x},${y}`] = original;
1723
+
1724
+ // intentionally duplicate to avoid extra bc for prim objs as rarely used
1725
+ bc[y] = bc[x];
1726
+ };
1727
+
1728
+ add(TYPES.boolean, TYPES.booleanobject);
1729
+ add(TYPES.number, TYPES.numberobject);
1730
+ };
1731
+
1683
1732
  const createThisArg = (scope, decl) => {
1684
1733
  const name = mapName(decl.callee?.name);
1685
1734
  if (decl._new) {
@@ -2075,6 +2124,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2075
2124
  // fallback to object prototype impl as a basic prototype chain hack
2076
2125
  if (protoBC[TYPES.object]) def = protoBC[TYPES.object];
2077
2126
 
2127
+ // alias primitive prototype with primitive object types
2128
+ aliasPrimObjsBC(protoBC);
2129
+
2078
2130
  return [
2079
2131
  ...out,
2080
2132
 
@@ -2718,27 +2770,40 @@ const typeUsed = (scope, x) => {
2718
2770
  scope.usedTypes ??= new Set();
2719
2771
  scope.usedTypes.add(x);
2720
2772
  };
2773
+
2721
2774
  const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = false) => {
2775
+ if (typeof bc === 'function') bc = bc();
2776
+
2777
+ let def;
2778
+ if (!Array.isArray(bc)) {
2779
+ def = bc.default;
2780
+ bc = Object.entries(bc);
2781
+
2782
+ // turn keys back into numbers from keys
2783
+ for (const x of bc) {
2784
+ const k = x[0];
2785
+ if (k === 'default') continue;
2786
+
2787
+ // uncomment if needed/used again
2788
+ // x[0] = k.split(',').map(x => +x);
2789
+ x[0] = +k;
2790
+ }
2791
+ }
2792
+
2722
2793
  const known = knownType(scope, type);
2723
2794
  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;
2795
+ for (const [ type, wasm ] of bc) {
2796
+ if (type === 'default') {
2797
+ def = wasm;
2798
+ continue;
2735
2799
  }
2736
2800
 
2737
- return typeof def === 'function' ? def() : def;
2738
- } else {
2739
- const wasm = bc[known] ?? bc.default;
2740
- return typeof wasm === 'function' ? wasm() : wasm;
2801
+ if (type === known || (Array.isArray(type) && type.includes(known))) {
2802
+ return typeof wasm === 'function' ? wasm() : wasm;
2803
+ }
2741
2804
  }
2805
+
2806
+ return typeof def === 'function' ? def() : def;
2742
2807
  }
2743
2808
 
2744
2809
  if (Prefs.typeswitchBrtable) {
@@ -2753,19 +2818,6 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
2753
2818
  [ Opcodes.block, returns ]
2754
2819
  ];
2755
2820
 
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
2821
  for (let i = 0; i < bc.length; i++) {
2770
2822
  let [ types, wasm ] = bc[i];
2771
2823
  if (types === 'default') {
@@ -2837,6 +2889,17 @@ const typeIsOneOf = (type, types, valtype = Valtype.i32) => {
2837
2889
  return out;
2838
2890
  };
2839
2891
 
2892
+ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
2893
+ const out = [];
2894
+
2895
+ for (let i = 0; i < types.length; i++) {
2896
+ out.push(...type, ...number(types[i], valtype), valtype === Valtype.f64 ? [ Opcodes.f64_ne ] : [ Opcodes.i32_ne ]);
2897
+ if (i !== 0) out.push([ Opcodes.i32_and ]);
2898
+ }
2899
+
2900
+ return out;
2901
+ };
2902
+
2840
2903
  const allocVar = (scope, name, global = false, type = true) => {
2841
2904
  const target = global ? globals : scope.locals;
2842
2905
 
@@ -3565,7 +3628,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3565
3628
  // default: internalThrow(scope, 'TypeError', `Cannot assign member with this type`)
3566
3629
  default: () => [
3567
3630
  ...objectWasm,
3568
- Opcodes.i32_to_u,
3631
+ Opcodes.i32_to,
3569
3632
  ...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_object', Valtype.i32) ] ]),
3570
3633
  ...getNodeType(scope, object),
3571
3634
 
@@ -5411,7 +5474,10 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5411
5474
  if (type === known) return bc[type]();
5412
5475
  }
5413
5476
 
5414
- if (known == null) extraBC = bc;
5477
+ if (known == null) {
5478
+ aliasPrimObjsBC(bc);
5479
+ extraBC = bc;
5480
+ }
5415
5481
  }
5416
5482
 
5417
5483
  // todo/perf: use i32 object (and prop?) locals
@@ -5574,7 +5640,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5574
5640
  // default: internalThrow(scope, 'TypeError', 'Unsupported member expression object', true)
5575
5641
  default: () => [
5576
5642
  ...objectWasm,
5577
- Opcodes.i32_to_u,
5643
+ Opcodes.i32_to,
5578
5644
  ...getNodeType(scope, object),
5579
5645
 
5580
5646
  ...toPropertyKey(scope, propertyWasm, getNodeType(scope, property), decl.computed, true),
@@ -5892,6 +5958,7 @@ const generateFunc = (scope, decl) => {
5892
5958
  const params = decl.params ?? [];
5893
5959
 
5894
5960
  // TODO: share scope/locals between !!!
5961
+ const arrow = decl.type === 'ArrowFunctionExpression' || decl.type === 'Program';
5895
5962
  const func = {
5896
5963
  locals: {},
5897
5964
  localInd: 0,
@@ -5899,11 +5966,8 @@ const generateFunc = (scope, decl) => {
5899
5966
  returns: [ valtypeBinary, Valtype.i32 ],
5900
5967
  name,
5901
5968
  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,
5969
+ arrow,
5970
+ constr: !arrow && !decl.generator && !decl.async,
5907
5971
  _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
5908
5972
  strict: scope.strict || decl.strict,
5909
5973
 
@@ -6097,10 +6161,11 @@ const generateFunc = (scope, decl) => {
6097
6161
  TYPES.weakref, TYPES.weakset, TYPES.weakmap,
6098
6162
  TYPES.arraybuffer, TYPES.sharedarraybuffer, TYPES.dataview
6099
6163
  ].includes(typeAnno.type)) {
6164
+ let types = [ typeAnno.type ];
6165
+ if (typeAnno.type === TYPES.number) types.push(TYPES.numberobject);
6166
+
6100
6167
  prelude.push(
6101
- [ Opcodes.local_get, func.locals[name].idx + 1 ],
6102
- ...number(typeAnno.type, Valtype.i32),
6103
- [ Opcodes.i32_ne ],
6168
+ ...typeIsNotOneOf([ [ Opcodes.local_get, func.locals[name].idx + 1 ] ], types),
6104
6169
  [ Opcodes.if, Blocktype.void ],
6105
6170
  ...internalThrow(func, 'TypeError', `${unhackName(func.name)} expects 'this' to be a ${TYPE_NAMES[typeAnno.type]}`),
6106
6171
  [ 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/nova.comp.cjs ADDED
@@ -0,0 +1,3 @@
1
+ const uniq = [...new Set(require('../nova.json').pass.map(x => x.slice(5))).difference(new Set(require('./test262/results.json').passes))];
2
+ console.log([...uniq.reduce((acc, x) => { let k = x.split('/').slice(0, -1).join('/'); return acc.set(k, (acc.get(k) || 0) + 1); }, new Map()).entries()].sort((a, b) => a[1] - b[1]).slice(-20).map(x => x[0] + ': ' + x[1]).join('\n'));
3
+ console.log(uniq.filter(x => x.startsWith('built-ins/Object/defineProperty')).join('\n'))
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.26+4f2db33d1",
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.26+4f2db33d1';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {