porffor 0.30.13 → 0.31.0

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.
@@ -1218,7 +1218,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
1218
1218
  type: 'CallExpression',
1219
1219
  callee: {
1220
1220
  type: 'Identifier',
1221
- name: '__Object_hasOwn'
1221
+ name: '__Porffor_object_in'
1222
1222
  },
1223
1223
  arguments: [
1224
1224
  decl.right,
@@ -1327,12 +1327,8 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
1327
1327
  locals[nameParam(i)] = { idx: i, type: allLocals[i] };
1328
1328
  }
1329
1329
 
1330
- for (const x of _data) {
1331
- let offset = x[0];
1332
- if (offset != null) offset += pages.size * pageSize;
1333
-
1334
- const bytes = x[1];
1335
- data.push({ offset, bytes });
1330
+ for (const x in _data) {
1331
+ data.push({ page: x, bytes: _data[x] });
1336
1332
  }
1337
1333
 
1338
1334
  const func = {
@@ -1515,6 +1511,7 @@ const setLastType = (scope, type = []) => [
1515
1511
 
1516
1512
  const getNodeType = (scope, node) => {
1517
1513
  const ret = (() => {
1514
+ if (node._type) return node._type;
1518
1515
  if (node.type === 'Literal') {
1519
1516
  if (node.regex) return TYPES.regexp;
1520
1517
 
@@ -1675,10 +1672,7 @@ const getNodeType = (scope, node) => {
1675
1672
 
1676
1673
  const objectKnownType = knownType(scope, getNodeType(scope, node.object));
1677
1674
  if (objectKnownType != null) {
1678
- if (name === 'length') {
1679
- if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
1680
- else return TYPES.undefined;
1681
- }
1675
+ if (name === 'length' && typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
1682
1676
 
1683
1677
  if (node.computed) {
1684
1678
  if (objectKnownType === TYPES.string) return TYPES.string;
@@ -3221,12 +3215,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3221
3215
  },
3222
3216
  arguments: [
3223
3217
  { type: 'Identifier', name: tmpName },
3224
- { type: 'Literal', value: i },
3225
- {
3226
- type: 'MemberExpression',
3227
- object: { type: 'Identifier', name: tmpName, },
3228
- property: { type: 'Identifier', name: 'length', }
3229
- }
3218
+ { type: 'Literal', value: i }
3230
3219
  ],
3231
3220
  _protoInternalCall: true
3232
3221
  }, undefined, global)
@@ -3419,15 +3408,16 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3419
3408
  const op = decl.operator.slice(0, -1) || '=';
3420
3409
 
3421
3410
  // hack: .length setter
3422
- if (type === 'MemberExpression' && decl.left.property.name === 'length') {
3411
+ if (type === 'MemberExpression' && decl.left.property.name === 'length' && !decl._internalAssign) {
3423
3412
  const newValueTmp = localTmp(scope, '__length_setter_tmp');
3424
- const pointerTmp = op === '=' ? null : localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
3413
+ const pointerTmp = localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
3425
3414
 
3426
- return [
3415
+ const out = [
3427
3416
  ...generate(scope, decl.left.object),
3428
- Opcodes.i32_to_u,
3429
- ...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3417
+ Opcodes.i32_to_u
3418
+ ];
3430
3419
 
3420
+ const lengthTypeWasm = [
3431
3421
  ...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
3432
3422
  [ Opcodes.local_get, pointerTmp ],
3433
3423
  [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
@@ -3440,6 +3430,33 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3440
3430
 
3441
3431
  [ Opcodes.local_get, newValueTmp ]
3442
3432
  ];
3433
+
3434
+ const type = getNodeType(scope, decl.left.object);
3435
+ const known = knownType(scope, type);
3436
+ if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
3437
+ ...out,
3438
+ ...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
3439
+
3440
+ ...lengthTypeWasm
3441
+ ];
3442
+
3443
+ return [
3444
+ ...out,
3445
+ [ Opcodes.local_set, pointerTmp ],
3446
+
3447
+ ...type,
3448
+ ...number(TYPE_FLAGS.length, Valtype.i32),
3449
+ [ Opcodes.i32_and ],
3450
+ [ Opcodes.if, valtypeBinary ],
3451
+ [ Opcodes.local_get, pointerTmp ],
3452
+ ...lengthTypeWasm,
3453
+ [ Opcodes.else ],
3454
+ ...generate(scope, {
3455
+ ...decl,
3456
+ _internalAssign: true
3457
+ }),
3458
+ [ Opcodes.end ]
3459
+ ];
3443
3460
  }
3444
3461
 
3445
3462
  // arr[i]
@@ -4951,7 +4968,7 @@ const compileBytes = (val, itemType) => {
4951
4968
  }
4952
4969
  };
4953
4970
 
4954
- const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
4971
+ const makeData = (scope, elements, page = null, itemType, initEmpty) => {
4955
4972
  const length = elements.length;
4956
4973
 
4957
4974
  // if length is 0 memory/data will just be 0000... anyway
@@ -4965,8 +4982,7 @@ const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
4965
4982
  bytes.push(...compileBytes(elements[i], itemType));
4966
4983
  }
4967
4984
 
4968
- const obj = { bytes };
4969
- if (offset != null) obj.offset = offset;
4985
+ const obj = { bytes, page };
4970
4986
 
4971
4987
  const idx = data.push(obj) - 1;
4972
4988
 
@@ -5068,7 +5084,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
5068
5084
  (!globalThis.precompile || !global)
5069
5085
  ) {
5070
5086
  if (Prefs.activeData && firstAssign) {
5071
- makeData(scope, elements, rawPtr, itemType, initEmpty);
5087
+ makeData(scope, elements, allocator.lastName, itemType, initEmpty);
5072
5088
 
5073
5089
  // local value as pointer
5074
5090
  return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
@@ -5363,6 +5379,7 @@ const countLength = (func, name = undefined) => {
5363
5379
  };
5364
5380
 
5365
5381
  const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) => {
5382
+ let final = [], finalEnd, extraBC = {};
5366
5383
  const name = decl.object.name;
5367
5384
 
5368
5385
  // hack: .name
@@ -5375,6 +5392,12 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5375
5392
  return withType(scope, makeString(scope, nameProp, _global, _name, true), TYPES.bytestring);
5376
5393
  }
5377
5394
 
5395
+ const object = decl.object;
5396
+ const property = getMemberProperty(decl);
5397
+
5398
+ // generate now so type is gotten correctly later (it gets cached)
5399
+ generate(scope, object);
5400
+
5378
5401
  // hack: .length
5379
5402
  if (decl.property.name === 'length') {
5380
5403
  // todo: support optional
@@ -5389,7 +5412,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5389
5412
  }
5390
5413
 
5391
5414
  const out = [
5392
- ...generate(scope, decl.object),
5415
+ ...generate(scope, object),
5393
5416
  Opcodes.i32_to_u,
5394
5417
  ];
5395
5418
 
@@ -5403,25 +5426,21 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5403
5426
  ];
5404
5427
  }
5405
5428
 
5406
- const type = getNodeType(scope, decl.object);
5429
+ const type = getNodeType(scope, object);
5407
5430
  const known = knownType(scope, type);
5408
- if (known != null && known != TYPES.function) {
5409
- if (typeHasFlag(known, TYPE_FLAGS.length)) return [
5410
- ...out,
5411
-
5412
- [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
5413
- Opcodes.i32_from_u
5414
- ];
5431
+ if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
5432
+ ...out,
5415
5433
 
5416
- return number(0);
5417
- }
5434
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
5435
+ Opcodes.i32_from_u
5436
+ ];
5418
5437
 
5419
5438
  const tmp = localTmp(scope, '#length_tmp', Valtype.i32);
5420
- return [
5439
+ final = [
5421
5440
  ...out,
5422
5441
  [ Opcodes.local_set, tmp ],
5423
5442
 
5424
- ...getNodeType(scope, decl.object),
5443
+ ...getNodeType(scope, object),
5425
5444
  ...number(TYPE_FLAGS.length, Valtype.i32),
5426
5445
  [ Opcodes.i32_and ],
5427
5446
  [ Opcodes.if, valtypeBinary ],
@@ -5431,22 +5450,14 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5431
5450
 
5432
5451
  ...setLastType(scope, TYPES.number),
5433
5452
  [ Opcodes.else ],
5434
- ...getNodeType(scope, decl.object),
5435
- ...number(TYPES.function, Valtype.i32),
5436
- [ Opcodes.i32_eq ],
5437
- [ Opcodes.if, Blocktype.void ],
5438
- [ Opcodes.local_get, tmp ],
5439
- [ Opcodes.call, includeBuiltin(scope, '__Porffor_funcLut_length').index ],
5440
- Opcodes.i32_from_u,
5441
-
5442
- ...setLastType(scope, TYPES.number),
5443
- [ Opcodes.br, 1 ],
5444
- [ Opcodes.end ],
5445
-
5446
- ...number(0),
5447
- ...setLastType(scope, TYPES.undefined),
5448
5453
  [ Opcodes.end ]
5449
5454
  ];
5455
+
5456
+ if (known != null) {
5457
+ final = [];
5458
+ } else {
5459
+ finalEnd = final.pop();
5460
+ }
5450
5461
  }
5451
5462
 
5452
5463
  // todo: generate this array procedurally during builtinFuncs creation
@@ -5455,33 +5466,67 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5455
5466
  const bc = {};
5456
5467
  const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
5457
5468
 
5469
+ localTmp(scope, '#member_obj');
5470
+ localTmp(scope, '#member_obj#type', Valtype.i32);
5471
+
5472
+ const known = knownType(scope, getNodeType(scope, object));
5458
5473
  if (cands.length > 0) {
5459
5474
  for (const x of cands) {
5460
5475
  const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
5461
5476
  if (type == null) continue;
5462
5477
 
5478
+ if (type === known) return generateCall(scope, {
5479
+ callee: {
5480
+ type: 'Identifier',
5481
+ name: x
5482
+ },
5483
+ arguments: [ object ],
5484
+ _protoInternalCall: true
5485
+ });
5486
+
5463
5487
  bc[type] = generateCall(scope, {
5464
5488
  callee: {
5465
5489
  type: 'Identifier',
5466
5490
  name: x
5467
5491
  },
5468
- arguments: [ decl.object ],
5492
+ arguments: [
5493
+ { type: 'Identifier', name: '#member_obj' }
5494
+ ],
5469
5495
  _protoInternalCall: true
5470
5496
  });
5471
5497
  }
5472
5498
  }
5473
5499
 
5474
- return typeSwitch(scope, getNodeType(scope, decl.object), {
5475
- ...bc,
5476
- default: withType(scope, number(0), TYPES.undefined)
5477
- }, valtypeBinary);
5500
+ if (known == null) extraBC = bc;
5478
5501
  }
5479
5502
 
5480
- const object = decl.object;
5481
- const property = getMemberProperty(decl);
5503
+ if (decl.property.name === '__proto__') {
5504
+ // todo: support optional
5505
+ const bc = {};
5506
+ const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
5482
5507
 
5483
- // generate now (it gets cached)
5484
- generate(scope, object);
5508
+ const known = knownType(scope, getNodeType(scope, decl.object));
5509
+ for (const x of prototypes) {
5510
+ const type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
5511
+ if (type == null) continue;
5512
+
5513
+ // do not __proto__ primitive hack for objects
5514
+ if (type === TYPES.object) continue;
5515
+
5516
+ const ident = {
5517
+ type: 'Identifier',
5518
+ name: x
5519
+ };
5520
+
5521
+ bc[type] = [
5522
+ ...generateIdent(scope, ident),
5523
+ ...setLastType(scope, getNodeType(scope, ident))
5524
+ ];
5525
+ if (type === known) return bc[type];
5526
+ }
5527
+
5528
+ if (known == null) extraBC = bc;
5529
+ }
5485
5530
 
5486
5531
  // todo/perf: use i32 object (and prop?) locals
5487
5532
  const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
@@ -5668,7 +5713,9 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5668
5713
  default: [
5669
5714
  ...number(0),
5670
5715
  ...setLastType(scope, TYPES.undefined)
5671
- ]
5716
+ ],
5717
+
5718
+ ...extraBC
5672
5719
  });
5673
5720
 
5674
5721
  if (decl.optional) {
@@ -5676,6 +5723,10 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5676
5723
  [ Opcodes.block, valtypeBinary ],
5677
5724
  ...(_objectWasm ? _objectWasm : generate(scope, object)),
5678
5725
  [ Opcodes.local_tee, localTmp(scope, '#member_obj') ],
5726
+ ...(scope.locals['#member_obj#type'] ? [
5727
+ ...getNodeType(scope, object),
5728
+ [ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
5729
+ ] : []),
5679
5730
 
5680
5731
  ...nullish(scope, [], getNodeType(scope, object), false, true),
5681
5732
  [ Opcodes.if, Blocktype.void ],
@@ -5695,12 +5746,22 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5695
5746
  out.unshift(
5696
5747
  ...(_objectWasm ? _objectWasm : generate(scope, object)),
5697
5748
  [ Opcodes.local_set, localTmp(scope, '#member_obj') ],
5749
+ ...(scope.locals['#member_obj#type'] ? [
5750
+ ...getNodeType(scope, object),
5751
+ [ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
5752
+ ] : []),
5698
5753
 
5699
5754
  ...generate(scope, property, false, '#member_prop'),
5700
5755
  [ Opcodes.local_set, localTmp(scope, '#member_prop') ]
5701
5756
  );
5702
5757
  }
5703
5758
 
5759
+ if (final.length > 0) {
5760
+ final = final.concat(out);
5761
+ final.push(finalEnd);
5762
+ return final;
5763
+ }
5764
+
5704
5765
  return out;
5705
5766
  };
5706
5767
 
@@ -5716,7 +5777,9 @@ const objectHack = node => {
5716
5777
  if (node.computed || node.optional) return;
5717
5778
 
5718
5779
  // hack: block these properties as they can be accessed on functions
5719
- if (node.property.name == 'length' || node.property.name == 'name' || node.property.name == 'call') return;
5780
+ if (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call') return;
5781
+
5782
+ if (node.property.name === '__proto__') return;
5720
5783
 
5721
5784
  let objectName = node.object.name;
5722
5785
 
@@ -53,7 +53,7 @@ export default wasm => {
53
53
  const replaceOp = newOp => {
54
54
  op.splice(0, op.length, ...newOp);
55
55
  };
56
- const replaceVal = (val, valtype) => replaceOp(number(val, valtype));
56
+ const replaceVal = (val, valtype) => replaceOp(number(val, valtype)[0]);
57
57
 
58
58
  const empty = () => {
59
59
  stack = [];
@@ -511,7 +511,7 @@ export default wasm => {
511
511
 
512
512
  // convert f64.const -> i32.const
513
513
  const n = wasm[i - 1][1];
514
- wasm.splice(i - 1, 1, number(n, Valtype.i32));
514
+ wasm.splice(i - 1, 1, number(n, Valtype.i32)[0]);
515
515
 
516
516
  // convert math op from f64 to i32
517
517
  wasm[i][0] = f64ToI32Op[wasm[i][0]];
@@ -551,7 +551,7 @@ export default wasm => {
551
551
 
552
552
  // convert f64.const -> i32.const
553
553
  const n = wasm[i - 2][1];
554
- wasm.splice(i - 2, 1, number(n, Valtype.i32));
554
+ wasm.splice(i - 2, 1, number(n, Valtype.i32)[0]);
555
555
 
556
556
  // convert math op from f64 to i32
557
557
  wasm[i - 1][0] = f64ToI32Op[wasm[i - 1][0]];
@@ -66,10 +66,7 @@ const compile = async (file, _funcs) => {
66
66
  const exports = funcs.filter(x => x.export && x.name !== 'main');
67
67
  for (const x of exports) {
68
68
  if (x.data) {
69
- x.data = x.data.map(x => data[x]);
70
- for (const y in x.data) {
71
- if (x.data[y].offset != null) x.data[y].offset -= x.data[0].offset;
72
- }
69
+ x.data = x.data.reduce((acc, x) => { acc[data[x].page] = data[x].bytes; return acc; }, {});
73
70
  }
74
71
 
75
72
  if (x.exceptions) {
@@ -226,7 +223,7 @@ ${funcs.map(x => {
226
223
  wasm:${rewriteWasm(x.wasm)},
227
224
  params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)}` : 'typedReturns:1'},
228
225
  locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
229
- ${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && x.data.length > 0 ? `data:[${x.data.map(x => `[${x.offset ?? 'null'},[${x.bytes.join(',')}]]`).join(',')}],` : ''}
226
+ ${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)},` : ''}
230
227
  ${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}
231
228
  };`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
232
229
  }).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.30.13+047f11fe9",
4
+ "version": "0.31.0+c8cd1d6c9",
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.30.13+047f11fe9';
3
+ globalThis.version = '0.31.0+c8cd1d6c9';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {