porffor 0.55.22 → 0.55.23

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.
@@ -1539,7 +1539,7 @@ const getNodeType = (scope, node) => {
1539
1539
  return getType(scope, node.name);
1540
1540
  }
1541
1541
 
1542
- if (node.type === 'ObjectExpression') {
1542
+ if (node.type === 'ObjectExpression' || node.type === 'Super') {
1543
1543
  return TYPES.object;
1544
1544
  }
1545
1545
 
@@ -1571,24 +1571,6 @@ const getNodeType = (scope, node) => {
1571
1571
  if (Object.hasOwn(builtinFuncs, name) && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
1572
1572
  if (Object.hasOwn(internalConstrs, name) && internalConstrs[name].type != null) return internalConstrs[name].type;
1573
1573
 
1574
- // check if this is a prototype function
1575
- // if so and there is only one impl (eg charCodeAt)
1576
- // or all impls have the same return type
1577
- // use that return type as that is the only possibility
1578
- // (if non-matching type it would error out)
1579
- if (name.startsWith('__')) {
1580
- const spl = name.slice(2).split('_');
1581
-
1582
- const func = spl[spl.length - 1];
1583
- const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
1584
- if (
1585
- protoFuncs.length === 1 ||
1586
- (protoFuncs.length > 1 && protoFuncs.every(x => x.returnType === protoFuncs[0].returnType))
1587
- ) {
1588
- if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
1589
- }
1590
- }
1591
-
1592
1574
  if (name.startsWith('__Porffor_wasm_')) {
1593
1575
  // todo: return undefined for non-returning ops
1594
1576
  return TYPES.number;
@@ -1860,29 +1842,6 @@ const createNewTarget = (scope, decl, idx = 0, force = false) => {
1860
1842
  ];
1861
1843
  };
1862
1844
 
1863
- const makeObject = (scope, obj) => {
1864
- const properties = [];
1865
- for (const x in obj) {
1866
- properties.push({
1867
- type: 'Property',
1868
- method: false,
1869
- shorthand: false,
1870
- computed: false,
1871
- key: {
1872
- type: 'Identifier',
1873
- name: x
1874
- },
1875
- value: obj[x],
1876
- kind: 'init'
1877
- });
1878
- }
1879
-
1880
- return generate(scope, {
1881
- type: 'ObjectExpression',
1882
- properties
1883
- });
1884
- };
1885
-
1886
1845
  const getObjProp = (obj, prop) => {
1887
1846
  if (typeof obj === 'string') obj = {
1888
1847
  type: 'Identifier',
@@ -1967,32 +1926,22 @@ const createThisArg = (scope, decl) => {
1967
1926
  number(TYPES.object, Valtype.i32)
1968
1927
  ];
1969
1928
 
1970
- // create new object with __proto__ set to callee prototype
1929
+ // create new object with prototype set to callee prototype
1971
1930
  const tmp = localTmp(scope, '#this_create_tmp');
1972
1931
  const proto = getObjProp(decl.callee, 'prototype');
1973
1932
 
1974
1933
  return [
1975
- ...makeObject(scope, {}),
1934
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_allocate').index ],
1935
+ Opcodes.i32_from_u,
1976
1936
  [ Opcodes.local_tee, tmp ],
1977
1937
  Opcodes.i32_to_u,
1978
-
1979
1938
  number(TYPES.object, Valtype.i32),
1980
1939
 
1981
- ...generate(scope, {
1982
- type: 'Literal',
1983
- value: '__proto__'
1984
- }),
1985
- Opcodes.i32_to_u,
1986
- number(TYPES.bytestring, Valtype.i32),
1987
-
1988
1940
  ...generate(scope, proto),
1941
+ Opcodes.i32_to_u,
1989
1942
  ...getNodeType(scope, proto),
1990
1943
 
1991
- // flags: writable
1992
- number(0b1000, Valtype.i32),
1993
- number(TYPES.number, Valtype.i32),
1994
-
1995
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
1944
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_object_setPrototype').index ],
1996
1945
 
1997
1946
  [ Opcodes.local_get, tmp ],
1998
1947
  number(TYPES.object, Valtype.i32)
@@ -2353,30 +2302,34 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2353
2302
  const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
2354
2303
 
2355
2304
  let optUnused = false;
2356
- const protoOut = protoFunc(getPointer, {
2357
- getCachedI32: () => [ [ Opcodes.local_get, lengthLocal ] ],
2358
- setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
2359
- get: () => ArrayUtil.getLength(getPointer),
2360
- getI32: () => ArrayUtil.getLengthI32(getPointer),
2361
- set: value => ArrayUtil.setLength(getPointer, value),
2362
- setI32: value => ArrayUtil.setLengthI32(getPointer, value)
2363
- },
2364
- generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
2365
- getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
2366
- protoLocal, protoLocal2,
2367
- bytes => [
2368
- number(bytes, Valtype.i32),
2369
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_allocateBytes').index ]
2370
- ],
2371
- () => {
2372
- optUnused = true;
2373
- return unusedValue;
2305
+ const protoOut = protoFunc({
2306
+ pointer: getPointer,
2307
+ length: {
2308
+ getCachedI32: () => [ [ Opcodes.local_get, lengthLocal ] ],
2309
+ setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
2310
+ get: () => ArrayUtil.getLength(getPointer),
2311
+ getI32: () => ArrayUtil.getLengthI32(getPointer),
2312
+ set: value => ArrayUtil.setLength(getPointer, value),
2313
+ setI32: value => ArrayUtil.setLengthI32(getPointer, value)
2314
+ },
2315
+ arg: generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
2316
+ argType: getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
2317
+ iTmp: protoLocal,
2318
+ iTmp2: protoLocal2,
2319
+ alloc: bytes => [
2320
+ number(bytes, Valtype.i32),
2321
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_allocateBytes').index ]
2322
+ ],
2323
+ unusedValue: () => {
2324
+ optUnused = true;
2325
+ return unusedValue;
2326
+ },
2327
+ setType: type => setLastType(scope, type)
2374
2328
  });
2375
2329
 
2376
2330
  return [
2377
2331
  [ Opcodes.block, unusedValue ? Blocktype.void : valtypeBinary ],
2378
2332
  ...protoOut,
2379
- ...(unusedValue && optUnused ? [] : (protoFunc.returnType != null ? setLastType(scope, protoFunc.returnType) : setLastType(scope))),
2380
2333
  ...(unusedValue && !optUnused ? [ [ Opcodes.drop ] ] : []),
2381
2334
  [ Opcodes.end ]
2382
2335
  ];
@@ -2774,8 +2727,19 @@ const generateThis = (scope, decl) => {
2774
2727
  ];
2775
2728
  };
2776
2729
 
2777
- const generateSuper = (scope, decl) => generate(scope,
2778
- getObjProp(getObjProp({ type: 'ThisExpression', _noGlobalThis: true }, '__proto__'), '__proto__'));
2730
+ const generateSuper = (scope, decl) => generate(scope, {
2731
+ type: 'CallExpression',
2732
+ callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
2733
+ arguments: [
2734
+ {
2735
+ type: 'CallExpression',
2736
+ callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
2737
+ arguments: [
2738
+ { type: 'ThisExpression', _noGlobalThis: true }
2739
+ ]
2740
+ }
2741
+ ]
2742
+ });
2779
2743
 
2780
2744
  // bad hack for undefined and null working without additional logic
2781
2745
  const DEFAULT_VALUE = () => ({
@@ -4887,7 +4851,7 @@ const generateForIn = (scope, decl) => {
4887
4851
 
4888
4852
  // get length
4889
4853
  [ Opcodes.local_get, pointer ],
4890
- [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
4854
+ [ Opcodes.i32_load16_u, 0, 0 ],
4891
4855
  [ Opcodes.local_tee, length ],
4892
4856
 
4893
4857
  [ Opcodes.if, Blocktype.void ]
@@ -4920,7 +4884,7 @@ const generateForIn = (scope, decl) => {
4920
4884
 
4921
4885
  // read key
4922
4886
  [ Opcodes.local_get, pointer ],
4923
- [ Opcodes.i32_load, 0, 5 ],
4887
+ [ Opcodes.i32_load, 0, 12 ],
4924
4888
  [ Opcodes.local_tee, tmp ],
4925
4889
 
4926
4890
  ...setType(scope, tmpName, [
@@ -4952,7 +4916,7 @@ const generateForIn = (scope, decl) => {
4952
4916
  // todo/perf: do not read key for non-enumerables
4953
4917
  // only run body if entry is enumerable
4954
4918
  [ Opcodes.local_get, pointer ],
4955
- [ Opcodes.i32_load8_u, 0, 17 ],
4919
+ [ Opcodes.i32_load8_u, 0, 24 ],
4956
4920
  [ Opcodes.i32_const, 0b0100 ],
4957
4921
  [ Opcodes.i32_and ],
4958
4922
  [ Opcodes.if, Blocktype.void ],
@@ -4960,9 +4924,9 @@ const generateForIn = (scope, decl) => {
4960
4924
  [ Opcodes.drop ],
4961
4925
  [ Opcodes.end ],
4962
4926
 
4963
- // increment pointer by 14
4927
+ // increment pointer by 18
4964
4928
  [ Opcodes.local_get, pointer ],
4965
- number(14, Valtype.i32),
4929
+ number(18, Valtype.i32),
4966
4930
  [ Opcodes.i32_add ],
4967
4931
  [ Opcodes.local_set, pointer ],
4968
4932
 
@@ -5786,60 +5750,6 @@ const generateMember = (scope, decl, _global, _name) => {
5786
5750
  if (known == null) extraBC = bc;
5787
5751
  }
5788
5752
 
5789
- if (decl.property.name === '__proto__') {
5790
- // todo: support optional
5791
- const bc = {};
5792
- const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
5793
-
5794
- const known = knownType(scope, getNodeType(scope, decl.object));
5795
- for (const x of prototypes) {
5796
- let type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
5797
- if (type == null) continue;
5798
-
5799
- // do not __proto__ primitive hack for objects or functions
5800
- if (type === TYPES.object || type === TYPES.function) continue;
5801
-
5802
- // hack: do not support primitives for Object.prototype.isPrototypeOf
5803
- if (scope.name === '__Object_prototype_isPrototypeOf') {
5804
- switch (type) {
5805
- case TYPES.boolean:
5806
- type = TYPES.booleanobject;
5807
- break;
5808
-
5809
- case TYPES.number:
5810
- type = TYPES.numberobject;
5811
- break;
5812
-
5813
- case TYPES.string:
5814
- type = TYPES.stringobject;
5815
- break;
5816
-
5817
- case TYPES.bytestring:
5818
- continue;
5819
- }
5820
- }
5821
-
5822
- const ident = {
5823
- type: 'Identifier',
5824
- name: x
5825
- };
5826
-
5827
- // hack: bytestrings should return string prototype
5828
- if (type === TYPES.bytestring) ident.name = '__String_prototype';
5829
-
5830
- bc[type] = () => [
5831
- ...generate(scope, ident),
5832
- ...setLastType(scope, getNodeType(scope, ident))
5833
- ];
5834
- if (type === known) return bc[type]();
5835
- }
5836
-
5837
- if (known == null) {
5838
- aliasPrimObjsBC(bc);
5839
- extraBC = bc;
5840
- }
5841
- }
5842
-
5843
5753
  const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
5844
5754
  const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5845
5755
 
@@ -6009,7 +5919,7 @@ const generateMember = (scope, decl, _global, _name) => {
6009
5919
  }),
6010
5920
  } : {}),
6011
5921
 
6012
- [TYPES.undefined]: internalThrow(scope, 'TypeError', 'Cannot read property of undefined', true),
5922
+ [TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
6013
5923
 
6014
5924
  // default: internalThrow(scope, 'TypeError', 'Unsupported member expression object', true)
6015
5925
  default: () => [
@@ -6164,10 +6074,25 @@ const generateClass = (scope, decl) => {
6164
6074
  // class Foo {}
6165
6075
  // class Bar extends Foo {}
6166
6076
  // Bar.__proto__ = Foo
6167
- // Bar.prototype.__proto__ = Foo.prototype
6168
- ...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
6077
+ ...generate(scope, {
6078
+ type: 'CallExpression',
6079
+ callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
6080
+ arguments: [
6081
+ root,
6082
+ decl.superClass
6083
+ ]
6084
+ }),
6169
6085
  [ Opcodes.drop ],
6170
- ...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype'))),
6086
+
6087
+ // Bar.prototype.__proto__ = Foo.prototype
6088
+ ...generate(scope, {
6089
+ type: 'CallExpression',
6090
+ callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
6091
+ arguments: [
6092
+ proto,
6093
+ getObjProp(decl.superClass, 'prototype')
6094
+ ]
6095
+ }),
6171
6096
  [ Opcodes.drop ]
6172
6097
  );
6173
6098
  }
@@ -6354,7 +6279,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
6354
6279
  return funcIndex[x];
6355
6280
  }
6356
6281
 
6357
- return scope.locals[x]?.idx ?? globals[x].idx;
6282
+ return scope.locals[x]?.idx ?? globals[x]?.idx ?? (log.warning('codegen', `unknown immediate in Porffor.wasm: ${x}`) || 0);
6358
6283
  }
6359
6284
 
6360
6285
  return n;
@@ -6428,7 +6353,6 @@ const objectHack = node => {
6428
6353
 
6429
6354
  // hack: block these properties as they can be accessed on functions
6430
6355
  if (node.object.name !== 'Porffor' && (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call')) return abortOut;
6431
-
6432
6356
  if (node.property.name === '__proto__') return abortOut;
6433
6357
 
6434
6358
  let objectName = node.object.name;
@@ -1,6 +1,6 @@
1
1
  import { Opcodes, Valtype } from './wasmSpec.js';
2
2
  import { read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
3
- import { TYPES } from './types.js';
3
+ import { TYPES, TYPE_NAMES } from './types.js';
4
4
  import { log } from './log.js';
5
5
 
6
6
  import process from 'node:process';
@@ -41,7 +41,7 @@ const compile = async (file, _funcs) => {
41
41
  let first = source.slice(0, source.indexOf('\n'));
42
42
 
43
43
  if (first.startsWith('export default')) {
44
- source = await (await import('file://' + file)).default();
44
+ source = await (await import('file://' + file)).default({ TYPES, TYPE_NAMES });
45
45
  first = source.slice(0, source.indexOf('\n'));
46
46
  }
47
47
 
@@ -155,11 +155,10 @@ const compile = async (file, _funcs) => {
155
155
  }
156
156
 
157
157
  if (n[0] === Opcodes.throw) {
158
- if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name}`);
159
-
160
158
  x.usesTag = true;
159
+ let id;
161
160
  if (y[0] === Opcodes.i32_const && n[1] === 0) {
162
- const id = read_signedLEB128(y.slice(1));
161
+ id = read_signedLEB128(y.slice(1));
163
162
  y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
164
163
 
165
164
  // remove throw inst
@@ -167,6 +166,8 @@ const compile = async (file, _funcs) => {
167
166
  } else {
168
167
  n[1]--;
169
168
  }
169
+
170
+ if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name} (${exceptions[id].constructor}: ${exceptions[id].message})`);
170
171
  }
171
172
 
172
173
  if (n[0] === Opcodes.catch) {