porffor 0.58.16 → 0.58.18

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.
@@ -1529,7 +1529,7 @@ const isExistingProtoFunc = name => {
1529
1529
 
1530
1530
  const getInferred = (scope, name, global = false) => {
1531
1531
  if (global) {
1532
- if (globalInfer.has(name)) return globalInfer.get(name);
1532
+ if (globalInfer.has(name) && inferLoopPrev.length === 0) return globalInfer.get(name);
1533
1533
  } else if (scope.inferTree) {
1534
1534
  for (let i = scope.inferTree.length - 1; i >= 0; i--) {
1535
1535
  const x = scope.inferTree[i];
@@ -119,18 +119,18 @@ const compile = async (file, _funcs) => {
119
119
  const f = funcs.find(x => x.index === idx);
120
120
  if (!f) {
121
121
  if (idx < importedFuncs.length) {
122
- y.splice(1, 10, importedFuncs[idx].name);
122
+ wasm[i] = [ Opcodes.call, importedFuncs[idx].name ];
123
123
  }
124
124
 
125
125
  continue;
126
126
  }
127
127
 
128
- y.splice(1, 10, f.name);
128
+ wasm[i] = [ Opcodes.call, f.name ];
129
129
  }
130
130
 
131
131
  if (y[0] === Opcodes.global_get || y[0] === Opcodes.global_set) {
132
132
  const global = invGlobals[y[1]];
133
- y.splice(0, 10, 'global', y[0], global.name, global.type);
133
+ wasm[i] = [ 'global', y[0], global.name, global.type ];
134
134
 
135
135
  if (!x.globalInits) {
136
136
  if (!main.rewrittenGlobalInits) {
@@ -147,7 +147,7 @@ const compile = async (file, _funcs) => {
147
147
 
148
148
  if (rewriteLocals && typeof y[1] === 'number' && (y[0] === Opcodes.local_get || y[0] === Opcodes.local_set || y[0] === Opcodes.local_tee)) {
149
149
  const local = locals[y[1]];
150
- y.splice(1, 10, 'local', local.name, local.type);
150
+ wasm[i] = [ y[0], 'local', local.name, local.type ];
151
151
  }
152
152
 
153
153
  if (!n) continue;
@@ -161,7 +161,7 @@ const compile = async (file, _funcs) => {
161
161
  if (!pageName || allocated.has(pageName)) return;
162
162
  allocated.add(pageName);
163
163
 
164
- y.splice(0, 10, 'alloc', pageName, valtypeBinary);
164
+ wasm[i] = [ 'alloc', pageName, valtypeBinary ];
165
165
  };
166
166
 
167
167
  if (y[0] === Opcodes.const &&(n[0] === Opcodes.local_set || n[0] === Opcodes.local_tee)) {
@@ -177,7 +177,7 @@ const compile = async (file, _funcs) => {
177
177
  let id;
178
178
  if (y[0] === Opcodes.i32_const && n[1] === 0) {
179
179
  id = read_signedLEB128(y.slice(1));
180
- y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
180
+ wasm[i] = [ 'throw', exceptions[id].constructor, exceptions[id].message ];
181
181
 
182
182
  // remove throw inst
183
183
  wasm.splice(i + 1, 1);
@@ -249,7 +249,7 @@ ${funcs.map(x => {
249
249
  .replace(/\"local","(.*?)",(.*?)\]/g, (_, name, valtype) => `loc('${name}',${valtype})]`)
250
250
  .replace(/\[16,"(.*?)"]/g, (_, name) => `[16,builtin('${name}')]`)
251
251
  .replace(/\["funcref",(.*?),"(.*?)"]/g, (_1, op, name) => op === '65' ? `...i32ify(funcRef('${name}'))` : `...funcRef('${name}')`)
252
- .replace(/\["str",(.*?),"(.*?)",(.*?)]/g, (_1, op, str, bytestring) => op === '65' ? `...i32ify(makeString(_,"${str}",${bytestring}))` : `...makeString(_,"${str}",${bytestring === 'true' ? 1 : 0})`)
252
+ .replace(/\["str",(.*?),"(.*?)",(.*?)]/g, (_1, op, str, bytestring) => op === '65' ? `...i32ify(makeString(_,"${str}",${bytestring === 'true' ? 1 : 0}))` : `...makeString(_,"${str}",${bytestring === 'true' ? 1 : 0})`)
253
253
  .replace(/\["throw","(.*?)","(.*?)"\]/g, (_, constructor, message) => `...internalThrow(_,'${constructor}',\`${message}\`)`)
254
254
  .replace(/\["get object","(.*?)"\]/g, (_, objName) => `...generateIdent(_,{name:'${objName}'})`)
255
255
  .replace(/\[null,"typeswitch case start",\[(.*?)\]\],/g, (_, types) => `...t([${types}],()=>[`)
package/fuzz/generator.js CHANGED
@@ -8,9 +8,17 @@ const generators = {
8
8
  return `(${num})`;
9
9
  },
10
10
  string: () => {
11
- const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
12
- const len = Math.floor(Math.random() * 8) + 1;
13
- return `'${Array.from({length: len}, () => chars[Math.floor(Math.random() * chars.length)]).join('')}'`;
11
+ if (Math.random() < 0.1) {
12
+ return `''`;
13
+ }
14
+
15
+ const len = Math.floor(Math.random() * 32) + 1;
16
+ if (Math.random() < 0.8) { // bytestring
17
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
18
+ return `'${Array.from({length: len}, () => chars[Math.floor(Math.random() * chars.length)]).join('')}'`;
19
+ } else { // unicode string
20
+ return `'${Array.from({length: len}, () => `\\u${Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0')}`).join('')}'`;
21
+ }
14
22
  },
15
23
  boolean: () => Math.random() < 0.5 ? 'true' : 'false',
16
24
  null: () => 'null',
@@ -21,7 +29,7 @@ const generators = {
21
29
  if (depth > 2) return '[]';
22
30
  const len = Math.floor(Math.random() * 3);
23
31
  if (len === 0) return '[]';
24
- const items = Array.from({length: len}, () => generateSimple());
32
+ const items = Array.from({ length: len }, () => generateExpression(depth + 1));
25
33
  return `[${items.join(', ')}]`;
26
34
  },
27
35
 
@@ -31,9 +39,12 @@ const generators = {
31
39
  const len = Math.floor(Math.random() * 3);
32
40
  if (len === 0) return '{}';
33
41
  const props = Array.from({length: len}, () => {
34
- const key = String.fromCharCode(97 + Math.floor(Math.random() * 26));
35
- // Ensure valid property syntax
36
- return `'${key}': ${generateSimple()}`;
42
+ if (Math.random() < 0.5) {
43
+ const key = String.fromCharCode(97 + Math.floor(Math.random() * 26));
44
+ return `'${key}': ${generateExpression(depth + 1)}`;
45
+ } else {
46
+ return `[${generateExpression(depth + 1)}]: ${generateExpression(depth + 1)}`;
47
+ }
37
48
  });
38
49
  return `({${props.join(', ')}})`;
39
50
  },
@@ -63,27 +74,27 @@ function generateExpression(depth = 0) {
63
74
 
64
75
  const roll = Math.random();
65
76
 
66
- if (roll < 0.4) {
77
+ if (roll < 0.3) {
67
78
  // Simple value
68
79
  return generateSimple();
69
- } else if (roll < 0.6) {
80
+ } else if (roll < 0.4) {
70
81
  // Binary operation
71
82
  const ops = ['+', '-', '*', '/', '%', '===', '!==', '>', '<', '>=', '<=', '&&', '||'];
72
83
  const op = ops[Math.floor(Math.random() * ops.length)];
73
84
  return `(${generateExpression(depth + 1)} ${op} ${generateExpression(depth + 1)})`;
74
- } else if (roll < 0.75) {
85
+ } else if (roll < 0.65) {
75
86
  // Unary operation
76
87
  const ops = ['!', '-', '+', 'typeof'];
77
88
  const op = ops[Math.floor(Math.random() * ops.length)];
78
89
  return `(${op} ${generateExpression(depth + 1)})`;
79
- } else if (roll < 0.85) {
90
+ } else if (roll < 0.75) {
80
91
  // Function call
81
92
  const builtins = ['Math.abs', 'Math.floor', 'Math.ceil', 'String', 'Number', 'Boolean'];
82
93
  const func = builtins[Math.floor(Math.random() * builtins.length)];
83
94
  const argCount = Math.floor(Math.random() * 2);
84
95
  const args = Array.from({length: argCount}, () => generateExpression(depth + 1));
85
96
  return `${func}(${args.join(', ')})`;
86
- } else if (roll < 0.95) {
97
+ } else if (roll < 0.85) {
87
98
  // Conditional
88
99
  return `(${generateExpression(depth + 1)} ? ${generateExpression(depth + 1)} : ${generateExpression(depth + 1)})`;
89
100
  } else {
@@ -105,10 +116,10 @@ function generateStatement(depth = 0, inFunction = false) {
105
116
  } else if (roll < 0.5 && declaredVars.length > 0) {
106
117
  // Variable assignment
107
118
  const varName = declaredVars[Math.floor(Math.random() * declaredVars.length)];
108
- const ops = ['=', '+=', '-=', '*='];
119
+ const ops = ['=', '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '>>=', '>>>=', '<<='];
109
120
  const op = ops[Math.floor(Math.random() * ops.length)];
110
121
  return `${varName} ${op} ${generateExpression()};`;
111
- } else if (roll < 0.65) {
122
+ } else if (roll < 0.6) {
112
123
  // If statement
113
124
  if (Math.random() < 0.5) {
114
125
  return `if (${generateExpression()}) { ${generateStatement(depth + 1, inFunction)} }`;
@@ -150,8 +161,7 @@ function generateFunction() {
150
161
  statements.push(' ' + generateStatement(0, true));
151
162
  }
152
163
 
153
- // Always add a simple return to avoid syntax issues
154
- statements.push(' return ' + generateSimple() + ';');
164
+ statements.push(' return ' + generateExpression() + ';');
155
165
 
156
166
  // Restore variables
157
167
  declaredVars = savedVars;
@@ -193,7 +203,7 @@ function generateProgram(options = {}) {
193
203
  }
194
204
 
195
205
  // Always end with a result
196
- code += `var result = ${generateExpression()};\n`;
206
+ code += `var result = ${generateExpression()};`;
197
207
 
198
208
  return code;
199
209
  }
package/fuzz/index.js CHANGED
@@ -17,8 +17,8 @@ if (cluster.isPrimary) {
17
17
  }
18
18
 
19
19
  const duration = parseFloat(process.argv.find(x => x.startsWith('--duration='))?.split('=')?.[1]) || 60; // seconds
20
- const maxStatements = parseInt(process.argv.find(x => x.startsWith('--max-statements='))?.split('=')?.[1]) || 8;
21
- const maxFunctions = parseInt(process.argv.find(x => x.startsWith('--max-functions='))?.split('=')?.[1]) || 2;
20
+ const maxStatements = parseInt(process.argv.find(x => x.startsWith('--max-statements='))?.split('=')?.[1]) || 20;
21
+ const maxFunctions = parseInt(process.argv.find(x => x.startsWith('--max-functions='))?.split('=')?.[1]) || 4;
22
22
  const verbose = process.argv.includes('--verbose');
23
23
  const saveFailures = process.argv.includes('--save-failures');
24
24
  const plainResults = process.argv.includes('--plain-results');
@@ -141,7 +141,17 @@ if (cluster.isPrimary) {
141
141
  const error = `${msg.error.name}: ${msg.error.message}`
142
142
  .replace(/\([0-9]+:[0-9]+\)/, '')
143
143
  .replace(/@\+[0-9]+/, '');
144
- errorCounts.set(error, (errorCounts.get(error) || 0) + 1);
144
+
145
+ const count = errorCounts.get(error) || 0;
146
+ errorCounts.set(error, count + 1);
147
+
148
+ if (count === 0) {
149
+ const resultNames = ['PASS', 'TODO', 'WASM_ERROR', 'COMPILE_ERROR', 'FAIL', 'TIMEOUT', 'RUNTIME_ERROR'];
150
+ console.log('\n---');
151
+ console.log(`\x1b[4mNEW ${resultNames[result]}: ${error}\x1b[0m`);
152
+ console.log(msg.code);
153
+ console.log('---\n');
154
+ }
145
155
  }
146
156
 
147
157
  if (result === 0) {
@@ -262,7 +272,8 @@ if (cluster.isPrimary) {
262
272
  process.send({
263
273
  result,
264
274
  error: error ? { name: error.name, message: error.message } : null,
265
- code: verbose || saveFailures ? code : null
275
+ // code: verbose || saveFailures ? code : null
276
+ code
266
277
  });
267
278
  });
268
279
 
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.58.16",
4
+ "version": "0.58.18",
5
5
  "author": "Oliver Medhurst <honk@goose.icu>",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.58.16';
3
+ globalThis.version = '0.58.18';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {