porffor 0.42.0 → 0.42.1
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/assemble.js +2 -1
- package/compiler/builtins_precompiled.js +383 -184
- package/compiler/codegen.js +116 -40
- package/compiler/precompile.js +6 -1
- package/compiler/wrap.js +3 -5
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -66,6 +66,34 @@ const funcRef = func => {
|
|
66
66
|
}
|
67
67
|
let localInd = (wrapperArgc + 2) * 2;
|
68
68
|
|
69
|
+
if (indirectFuncs.length === 0) {
|
70
|
+
// add empty indirect func
|
71
|
+
const emptyFunc = {
|
72
|
+
name: '#indirect#empty',
|
73
|
+
params,
|
74
|
+
locals: { ...locals }, localInd,
|
75
|
+
returns: [ valtypeBinary, Valtype.i32 ],
|
76
|
+
wasm: [
|
77
|
+
...number(0),
|
78
|
+
...number(0, Valtype.i32)
|
79
|
+
],
|
80
|
+
constr: true,
|
81
|
+
internal: true,
|
82
|
+
indirect: true
|
83
|
+
};
|
84
|
+
|
85
|
+
// check not being constructed
|
86
|
+
emptyFunc.wasm.unshift(
|
87
|
+
[ Opcodes.local_get, 0 ], // new.target value
|
88
|
+
Opcodes.i32_to_u,
|
89
|
+
[ Opcodes.if, Blocktype.void ], // if value is non-zero
|
90
|
+
...internalThrow(emptyFunc, 'TypeError', `Function is not a constructor`), // throw type error
|
91
|
+
[ Opcodes.end ]
|
92
|
+
);
|
93
|
+
|
94
|
+
indirectFuncs.push(emptyFunc);
|
95
|
+
}
|
96
|
+
|
69
97
|
const wasm = [];
|
70
98
|
const offset = func.constr ? 0 : 4;
|
71
99
|
for (let i = 0; i < func.params.length; i++) {
|
@@ -427,32 +455,75 @@ const generateReturn = (scope, decl) => {
|
|
427
455
|
];
|
428
456
|
}
|
429
457
|
|
430
|
-
const out = [];
|
431
458
|
if (
|
432
459
|
scope.constr && // only do this in constructors
|
433
460
|
!globalThis.precompile // skip in precompiled built-ins, we should not require this and handle it ourselves
|
434
461
|
) {
|
435
|
-
//
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
Opcodes.
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
462
|
+
// perform return value checks for constructors and (sub)classes
|
463
|
+
return [
|
464
|
+
...generate(scope, arg),
|
465
|
+
[ Opcodes.local_set, localTmp(scope, '#return') ],
|
466
|
+
...(scope.returnType != null ? [] : getNodeType(scope, arg)),
|
467
|
+
[ Opcodes.local_set, localTmp(scope, '#return#type', Valtype.i32) ],
|
468
|
+
|
469
|
+
...(scope._onlyConstr ? [] : [
|
470
|
+
[ Opcodes.local_get, scope.locals['#newtarget'].idx ],
|
471
|
+
Opcodes.i32_to_u,
|
472
|
+
[ Opcodes.if, Blocktype.void ]
|
473
|
+
]),
|
474
|
+
...(scope.subclass ? [
|
475
|
+
// if subclass and returning undefined, return this
|
476
|
+
[ Opcodes.local_get, localTmp(scope, '#return#type') ],
|
477
|
+
...number(TYPE_FLAGS.parity, Valtype.i32),
|
478
|
+
[ Opcodes.i32_or ],
|
479
|
+
...number(TYPES.undefined, Valtype.i32),
|
480
|
+
[ Opcodes.i32_eq ],
|
481
|
+
[ Opcodes.if, Blocktype.void ],
|
482
|
+
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
483
|
+
...(scope.returnType != null ? [] : [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ]),
|
484
|
+
[ Opcodes.return ],
|
485
|
+
[ Opcodes.end ]
|
486
|
+
] : []),
|
487
|
+
|
488
|
+
// if not object, then...
|
489
|
+
...generate(scope, {
|
490
|
+
type: 'CallExpression',
|
491
|
+
callee: {
|
492
|
+
type: 'Identifier',
|
493
|
+
name: '__Porffor_object_isObject'
|
494
|
+
},
|
495
|
+
arguments: [
|
496
|
+
{ type: 'Identifier', name: '#return' }
|
497
|
+
]
|
498
|
+
}),
|
499
|
+
Opcodes.i32_to_u,
|
500
|
+
[ Opcodes.i32_eqz ],
|
501
|
+
[ Opcodes.if, Blocktype.void ],
|
502
|
+
...(scope.subclass ? [
|
503
|
+
// throw if subclass
|
504
|
+
...internalThrow(scope, 'TypeError', 'Subclass can only return an object or undefined'),
|
505
|
+
] : [
|
506
|
+
// return this if not subclass
|
507
|
+
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
508
|
+
...(scope.returnType != null ? [] : [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ]),
|
509
|
+
[ Opcodes.return ],
|
510
|
+
]),
|
511
|
+
[ Opcodes.end ],
|
512
|
+
...(scope._onlyConstr ? [] : [
|
513
|
+
[ Opcodes.end ]
|
514
|
+
]),
|
515
|
+
|
516
|
+
[ Opcodes.local_get, localTmp(scope, '#return') ],
|
517
|
+
[ Opcodes.local_get, localTmp(scope, '#return#type') ],
|
518
|
+
[ Opcodes.return ]
|
519
|
+
];
|
447
520
|
}
|
448
521
|
|
449
|
-
|
522
|
+
return [
|
450
523
|
...generate(scope, arg),
|
451
524
|
...(scope.returnType != null ? [] : getNodeType(scope, arg)),
|
452
525
|
[ Opcodes.return ]
|
453
|
-
|
454
|
-
|
455
|
-
return out;
|
526
|
+
];
|
456
527
|
};
|
457
528
|
|
458
529
|
const localTmp = (scope, name, type = valtypeBinary) => {
|
@@ -1061,7 +1132,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1061
1132
|
});
|
1062
1133
|
};
|
1063
1134
|
|
1064
|
-
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usedTypes = [] } = {}) => {
|
1135
|
+
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usedTypes = [] } = {}) => {
|
1065
1136
|
if (wasm == null) { // called with no builtin
|
1066
1137
|
log.warning('codegen', `${name} has no built-in!`);
|
1067
1138
|
wasm = [];
|
@@ -1134,6 +1205,7 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1134
1205
|
}
|
1135
1206
|
|
1136
1207
|
if (hasRestArgument) func.hasRestArgument = true;
|
1208
|
+
if (usesTag) ensureTag();
|
1137
1209
|
|
1138
1210
|
for (const x of usedTypes) typeUsed(func, x);
|
1139
1211
|
|
@@ -4604,9 +4676,20 @@ const generateLabel = (scope, decl) => {
|
|
4604
4676
|
return generate(scope, decl.body);
|
4605
4677
|
};
|
4606
4678
|
|
4679
|
+
const ensureTag = (exceptionMode = Prefs.exceptionMode ?? 'stack') => {
|
4680
|
+
if (tags.length !== 0) return;
|
4681
|
+
|
4682
|
+
tags.push({
|
4683
|
+
params: exceptionMode === 'lut' ? [ Valtype.i32 ] : [ valtypeBinary, Valtype.i32 ],
|
4684
|
+
results: [],
|
4685
|
+
idx: tags.length
|
4686
|
+
});
|
4687
|
+
};
|
4688
|
+
|
4607
4689
|
const generateThrow = (scope, decl) => {
|
4608
4690
|
let exceptionMode = Prefs.exceptionMode ?? 'stack';
|
4609
4691
|
if (globalThis.precompile) exceptionMode = decl.argument.callee != null ? 'lut' : 'stack';
|
4692
|
+
ensureTag(exceptionMode);
|
4610
4693
|
|
4611
4694
|
if (exceptionMode === 'lut') {
|
4612
4695
|
let message = decl.argument.value, constructor = null;
|
@@ -4617,12 +4700,6 @@ const generateThrow = (scope, decl) => {
|
|
4617
4700
|
message = decl.argument.arguments[0]?.value ?? '';
|
4618
4701
|
}
|
4619
4702
|
|
4620
|
-
if (tags.length === 0) tags.push({
|
4621
|
-
params: [ Valtype.i32 ],
|
4622
|
-
results: [],
|
4623
|
-
idx: tags.length
|
4624
|
-
});
|
4625
|
-
|
4626
4703
|
if (constructor && constructor.startsWith('__')) constructor = constructor.split('_').pop();
|
4627
4704
|
|
4628
4705
|
let exceptId = exceptions.findIndex(x => x.constructor === constructor && x.message === message);
|
@@ -4637,19 +4714,11 @@ const generateThrow = (scope, decl) => {
|
|
4637
4714
|
];
|
4638
4715
|
}
|
4639
4716
|
|
4640
|
-
|
4641
|
-
|
4642
|
-
|
4643
|
-
|
4644
|
-
|
4645
|
-
});
|
4646
|
-
|
4647
|
-
return [
|
4648
|
-
...generate(scope, decl.argument),
|
4649
|
-
...getNodeType(scope, decl.argument),
|
4650
|
-
[ Opcodes.throw, globalThis.precompile ? 1 : 0 ]
|
4651
|
-
];
|
4652
|
-
}
|
4717
|
+
return [
|
4718
|
+
...generate(scope, decl.argument),
|
4719
|
+
...getNodeType(scope, decl.argument),
|
4720
|
+
[ Opcodes.throw, globalThis.precompile ? 1 : 0 ]
|
4721
|
+
];
|
4653
4722
|
};
|
4654
4723
|
|
4655
4724
|
const generateTry = (scope, decl) => {
|
@@ -4692,6 +4761,9 @@ const generateTry = (scope, decl) => {
|
|
4692
4761
|
|
4693
4762
|
...generateVarDstr(scope, 'let', param, { type: 'Identifier', name: tmpName }, undefined, false)
|
4694
4763
|
);
|
4764
|
+
|
4765
|
+
// ensure tag exists for specific catch
|
4766
|
+
ensureTag();
|
4695
4767
|
} else {
|
4696
4768
|
out.push([ Opcodes.catch_all ]);
|
4697
4769
|
}
|
@@ -5633,9 +5705,10 @@ const generateClass = (scope, decl) => {
|
|
5633
5705
|
}
|
5634
5706
|
}),
|
5635
5707
|
id: root,
|
5636
|
-
_onlyConstr: true,
|
5637
5708
|
strict: true,
|
5638
|
-
type: expr ? 'FunctionExpression' : 'FunctionDeclaration'
|
5709
|
+
type: expr ? 'FunctionExpression' : 'FunctionDeclaration',
|
5710
|
+
_onlyConstr: true,
|
5711
|
+
_subclass: !!decl.superClass
|
5639
5712
|
});
|
5640
5713
|
|
5641
5714
|
// always generate class constructor funcs
|
@@ -5943,7 +6016,7 @@ const generateFunc = (scope, decl) => {
|
|
5943
6016
|
index: currentFuncIndex++,
|
5944
6017
|
arrow,
|
5945
6018
|
constr: !arrow && !decl.generator && !decl.async,
|
5946
|
-
_onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
6019
|
+
subclass: decl._subclass, _onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
5947
6020
|
strict: scope.strict || decl.strict,
|
5948
6021
|
|
5949
6022
|
generate() {
|
@@ -6031,6 +6104,9 @@ const generateFunc = (scope, decl) => {
|
|
6031
6104
|
...number(TYPES.promise, Valtype.i32),
|
6032
6105
|
[ Opcodes.return ]
|
6033
6106
|
);
|
6107
|
+
|
6108
|
+
// ensure tag exists for specific catch
|
6109
|
+
ensureTag();
|
6034
6110
|
}
|
6035
6111
|
|
6036
6112
|
if (name === 'main') {
|
package/compiler/precompile.js
CHANGED
@@ -153,6 +153,7 @@ const compile = async (file, _funcs) => {
|
|
153
153
|
}
|
154
154
|
|
155
155
|
if (n[0] === Opcodes.throw) {
|
156
|
+
x.usesTag = true;
|
156
157
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
157
158
|
const id = read_signedLEB128(y.slice(1));
|
158
159
|
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
@@ -163,6 +164,10 @@ const compile = async (file, _funcs) => {
|
|
163
164
|
n[1]--;
|
164
165
|
}
|
165
166
|
}
|
167
|
+
|
168
|
+
if (n[0] === Opcodes.catch) {
|
169
|
+
x.usesTag = true;
|
170
|
+
}
|
166
171
|
}
|
167
172
|
};
|
168
173
|
|
@@ -251,7 +256,7 @@ params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.retu
|
|
251
256
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
252
257
|
${usedTypes.length > 0 ? `usedTypes:${JSON.stringify(usedTypes)},` : ''}
|
253
258
|
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && Object.keys(x.data).length > 0 ? `data:${JSON.stringify(x.data)},` : ''}
|
254
|
-
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}
|
259
|
+
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}${x.usesTag ? `usesTag:1,` : ''}
|
255
260
|
}`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
256
261
|
}).join('\n')}
|
257
262
|
}`;
|
package/compiler/wrap.js
CHANGED
@@ -520,12 +520,10 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
520
520
|
throw new constructor(exception.message);
|
521
521
|
}
|
522
522
|
|
523
|
-
|
524
|
-
|
525
|
-
const type = e.getArg(exceptTag, 1);
|
523
|
+
const value = e.getArg(exceptTag, 0);
|
524
|
+
const type = e.getArg(exceptTag, 1);
|
526
525
|
|
527
|
-
|
528
|
-
}
|
526
|
+
throw porfToJSValue({ memory, funcs, pages }, value, type);
|
529
527
|
}
|
530
528
|
|
531
529
|
if (e instanceof WebAssembly.RuntimeError) {
|
package/package.json
CHANGED