porffor 0.41.7 → 0.42.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.
@@ -48,6 +48,7 @@ const cacheAst = (decl, wasm) => {
48
48
  return wasm;
49
49
  };
50
50
 
51
+ let indirectFuncs = [];
51
52
  const funcRef = func => {
52
53
  func.generate?.();
53
54
 
@@ -55,35 +56,53 @@ const funcRef = func => {
55
56
  [ Opcodes.const, 'funcref', func.name ]
56
57
  ];
57
58
 
58
- const wrapperArgc = Prefs.indirectWrapperArgc ?? 6;
59
- if (func.returns.length === 2 && countParams(func) < wrapperArgc && !func.wrapperFunc) {
59
+ const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
60
+ if (!func.wrapperFunc) {
60
61
  const locals = {}, params = [];
61
- for (let i = 0; i < wrapperArgc + (func.constr ? 2 : 0); i++) {
62
+ for (let i = 0; i < wrapperArgc + 2; i++) {
62
63
  params.push(valtypeBinary, Valtype.i32);
63
64
  locals[i * 2] = { idx: i * 2, type: valtypeBinary };
64
65
  locals[i * 2 + 1] = { idx: i * 2 + 1, type: Valtype.i32 };
65
66
  }
66
- let localInd = (wrapperArgc + (func.constr ? 2 : 0)) * 2;
67
+ let localInd = (wrapperArgc + 2) * 2;
67
68
 
68
69
  const wasm = [];
70
+ const offset = func.constr ? 0 : 4;
69
71
  for (let i = 0; i < func.params.length; i++) {
70
- wasm.push(
71
- [ Opcodes.local_get, i ],
72
- ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
73
- );
72
+ if (func.internal && func.name.includes('_prototype_') && i < 2) {
73
+ // special case: use real this for prototype internals
74
+ wasm.push(
75
+ [ Opcodes.local_get, 2 + i ],
76
+ ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
77
+ );
78
+ } else {
79
+ wasm.push(
80
+ [ Opcodes.local_get, offset + (!func.internal || func.typedParams ? i : i * 2) ],
81
+ ...(i % 2 === 0 && func.params[i] === Valtype.i32 ? [ Opcodes.i32_to ]: [])
82
+ );
83
+ }
74
84
  }
75
85
 
76
86
  wasm.push([ Opcodes.call, func.index ]);
77
87
 
78
88
  if (func.returns[0] === Valtype.i32) {
79
- const localIdx = localInd++;
80
- locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
89
+ if (func.returns.length === 2) {
90
+ const localIdx = localInd++;
91
+ locals[localIdx] = { idx: localIdx, type: Valtype.i32 };
81
92
 
82
- wasm.push(
83
- [ Opcodes.local_set, localIdx ],
84
- Opcodes.i32_from,
85
- [ Opcodes.local_get, localIdx ]
86
- );
93
+ wasm.push(
94
+ [ Opcodes.local_set, localIdx ],
95
+ Opcodes.i32_from,
96
+ [ Opcodes.local_get, localIdx ]
97
+ );
98
+ } else {
99
+ wasm.push(Opcodes.i32_from);
100
+ }
101
+ }
102
+
103
+ if (func.returns.length === 1) {
104
+ // add built-in returnType if only returns a value
105
+ wasm.push(...number(func.returnType ?? TYPES.number, Valtype.i32));
87
106
  }
88
107
 
89
108
  const name = '#indirect_' + func.name;
@@ -93,16 +112,26 @@ const funcRef = func => {
93
112
  locals, localInd,
94
113
  returns: [ valtypeBinary, Valtype.i32 ],
95
114
  wasm,
96
- constr: func.constr,
115
+ constr: true,
97
116
  internal: true,
98
- index: currentFuncIndex++
117
+ indirect: true
99
118
  };
100
119
 
101
- funcs.push(wrapperFunc);
102
- funcIndex[name] = wrapperFunc.index;
120
+ indirectFuncs.push(wrapperFunc);
103
121
 
104
122
  wrapperFunc.jsLength = countLength(func);
105
123
  func.wrapperFunc = wrapperFunc;
124
+
125
+ if (!func.constr) {
126
+ // check not being constructed
127
+ wasm.unshift(
128
+ [ Opcodes.local_get, 0 ], // new.target value
129
+ Opcodes.i32_to_u,
130
+ [ Opcodes.if, Blocktype.void ], // if value is non-zero
131
+ ...internalThrow(wrapperFunc, 'TypeError', `${unhackName(func.name)} is not a constructor`), // throw type error
132
+ [ Opcodes.end ]
133
+ );
134
+ }
106
135
  }
107
136
 
108
137
  return [
@@ -2233,7 +2262,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2233
2262
  scope.table = true;
2234
2263
 
2235
2264
  let args = decl.arguments;
2236
- const wrapperArgc = Prefs.indirectWrapperArgc ?? 6;
2265
+ const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
2237
2266
  if (args.length < wrapperArgc) {
2238
2267
  args = args.concat(new Array(wrapperArgc - args.length).fill(DEFAULT_VALUE()));
2239
2268
  }
@@ -2293,39 +2322,14 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2293
2322
 
2294
2323
  ...typeSwitch(scope, getNodeType(scope, callee), {
2295
2324
  [TYPES.function]: () => [
2296
- // get if func we are calling is a constructor or not
2325
+ ...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
2326
+ ...forceDuoValtype(scope, thisWasm, Valtype.f64),
2327
+ ...out,
2328
+
2297
2329
  [ Opcodes.local_get, calleeLocal ],
2298
2330
  Opcodes.i32_to_u,
2299
- ...number(48, Valtype.i32),
2300
- [ Opcodes.i32_mul ],
2301
- ...number(2, Valtype.i32),
2302
- [ Opcodes.i32_add ],
2303
- [ Opcodes.i32_load8_u, 0, ...unsignedLEB128(allocPage(scope, 'func lut')), 'read func lut' ],
2304
-
2305
- ...number(0b10, Valtype.i32),
2306
- [ Opcodes.i32_and ],
2307
- [ Opcodes.if, Valtype.f64 ],
2308
- ...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
2309
- ...forceDuoValtype(scope, thisWasm, Valtype.f64),
2310
- ...out,
2311
-
2312
- [ Opcodes.local_get, calleeLocal ],
2313
- Opcodes.i32_to_u,
2314
- [ Opcodes.call_indirect, args.length + 2, 0 ],
2315
- ...setLastType(scope),
2316
- [ Opcodes.else ],
2317
- // throw if non-constructor called with new
2318
- ...(callAsNew ? [
2319
- ...internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, Valtype.f64)
2320
- ] : [
2321
- ...out,
2322
-
2323
- [ Opcodes.local_get, calleeLocal ],
2324
- Opcodes.i32_to_u,
2325
- [ Opcodes.call_indirect, args.length, 0 ],
2326
- ...setLastType(scope)
2327
- ]),
2328
- [ Opcodes.end ]
2331
+ [ Opcodes.call_indirect, args.length + 2, 0 ],
2332
+ ...setLastType(scope)
2329
2333
  ],
2330
2334
 
2331
2335
  default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
@@ -2362,16 +2366,12 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2362
2366
  paramOffset += 4;
2363
2367
  }
2364
2368
 
2365
- if (func && !func.hasRestArgument && args.length < paramCount) {
2369
+ if (func && args.length < paramCount) {
2366
2370
  // too little args, push undefineds
2367
- args = args.concat(new Array(paramCount - args.length).fill(DEFAULT_VALUE()));
2371
+ args = args.concat(new Array(paramCount - (func.hasRestArgument ? 1 : 0) - args.length).fill(DEFAULT_VALUE()));
2368
2372
  }
2369
2373
 
2370
2374
  if (func && func.hasRestArgument) {
2371
- if (args.length < paramCount) {
2372
- args = args.concat(new Array(paramCount - 1 - args.length).fill(DEFAULT_VALUE()));
2373
- }
2374
-
2375
2375
  const restArgs = args.slice(paramCount - 1);
2376
2376
  args = args.slice(0, paramCount - 1);
2377
2377
  args.push({
@@ -2385,13 +2385,18 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2385
2385
  args = args.slice(0, paramCount);
2386
2386
  }
2387
2387
 
2388
- if (func && func.throws) scope.throws = true;
2389
-
2390
2388
  for (let i = 0; i < args.length; i++) {
2391
2389
  const arg = args[i];
2392
2390
  if (Array.isArray(arg)) {
2393
2391
  // if wasm, just append it
2394
2392
  out = out.concat(arg);
2393
+
2394
+ if (valtypeBinary !== Valtype.i32 &&
2395
+ (func && func.params[paramOffset + i * (typedParams ? 2 : 1)] === Valtype.i32)
2396
+ ) {
2397
+ out.push(...forceDuoValtype(scope, [], Valtype.i32));
2398
+ }
2399
+
2395
2400
  continue;
2396
2401
  }
2397
2402
 
@@ -3662,8 +3667,11 @@ const generateUnary = (scope, decl) => {
3662
3667
  case 'delete': {
3663
3668
  if (decl.argument.type === 'MemberExpression') {
3664
3669
  const object = decl.argument.object;
3665
- const property = getProperty(decl.argument);
3666
3670
 
3671
+ // disallow `delete super.*`
3672
+ if (object.type === 'Super') return internalThrow(scope, 'ReferenceError', 'Cannot delete super property', true);
3673
+
3674
+ const property = getProperty(decl.argument);
3667
3675
  if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
3668
3676
 
3669
3677
  return [
@@ -4597,8 +4605,6 @@ const generateLabel = (scope, decl) => {
4597
4605
  };
4598
4606
 
4599
4607
  const generateThrow = (scope, decl) => {
4600
- scope.throws = true;
4601
-
4602
4608
  let exceptionMode = Prefs.exceptionMode ?? 'stack';
4603
4609
  if (globalThis.precompile) exceptionMode = decl.argument.callee != null ? 'lut' : 'stack';
4604
4610
 
@@ -5056,11 +5062,7 @@ const toPropertyKey = (scope, wasm, type, computed = false, i32Conv = false) =>
5056
5062
  ...wasm,
5057
5063
  ...type,
5058
5064
  [ Opcodes.call, includeBuiltin(scope, '__ecma262_ToPropertyKey').index ],
5059
- ...(i32Conv ? [
5060
- [ Opcodes.local_set, localTmp(scope, '#swap', Valtype.i32) ],
5061
- Opcodes.i32_to_u,
5062
- [ Opcodes.local_get, localTmp(scope, '#swap', Valtype.i32) ]
5063
- ] : [])
5065
+ ...(i32Conv ? forceDuoValtype(scope, [], Valtype.i32) : [])
5064
5066
  ] : [
5065
5067
  ...wasm,
5066
5068
  ...(i32Conv ? [ Opcodes.i32_to_u ] : []),
@@ -5203,7 +5205,6 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5203
5205
  if (decl.property.name === 'name' && hasFuncWithName(name) && !scope.noFastFuncMembers) {
5204
5206
  // eg: __String_prototype_toLowerCase -> toLowerCase
5205
5207
  if (name.startsWith('__')) name = name.split('_').pop();
5206
- if (name.startsWith('#indirect_')) name = name.slice(10);
5207
5208
  if (name.startsWith('#')) name = '';
5208
5209
 
5209
5210
  return withType(scope, makeString(scope, name, _global, _name, true), TYPES.bytestring);
@@ -5620,16 +5621,7 @@ const generateClass = (scope, decl) => {
5620
5621
  type: 'Identifier',
5621
5622
  name
5622
5623
  };
5623
- const proto = {
5624
- type: 'MemberExpression',
5625
- object: root,
5626
- property: {
5627
- type: 'Identifier',
5628
- name: 'prototype'
5629
- },
5630
- computed: false,
5631
- optional: false
5632
- };
5624
+ const proto = getObjProp(root, 'prototype');
5633
5625
 
5634
5626
  const [ func, out ] = generateFunc(scope, {
5635
5627
  ...(body.find(x => x.kind === 'constructor')?.value ?? {
@@ -5656,7 +5648,7 @@ const generateClass = (scope, decl) => {
5656
5648
  // Bar.__proto__ = Foo
5657
5649
  // Bar.prototype.__proto__ = Foo.prototype
5658
5650
  ...generate(scope, setObjProp(root, '__proto__', decl.superClass)),
5659
- ...generate(scope, setObjProp(getObjProp(root, 'prototype'), '__proto__', getObjProp(decl.superClass, 'prototype')))
5651
+ ...generate(scope, setObjProp(proto, '__proto__', getObjProp(decl.superClass, 'prototype')))
5660
5652
  );
5661
5653
  }
5662
5654
 
@@ -6339,7 +6331,7 @@ export default program => {
6339
6331
  };
6340
6332
  tags = [];
6341
6333
  exceptions = [];
6342
- funcs = [];
6334
+ funcs = []; indirectFuncs = [];
6343
6335
  funcIndex = {};
6344
6336
  depth = [];
6345
6337
  pages = new Map();
@@ -6394,6 +6386,7 @@ export default program => {
6394
6386
  // todo: these should just be deleted once able
6395
6387
  for (let i = 0; i < funcs.length; i++) {
6396
6388
  const f = funcs[i];
6389
+
6397
6390
  if (f.wasm) {
6398
6391
  // run callbacks
6399
6392
  const wasm = f.wasm;
@@ -6450,9 +6443,15 @@ export default program => {
6450
6443
  // }
6451
6444
  // }
6452
6445
 
6453
- delete globals['#ind'];
6446
+ // add indirect funcs to end of funcs
6447
+ for (let i = 0; i < indirectFuncs.length; i++) {
6448
+ const f = indirectFuncs[i];
6449
+ f.index = currentFuncIndex++;
6450
+ }
6451
+
6452
+ funcs.push(...indirectFuncs);
6454
6453
 
6455
- // console.log([...usedTypes].map(x => TYPE_NAMES[x]));
6454
+ delete globals['#ind'];
6456
6455
 
6457
6456
  return { funcs, globals, tags, exceptions, pages, data };
6458
6457
  };
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.41.7+89be416c1",
4
+ "version": "0.42.0+93da2c806",
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.41.7+89be416c1';
3
+ globalThis.version = '0.42.0+93da2c806';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {