porffor 0.50.18 → 0.50.19

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.
@@ -219,7 +219,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
219
219
  return cacheAst(decl, generateFunc(scope, decl)[1]);
220
220
 
221
221
  case 'BlockStatement':
222
- return cacheAst(decl, generateCode(scope, decl));
222
+ return cacheAst(decl, generateBlock(scope, decl));
223
223
 
224
224
  case 'ReturnStatement':
225
225
  return cacheAst(decl, generateReturn(scope, decl));
@@ -304,7 +304,10 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
304
304
  return cacheAst(decl, generateTry(scope, decl));
305
305
 
306
306
  case 'DebuggerStatement':
307
- return cacheAst(decl, [[ Opcodes.call, importedFuncs.debugger ]]);
307
+ return cacheAst(decl, [
308
+ [ Opcodes.call, importedFuncs.debugger ],
309
+ number(UNDEFINED)
310
+ ]);
308
311
 
309
312
  case 'ArrayExpression':
310
313
  return cacheAst(decl, generateArray(scope, decl, global, name, globalThis.precompile));
@@ -332,7 +335,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
332
335
  return cacheAst(decl, generateTaggedTemplate(scope, decl, global, name));
333
336
 
334
337
  case 'ExportNamedDeclaration':
335
- if (!decl.declaration) return todo(scope, 'unsupported export declaration');
338
+ if (!decl.declaration) return todo(scope, 'unsupported export declaration', true);
336
339
 
337
340
  const funcsBefore = funcs.map(x => x.name);
338
341
  generate(scope, decl.declaration);
@@ -349,16 +352,16 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
349
352
  }
350
353
  }
351
354
 
352
- return cacheAst(decl, []);
355
+ return cacheAst(decl, [ number(UNDEFINED) ]);
353
356
 
354
357
  default:
355
358
  // ignore typescript nodes
356
359
  if (decl.type.startsWith('TS') ||
357
360
  decl.type === 'ImportDeclaration' && decl.importKind === 'type') {
358
- return cacheAst(decl, []);
361
+ return cacheAst(decl, [ number(UNDEFINED) ]);
359
362
  }
360
363
 
361
- return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`, !decl.type.endsWith('Statement') && !decl.type.endsWith('Declaration')));
364
+ return cacheAst(decl, todo(scope, `no generation for ${decl.type}!`, true));
362
365
  }
363
366
  };
364
367
 
@@ -1110,7 +1113,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
1110
1113
  let checkType = TYPES[rightName.toLowerCase()];
1111
1114
  if (checkType != null && rightName === TYPE_NAMES[checkType] && !rightName.endsWith('Error')) {
1112
1115
  const out = generate(scope, decl.left);
1113
- disposeLeftover(out);
1116
+ out.push([ Opcodes.drop ]);
1114
1117
 
1115
1118
  // switch primitive types to primitive object types
1116
1119
  if (checkType === TYPES.number) checkType = TYPES.numberobject;
@@ -1532,6 +1535,7 @@ const getNodeType = (scope, node) => {
1532
1535
  }
1533
1536
 
1534
1537
  if (isFuncType(node.type)) {
1538
+ if (node.type.endsWith('Declaration')) return TYPES.undefined;
1535
1539
  return TYPES.function;
1536
1540
  }
1537
1541
 
@@ -1711,6 +1715,18 @@ const getNodeType = (scope, node) => {
1711
1715
  return getNodeType(scope, node.expression);
1712
1716
  }
1713
1717
 
1718
+ if (node.type === 'BlockStatement') {
1719
+ return getNodeType(scope, getLastNode(node.body));
1720
+ }
1721
+
1722
+ if (node.type === 'LabeledStatement') {
1723
+ return getNodeType(scope, node.body);
1724
+ }
1725
+
1726
+ if (node.type.endsWith('Statement') || node.type.endsWith('Declaration')) {
1727
+ return TYPES.undefined;
1728
+ }
1729
+
1714
1730
  return getLastType(scope);
1715
1731
  })();
1716
1732
 
@@ -1745,68 +1761,13 @@ const generateLiteral = (scope, decl, global, name) => {
1745
1761
  }
1746
1762
  };
1747
1763
 
1748
- const countLeftover = wasm => {
1749
- let count = 0, depth = 0;
1750
-
1751
- for (let i = 0; i < wasm.length; i++) {
1752
- const inst = wasm[i];
1753
- if (depth === 0 && inst[0] == null) {
1754
- if (typeof inst[1] === 'function' && typeof inst[2] === 'number') count += inst[2];
1755
- continue;
1756
- }
1757
-
1758
- if (depth === 0 && (inst[0] === Opcodes.if || inst[0] === Opcodes.block || inst[0] === Opcodes.loop)) {
1759
- if (inst[0] === Opcodes.if) count--;
1760
- if (inst[1] !== Blocktype.void) count++;
1761
- }
1762
- if ([Opcodes.if, Opcodes.try, Opcodes.loop, Opcodes.block].includes(inst[0])) depth++;
1763
- if (inst[0] === Opcodes.end) depth--;
1764
-
1765
- if (depth === 0)
1766
- if ([Opcodes.drop, Opcodes.local_set, Opcodes.global_set].includes(inst[0])) count--;
1767
- else if ([Opcodes.i32_eqz, Opcodes.i64_eqz, Opcodes.f64_abs, Opcodes.f64_ceil, Opcodes.f64_floor, Opcodes.f64_trunc, Opcodes.f64_nearest, Opcodes.f64_sqrt, Opcodes.local_tee, Opcodes.i32_wrap_i64, Opcodes.i64_extend_i32_s, Opcodes.i64_extend_i32_u, Opcodes.f32_demote_f64, Opcodes.f64_promote_f32, Opcodes.f64_convert_i32_s, Opcodes.f64_convert_i32_u, Opcodes.i32_clz, Opcodes.i32_ctz, Opcodes.i32_popcnt, Opcodes.f64_neg, Opcodes.end, Opcodes.i32_trunc_sat_f64_s[0], Opcodes.i32x4_extract_lane, Opcodes.i16x8_extract_lane, Opcodes.i32_load, Opcodes.i64_load, Opcodes.f64_load, Opcodes.f32_load, Opcodes.v128_load, Opcodes.i32_load16_u, Opcodes.i32_load16_s, Opcodes.i32_load8_u, Opcodes.i32_load8_s, Opcodes.memory_grow].includes(inst[0]) && (inst[0] !== 0xfc || inst[1] < 0x04)) {}
1768
- else if ([Opcodes.local_get, Opcodes.global_get, Opcodes.f64_const, Opcodes.i32_const, Opcodes.i64_const, Opcodes.v128_const, Opcodes.memory_size].includes(inst[0])) count++;
1769
- else if ([Opcodes.i32_store, Opcodes.i64_store, Opcodes.f64_store, Opcodes.f32_store, Opcodes.i32_store16, Opcodes.i32_store8, Opcodes.select].includes(inst[0])) count -= 2;
1770
- else if (inst[0] === Opcodes.memory_copy[0] && (inst[1] === Opcodes.memory_copy[1] || inst[1] === Opcodes.memory_init[1])) count -= 3;
1771
- else if (inst[0] === Opcodes.return) count = 0;
1772
- else if (inst[0] === Opcodes.catch) count += 2;
1773
- else if (inst[0] === Opcodes.throw) {
1774
- count--;
1775
- if ((Prefs.exceptionMode ?? 'stack') === 'stack' || (globalThis.precompile && inst[1] === 1)) count--;
1776
- } else if (inst[0] === Opcodes.call) {
1777
- if (inst[1] < importedFuncs.length) {
1778
- const func = importedFuncs[inst[1]];
1779
- count = count - func.params + func.returns;
1780
- } else {
1781
- const func = funcByIndex(inst[1]);
1782
- count = count - func.params.length + func.returns.length;
1783
- }
1784
- } else if (inst[0] === Opcodes.call_indirect) {
1785
- count--; // funcidx
1786
- count -= inst[1] * 2; // params * 2 (typed)
1787
- count += 2; // fixed return (value, type)
1788
- } else count--;
1789
-
1790
- // console.log(count, depth, decompile([ inst ], undefined, undefined, undefined, undefined, undefined, funcs).slice(0, -1));
1791
- }
1792
-
1793
- return count;
1794
- };
1795
-
1796
- const disposeLeftover = wasm => {
1797
- const leftover = countLeftover(wasm);
1798
- for (let i = 0; i < leftover; i++) wasm.push([ Opcodes.drop ]);
1799
- };
1800
-
1801
1764
  const generateExp = (scope, decl) => {
1802
1765
  if (decl.directive === 'use strict') {
1803
1766
  scope.strict = true;
1767
+ return [ number(UNDEFINED) ];
1804
1768
  }
1805
1769
 
1806
- const out = generate(scope, decl.expression, undefined, undefined, !scope.inEval);
1807
- disposeLeftover(out);
1808
-
1809
- return out;
1770
+ return generate(scope, decl.expression, undefined, undefined, !scope.inEval);
1810
1771
  };
1811
1772
 
1812
1773
  const generateSequence = (scope, decl) => {
@@ -1814,8 +1775,8 @@ const generateSequence = (scope, decl) => {
1814
1775
 
1815
1776
  const exprs = decl.expressions;
1816
1777
  for (let i = 0; i < exprs.length; i++) {
1817
- if (i > 0) disposeLeftover(out);
1818
1778
  out.push(...generate(scope, exprs[i]));
1779
+ if (i !== exprs.length - 1) out.push([ Opcodes.drop ]);
1819
1780
  }
1820
1781
 
1821
1782
  return out;
@@ -1932,19 +1893,16 @@ const setObjProp = (obj, prop, value) => {
1932
1893
  };
1933
1894
 
1934
1895
  return objectHack({
1935
- type: 'ExpressionStatement',
1936
- expression: {
1937
- type: 'AssignmentExpression',
1938
- operator: '=',
1939
- left: {
1940
- type: 'MemberExpression',
1941
- object: obj,
1942
- property: prop,
1943
- computed: false,
1944
- optional: false
1945
- },
1946
- right: value
1947
- }
1896
+ type: 'AssignmentExpression',
1897
+ operator: '=',
1898
+ left: {
1899
+ type: 'MemberExpression',
1900
+ object: obj,
1901
+ property: prop,
1902
+ computed: false,
1903
+ optional: false
1904
+ },
1905
+ right: value
1948
1906
  });
1949
1907
  };
1950
1908
 
@@ -2058,6 +2016,14 @@ const createThisArg = (scope, decl) => {
2058
2016
  }
2059
2017
  };
2060
2018
 
2019
+ const isEmptyNode = x => x && (x.type === 'EmptyStatement' || (x.type === 'BlockStatement' && x.body.length === 0));
2020
+ const getLastNode = body => {
2021
+ let offset = 1, node = body[body.length - offset];
2022
+ while (isEmptyNode(node)) node = body[body.length - ++offset];
2023
+
2024
+ return node ?? { type: 'EmptyStatement' };
2025
+ };
2026
+
2061
2027
  const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2062
2028
  if (decl.type === 'NewExpression') decl._new = true;
2063
2029
 
@@ -2095,17 +2061,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2095
2061
  });
2096
2062
  scope.inEval = false;
2097
2063
 
2098
- const lastInst = getLastInst(out);
2099
- if (lastInst && lastInst[0] === Opcodes.drop) {
2100
- out.splice(out.length - 1, 1);
2101
-
2102
- const finalStatement = parsed.body[parsed.body.length - 1];
2103
- out.push(...setLastType(scope, getNodeType(scope, finalStatement)));
2104
- } else if (countLeftover(out) === 0) {
2105
- out.push(number(UNDEFINED));
2106
- out.push(...setLastType(scope, TYPES.undefined));
2107
- }
2108
-
2064
+ out.push(...setLastType(scope, getNodeType(scope, getLastNode(parsed.body))));
2109
2065
  return out;
2110
2066
  }
2111
2067
  }
@@ -2406,6 +2362,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2406
2362
  // TODO: error better
2407
2363
  default: internalThrow(scope, 'TypeError', `'${protoName}' proto func tried to be called on a type without an impl`, !unusedValue)
2408
2364
  }, unusedValue ? Blocktype.void : valtypeBinary),
2365
+ ...(unusedValue ? [ number(UNDEFINED) ] : [])
2409
2366
  ];
2410
2367
  }
2411
2368
 
@@ -3060,6 +3017,7 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary, fallthrough = fals
3060
3017
 
3061
3018
  out.push([ Opcodes.end ]);
3062
3019
 
3020
+ // todo: sometimes gets stuck?
3063
3021
  if (depth.at(-1) === 'typeswitch') {
3064
3022
  depth.pop();
3065
3023
  }
@@ -3524,6 +3482,7 @@ const generateVar = (scope, decl) => {
3524
3482
  out = out.concat(generateVarDstr(scope, decl.kind, x.id, x.init, undefined, global));
3525
3483
  }
3526
3484
 
3485
+ out.push(number(UNDEFINED));
3527
3486
  return out;
3528
3487
  };
3529
3488
 
@@ -3704,7 +3663,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3704
3663
  ...decl,
3705
3664
  _internalAssign: true
3706
3665
  });
3707
- if (valueUnused) disposeLeftover(slow);
3666
+ if (valueUnused) slow.push([ Opcodes.drop ]);
3708
3667
 
3709
3668
  return [
3710
3669
  ...out,
@@ -4053,7 +4012,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
4053
4012
  [ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
4054
4013
  [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ]
4055
4014
  ], getType(scope, name), getNodeType(scope, decl.right), isGlobal, name, true),
4056
- [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
4057
4015
 
4058
4016
  ...setType(scope, name, getLastType(scope), true)
4059
4017
  ];
@@ -4148,7 +4106,7 @@ const generateUnary = (scope, decl) => {
4148
4106
  case 'void': {
4149
4107
  // drop current expression value after running, give undefined
4150
4108
  const out = generate(scope, decl.argument);
4151
- disposeLeftover(out);
4109
+ out.push([ Opcodes.drop ]);
4152
4110
 
4153
4111
  out.push(number(UNDEFINED));
4154
4112
  return out;
@@ -4215,7 +4173,7 @@ const generateUnary = (scope, decl) => {
4215
4173
  }
4216
4174
 
4217
4175
  const out = toGenerate ? generate(scope, decl.argument) : [];
4218
- disposeLeftover(out);
4176
+ if (toGenerate) out.push([ Opcodes.drop ]);
4219
4177
 
4220
4178
  out.push(number(toReturn ? 1 : 0));
4221
4179
  return out;
@@ -4229,7 +4187,7 @@ const generateUnary = (scope, decl) => {
4229
4187
  }
4230
4188
 
4231
4189
  const out = toGenerate ? generate(scope, decl.argument) : [];
4232
- disposeLeftover(out);
4190
+ if (toGenerate) out.push([ Opcodes.drop ]);
4233
4191
 
4234
4192
  out.push(...typeSwitch(scope, overrideType ?? getNodeType(scope, decl.argument), [
4235
4193
  [ TYPES.number, () => makeString(scope, 'number') ],
@@ -4308,8 +4266,7 @@ const generateUpdate = (scope, decl, _global, _name, valueUnused = false) => {
4308
4266
  right: { type: 'Literal', value: 1 }
4309
4267
  }
4310
4268
  }, _global, _name, valueUnused),
4311
- ...(decl.prefix || valueUnused ? [] : [ [ Opcodes.drop ] ]),
4312
- ...optional([ number(UNDEFINED) ], valueUnused)
4269
+ ...(decl.prefix || valueUnused ? [] : [ [ Opcodes.drop ] ])
4313
4270
  ];
4314
4271
  };
4315
4272
 
@@ -4351,22 +4308,26 @@ const generateIf = (scope, decl) => {
4351
4308
  depth.push('if');
4352
4309
  inferBranchStart(scope, decl.consequent);
4353
4310
 
4354
- const consOut = generate(scope, decl.consequent);
4355
- disposeLeftover(consOut);
4356
- out.push(...consOut);
4311
+ out.push(
4312
+ ...generate(scope, decl.consequent),
4313
+ [ Opcodes.drop ]
4314
+ );
4357
4315
 
4358
4316
  inferBranchEnd(scope);
4359
4317
  if (decl.alternate) {
4360
- out.push([ Opcodes.else ]);
4361
4318
  inferBranchStart(scope, decl.alternate);
4362
-
4363
- const altOut = generate(scope, decl.alternate);
4364
- disposeLeftover(altOut);
4365
- out.push(...altOut);
4319
+ out.push(
4320
+ [ Opcodes.else ],
4321
+ ...generate(scope, decl.alternate),
4322
+ [ Opcodes.drop ]
4323
+ );
4366
4324
  inferBranchEnd(scope);
4367
4325
  }
4368
4326
 
4369
- out.push([ Opcodes.end ]);
4327
+ out.push(
4328
+ [ Opcodes.end ],
4329
+ number(UNDEFINED)
4330
+ );
4370
4331
  depth.pop();
4371
4332
 
4372
4333
  return out;
@@ -4402,10 +4363,10 @@ let depth = [];
4402
4363
  const generateFor = (scope, decl) => {
4403
4364
  const out = [];
4404
4365
 
4405
- if (decl.init) {
4406
- out.push(...generate(scope, decl.init, false, undefined, true));
4407
- disposeLeftover(out);
4408
- }
4366
+ if (decl.init) out.push(
4367
+ ...generate(scope, decl.init, false, undefined, true),
4368
+ [ Opcodes.drop ]
4369
+ );
4409
4370
 
4410
4371
  inferLoopStart(scope, decl);
4411
4372
  out.push([ Opcodes.loop, Blocktype.void ]);
@@ -4414,19 +4375,31 @@ const generateFor = (scope, decl) => {
4414
4375
  if (decl.test) out.push(...generate(scope, decl.test), Opcodes.i32_to);
4415
4376
  else out.push(number(1, Valtype.i32));
4416
4377
 
4417
- out.push([ Opcodes.if, Blocktype.void ]);
4418
- depth.push('if');
4378
+ out.push(
4379
+ [ Opcodes.if, Blocktype.void ],
4380
+ [ Opcodes.block, Blocktype.void ]
4381
+ );
4382
+ depth.push('if', 'block');
4419
4383
 
4420
- out.push([ Opcodes.block, Blocktype.void ]);
4421
- depth.push('block');
4422
- out.push(...generate(scope, decl.body));
4423
- out.push([ Opcodes.end ]);
4384
+ out.push(
4385
+ ...generate(scope, decl.body),
4386
+ [ Opcodes.drop ],
4387
+ [ Opcodes.end ]
4388
+ );
4389
+ depth.pop();
4424
4390
 
4425
- if (decl.update) out.push(...generate(scope, decl.update, false, undefined, true));
4391
+ if (decl.update) out.push(
4392
+ ...generate(scope, decl.update, false, undefined, true),
4393
+ [ Opcodes.drop ]
4394
+ );
4426
4395
 
4427
- out.push([ Opcodes.br, 1 ]);
4428
- out.push([ Opcodes.end ], [ Opcodes.end ]);
4429
- depth.pop(); depth.pop(); depth.pop();
4396
+ out.push(
4397
+ [ Opcodes.br, 1 ],
4398
+ [ Opcodes.end ],
4399
+ [ Opcodes.end ],
4400
+ number(UNDEFINED)
4401
+ );
4402
+ depth.pop(); depth.pop();
4430
4403
 
4431
4404
  inferLoopEnd(scope);
4432
4405
  return out;
@@ -4439,14 +4412,21 @@ const generateWhile = (scope, decl) => {
4439
4412
  out.push([ Opcodes.loop, Blocktype.void ]);
4440
4413
  depth.push('while');
4441
4414
 
4442
- out.push(...generate(scope, decl.test));
4443
- out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
4415
+ out.push(
4416
+ ...generate(scope, decl.test),
4417
+ Opcodes.i32_to,
4418
+ [ Opcodes.if, Blocktype.void ]
4419
+ );
4444
4420
  depth.push('if');
4445
4421
 
4446
- out.push(...generate(scope, decl.body));
4447
-
4448
- out.push([ Opcodes.br, 1 ]);
4449
- out.push([ Opcodes.end ], [ Opcodes.end ]);
4422
+ out.push(
4423
+ ...generate(scope, decl.body),
4424
+ [ Opcodes.drop ],
4425
+ [ Opcodes.br, 1 ],
4426
+ [ Opcodes.end ],
4427
+ [ Opcodes.end ],
4428
+ number(UNDEFINED)
4429
+ );
4450
4430
  depth.pop(); depth.pop();
4451
4431
 
4452
4432
  inferLoopEnd(scope);
@@ -4458,27 +4438,31 @@ const generateDoWhile = (scope, decl) => {
4458
4438
  inferLoopStart(scope, decl);
4459
4439
 
4460
4440
  out.push([ Opcodes.loop, Blocktype.void ]);
4461
- depth.push('dowhile');
4462
4441
 
4463
4442
  // block for break (includes all)
4464
4443
  out.push([ Opcodes.block, Blocktype.void ]);
4465
- depth.push('block');
4466
4444
 
4467
4445
  // block for continue
4468
4446
  // includes body but not test+loop so we can exit body at anytime
4469
4447
  // and still test+loop after
4470
4448
  out.push([ Opcodes.block, Blocktype.void ]);
4471
- depth.push('block');
4449
+ depth.push('dowhile', 'block', 'block');
4472
4450
 
4473
- out.push(...generate(scope, decl.body));
4474
-
4475
- out.push([ Opcodes.end ]);
4451
+ out.push(
4452
+ ...generate(scope, decl.body),
4453
+ [ Opcodes.drop ],
4454
+ [ Opcodes.end ]
4455
+ );
4476
4456
  depth.pop();
4477
4457
 
4478
- out.push(...generate(scope, decl.test), Opcodes.i32_to);
4479
- out.push([ Opcodes.br_if, 1 ]);
4480
-
4481
- out.push([ Opcodes.end ], [ Opcodes.end ]);
4458
+ out.push(
4459
+ ...generate(scope, decl.test),
4460
+ Opcodes.i32_to,
4461
+ [ Opcodes.br_if, 1 ],
4462
+ [ Opcodes.end ],
4463
+ [ Opcodes.end ],
4464
+ number(UNDEFINED)
4465
+ );
4482
4466
  depth.pop(); depth.pop();
4483
4467
 
4484
4468
  inferLoopEnd(scope);
@@ -4811,17 +4795,17 @@ const generateForOf = (scope, decl) => {
4811
4795
  }
4812
4796
 
4813
4797
  // next and set local
4814
- out.push(...setVar);
4815
-
4816
- // generate body
4817
- out.push(...generate(scope, decl.body));
4818
-
4819
- out.push([ Opcodes.br, 1 ]); // continue
4820
- out.push([ Opcodes.end ]); // end block
4821
- out.push([ Opcodes.end ]); // end loop
4798
+ out.push(
4799
+ ...setVar,
4800
+ ...generate(scope, decl.body),
4801
+ [ Opcodes.drop ],
4802
+ [ Opcodes.br, 1 ], // continue
4803
+ [ Opcodes.end ], // end block
4804
+ [ Opcodes.end ], // end loop
4805
+ number(UNDEFINED)
4806
+ );
4822
4807
 
4823
- depth.pop();
4824
- depth.pop();
4808
+ depth.pop(); depth.pop();
4825
4809
 
4826
4810
  inferLoopEnd(scope);
4827
4811
  return out;
@@ -4921,6 +4905,7 @@ const generateForIn = (scope, decl) => {
4921
4905
  [ Opcodes.i32_and ],
4922
4906
  [ Opcodes.if, Blocktype.void ],
4923
4907
  ...generate(scope, decl.body),
4908
+ [ Opcodes.drop ],
4924
4909
  [ Opcodes.end ],
4925
4910
 
4926
4911
  // increment pointer by 14
@@ -4953,33 +4938,41 @@ const generateForIn = (scope, decl) => {
4953
4938
 
4954
4939
  inferLoopEnd(scope);
4955
4940
 
4956
- return typeSwitch(scope, getNodeType(scope, decl.right), {
4941
+ const final = typeSwitch(scope, getNodeType(scope, decl.right), {
4957
4942
  // fast path for objects
4958
4943
  [TYPES.object]: out,
4959
4944
 
4960
4945
  // wrap for of object.keys
4961
- default: () => generate(scope, {
4962
- type: 'ForOfStatement',
4963
- left: decl.left,
4964
- body: decl.body,
4965
- right: {
4966
- type: 'CallExpression',
4967
- callee: {
4968
- type: 'Identifier',
4969
- name: '__Object_keys'
4970
- },
4971
- arguments: [ {
4972
- type: 'LogicalExpression',
4973
- left: decl.right,
4974
- operator: '??',
4975
- right: {
4976
- type: 'Literal',
4977
- value: 0
4978
- }
4979
- } ]
4980
- }
4981
- })
4946
+ default: () => {
4947
+ const out = generate(scope, {
4948
+ type: 'ForOfStatement',
4949
+ left: decl.left,
4950
+ body: decl.body,
4951
+ right: {
4952
+ type: 'CallExpression',
4953
+ callee: {
4954
+ type: 'Identifier',
4955
+ name: '__Object_keys'
4956
+ },
4957
+ arguments: [ {
4958
+ type: 'LogicalExpression',
4959
+ left: decl.right,
4960
+ operator: '??',
4961
+ right: {
4962
+ type: 'Literal',
4963
+ value: 0
4964
+ }
4965
+ } ]
4966
+ }
4967
+ });
4968
+
4969
+ out.push([ Opcodes.drop ]);
4970
+ return out;
4971
+ }
4982
4972
  }, Blocktype.void);
4973
+
4974
+ final.push(number(UNDEFINED));
4975
+ return final;
4983
4976
  };
4984
4977
 
4985
4978
  const generateSwitch = (scope, decl) => {
@@ -5024,6 +5017,7 @@ const generateSwitch = (scope, decl) => {
5024
5017
  }, Blocktype.void, true);
5025
5018
 
5026
5019
  depth.pop();
5020
+ out.push(number(UNDEFINED));
5027
5021
  return out;
5028
5022
  }
5029
5023
  }
@@ -5082,13 +5076,15 @@ const generateSwitch = (scope, decl) => {
5082
5076
  depth.pop();
5083
5077
  out.push(
5084
5078
  [ Opcodes.end ],
5085
- ...generate(scope, { type: 'BlockStatement', body: cases[i].consequent })
5079
+ ...generate(scope, { type: 'BlockStatement', body: cases[i].consequent }),
5080
+ [ Opcodes.drop ]
5086
5081
  );
5087
5082
  }
5088
5083
 
5089
5084
  out.push([ Opcodes.end ]);
5090
5085
  depth.pop();
5091
5086
 
5087
+ out.push(number(UNDEFINED));
5092
5088
  return out;
5093
5089
  };
5094
5090
 
@@ -5211,13 +5207,19 @@ const generateTry = (scope, decl) => {
5211
5207
 
5212
5208
  const out = [];
5213
5209
 
5214
- const finalizer = decl.finalizer ? generate(scope, decl.finalizer) : [];
5210
+ const finalizer = decl.finalizer ? [
5211
+ ...generate(scope, decl.finalizer),
5212
+ [ Opcodes.drop ]
5213
+ ]: [];
5215
5214
 
5216
5215
  out.push([ Opcodes.try, Blocktype.void ]);
5217
5216
  depth.push('try');
5218
5217
 
5219
- out.push(...generate(scope, decl.block));
5220
- out.push(...finalizer);
5218
+ out.push(
5219
+ ...generate(scope, decl.block),
5220
+ [ Opcodes.drop ],
5221
+ ...finalizer
5222
+ );
5221
5223
 
5222
5224
  if (decl.handler) {
5223
5225
  depth.pop();
@@ -5252,6 +5254,7 @@ const generateTry = (scope, decl) => {
5252
5254
 
5253
5255
  out.push(
5254
5256
  ...generate(scope, decl.handler.body),
5257
+ [ Opcodes.drop ],
5255
5258
  ...finalizer
5256
5259
  );
5257
5260
  }
@@ -5259,11 +5262,12 @@ const generateTry = (scope, decl) => {
5259
5262
  out.push([ Opcodes.end ]);
5260
5263
  depth.pop();
5261
5264
 
5265
+ out.push(number(UNDEFINED));
5262
5266
  return out;
5263
5267
  };
5264
5268
 
5265
5269
  const generateEmpty = (scope, decl) => {
5266
- return [];
5270
+ return [ number(UNDEFINED) ];
5267
5271
  };
5268
5272
 
5269
5273
  const generateMeta = (scope, decl) => {
@@ -6143,13 +6147,15 @@ const generateClass = (scope, decl) => {
6143
6147
  // Bar.__proto__ = Foo
6144
6148
  // Bar.prototype.__proto__ = Foo.prototype
6145
6149
  ...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
6146
- ...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype')))
6150
+ [ Opcodes.drop ],
6151
+ ...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype'))),
6152
+ [ Opcodes.drop ]
6147
6153
  );
6148
6154
  }
6149
6155
 
6150
6156
  for (const x of body) {
6151
6157
  let { type, key, value, kind, static: _static, computed } = x;
6152
- if (type !== 'MethodDefinition' && type !== 'PropertyDefinition') return todo(scope, `class body type ${type} is not supported yet`, expr);
6158
+ if (type !== 'MethodDefinition' && type !== 'PropertyDefinition') return todo(scope, `class body type ${type} is not supported yet`, true);
6153
6159
 
6154
6160
  if (kind === 'constructor') continue;
6155
6161
 
@@ -6584,6 +6590,30 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6584
6590
  wasm = generate(func, body);
6585
6591
  wasm.unshift(...preface);
6586
6592
 
6593
+ if (name === '#main') {
6594
+ func.gotLastType = true;
6595
+ func.export = true;
6596
+
6597
+ wasm.push(...getNodeType(func, getLastNode(decl.body.body)));
6598
+
6599
+ // inject promise job runner func at the end of main if promises are made
6600
+ if (Object.hasOwn(funcIndex, 'Promise') || Object.hasOwn(funcIndex, '__Promise_resolve') || Object.hasOwn(funcIndex, '__Promise_reject')) {
6601
+ wasm.push(
6602
+ [ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ],
6603
+ [ Opcodes.drop ],
6604
+ [ Opcodes.drop ]
6605
+ );
6606
+ }
6607
+ } else {
6608
+ // add end empty return if not found
6609
+ if (wasm[wasm.length - 1]?.[0] !== Opcodes.return) {
6610
+ wasm.push(
6611
+ [ Opcodes.drop ],
6612
+ ...generateReturn(func, {})
6613
+ );
6614
+ }
6615
+ }
6616
+
6587
6617
  if (func.generator) {
6588
6618
  // make generator at the start
6589
6619
  wasm.unshift(
@@ -6628,57 +6658,6 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6628
6658
  ensureTag();
6629
6659
  }
6630
6660
 
6631
- if (name === '#main') {
6632
- func.gotLastType = true;
6633
- func.export = true;
6634
-
6635
- let finalStatement = decl.body.body[decl.body.body.length - 1];
6636
- if (finalStatement?.type === 'EmptyStatement') finalStatement = decl.body.body[decl.body.body.length - 2];
6637
-
6638
- const lastInst = getLastInst(wasm) ?? [ Opcodes.end ];
6639
- if (lastInst[0] === Opcodes.drop || lastInst[0] === Opcodes.f64_const) {
6640
- if (finalStatement.type.endsWith('Declaration')) {
6641
- // final statement is decl, force undefined
6642
- disposeLeftover(wasm);
6643
- wasm.push(
6644
- number(UNDEFINED),
6645
- number(TYPES.undefined, Valtype.i32)
6646
- );
6647
- } else {
6648
- wasm.splice(wasm.length - 1, 1);
6649
- wasm.push(...getNodeType(func, finalStatement));
6650
- }
6651
- }
6652
-
6653
- if (lastInst[0] === Opcodes.end || lastInst[0] === Opcodes.local_set || lastInst[0] === Opcodes.global_set) {
6654
- if (lastInst[0] === Opcodes.local_set && lastInst[1] === func.locals['#last_type'].idx) {
6655
- wasm.splice(wasm.length - 1, 1);
6656
- } else {
6657
- func.returns = [];
6658
- }
6659
- }
6660
-
6661
- if (lastInst[0] === Opcodes.call) {
6662
- const callee = funcByIndex(lastInst[1]);
6663
- if (callee) func.returns = callee.returns.slice();
6664
- else func.returns = [];
6665
- }
6666
-
6667
- // inject promise job runner func at the end of main if promises are made
6668
- if (Object.hasOwn(funcIndex, 'Promise') || Object.hasOwn(funcIndex, '__Promise_resolve') || Object.hasOwn(funcIndex, '__Promise_reject')) {
6669
- wasm.push(
6670
- [ Opcodes.call, includeBuiltin(func, '__Porffor_promise_runJobs').index ],
6671
- [ Opcodes.drop ],
6672
- [ Opcodes.drop ]
6673
- );
6674
- }
6675
- } else {
6676
- // add end return if not found
6677
- if (wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) < func.returns.length) {
6678
- wasm.push(...generateReturn(func, {}));
6679
- }
6680
- }
6681
-
6682
6661
  return func.wasm = wasm;
6683
6662
  }
6684
6663
  };
@@ -6747,24 +6726,31 @@ const generateFunc = (scope, decl, forceNoExpr = false) => {
6747
6726
  if (globalThis.precompile) func.generate();
6748
6727
 
6749
6728
  if (decl._doNotMarkFuncRef) doNotMarkFuncRef = true;
6750
- const out = decl.type.endsWith('Expression') && !forceNoExpr ? funcRef(func) : [];
6729
+ const out = decl.type.endsWith('Expression') && !forceNoExpr ? funcRef(func) : [ number(UNDEFINED) ];
6751
6730
  doNotMarkFuncRef = false;
6752
6731
 
6753
6732
  astCache.set(decl, out);
6754
6733
  return [ func, out ];
6755
6734
  };
6756
6735
 
6757
- const generateCode = (scope, decl) => {
6736
+ const generateBlock = (scope, decl) => {
6758
6737
  let out = [];
6759
6738
 
6760
6739
  scope.inferTree ??= [];
6761
6740
  scope.inferTree.push(decl);
6762
6741
 
6763
- for (const x of decl.body) {
6742
+ let j = 0;
6743
+ for (let i = 0; i < decl.body.length; i++) {
6744
+ const x = decl.body[i];
6745
+ if (isEmptyNode(x)) continue;
6746
+
6747
+ if (j++ > 0) out.push([ Opcodes.drop ]);
6764
6748
  out = out.concat(generate(scope, x));
6765
6749
  }
6766
6750
 
6767
6751
  scope.inferTree.pop();
6752
+
6753
+ if (out.length === 0) out.push(number(UNDEFINED));
6768
6754
  return out;
6769
6755
  };
6770
6756
 
@@ -6867,7 +6853,9 @@ const internalConstrs = {
6867
6853
  scope.usesImports = true;
6868
6854
 
6869
6855
  const str = decl.arguments[0].value;
6870
- return printStaticStr(str);
6856
+ const out = printStaticStr(str);
6857
+ out.push(number(UNDEFINED));
6858
+ return out;
6871
6859
  },
6872
6860
  type: TYPES.undefined,
6873
6861
  notConstr: true,
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.50.18",
4
+ "version": "0.50.19",
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.50.18';
3
+ globalThis.version = '0.50.19';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {