porffor 0.17.0-55999d22b → 0.17.0-94400a2b8
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.
- package/compiler/codegen.js +125 -26
- package/compiler/wrap.js +50 -8
- package/package.json +1 -1
- package/runner/index.js +3 -1
package/compiler/codegen.js
CHANGED
@@ -264,10 +264,12 @@ const internalThrow = (scope, constructor, message, expectsValue = Prefs.alwaysV
|
|
264
264
|
argument: {
|
265
265
|
type: 'NewExpression',
|
266
266
|
callee: {
|
267
|
+
type: 'Identifier',
|
267
268
|
name: constructor
|
268
269
|
},
|
269
270
|
arguments: [
|
270
271
|
{
|
272
|
+
type: 'Literal',
|
271
273
|
value: message
|
272
274
|
}
|
273
275
|
]
|
@@ -289,12 +291,13 @@ const generateIdent = (scope, decl) => {
|
|
289
291
|
return wasm.slice();
|
290
292
|
}
|
291
293
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
294
|
+
// todo: enable this by default in future
|
295
|
+
// if (!Object.hasOwn(funcIndex, name) && Object.hasOwn(builtinFuncs, name)) {
|
296
|
+
// includeBuiltin(scope, name);
|
297
|
+
// return number(funcIndex[name] - importedFuncs.length);
|
298
|
+
// }
|
296
299
|
|
297
|
-
if (isExistingProtoFunc(name)) {
|
300
|
+
if (isExistingProtoFunc(name) || Object.hasOwn(internalConstrs, name) || Object.hasOwn(builtinFuncs, name)) {
|
298
301
|
// todo: return an actual something
|
299
302
|
return number(1);
|
300
303
|
}
|
@@ -973,6 +976,33 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
973
976
|
};
|
974
977
|
|
975
978
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
979
|
+
if (decl.operator === 'instanceof') {
|
980
|
+
// very hacky basic instanceof
|
981
|
+
// todo: support dynamic right-hand side
|
982
|
+
|
983
|
+
const out = generate(scope, decl.left);
|
984
|
+
disposeLeftover(out);
|
985
|
+
|
986
|
+
const rightName = decl.right.name;
|
987
|
+
if (!rightName) return todo(scope, 'instanceof dynamic right-hand side is not supported yet', true);
|
988
|
+
|
989
|
+
const checkType = TYPES[rightName.toLowerCase()];
|
990
|
+
if (checkType == null || rightName !== TYPE_NAMES[checkType] || checkType === TYPES.undefined) return todo(scope, 'instanceof right-hand side type unsupported', true);
|
991
|
+
|
992
|
+
if ([TYPES.number, TYPES.boolean, TYPES.string, TYPES.symbol, TYPES.object].includes(checkType)) {
|
993
|
+
out.push(...number(0));
|
994
|
+
} else {
|
995
|
+
out.push(
|
996
|
+
...getNodeType(scope, decl.left),
|
997
|
+
...number(checkType, Valtype.i32),
|
998
|
+
[ Opcodes.i32_eq ],
|
999
|
+
Opcodes.i32_from_u
|
1000
|
+
);
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
return out;
|
1004
|
+
}
|
1005
|
+
|
976
1006
|
const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
|
977
1007
|
|
978
1008
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
@@ -1279,7 +1309,7 @@ const getNodeType = (scope, node) => {
|
|
1279
1309
|
}
|
1280
1310
|
|
1281
1311
|
if (node.type === 'BinaryExpression') {
|
1282
|
-
if (['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(node.operator)) return TYPES.boolean;
|
1312
|
+
if (['==', '===', '!=', '!==', '>', '>=', '<', '<=', 'instanceof'].includes(node.operator)) return TYPES.boolean;
|
1283
1313
|
if (node.operator !== '+') return TYPES.number;
|
1284
1314
|
|
1285
1315
|
const knownLeft = knownType(scope, getNodeType(scope, node.left));
|
@@ -3029,32 +3059,101 @@ const generateLabel = (scope, decl) => {
|
|
3029
3059
|
const generateThrow = (scope, decl) => {
|
3030
3060
|
scope.throws = true;
|
3031
3061
|
|
3032
|
-
|
3062
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
3063
|
+
if (exceptionMode === 'lut') {
|
3064
|
+
let message = decl.argument.value, constructor = null;
|
3065
|
+
|
3066
|
+
// support `throw (new)? Error(...)`
|
3067
|
+
if (!message && (decl.argument.type === 'NewExpression' || decl.argument.type === 'CallExpression')) {
|
3068
|
+
constructor = decl.argument.callee.name;
|
3069
|
+
message = decl.argument.arguments[0]?.value ?? '';
|
3070
|
+
}
|
3071
|
+
|
3072
|
+
if (tags.length === 0) tags.push({
|
3073
|
+
params: [ Valtype.i32 ],
|
3074
|
+
results: [],
|
3075
|
+
idx: tags.length
|
3076
|
+
});
|
3077
|
+
|
3078
|
+
let exceptId = exceptions.push({ constructor, message }) - 1;
|
3079
|
+
|
3080
|
+
scope.exceptions ??= [];
|
3081
|
+
scope.exceptions.push(exceptId);
|
3082
|
+
|
3083
|
+
return [
|
3084
|
+
[ Opcodes.i32_const, signedLEB128(exceptId) ],
|
3085
|
+
[ Opcodes.throw, tags[0].idx ]
|
3086
|
+
];
|
3087
|
+
}
|
3033
3088
|
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3089
|
+
if (exceptionMode === 'stack') {
|
3090
|
+
if (tags.length === 0) tags.push({
|
3091
|
+
params: [ valtypeBinary, Valtype.i32 ],
|
3092
|
+
results: [],
|
3093
|
+
idx: tags.length
|
3094
|
+
});
|
3095
|
+
|
3096
|
+
return [
|
3097
|
+
...generate(scope, decl.argument),
|
3098
|
+
...getNodeType(scope, decl.argument),
|
3099
|
+
[ Opcodes.throw, tags[0].idx ]
|
3100
|
+
];
|
3038
3101
|
}
|
3039
3102
|
|
3040
|
-
if (
|
3041
|
-
|
3042
|
-
results: [],
|
3043
|
-
idx: tags.length
|
3044
|
-
});
|
3103
|
+
if (exceptionMode === 'stackest') {
|
3104
|
+
let message = decl.argument, constructor = null;
|
3045
3105
|
|
3046
|
-
|
3047
|
-
|
3106
|
+
// support `throw (new)? Error(...)`
|
3107
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3108
|
+
constructor = decl.argument.callee;
|
3109
|
+
message = decl.argument.arguments[0];
|
3110
|
+
}
|
3048
3111
|
|
3049
|
-
|
3050
|
-
scope.exceptions.push(exceptId);
|
3112
|
+
message ??= DEFAULT_VALUE;
|
3051
3113
|
|
3052
|
-
|
3114
|
+
if (tags.length === 0) tags.push({
|
3115
|
+
params: [ valtypeBinary, valtypeBinary, Valtype.i32 ],
|
3116
|
+
results: [],
|
3117
|
+
idx: tags.length
|
3118
|
+
});
|
3053
3119
|
|
3054
|
-
|
3055
|
-
|
3056
|
-
|
3057
|
-
|
3120
|
+
return [
|
3121
|
+
...(constructor == null ? number(-1) : generate(scope, constructor)),
|
3122
|
+
...generate(scope, message),
|
3123
|
+
...getNodeType(scope, message),
|
3124
|
+
[ Opcodes.throw, tags[0].idx ]
|
3125
|
+
];
|
3126
|
+
}
|
3127
|
+
|
3128
|
+
if (exceptionMode === 'partial') {
|
3129
|
+
let message = decl.argument, constructor = null;
|
3130
|
+
|
3131
|
+
// support `throw (new)? Error(...)`
|
3132
|
+
if (message.type === 'NewExpression' || message.type === 'CallExpression') {
|
3133
|
+
constructor = decl.argument.callee.name;
|
3134
|
+
message = decl.argument.arguments[0];
|
3135
|
+
}
|
3136
|
+
|
3137
|
+
message ??= DEFAULT_VALUE;
|
3138
|
+
|
3139
|
+
if (tags.length === 0) tags.push({
|
3140
|
+
params: [ Valtype.i32, valtypeBinary, Valtype.i32 ],
|
3141
|
+
results: [],
|
3142
|
+
idx: tags.length
|
3143
|
+
});
|
3144
|
+
|
3145
|
+
let exceptId = exceptions.push({ constructor }) - 1;
|
3146
|
+
|
3147
|
+
scope.exceptions ??= [];
|
3148
|
+
scope.exceptions.push(exceptId);
|
3149
|
+
|
3150
|
+
return [
|
3151
|
+
[ Opcodes.i32_const, signedLEB128(exceptId) ],
|
3152
|
+
...generate(scope, message),
|
3153
|
+
...getNodeType(scope, message),
|
3154
|
+
[ Opcodes.throw, tags[0].idx ]
|
3155
|
+
];
|
3156
|
+
}
|
3058
3157
|
};
|
3059
3158
|
|
3060
3159
|
const generateTry = (scope, decl) => {
|
@@ -3772,7 +3871,7 @@ const internalConstrs = {
|
|
3772
3871
|
|
3773
3872
|
// todo: check in wasm instead of here
|
3774
3873
|
const literalValue = arg.value ?? 0;
|
3775
|
-
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, '
|
3874
|
+
if (literalValue < 0 || !Number.isFinite(literalValue) || literalValue > 4294967295) return internalThrow(scope, 'RangeError', 'Invalid array length', true);
|
3776
3875
|
|
3777
3876
|
return [
|
3778
3877
|
...out,
|
package/compiler/wrap.js
CHANGED
@@ -127,7 +127,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
127
127
|
|
128
128
|
globalThis.porfDebugInfo = { funcs, globals };
|
129
129
|
|
130
|
-
if (source.includes?.('export ')) flags.push('module');
|
130
|
+
if (process.argv[1].includes('/runner') && source.includes?.('export ')) flags.push('module');
|
131
131
|
|
132
132
|
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
133
133
|
|
@@ -297,16 +297,58 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
297
297
|
return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
|
298
298
|
} catch (e) {
|
299
299
|
if (e.is && e.is(exceptTag)) {
|
300
|
-
const
|
301
|
-
|
300
|
+
const exceptionMode = Prefs.exceptionMode ?? 'lut';
|
301
|
+
if (exceptionMode === 'lut') {
|
302
|
+
const exceptId = e.getArg(exceptTag, 0);
|
303
|
+
const exception = exceptions[exceptId];
|
302
304
|
|
303
|
-
|
305
|
+
const constructorName = exception.constructor;
|
304
306
|
|
305
|
-
|
306
|
-
|
307
|
+
// no constructor, just throw message
|
308
|
+
if (!constructorName) throw exception.message;
|
307
309
|
|
308
|
-
|
309
|
-
|
310
|
+
const constructor = globalThis[constructorName] ?? eval(`class ${constructorName} extends Error { constructor(message) { super(message); this.name = "${constructorName}"; } }; ${constructorName}`);
|
311
|
+
throw new constructor(exception.message);
|
312
|
+
}
|
313
|
+
|
314
|
+
if (exceptionMode === 'stack') {
|
315
|
+
const value = e.getArg(exceptTag, 0);
|
316
|
+
const type = e.getArg(exceptTag, 1);
|
317
|
+
|
318
|
+
throw porfToJSValue({ memory, funcs, pages }, value, type);
|
319
|
+
}
|
320
|
+
|
321
|
+
if (exceptionMode === 'stackest') {
|
322
|
+
const constructorIdx = e.getArg(exceptTag, 0);
|
323
|
+
const constructorName = constructorIdx == -1 ? null : funcs.find(x => ((x.originalIndex ?? x.index) - importedFuncs.length) === constructorIdx)?.name;
|
324
|
+
|
325
|
+
const value = e.getArg(exceptTag, 1);
|
326
|
+
const type = e.getArg(exceptTag, 2);
|
327
|
+
const message = porfToJSValue({ memory, funcs, pages }, value, type);
|
328
|
+
|
329
|
+
// no constructor, just throw message
|
330
|
+
if (!constructorName) throw message;
|
331
|
+
|
332
|
+
const constructor = globalThis[constructorName] ?? eval(`class ${constructorName} extends Error { constructor(message) { super(message); this.name = "${constructorName}"; } }; ${constructorName}`);
|
333
|
+
throw new constructor(message);
|
334
|
+
}
|
335
|
+
|
336
|
+
if (exceptionMode === 'partial') {
|
337
|
+
const exceptId = e.getArg(exceptTag, 0);
|
338
|
+
const exception = exceptions[exceptId];
|
339
|
+
|
340
|
+
const constructorName = exception.constructor;
|
341
|
+
|
342
|
+
const value = e.getArg(exceptTag, 1);
|
343
|
+
const type = e.getArg(exceptTag, 2);
|
344
|
+
const message = porfToJSValue({ memory, funcs, pages }, value, type);
|
345
|
+
|
346
|
+
// no constructor, just throw message
|
347
|
+
if (!constructorName) throw message;
|
348
|
+
|
349
|
+
const constructor = globalThis[constructorName] ?? eval(`class ${constructorName} extends Error { constructor(message) { super(message); this.name = "${constructorName}"; } }; ${constructorName}`);
|
350
|
+
throw new constructor(message);
|
351
|
+
}
|
310
352
|
}
|
311
353
|
|
312
354
|
if (e instanceof WebAssembly.RuntimeError) {
|
package/package.json
CHANGED
package/runner/index.js
CHANGED
@@ -145,7 +145,9 @@ try {
|
|
145
145
|
// if (cache) process.stdout.write(cache);
|
146
146
|
} catch (e) {
|
147
147
|
// if (cache) process.stdout.write(cache);
|
148
|
-
|
148
|
+
let out = e;
|
149
|
+
if (!process.argv.includes('-i') && e.__proto__.message != null) out = `${e.constructor.name}${e.message != null ? `: ${e.message}` : ''}`;
|
150
|
+
console.error(out);
|
149
151
|
}
|
150
152
|
|
151
153
|
if (process.argv.includes('-t')) console.log(`${process.argv.includes('-b') ? '' : '\n\n'}total time: ${(performance.now() - start).toFixed(2)}ms\nexecution time: ${(performance.now() - runStart).toFixed(2)}ms`);
|