porffor 0.24.12 → 0.24.14

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.
@@ -91,6 +91,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
91
91
  case 'NewExpression':
92
92
  return cacheAst(decl, generateNew(scope, decl, global, name));
93
93
 
94
+ case 'ThisExpression':
95
+ return cacheAst(decl, generateThis(scope, decl, global, name));
96
+
94
97
  case 'Literal':
95
98
  return cacheAst(decl, generateLiteral(scope, decl, global, name));
96
99
 
@@ -351,22 +354,33 @@ const generateIdent = (scope, decl) => {
351
354
  };
352
355
 
353
356
  const generateReturn = (scope, decl) => {
354
- if (decl.argument === null) {
355
- // just bare "return"
356
- return [
357
- ...number(UNDEFINED), // "undefined" if func returns
358
- ...(scope.returnType != null ? [] : [
359
- ...number(TYPES.undefined, Valtype.i32) // type undefined
360
- ]),
361
- [ Opcodes.return ]
362
- ];
357
+ const arg = decl.argument ?? DEFAULT_VALUE();
358
+
359
+ const out = [];
360
+ if (
361
+ scope.constr && // only do this in constructors
362
+ !globalThis.precompile // skip in precompiled built-ins, we should not require this and handle it ourselves
363
+ ) {
364
+ // ignore return value and return this if being constructed
365
+ out.push(
366
+ // ...truthy(scope, [ [ Opcodes.local_get, '#newtarget' ] ], [ [ Opcodes.local_get, '#newtarget#type' ] ], false, true),
367
+ [ Opcodes.local_get, '#newtarget' ],
368
+ Opcodes.i32_to_u,
369
+ [ Opcodes.if, Blocktype.void ],
370
+ [ Opcodes.local_get, '#this' ],
371
+ ...(scope.returnType != null ? [] : [ [ Opcodes.local_get, '#this#type' ] ]),
372
+ [ Opcodes.return ],
373
+ [ Opcodes.end ]
374
+ );
363
375
  }
364
376
 
365
- return [
366
- ...generate(scope, decl.argument),
367
- ...(scope.returnType != null ? [] : getNodeType(scope, decl.argument)),
377
+ out.push(
378
+ ...generate(scope, arg),
379
+ ...(scope.returnType != null ? [] : getNodeType(scope, arg)),
368
380
  [ Opcodes.return ]
369
- ];
381
+ );
382
+
383
+ return out;
370
384
  };
371
385
 
372
386
  const localTmp = (scope, name, type = valtypeBinary) => {
@@ -1303,26 +1317,6 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
1303
1317
  funcs.table = true;
1304
1318
  }
1305
1319
 
1306
- if (constr) {
1307
- func.params = [...func.params];
1308
- func.params.unshift(Valtype.i32);
1309
-
1310
- // move all locals +1 idx (sigh)
1311
- func.localInd++;
1312
- const locals = func.locals;
1313
- for (const x in locals) {
1314
- locals[x].idx++;
1315
- }
1316
-
1317
- locals['#newtarget'] = { idx: 0, type: Valtype.i32 };
1318
-
1319
- for (const inst of wasm) {
1320
- if (inst[0] === Opcodes.local_get || inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) {
1321
- inst[1]++;
1322
- }
1323
- }
1324
- }
1325
-
1326
1320
  if (hasRestArgument) func.hasRestArgument = true;
1327
1321
 
1328
1322
  func.wasm = wasm;
@@ -1605,6 +1599,22 @@ const getNodeType = (scope, node) => {
1605
1599
  }
1606
1600
  }
1607
1601
 
1602
+ if (node.type == 'ThisExpression') {
1603
+ if (!scope.constr) return getType(scope, 'globalThis');
1604
+ return [ [ Opcodes.local_get, '#this#type' ] ];
1605
+ }
1606
+
1607
+ if (node.type == 'MetaProperty') {
1608
+ switch (`${node.meta.name}.${node.property.name}`) {
1609
+ case 'new.target': {
1610
+ return [ [ Opcodes.local_get, '#newtarget#type' ] ];
1611
+ }
1612
+
1613
+ default:
1614
+ return todo(scope, `meta property object ${node.meta.name} is not supported yet`, true);
1615
+ }
1616
+ }
1617
+
1608
1618
  if (scope.locals['#last_type']) return getLastType(scope);
1609
1619
 
1610
1620
  // presume
@@ -1762,6 +1772,42 @@ const RTArrayUtil = {
1762
1772
  ]
1763
1773
  };
1764
1774
 
1775
+ const createNewTarget = (scope, decl, idx) => {
1776
+ if (decl._new) {
1777
+ return [
1778
+ ...number(idx),
1779
+ ...number(TYPES.function, Valtype.i32)
1780
+ ];
1781
+ }
1782
+
1783
+ return [
1784
+ ...number(UNDEFINED),
1785
+ ...number(TYPES.undefined, Valtype.i32)
1786
+ ];
1787
+ };
1788
+
1789
+ const createThisArg = (scope, decl, getFunc, knownThis = undefined) => {
1790
+ if (knownThis) {
1791
+ // todo: check compliance
1792
+ return knownThis;
1793
+ }
1794
+
1795
+ if (decl._new) {
1796
+ // todo: created object should have .prototype = func.prototype
1797
+ // todo: created object should have .constructor = func
1798
+ return [
1799
+ // create an empty object
1800
+ ...generateObject(scope, { properties: [] }),
1801
+ ...number(TYPES.object, Valtype.i32)
1802
+ ];
1803
+ } else {
1804
+ return [
1805
+ ...generate(scope, { type: 'Identifier', name: 'globalThis' }),
1806
+ ...getType(scope, 'globalThis')
1807
+ ];
1808
+ }
1809
+ }
1810
+
1765
1811
  const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1766
1812
  let name = mapName(decl.callee.name);
1767
1813
  if (isFuncType(decl.callee.type)) { // iife
@@ -1978,7 +2024,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1978
2024
  getI32: () => RTArrayUtil.getLengthI32(getPointer),
1979
2025
  set: value => RTArrayUtil.setLength(getPointer, value),
1980
2026
  setI32: value => RTArrayUtil.setLengthI32(getPointer, value)
1981
- }, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, protoLocal2, (length, itemType) => {
2027
+ }, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()), getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()), protoLocal, protoLocal2, (length, itemType) => {
1982
2028
  return makeArray(scope, {
1983
2029
  rawElements: new Array(length)
1984
2030
  }, _global, _name, true, itemType, true);
@@ -2115,7 +2161,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2115
2161
  const minArgc = Prefs.indirectCallMinArgc ?? 3;
2116
2162
 
2117
2163
  if (args.length < minArgc) {
2118
- args = args.concat(new Array(minArgc - args.length).fill(DEFAULT_VALUE));
2164
+ args = args.concat(new Array(minArgc - args.length).fill(DEFAULT_VALUE()));
2119
2165
  }
2120
2166
  }
2121
2167
 
@@ -2182,6 +2228,26 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2182
2228
  const funcLocal = localTmp(scope, '#indirect_func', Valtype.i32);
2183
2229
  const flags = localTmp(scope, '#indirect_flags', Valtype.i32);
2184
2230
 
2231
+ let knownThis = undefined;
2232
+ let getCalleeObj = undefined;
2233
+ let initCalleeObj = undefined;
2234
+
2235
+ // hack: this should be more thorough, Function.bind, etc.
2236
+ if (decl.callee.type == 'MemberExpression') {
2237
+ const callee = localTmp(scope, '#indirect_callee_obj', Valtype.f64);
2238
+ initCalleeObj = [
2239
+ ...generate(scope, decl.callee.object),
2240
+ [ Opcodes.local_set, callee ]
2241
+ ];
2242
+ getCalleeObj = [
2243
+ [ Opcodes.local_get, callee ]
2244
+ ];
2245
+ knownThis = [
2246
+ [ Opcodes.local_get, callee ],
2247
+ ...getNodeType(scope, decl.callee.object)
2248
+ ];
2249
+ }
2250
+
2185
2251
  const gen = argc => {
2186
2252
  const argsOut = [];
2187
2253
  for (let i = 0; i < argc; i++) {
@@ -2202,43 +2268,39 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2202
2268
  [ Opcodes.end ]
2203
2269
  ];
2204
2270
 
2205
- // pain.
2206
- // return checkFlag(0b10, [ // constr
2207
- // [ Opcodes.i32_const, decl._new ? 1 : 0 ],
2208
- // ...argsOut,
2209
- // [ Opcodes.local_get, funcLocal ],
2210
- // [ Opcodes.call_indirect, argc, 0, 'constr' ],
2211
- // ...setLastType(scope),
2212
- // ], [
2213
- // ...argsOut,
2214
- // [ Opcodes.local_get, funcLocal ],
2215
- // [ Opcodes.call_indirect, argc, 0 ],
2216
- // ...setLastType(scope),
2217
- // ]);
2218
-
2219
- return checkFlag(0b1, // no type return
2220
- checkFlag(0b10, [ // no type return & constr
2221
- [ Opcodes.i32_const, decl._new ? 1 : 0 ],
2271
+ // todo: i'm sure this could be made better somehow, probably only with #96?
2272
+ return checkFlag(0b1,
2273
+ // no type return
2274
+ checkFlag(0b10, [
2275
+ // no type return & constr
2276
+ ...createNewTarget(scope, decl),
2277
+ ...createThisArg(scope, decl, [], knownThis),
2222
2278
  ...argsOut,
2223
2279
  [ Opcodes.local_get, funcLocal ],
2224
- [ Opcodes.call_indirect, argc, 0, 'no_type_return', 'constr' ],
2280
+ [ Opcodes.call_indirect, argc + 2, 0, 'no_type_return' ],
2225
2281
  ], [
2282
+ // no type return & not constr
2226
2283
  ...argsOut,
2227
2284
  [ Opcodes.local_get, funcLocal ],
2228
2285
  [ Opcodes.call_indirect, argc, 0, 'no_type_return' ]
2229
2286
  ]),
2230
- checkFlag(0b10, [ // type return & constr
2231
- [ Opcodes.i32_const, decl._new ? 1 : 0 ],
2287
+
2288
+ // type return
2289
+ checkFlag(0b10, [
2290
+ // type return & constr
2291
+ ...createNewTarget(scope, decl),
2292
+ ...createThisArg(scope, decl, [], knownThis),
2232
2293
  ...argsOut,
2233
2294
  [ Opcodes.local_get, funcLocal ],
2234
- [ Opcodes.call_indirect, argc, 0, 'constr' ],
2295
+ [ Opcodes.call_indirect, argc + 2, 0 ],
2235
2296
  ...setLastType(scope),
2236
2297
  ], [
2298
+ // type return
2237
2299
  ...argsOut,
2238
2300
  [ Opcodes.local_get, funcLocal ],
2239
2301
  [ Opcodes.call_indirect, argc, 0 ],
2240
2302
  ...setLastType(scope),
2241
- ]),
2303
+ ])
2242
2304
  );
2243
2305
  };
2244
2306
 
@@ -2250,7 +2312,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2250
2312
  // todo/perf: check if we should use br_table here or just generate our own big if..elses
2251
2313
 
2252
2314
  return [
2253
- ...generate(scope, decl.callee),
2315
+ ...(getCalleeObj ? [
2316
+ ...initCalleeObj,
2317
+ ...generateMember(scope, decl.callee, false, undefined, getCalleeObj)
2318
+ ]: generate(scope, decl.callee)),
2254
2319
  [ Opcodes.local_set, localTmp(scope, '#indirect_callee') ],
2255
2320
 
2256
2321
  ...typeSwitch(scope, getNodeType(scope, decl.callee), {
@@ -2298,26 +2363,28 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2298
2363
  const userFunc = func && !func.internal;
2299
2364
  const typedParams = userFunc || func?.typedParams;
2300
2365
  const typedReturns = (userFunc && func.returnType == null) || builtinFuncs[name]?.typedReturns;
2301
- let paramCount = func && (typedParams ? Math.floor(func.params.length / 2) : func.params.length);
2366
+ let paramCount = countParams(func, name);
2302
2367
 
2303
2368
  let paramOffset = 0;
2304
- if (func && func.constr) {
2305
- // new.target arg
2306
- if (func.internal) paramOffset = 1;
2307
- if (!typedParams) paramCount--;
2308
- out.push([ Opcodes.i32_const, decl._new ? 1 : 0 ]);
2309
- } else if (decl._new)
2369
+ if (decl._new && func && !func.constr) {
2310
2370
  return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
2371
+ }
2372
+
2373
+ if (func && func.constr) {
2374
+ out.push(...createNewTarget(scope, decl, idx - importedFuncs.length));
2375
+ out.push(...createThisArg(scope, decl, func));
2376
+ paramOffset += 4;
2377
+ }
2311
2378
 
2312
2379
  let args = [...decl.arguments];
2313
2380
  if (func && !func.hasRestArgument && args.length < paramCount) {
2314
2381
  // too little args, push undefineds
2315
- args = args.concat(new Array(paramCount - args.length).fill(DEFAULT_VALUE));
2382
+ args = args.concat(new Array(paramCount - args.length).fill(DEFAULT_VALUE()));
2316
2383
  }
2317
2384
 
2318
2385
  if (func && func.hasRestArgument) {
2319
2386
  if (args.length < paramCount) {
2320
- args = args.concat(new Array(paramCount - 1 - args.length).fill(DEFAULT_VALUE));
2387
+ args = args.concat(new Array(paramCount - 1 - args.length).fill(DEFAULT_VALUE()));
2321
2388
  }
2322
2389
 
2323
2390
  const restArgs = args.slice(paramCount - 1);
@@ -2391,11 +2458,26 @@ const generateNew = (scope, decl, _global, _name) => generateCall(scope, {
2391
2458
  _new: true
2392
2459
  }, _global, _name);
2393
2460
 
2461
+ const generateThis = (scope, decl, _global, _name) => {
2462
+ if (!scope.constr) {
2463
+ // this in a non-constructor context is a reference to globalThis
2464
+ return [
2465
+ ...generate(scope, { type: 'Identifier', name: 'globalThis' }),
2466
+ ...setLastType(scope, getType(scope, 'globalThis'))
2467
+ ];
2468
+ }
2469
+
2470
+ return [
2471
+ [ Opcodes.local_get, '#this' ],
2472
+ ...setLastType(scope, [ [ Opcodes.local_get, '#this#type' ] ])
2473
+ ];
2474
+ };
2475
+
2394
2476
  // bad hack for undefined and null working without additional logic
2395
- const DEFAULT_VALUE = {
2477
+ const DEFAULT_VALUE = () => ({
2396
2478
  type: 'Identifier',
2397
2479
  name: 'undefined'
2398
- };
2480
+ });
2399
2481
 
2400
2482
  const codeToSanitizedStr = code => {
2401
2483
  let out = '';
@@ -4128,7 +4210,7 @@ const generateThrow = (scope, decl) => {
4128
4210
  message = decl.argument.arguments[0];
4129
4211
  }
4130
4212
 
4131
- message ??= DEFAULT_VALUE;
4213
+ message ??= DEFAULT_VALUE();
4132
4214
 
4133
4215
  if (tags.length === 0) tags.push({
4134
4216
  params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
@@ -4153,7 +4235,7 @@ const generateThrow = (scope, decl) => {
4153
4235
  message = decl.argument.arguments[0];
4154
4236
  }
4155
4237
 
4156
- message ??= DEFAULT_VALUE;
4238
+ message ??= DEFAULT_VALUE();
4157
4239
 
4158
4240
  if (tags.length === 0) tags.push({
4159
4241
  params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
@@ -4209,18 +4291,15 @@ const generateEmpty = (scope, decl) => {
4209
4291
  };
4210
4292
 
4211
4293
  const generateMeta = (scope, decl) => {
4212
- if (decl.meta.name !== 'new') return todo(scope, `meta property object ${decl.meta.name} is not supported yet`, true);
4213
-
4214
4294
  switch (`${decl.meta.name}.${decl.property.name}`) {
4215
4295
  case 'new.target': {
4216
- scope.constr = true;
4217
-
4218
4296
  return [
4219
- [ Opcodes.local_get, -1 ],
4220
- Opcodes.i32_from_u,
4221
- ...setLastType(scope, TYPES.boolean)
4297
+ [ Opcodes.local_get, '#newtarget' ],
4222
4298
  ];
4223
4299
  }
4300
+
4301
+ default:
4302
+ return todo(scope, `meta property object ${decl.meta.name} is not supported yet`, true);
4224
4303
  }
4225
4304
  };
4226
4305
 
@@ -4641,7 +4720,25 @@ const wrapBC = (bc, { prelude = [], postlude = [] } = {}) => {
4641
4720
  return out;
4642
4721
  };
4643
4722
 
4644
- const generateMember = (scope, decl, _global, _name) => {
4723
+ const countParams = (func, name = undefined) => {
4724
+ if (!func) {
4725
+ if (Object.hasOwn(importedFuncs, name)) {
4726
+ // reverse lookup then normal lookup
4727
+ func = importedFuncs[importedFuncs[name]];
4728
+ if (func) return func.params?.length ?? func.params;
4729
+ }
4730
+ return;
4731
+ }
4732
+ if (func.argc) return func.argc;
4733
+
4734
+ let params = func.params.length;
4735
+ if (func.constr) params -= 4;
4736
+ if (!func.internal || builtinFuncs[func.name]?.typedParams) params = Math.floor(params / 2);
4737
+
4738
+ return func.argc = params;
4739
+ };
4740
+
4741
+ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) => {
4645
4742
  const name = decl.object.name;
4646
4743
 
4647
4744
  // hack: .name
@@ -4659,12 +4756,9 @@ const generateMember = (scope, decl, _global, _name) => {
4659
4756
  // todo: support optional
4660
4757
 
4661
4758
  const func = funcs.find(x => x.name === name);
4662
- if (func) {
4663
- const typedParams = !func.internal || func.typedParams;
4664
- return withType(scope, number(typedParams ? Math.floor(func.params.length / 2) : (func.constr ? (func.params.length - 1) : func.params.length)), TYPES.number);
4665
- }
4759
+ if (func) return withType(scope, number(countParams(func)), TYPES.number);
4666
4760
 
4667
- if (Object.hasOwn(builtinFuncs, name)) return withType(scope, number(builtinFuncs[name].typedParams ? Math.floor(builtinFuncs[name].params.length / 2) : (builtinFuncs[name].constr ? (builtinFuncs[name].params.length - 1) : builtinFuncs[name].params.length)), TYPES.number);
4761
+ if (Object.hasOwn(builtinFuncs, name)) return withType(scope, number(countParams(builtinFuncs[name])), TYPES.number);
4668
4762
  if (Object.hasOwn(importedFuncs, name)) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
4669
4763
  if (Object.hasOwn(internalConstrs, name)) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
4670
4764
 
@@ -4954,7 +5048,7 @@ const generateMember = (scope, decl, _global, _name) => {
4954
5048
  if (decl.optional) {
4955
5049
  out.unshift(
4956
5050
  [ Opcodes.block, valtypeBinary ],
4957
- ...generate(scope, object),
5051
+ ...(_objectWasm ? _objectWasm : generate(scope, object)),
4958
5052
  [ Opcodes.local_tee, localTmp(scope, '#member_obj') ],
4959
5053
 
4960
5054
  ...nullish(scope, [], getNodeType(scope, object), false, true),
@@ -4973,7 +5067,7 @@ const generateMember = (scope, decl, _global, _name) => {
4973
5067
  );
4974
5068
  } else {
4975
5069
  out.unshift(
4976
- ...generate(scope, object),
5070
+ ...(_objectWasm ? _objectWasm : generate(scope, object)),
4977
5071
  [ Opcodes.local_set, localTmp(scope, '#member_obj') ],
4978
5072
 
4979
5073
  ...generate(scope, property, false, '#member_prop'),
@@ -4995,7 +5089,7 @@ const objectHack = node => {
4995
5089
  if (node.computed || node.optional) return;
4996
5090
 
4997
5091
  // hack: block these properties as they can be accessed on functions
4998
- if (node.property.name == "length" || node.property.name == "name") return;
5092
+ if (node.property.name == 'length' || node.property.name == 'name') return;
4999
5093
 
5000
5094
  let objectName = node.object.name;
5001
5095
 
@@ -5045,7 +5139,8 @@ const generateFunc = (scope, decl) => {
5045
5139
  returns: [ valtypeBinary, Valtype.i32 ],
5046
5140
  throws: false,
5047
5141
  name,
5048
- index: currentFuncIndex++
5142
+ index: currentFuncIndex++,
5143
+ constr: decl.type && decl.type !== 'ArrowFunctionExpression' && decl.type !== 'Program'
5049
5144
  };
5050
5145
 
5051
5146
  funcIndex[name] = func.index;
@@ -5123,11 +5218,38 @@ const generateFunc = (scope, decl) => {
5123
5218
 
5124
5219
  // add end return if not found
5125
5220
  if (name !== 'main' && wasm[wasm.length - 1]?.[0] !== Opcodes.return && countLeftover(wasm) === 0) {
5126
- wasm.push(
5127
- ...number(0),
5128
- ...(func.returnType != null ? [] : number(TYPES.undefined, Valtype.i32)),
5129
- [ Opcodes.return ]
5130
- );
5221
+ wasm.push(...generateReturn(func, {}));
5222
+ }
5223
+
5224
+ if (func.constr) {
5225
+ const locals = func.locals;
5226
+ let idxOffset = 4;
5227
+ func.params = [ valtypeBinary, Valtype.i32, valtypeBinary, Valtype.i32, ...func.params ];
5228
+
5229
+ // move all local indexes by idxOffset
5230
+ func.localInd += idxOffset;
5231
+ for (const x in locals) {
5232
+ locals[x].idx += idxOffset;
5233
+ }
5234
+
5235
+ let indexes = idxOffset;
5236
+
5237
+ locals['#this#type'] = { idx: --indexes, type: Valtype.i32 };
5238
+ locals['#this'] = { idx: --indexes, type: valtypeBinary };
5239
+ locals['#newtarget#type'] = { idx: --indexes, type: Valtype.i32 };
5240
+ locals['#newtarget'] = { idx: --indexes, type: valtypeBinary };
5241
+
5242
+ for (let i = 0; i < wasm.length; i++) {
5243
+ // note: these needs to be copied, even though they realistically shouldn't
5244
+ const inst = wasm[i];
5245
+ if (inst[0] === Opcodes.local_get || inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) {
5246
+ if (typeof inst[1] == 'string') {
5247
+ wasm[i] = [ inst[0], locals[inst[1]].idx ];
5248
+ } else {
5249
+ wasm[i] = [ inst[0], inst[1] + idxOffset ];
5250
+ }
5251
+ }
5252
+ }
5131
5253
  }
5132
5254
 
5133
5255
  return func;
@@ -5156,7 +5278,7 @@ const internalConstrs = {
5156
5278
  rawElements: new Array(0)
5157
5279
  }, global, name, true, undefined, true, true);
5158
5280
 
5159
- const arg = decl.arguments[0] ?? DEFAULT_VALUE;
5281
+ const arg = decl.arguments[0] ?? DEFAULT_VALUE();
5160
5282
 
5161
5283
  // todo: check in wasm instead of here
5162
5284
  const literalValue = arg.value ?? 0;
@@ -5232,7 +5354,7 @@ const internalConstrs = {
5232
5354
  Boolean: {
5233
5355
  generate: (scope, decl) => {
5234
5356
  // todo: boolean object when used as constructor
5235
- const arg = decl.arguments[0] ?? DEFAULT_VALUE;
5357
+ const arg = decl.arguments[0] ?? DEFAULT_VALUE();
5236
5358
  return truthy(scope, generate(scope, arg), getNodeType(scope, arg), false, false, 'full');
5237
5359
  },
5238
5360
  type: TYPES.boolean,
@@ -209,11 +209,13 @@ ${funcs.map(x => {
209
209
  return `(scope, {${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}`.slice(0, -1)}}) => ` + str;
210
210
  };
211
211
 
212
+ const locals = Object.entries(x.locals).sort((a,b) => a[1].idx - b[1].idx)
213
+
212
214
  return ` this.${x.name} = {
213
215
  wasm: ${rewriteWasm(x.wasm)},
214
216
  params: ${JSON.stringify(x.params)}, typedParams: 1,
215
217
  returns: ${JSON.stringify(x.returns)}, ${x.returnType != null ? `returnType: ${JSON.stringify(x.returnType)}` : 'typedReturns: 1'},
216
- locals: ${JSON.stringify(Object.values(x.locals).slice(x.params.length).map(x => x.type))}, localNames: ${JSON.stringify(Object.keys(x.locals))},
218
+ locals: ${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))}, localNames: ${JSON.stringify(locals.map(x => x[0]))},
217
219
  ${x.globalInits ? ` globalInits: {${Object.keys(x.globalInits).map(y => `${y}: ${rewriteWasm(x.globalInits[y])}`).join(',')}},\n` : ''}${x.data && x.data.length > 0 ? ` data: [${x.data.map(x => `[${x.offset ?? 'null'},[${x.bytes.join(',')}]]`).join(',')}],` : ''}
218
220
  ${x.table ? ` table: 1,` : ''}${x.constr ? ` constr: 1,` : ''}${x.hasRestArgument ? ` hasRestArgument: 1,` : ''}
219
221
  };`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\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.24.12+276aa969c",
4
+ "version": "0.24.14+e5d79b96e",
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.24.12+276aa969c';
3
+ globalThis.version = '0.24.14+e5d79b96e';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {