porffor 0.55.20 → 0.55.22

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.
@@ -5,11 +5,11 @@ export const __Porffor_bigint_fromDigits = (negative: boolean, digits: i32[]): b
5
5
  const len: i32 = digits.length;
6
6
  if (len > 16383) throw new RangeError('Maximum BigInt size exceeded'); // (65536 - 4) / 4
7
7
 
8
- // const ptr: i32 = Porffor.allocate();
8
+ // use digits pointer as bigint pointer, as only used here
9
9
  let ptr: i32 = Porffor.wasm`local.get ${digits}`;
10
10
 
11
- Porffor.wasm.i32.store8(ptr, negative ? 1 : 0, 0, 0);
12
- Porffor.wasm.i32.store16(ptr, len, 0, 2);
11
+ Porffor.wasm.i32.store8(ptr, negative ? 1 : 0, 0, 0); // sign
12
+ Porffor.wasm.i32.store16(ptr, len, 0, 2); // digit count
13
13
 
14
14
  let allZero: boolean = true;
15
15
  for (let i: i32 = 0; i < len; i++) {
@@ -84,14 +84,10 @@ export const __Porffor_bigint_fromString = (n: string|bytestring): bigint => {
84
84
  offset = 1;
85
85
  }
86
86
 
87
- // n -> digits (base 2^32) (most to least significant)
88
- // 4294967294 -> [ 4294967294 ]
87
+ // n -> base 2^32 digits (most to least significant)
89
88
  // 4294967295 -> [ 4294967295 ]
90
89
  // 4294967296 -> [ 1, 0 ]
91
90
  // 4294967297 -> [ 1, 1 ]
92
- // 9007199254740992 -> [ 2097152, 0 ]
93
- // 9007199254740993 -> [ 2097152, 1 ]
94
- // 9007199254740994 -> [ 2097152, 2 ]
95
91
 
96
92
  const BASE: i32 = 0x100000000; // 2^32
97
93
  const digits: i32[] = Porffor.allocate(); // todo: free later
@@ -10,14 +10,6 @@ import { log } from './log.js';
10
10
  import { allocPage, allocStr } from './allocator.js';
11
11
  import './prefs.js';
12
12
 
13
- let globals = {};
14
- let tags = [];
15
- let funcs = [];
16
- let exceptions = [];
17
- let funcIndex = {};
18
- let currentFuncIndex = importedFuncs.length;
19
- let builtinFuncs = {}, builtinVars = {}, prototypeFuncs = {};
20
-
21
13
  class TodoError extends Error {
22
14
  constructor(message) {
23
15
  super(message);
@@ -46,7 +38,6 @@ const cacheAst = (decl, wasm) => {
46
38
  return wasm;
47
39
  };
48
40
 
49
- let indirectFuncs = [];
50
41
  let doNotMarkFuncRef = false;
51
42
  const funcRef = func => {
52
43
  if (!doNotMarkFuncRef) func.referenced = true;
@@ -462,7 +453,7 @@ const lookup = (scope, name, failEarly = false) => {
462
453
  }
463
454
 
464
455
  if (local?.idx === undefined) {
465
- if (name === 'arguments' && scope.name !== '#main' && !scope.arrow) {
456
+ if (name === 'arguments' && !scope.arrow) {
466
457
  // todo: not compliant
467
458
  let len = countLength(scope);
468
459
  const names = new Array(len);
@@ -1386,29 +1377,6 @@ const generateLogicExp = (scope, decl) => {
1386
1377
  return performLogicOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right));
1387
1378
  };
1388
1379
 
1389
- // potential future ideas for nan boxing (unused):
1390
- // T = JS type, V = value/pointer
1391
- // 0bTTT
1392
- // qNAN: 0 11111111111 1000000000000000000000000000000000000000000000000001
1393
- // 50 bits usable: 0 11111111111 11??????????????????????????????????????????????????
1394
- // js type: 4 bits
1395
- // internal type: ? bits
1396
- // pointer: 32 bits
1397
- // https://piotrduperas.com/posts/nan-boxing
1398
- // 0x7ffc000000000000
1399
- // budget: 50 bits
1400
- // js type: 4 bits
1401
- // internal type: ? bits
1402
- // pointer: 32 bits
1403
- // generic
1404
- // 1 23 4 5
1405
- // 0 11111111111 11TTTTIIII??????????PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
1406
- // 1: regular iEEE 754 double NaN
1407
- // 2: extra 1 bit to identify NaN box
1408
- // 3: js type
1409
- // 4: internal type
1410
- // 5: pointer
1411
-
1412
1380
  const isExistingProtoFunc = name => {
1413
1381
  if (name.startsWith('__Array_prototype')) return !!prototypeFuncs[TYPES.array][name.slice(18)];
1414
1382
  if (name.startsWith('__String_prototype_')) return !!prototypeFuncs[TYPES.string][name.slice(19)];
@@ -1416,7 +1384,6 @@ const isExistingProtoFunc = name => {
1416
1384
  return false;
1417
1385
  };
1418
1386
 
1419
- let globalInfer;
1420
1387
  const getInferred = (scope, name, global = false) => {
1421
1388
  if (global) {
1422
1389
  if (globalInfer.has(name)) return globalInfer.get(name);
@@ -1470,7 +1437,7 @@ const getType = (scope, name, failEarly = false) => {
1470
1437
  global = true;
1471
1438
  }
1472
1439
 
1473
- if (global !== false && name === 'arguments' && scope.name !== '#main' && !scope.arrow) {
1440
+ if (global !== false && name === 'arguments' && !scope.arrow) {
1474
1441
  return [ number(TYPES.array, Valtype.i32) ];
1475
1442
  }
1476
1443
 
@@ -2750,18 +2717,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2750
2717
  }
2751
2718
 
2752
2719
  out.push([ Opcodes.call, idx ]);
2753
-
2754
- if (!typedReturns) {
2755
- // let type;
2756
- // if (builtinFuncs[name]) type = TYPES[builtinFuncs[name].returnType ?? 'number'];
2757
- // if (internalConstrs[name]) type = internalConstrs[name].type;
2758
- // if (importedFuncs[name] && importedFuncs[]) type =
2759
-
2760
- // if (type) out.push(
2761
- // number(type, Valtype.i32),
2762
- // [ Opcodes.local_set, localTmp(scope, '#last_type', Valtype.i32) ]
2763
- // );
2764
- } else out.push(...setLastType(scope));
2720
+ if (typedReturns) out.push(...setLastType(scope));
2765
2721
 
2766
2722
  if (
2767
2723
  func?.returns?.length === 0 ||
@@ -2941,8 +2897,7 @@ const brTable = (input, bc, returns) => {
2941
2897
  for (let i = offset; i <= max; i++) {
2942
2898
  // if branch for this num, go to that block
2943
2899
  if (bc[i]) {
2944
- table.push(br);
2945
- br++;
2900
+ table.push(br++);
2946
2901
  continue;
2947
2902
  }
2948
2903
 
@@ -2979,9 +2934,6 @@ const brTable = (input, bc, returns) => {
2979
2934
  return out;
2980
2935
  };
2981
2936
 
2982
- let typeswitchDepth = 0;
2983
-
2984
- let usedTypes = new Set();
2985
2937
  const typeUsed = (scope, x) => {
2986
2938
  if (x == null) return;
2987
2939
  usedTypes.add(x);
@@ -3137,7 +3089,7 @@ const typeIsNotOneOf = (type, types, valtype = Valtype.i32) => {
3137
3089
  return out;
3138
3090
  };
3139
3091
 
3140
- const allocVar = (scope, name, global = false, type = true, redecl = false) => {
3092
+ const allocVar = (scope, name, global = false, type = true, redecl = false, i32 = false) => {
3141
3093
  const target = global ? globals : scope.locals;
3142
3094
 
3143
3095
  // already declared
@@ -3152,7 +3104,7 @@ const allocVar = (scope, name, global = false, type = true, redecl = false) => {
3152
3104
  }
3153
3105
 
3154
3106
  let idx = global ? globals['#ind']++ : scope.localInd++;
3155
- target[name] = { idx, type: valtypeBinary };
3107
+ target[name] = { idx, type: i32 ? Valtype.i32 : valtypeBinary };
3156
3108
 
3157
3109
  if (type) {
3158
3110
  let typeIdx = global ? globals['#ind']++ : scope.localInd++;
@@ -3571,9 +3523,8 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3571
3523
  const generateVar = (scope, decl) => {
3572
3524
  let out = [];
3573
3525
 
3574
- const topLevel = scope.name === '#main';
3575
-
3576
3526
  // global variable if in top scope (main) or if internally wanted
3527
+ const topLevel = scope.name === '#main';
3577
3528
  const global = decl._global ?? (topLevel || decl._bare);
3578
3529
 
3579
3530
  for (const x of decl.declarations) {
@@ -3635,8 +3586,16 @@ const memberTmpNames = scope => {
3635
3586
  };
3636
3587
 
3637
3588
  // COCTC: cross-object compile-time cache
3638
- let coctc = new Map();
3639
3589
  const coctcOffset = prop => {
3590
+ if (typeof prop === 'object') {
3591
+ if (
3592
+ prop.computed || prop.optional ||
3593
+ ['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'length', '__proto__'].includes(prop.property.name)
3594
+ ) return 0;
3595
+
3596
+ prop = prop.property.name;
3597
+ }
3598
+
3640
3599
  let offset = coctc.get(prop);
3641
3600
  if (offset == null) {
3642
3601
  offset = (coctc.lastOffset ?? 60000) - 9;
@@ -3768,7 +3727,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3768
3727
  // todo/perf: use i32 object (and prop?) locals
3769
3728
  const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
3770
3729
 
3771
- const useCoctc = Prefs.coctc && !decl.left.computed && !decl.left.optional && !['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'length', '__proto__'].includes(decl.left.property.name) && coctcOffset(decl.left.property.name) > 0;
3730
+ const useCoctc = Prefs.coctc && coctcOffset(decl.left) > 0;
3772
3731
  if (useCoctc) valueUnused = false;
3773
3732
 
3774
3733
  // opt: do not mark prototype funcs as referenced to optimize this in them
@@ -4214,7 +4173,7 @@ const generateUnary = (scope, decl) => {
4214
4173
  const property = getProperty(decl.argument);
4215
4174
  if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
4216
4175
 
4217
- const useCoctc = Prefs.coctc && !decl.argument.computed && !decl.argument.optional && !['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'length', '__proto__'].includes(decl.argument.property.name) && coctcOffset(decl.argument.property.name) > 0;
4176
+ const useCoctc = Prefs.coctc && coctcOffset(decl.argument) > 0;
4218
4177
  const objectTmp = useCoctc && localTmp(scope, '#coctc_object', Valtype.i32);
4219
4178
 
4220
4179
  const out = [
@@ -4453,7 +4412,6 @@ const generateConditional = (scope, decl) => {
4453
4412
  return out;
4454
4413
  };
4455
4414
 
4456
- let depth = [];
4457
4415
  const generateFor = (scope, decl) => {
4458
4416
  const out = [];
4459
4417
 
@@ -5390,9 +5348,6 @@ const generateMeta = (scope, decl) => {
5390
5348
  return todo(scope, `meta property object ${decl.meta.name} is not supported yet`, true);
5391
5349
  };
5392
5350
 
5393
- let pages = new Map();
5394
- let data = [];
5395
-
5396
5351
  const compileBytes = (val, itemType) => {
5397
5352
  switch (itemType) {
5398
5353
  case 'i8': return [ val % 256 ];
@@ -5410,7 +5365,7 @@ const makeData = (scope, elements, page = null, itemType = 'i8') => {
5410
5365
 
5411
5366
  const length = elements.length;
5412
5367
 
5413
- // if length is 0 memory/data will just be 0000... anyway
5368
+ // if length is 0, memory/data will just be 0000... anyway
5414
5369
  if (length === 0) return false;
5415
5370
 
5416
5371
  let bytes = compileBytes(length, 'i32');
@@ -5424,7 +5379,6 @@ const makeData = (scope, elements, page = null, itemType = 'i8') => {
5424
5379
  }
5425
5380
 
5426
5381
  const obj = { bytes, page };
5427
-
5428
5382
  const idx = data.push(obj) - 1;
5429
5383
 
5430
5384
  scope.data ??= [];
@@ -5448,63 +5402,6 @@ const printStaticStr = str => {
5448
5402
  return out;
5449
5403
  };
5450
5404
 
5451
- const storeArray = (scope, array, index, element) => {
5452
- if (!Array.isArray(element)) element = generate(scope, element);
5453
- if (typeof index === 'number') index = [ number(index) ];
5454
-
5455
- const offset = localTmp(scope, '#storeArray_offset', Valtype.i32);
5456
-
5457
- return [
5458
- // calculate offset
5459
- ...index,
5460
- Opcodes.i32_to_u,
5461
- number(ValtypeSize[valtype] + 1, Valtype.i32),
5462
- [ Opcodes.i32_mul ],
5463
-
5464
- ...array,
5465
- Opcodes.i32_to_u,
5466
- [ Opcodes.i32_add ],
5467
- [ Opcodes.local_set, offset ],
5468
-
5469
- // store value
5470
- [ Opcodes.local_get, offset ],
5471
- ...generate(scope, element),
5472
- [ Opcodes.store, 0, ValtypeSize.i32 ],
5473
-
5474
- // store type
5475
- [ Opcodes.local_get, offset ],
5476
- ...getNodeType(scope, element),
5477
- [ Opcodes.i32_store8, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
5478
- ];
5479
- };
5480
-
5481
- const loadArray = (scope, array, index) => {
5482
- if (typeof index === 'number') index = [ number(index) ];
5483
-
5484
- const offset = localTmp(scope, '#loadArray_offset', Valtype.i32);
5485
-
5486
- return [
5487
- // calculate offset
5488
- ...index,
5489
- Opcodes.i32_to_u,
5490
- number(ValtypeSize[valtype] + 1, Valtype.i32),
5491
- [ Opcodes.i32_mul ],
5492
-
5493
- ...array,
5494
- Opcodes.i32_to_u,
5495
- [ Opcodes.i32_add ],
5496
- [ Opcodes.local_set, offset ],
5497
-
5498
- // load value
5499
- [ Opcodes.local_get, offset ],
5500
- [ Opcodes.load, 0, ValtypeSize.i32 ],
5501
-
5502
- // load type
5503
- [ Opcodes.local_get, offset ],
5504
- [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ]
5505
- ];
5506
- };
5507
-
5508
5405
  const byteStringable = str => {
5509
5406
  for (let i = 0; i < str.length; i++) {
5510
5407
  if (str.charCodeAt(i) > 0xFF) return false;
@@ -5943,14 +5840,27 @@ const generateMember = (scope, decl, _global, _name) => {
5943
5840
  }
5944
5841
  }
5945
5842
 
5946
- const useCoctc = Prefs.coctc && !decl.computed && !decl.optional && !['prototype', 'size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength', 'length', '__proto__'].includes(decl.property.name) && coctcOffset(decl.property.name) > 0;
5843
+ const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
5947
5844
  const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
5948
5845
 
5949
5846
  const out = typeSwitch(scope, getNodeType(scope, object), {
5950
5847
  ...(decl.computed ? {
5951
5848
  [TYPES.array]: () => [
5952
- ...loadArray(scope, [ objectGet ], [ propertyGet ]),
5953
- ...setLastType(scope)
5849
+ propertyGet,
5850
+ Opcodes.i32_to_u,
5851
+ number(ValtypeSize[valtype] + 1, Valtype.i32),
5852
+ [ Opcodes.i32_mul ],
5853
+
5854
+ objectGet,
5855
+ Opcodes.i32_to_u,
5856
+ [ Opcodes.i32_add ],
5857
+ [ Opcodes.local_tee, localTmp(scope, '#loadArray_offset', Valtype.i32) ],
5858
+ [ Opcodes.load, 0, ValtypeSize.i32 ],
5859
+
5860
+ ...setLastType(scope, [
5861
+ [ Opcodes.local_get, localTmp(scope, '#loadArray_offset', Valtype.i32) ],
5862
+ [ Opcodes.i32_load8_u, 0, ValtypeSize.i32 + ValtypeSize[valtype] ],
5863
+ ])
5954
5864
  ],
5955
5865
 
5956
5866
  [TYPES.string]: () => [
@@ -6291,18 +6201,6 @@ const generateClass = (scope, decl) => {
6291
6201
  // default value to undefined
6292
6202
  value ??= DEFAULT_VALUE();
6293
6203
 
6294
- let outArr = out, outOp = 'push', outScope = scope;
6295
- if (type === 'PropertyDefinition' && !_static) {
6296
- // define in construction instead
6297
- outArr = func.wasm;
6298
- outOp = 'unshift';
6299
- object = {
6300
- type: 'ThisExpression',
6301
- _noGlobalThis: true
6302
- };
6303
- outScope = func;
6304
- }
6305
-
6306
6204
  if (isFuncType(value.type)) {
6307
6205
  let id = value.id;
6308
6206
 
@@ -6320,19 +6218,60 @@ const generateClass = (scope, decl) => {
6320
6218
  };
6321
6219
  }
6322
6220
 
6323
- outArr[outOp](
6324
- ...generate(outScope, object),
6325
- Opcodes.i32_to_u,
6326
- ...getNodeType(outScope, object),
6221
+ if (type === 'PropertyDefinition' && !_static) {
6222
+ // define in construction instead
6223
+ object = {
6224
+ type: 'ThisExpression',
6225
+ _noGlobalThis: true
6226
+ };
6327
6227
 
6328
- ...toPropertyKey(outScope, generate(outScope, k), getNodeType(outScope, k), computed, true),
6228
+ let computedTmp;
6229
+ if (computed) {
6230
+ // compute now, reference in construction
6231
+ computedTmp = allocVar(scope, `#class_computed_prop${uniqId()}`, true, true, false, true);
6329
6232
 
6330
- ...generate(outScope, value),
6331
- ...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
6332
- ...getNodeType(outScope, value),
6233
+ out.push(
6234
+ ...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
6235
+ [ Opcodes.global_set, computedTmp + 1 ],
6236
+ [ Opcodes.global_set, computedTmp ]
6237
+ );
6238
+ }
6333
6239
 
6334
- [ Opcodes.call, includeBuiltin(outScope, `__Porffor_object_class_${initKind}`).index ]
6335
- );
6240
+ func.wasm.unshift(
6241
+ ...generate(func, object),
6242
+ Opcodes.i32_to_u,
6243
+ ...getNodeType(func, object),
6244
+
6245
+ ...(computed ? [
6246
+ [ Opcodes.global_get, computedTmp ],
6247
+ [ Opcodes.global_get, computedTmp + 1 ],
6248
+ ] : [
6249
+ ...generate(func, k),
6250
+ Opcodes.i32_to_u,
6251
+ ...getNodeType(func, k)
6252
+ ]),
6253
+
6254
+ ...generate(func, value),
6255
+ ...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
6256
+ ...getNodeType(func, value),
6257
+
6258
+ [ Opcodes.call, includeBuiltin(func, `__Porffor_object_class_${initKind}`).index ]
6259
+ );
6260
+ } else {
6261
+ out.push(
6262
+ ...generate(scope, object),
6263
+ Opcodes.i32_to_u,
6264
+ ...getNodeType(scope, object),
6265
+
6266
+ ...toPropertyKey(scope, generate(scope, k), getNodeType(scope, k), computed, true),
6267
+
6268
+ ...generate(scope, value),
6269
+ ...(initKind !== 'value' && initKind !== 'method' ? [ Opcodes.i32_to_u ] : []),
6270
+ ...getNodeType(scope, value),
6271
+
6272
+ [ Opcodes.call, includeBuiltin(scope, `__Porffor_object_class_${initKind}`).index ]
6273
+ );
6274
+ }
6336
6275
  }
6337
6276
 
6338
6277
  delete scope.overrideThis;
@@ -6855,7 +6794,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6855
6794
  return [ func, out ];
6856
6795
  };
6857
6796
 
6858
- let largestBlockBody = 0;
6859
6797
  const generateBlock = (scope, decl) => {
6860
6798
  let out = [];
6861
6799
 
@@ -6863,10 +6801,8 @@ const generateBlock = (scope, decl) => {
6863
6801
  scope.inferTree.push(decl);
6864
6802
 
6865
6803
  let len = decl.body.length, j = 0;
6866
- if (len > largestBlockBody) largestBlockBody = len;
6867
6804
  for (let i = 0; i < len; i++) {
6868
6805
  const x = decl.body[i];
6869
- if (len >= largestBlockBody) globalThis.progress?.(`${i}/${len}`);
6870
6806
  if (isEmptyNode(x)) continue;
6871
6807
 
6872
6808
  if (j++ > 0) out.push([ Opcodes.drop ]);
@@ -7029,10 +6965,9 @@ const internalConstrs = {
7029
6965
  }
7030
6966
  };
7031
6967
 
6968
+ let globals, tags, exceptions, funcs, indirectFuncs, funcIndex, currentFuncIndex, depth, pages, data, typeswitchDepth, usedTypes, coctc, globalInfer, builtinFuncs, builtinVars, prototypeFuncs;
7032
6969
  export default program => {
7033
- globals = {
7034
- ['#ind']: 0
7035
- };
6970
+ globals = { ['#ind']: 0 };
7036
6971
  tags = [];
7037
6972
  exceptions = [];
7038
6973
  funcs = []; indirectFuncs = [];
@@ -7042,26 +6977,22 @@ export default program => {
7042
6977
  data = [];
7043
6978
  currentFuncIndex = importedFuncs.length;
7044
6979
  typeswitchDepth = 0;
7045
- largestBlockBody = 0;
7046
6980
  usedTypes = new Set([ TYPES.empty, TYPES.undefined, TYPES.number, TYPES.boolean, TYPES.function ]);
7047
6981
  coctc = new Map();
7048
6982
  globalInfer = new Map();
7049
6983
 
7050
- const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
7051
-
7052
6984
  // set generic opcodes for current valtype
6985
+ const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
7053
6986
  Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
7054
6987
  Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
7055
6988
  Opcodes.eqz = [ [ [ Opcodes.i32_eqz ] ], [ [ Opcodes.i64_eqz ] ], [ number(0), [ Opcodes.f64_eq ] ] ][valtypeInd];
7056
6989
  Opcodes.mul = [ Opcodes.i32_mul, Opcodes.i64_mul, Opcodes.f64_mul ][valtypeInd];
7057
6990
  Opcodes.add = [ Opcodes.i32_add, Opcodes.i64_add, Opcodes.f64_add ][valtypeInd];
7058
6991
  Opcodes.sub = [ Opcodes.i32_sub, Opcodes.i64_sub, Opcodes.f64_sub ][valtypeInd];
7059
-
7060
6992
  Opcodes.i32_to = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_s ][valtypeInd];
7061
6993
  Opcodes.i32_to_u = [ [], [ Opcodes.i32_wrap_i64 ], Opcodes.i32_trunc_sat_f64_u ][valtypeInd];
7062
6994
  Opcodes.i32_from = [ [], [ Opcodes.i64_extend_i32_s ], [ Opcodes.f64_convert_i32_s ] ][valtypeInd];
7063
6995
  Opcodes.i32_from_u = [ [], [ Opcodes.i64_extend_i32_u ], [ Opcodes.f64_convert_i32_u ] ][valtypeInd];
7064
-
7065
6996
  Opcodes.load = [ Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load ][valtypeInd];
7066
6997
  Opcodes.store = [ Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store ][valtypeInd];
7067
6998
 
@@ -7072,28 +7003,24 @@ export default program => {
7072
7003
  const getObjectName = x => x.startsWith('__') && x.slice(2, x.indexOf('_', 2));
7073
7004
  objectHackers = ['assert', 'compareArray', 'Test262Error', ...new Set(Object.keys(builtinFuncs).map(getObjectName).concat(Object.keys(builtinVars).map(getObjectName)).filter(x => x))];
7074
7005
 
7075
- program.id = { name: '#main' };
7076
-
7077
- program.body = {
7078
- type: 'BlockStatement',
7079
- body: program.body
7080
- };
7081
-
7082
- if (Prefs.astLog) console.log(JSON.stringify(program.body.body, null, 2));
7083
-
7084
- const [ main ] = generateFunc({}, program);
7006
+ const [ main ] = generateFunc({}, {
7007
+ type: 'Program',
7008
+ id: { name: '#main' },
7009
+ body: {
7010
+ type: 'BlockStatement',
7011
+ body: program.body
7012
+ }
7013
+ });
7085
7014
 
7086
7015
  // if wanted and blank main func and other exports, remove it
7087
7016
  if (Prefs.rmBlankMain && main.wasm.length === 0 && funcs.some(x => x.export)) funcs.splice(main.index - importedFuncs.length, 1);
7088
7017
 
7089
- // make ~empty funcs for never generated funcs
7090
- // todo: these should just be deleted once able
7091
7018
  for (let i = 0; i < funcs.length; i++) {
7092
7019
  const f = funcs[i];
7093
7020
 
7094
- if (f.wasm) {
7095
- // run callbacks
7096
- const wasm = f.wasm;
7021
+ const wasm = f.wasm;
7022
+ if (wasm) {
7023
+ // func was generated, run callback ops
7097
7024
  for (let j = 0; j < wasm.length; j++) {
7098
7025
  const o = wasm[j];
7099
7026
  if (o[0] === null && typeof o[1] === 'function') {
@@ -7104,14 +7031,8 @@ export default program => {
7104
7031
  continue;
7105
7032
  }
7106
7033
 
7107
- // make wasm just return 0s for expected returns
7034
+ // func was never generated, make wasm just return 0s for expected returns
7108
7035
  f.wasm = f.returns.map(x => number(0, x));
7109
-
7110
- // alternative: make func empty, may break some indirect calls
7111
- // f.wasm = [];
7112
- // f.returns = [];
7113
- // f.params = [];
7114
- // f.locals = {};
7115
7036
  }
7116
7037
 
7117
7038
  // // remove never generated functions
@@ -7151,10 +7072,9 @@ export default program => {
7151
7072
  for (let i = 0; i < indirectFuncs.length; i++) {
7152
7073
  const f = indirectFuncs[i];
7153
7074
  f.index = currentFuncIndex++;
7075
+ funcs.push(f);
7154
7076
  }
7155
7077
 
7156
- funcs.push(...indirectFuncs);
7157
-
7158
7078
  delete globals['#ind'];
7159
7079
 
7160
7080
  return { funcs, globals, tags, exceptions, pages, data };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "An ahead-of-time JavaScript compiler",
4
- "version": "0.55.20",
4
+ "version": "0.55.22",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/r.cjs CHANGED
@@ -1,4 +1,10 @@
1
+ class C {
2
+ [(() => { return Math.random(); })()] = 1337;
3
+ }
1
4
 
5
+ console.log(new C());
6
+ console.log(new C());
7
+ console.log(new C());
2
8
 
3
9
  // let o = { set foo(x) { console.log('set foo', x); }, __proto__: { set bar(x) { console.log('set bar', x); } } };
4
10
 
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.55.20';
3
+ globalThis.version = '0.55.22';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {