porffor 0.55.22 → 0.55.23
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/allocator.js +1 -1
- package/compiler/builtins/_internal_object.ts +560 -279
- package/compiler/builtins/bigint.ts +2 -2
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/object.ts +35 -44
- package/compiler/builtins/object_prototypeWithHidden.js +47 -0
- package/compiler/builtins/reflect.ts +4 -4
- package/compiler/builtins/z_ecma262.ts +3 -0
- package/compiler/builtins_precompiled.js +569 -550
- package/compiler/codegen.js +67 -143
- package/compiler/precompile.js +6 -5
- package/compiler/prototype.js +80 -66
- package/compiler/wrap.js +3 -4
- package/package.json +1 -1
- package/r.cjs +29 -6
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -1539,7 +1539,7 @@ const getNodeType = (scope, node) => {
|
|
1539
1539
|
return getType(scope, node.name);
|
1540
1540
|
}
|
1541
1541
|
|
1542
|
-
if (node.type === 'ObjectExpression') {
|
1542
|
+
if (node.type === 'ObjectExpression' || node.type === 'Super') {
|
1543
1543
|
return TYPES.object;
|
1544
1544
|
}
|
1545
1545
|
|
@@ -1571,24 +1571,6 @@ const getNodeType = (scope, node) => {
|
|
1571
1571
|
if (Object.hasOwn(builtinFuncs, name) && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
|
1572
1572
|
if (Object.hasOwn(internalConstrs, name) && internalConstrs[name].type != null) return internalConstrs[name].type;
|
1573
1573
|
|
1574
|
-
// check if this is a prototype function
|
1575
|
-
// if so and there is only one impl (eg charCodeAt)
|
1576
|
-
// or all impls have the same return type
|
1577
|
-
// use that return type as that is the only possibility
|
1578
|
-
// (if non-matching type it would error out)
|
1579
|
-
if (name.startsWith('__')) {
|
1580
|
-
const spl = name.slice(2).split('_');
|
1581
|
-
|
1582
|
-
const func = spl[spl.length - 1];
|
1583
|
-
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1584
|
-
if (
|
1585
|
-
protoFuncs.length === 1 ||
|
1586
|
-
(protoFuncs.length > 1 && protoFuncs.every(x => x.returnType === protoFuncs[0].returnType))
|
1587
|
-
) {
|
1588
|
-
if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
|
1589
|
-
}
|
1590
|
-
}
|
1591
|
-
|
1592
1574
|
if (name.startsWith('__Porffor_wasm_')) {
|
1593
1575
|
// todo: return undefined for non-returning ops
|
1594
1576
|
return TYPES.number;
|
@@ -1860,29 +1842,6 @@ const createNewTarget = (scope, decl, idx = 0, force = false) => {
|
|
1860
1842
|
];
|
1861
1843
|
};
|
1862
1844
|
|
1863
|
-
const makeObject = (scope, obj) => {
|
1864
|
-
const properties = [];
|
1865
|
-
for (const x in obj) {
|
1866
|
-
properties.push({
|
1867
|
-
type: 'Property',
|
1868
|
-
method: false,
|
1869
|
-
shorthand: false,
|
1870
|
-
computed: false,
|
1871
|
-
key: {
|
1872
|
-
type: 'Identifier',
|
1873
|
-
name: x
|
1874
|
-
},
|
1875
|
-
value: obj[x],
|
1876
|
-
kind: 'init'
|
1877
|
-
});
|
1878
|
-
}
|
1879
|
-
|
1880
|
-
return generate(scope, {
|
1881
|
-
type: 'ObjectExpression',
|
1882
|
-
properties
|
1883
|
-
});
|
1884
|
-
};
|
1885
|
-
|
1886
1845
|
const getObjProp = (obj, prop) => {
|
1887
1846
|
if (typeof obj === 'string') obj = {
|
1888
1847
|
type: 'Identifier',
|
@@ -1967,32 +1926,22 @@ const createThisArg = (scope, decl) => {
|
|
1967
1926
|
number(TYPES.object, Valtype.i32)
|
1968
1927
|
];
|
1969
1928
|
|
1970
|
-
// create new object with
|
1929
|
+
// create new object with prototype set to callee prototype
|
1971
1930
|
const tmp = localTmp(scope, '#this_create_tmp');
|
1972
1931
|
const proto = getObjProp(decl.callee, 'prototype');
|
1973
1932
|
|
1974
1933
|
return [
|
1975
|
-
|
1934
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocate').index ],
|
1935
|
+
Opcodes.i32_from_u,
|
1976
1936
|
[ Opcodes.local_tee, tmp ],
|
1977
1937
|
Opcodes.i32_to_u,
|
1978
|
-
|
1979
1938
|
number(TYPES.object, Valtype.i32),
|
1980
1939
|
|
1981
|
-
...generate(scope, {
|
1982
|
-
type: 'Literal',
|
1983
|
-
value: '__proto__'
|
1984
|
-
}),
|
1985
|
-
Opcodes.i32_to_u,
|
1986
|
-
number(TYPES.bytestring, Valtype.i32),
|
1987
|
-
|
1988
1940
|
...generate(scope, proto),
|
1941
|
+
Opcodes.i32_to_u,
|
1989
1942
|
...getNodeType(scope, proto),
|
1990
1943
|
|
1991
|
-
|
1992
|
-
number(0b1000, Valtype.i32),
|
1993
|
-
number(TYPES.number, Valtype.i32),
|
1994
|
-
|
1995
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
|
1944
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_setPrototype').index ],
|
1996
1945
|
|
1997
1946
|
[ Opcodes.local_get, tmp ],
|
1998
1947
|
number(TYPES.object, Valtype.i32)
|
@@ -2353,30 +2302,34 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2353
2302
|
const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
|
2354
2303
|
|
2355
2304
|
let optUnused = false;
|
2356
|
-
const protoOut = protoFunc(
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2305
|
+
const protoOut = protoFunc({
|
2306
|
+
pointer: getPointer,
|
2307
|
+
length: {
|
2308
|
+
getCachedI32: () => [ [ Opcodes.local_get, lengthLocal ] ],
|
2309
|
+
setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
|
2310
|
+
get: () => ArrayUtil.getLength(getPointer),
|
2311
|
+
getI32: () => ArrayUtil.getLengthI32(getPointer),
|
2312
|
+
set: value => ArrayUtil.setLength(getPointer, value),
|
2313
|
+
setI32: value => ArrayUtil.setLengthI32(getPointer, value)
|
2314
|
+
},
|
2315
|
+
arg: generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2316
|
+
argType: getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2317
|
+
iTmp: protoLocal,
|
2318
|
+
iTmp2: protoLocal2,
|
2319
|
+
alloc: bytes => [
|
2320
|
+
number(bytes, Valtype.i32),
|
2321
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocateBytes').index ]
|
2322
|
+
],
|
2323
|
+
unusedValue: () => {
|
2324
|
+
optUnused = true;
|
2325
|
+
return unusedValue;
|
2326
|
+
},
|
2327
|
+
setType: type => setLastType(scope, type)
|
2374
2328
|
});
|
2375
2329
|
|
2376
2330
|
return [
|
2377
2331
|
[ Opcodes.block, unusedValue ? Blocktype.void : valtypeBinary ],
|
2378
2332
|
...protoOut,
|
2379
|
-
...(unusedValue && optUnused ? [] : (protoFunc.returnType != null ? setLastType(scope, protoFunc.returnType) : setLastType(scope))),
|
2380
2333
|
...(unusedValue && !optUnused ? [ [ Opcodes.drop ] ] : []),
|
2381
2334
|
[ Opcodes.end ]
|
2382
2335
|
];
|
@@ -2774,8 +2727,19 @@ const generateThis = (scope, decl) => {
|
|
2774
2727
|
];
|
2775
2728
|
};
|
2776
2729
|
|
2777
|
-
const generateSuper = (scope, decl) => generate(scope,
|
2778
|
-
|
2730
|
+
const generateSuper = (scope, decl) => generate(scope, {
|
2731
|
+
type: 'CallExpression',
|
2732
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2733
|
+
arguments: [
|
2734
|
+
{
|
2735
|
+
type: 'CallExpression',
|
2736
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2737
|
+
arguments: [
|
2738
|
+
{ type: 'ThisExpression', _noGlobalThis: true }
|
2739
|
+
]
|
2740
|
+
}
|
2741
|
+
]
|
2742
|
+
});
|
2779
2743
|
|
2780
2744
|
// bad hack for undefined and null working without additional logic
|
2781
2745
|
const DEFAULT_VALUE = () => ({
|
@@ -4887,7 +4851,7 @@ const generateForIn = (scope, decl) => {
|
|
4887
4851
|
|
4888
4852
|
// get length
|
4889
4853
|
[ Opcodes.local_get, pointer ],
|
4890
|
-
[ Opcodes.
|
4854
|
+
[ Opcodes.i32_load16_u, 0, 0 ],
|
4891
4855
|
[ Opcodes.local_tee, length ],
|
4892
4856
|
|
4893
4857
|
[ Opcodes.if, Blocktype.void ]
|
@@ -4920,7 +4884,7 @@ const generateForIn = (scope, decl) => {
|
|
4920
4884
|
|
4921
4885
|
// read key
|
4922
4886
|
[ Opcodes.local_get, pointer ],
|
4923
|
-
[ Opcodes.i32_load, 0,
|
4887
|
+
[ Opcodes.i32_load, 0, 12 ],
|
4924
4888
|
[ Opcodes.local_tee, tmp ],
|
4925
4889
|
|
4926
4890
|
...setType(scope, tmpName, [
|
@@ -4952,7 +4916,7 @@ const generateForIn = (scope, decl) => {
|
|
4952
4916
|
// todo/perf: do not read key for non-enumerables
|
4953
4917
|
// only run body if entry is enumerable
|
4954
4918
|
[ Opcodes.local_get, pointer ],
|
4955
|
-
[ Opcodes.i32_load8_u, 0,
|
4919
|
+
[ Opcodes.i32_load8_u, 0, 24 ],
|
4956
4920
|
[ Opcodes.i32_const, 0b0100 ],
|
4957
4921
|
[ Opcodes.i32_and ],
|
4958
4922
|
[ Opcodes.if, Blocktype.void ],
|
@@ -4960,9 +4924,9 @@ const generateForIn = (scope, decl) => {
|
|
4960
4924
|
[ Opcodes.drop ],
|
4961
4925
|
[ Opcodes.end ],
|
4962
4926
|
|
4963
|
-
// increment pointer by
|
4927
|
+
// increment pointer by 18
|
4964
4928
|
[ Opcodes.local_get, pointer ],
|
4965
|
-
number(
|
4929
|
+
number(18, Valtype.i32),
|
4966
4930
|
[ Opcodes.i32_add ],
|
4967
4931
|
[ Opcodes.local_set, pointer ],
|
4968
4932
|
|
@@ -5786,60 +5750,6 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5786
5750
|
if (known == null) extraBC = bc;
|
5787
5751
|
}
|
5788
5752
|
|
5789
|
-
if (decl.property.name === '__proto__') {
|
5790
|
-
// todo: support optional
|
5791
|
-
const bc = {};
|
5792
|
-
const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
|
5793
|
-
|
5794
|
-
const known = knownType(scope, getNodeType(scope, decl.object));
|
5795
|
-
for (const x of prototypes) {
|
5796
|
-
let type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
|
5797
|
-
if (type == null) continue;
|
5798
|
-
|
5799
|
-
// do not __proto__ primitive hack for objects or functions
|
5800
|
-
if (type === TYPES.object || type === TYPES.function) continue;
|
5801
|
-
|
5802
|
-
// hack: do not support primitives for Object.prototype.isPrototypeOf
|
5803
|
-
if (scope.name === '__Object_prototype_isPrototypeOf') {
|
5804
|
-
switch (type) {
|
5805
|
-
case TYPES.boolean:
|
5806
|
-
type = TYPES.booleanobject;
|
5807
|
-
break;
|
5808
|
-
|
5809
|
-
case TYPES.number:
|
5810
|
-
type = TYPES.numberobject;
|
5811
|
-
break;
|
5812
|
-
|
5813
|
-
case TYPES.string:
|
5814
|
-
type = TYPES.stringobject;
|
5815
|
-
break;
|
5816
|
-
|
5817
|
-
case TYPES.bytestring:
|
5818
|
-
continue;
|
5819
|
-
}
|
5820
|
-
}
|
5821
|
-
|
5822
|
-
const ident = {
|
5823
|
-
type: 'Identifier',
|
5824
|
-
name: x
|
5825
|
-
};
|
5826
|
-
|
5827
|
-
// hack: bytestrings should return string prototype
|
5828
|
-
if (type === TYPES.bytestring) ident.name = '__String_prototype';
|
5829
|
-
|
5830
|
-
bc[type] = () => [
|
5831
|
-
...generate(scope, ident),
|
5832
|
-
...setLastType(scope, getNodeType(scope, ident))
|
5833
|
-
];
|
5834
|
-
if (type === known) return bc[type]();
|
5835
|
-
}
|
5836
|
-
|
5837
|
-
if (known == null) {
|
5838
|
-
aliasPrimObjsBC(bc);
|
5839
|
-
extraBC = bc;
|
5840
|
-
}
|
5841
|
-
}
|
5842
|
-
|
5843
5753
|
const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
|
5844
5754
|
const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
|
5845
5755
|
|
@@ -6009,7 +5919,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
6009
5919
|
}),
|
6010
5920
|
} : {}),
|
6011
5921
|
|
6012
|
-
[TYPES.undefined]: internalThrow(scope, 'TypeError',
|
5922
|
+
[TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
|
6013
5923
|
|
6014
5924
|
// default: internalThrow(scope, 'TypeError', 'Unsupported member expression object', true)
|
6015
5925
|
default: () => [
|
@@ -6164,10 +6074,25 @@ const generateClass = (scope, decl) => {
|
|
6164
6074
|
// class Foo {}
|
6165
6075
|
// class Bar extends Foo {}
|
6166
6076
|
// Bar.__proto__ = Foo
|
6167
|
-
|
6168
|
-
|
6077
|
+
...generate(scope, {
|
6078
|
+
type: 'CallExpression',
|
6079
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6080
|
+
arguments: [
|
6081
|
+
root,
|
6082
|
+
decl.superClass
|
6083
|
+
]
|
6084
|
+
}),
|
6169
6085
|
[ Opcodes.drop ],
|
6170
|
-
|
6086
|
+
|
6087
|
+
// Bar.prototype.__proto__ = Foo.prototype
|
6088
|
+
...generate(scope, {
|
6089
|
+
type: 'CallExpression',
|
6090
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6091
|
+
arguments: [
|
6092
|
+
proto,
|
6093
|
+
getObjProp(decl.superClass, 'prototype')
|
6094
|
+
]
|
6095
|
+
}),
|
6171
6096
|
[ Opcodes.drop ]
|
6172
6097
|
);
|
6173
6098
|
}
|
@@ -6354,7 +6279,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6354
6279
|
return funcIndex[x];
|
6355
6280
|
}
|
6356
6281
|
|
6357
|
-
return scope.locals[x]?.idx ?? globals[x].
|
6282
|
+
return scope.locals[x]?.idx ?? globals[x]?.idx ?? (log.warning('codegen', `unknown immediate in Porffor.wasm: ${x}`) || 0);
|
6358
6283
|
}
|
6359
6284
|
|
6360
6285
|
return n;
|
@@ -6428,7 +6353,6 @@ const objectHack = node => {
|
|
6428
6353
|
|
6429
6354
|
// hack: block these properties as they can be accessed on functions
|
6430
6355
|
if (node.object.name !== 'Porffor' && (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call')) return abortOut;
|
6431
|
-
|
6432
6356
|
if (node.property.name === '__proto__') return abortOut;
|
6433
6357
|
|
6434
6358
|
let objectName = node.object.name;
|
package/compiler/precompile.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
2
|
import { read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
3
|
-
import { TYPES } from './types.js';
|
3
|
+
import { TYPES, TYPE_NAMES } from './types.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
|
6
6
|
import process from 'node:process';
|
@@ -41,7 +41,7 @@ const compile = async (file, _funcs) => {
|
|
41
41
|
let first = source.slice(0, source.indexOf('\n'));
|
42
42
|
|
43
43
|
if (first.startsWith('export default')) {
|
44
|
-
source = await (await import('file://' + file)).default();
|
44
|
+
source = await (await import('file://' + file)).default({ TYPES, TYPE_NAMES });
|
45
45
|
first = source.slice(0, source.indexOf('\n'));
|
46
46
|
}
|
47
47
|
|
@@ -155,11 +155,10 @@ const compile = async (file, _funcs) => {
|
|
155
155
|
}
|
156
156
|
|
157
157
|
if (n[0] === Opcodes.throw) {
|
158
|
-
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name}`);
|
159
|
-
|
160
158
|
x.usesTag = true;
|
159
|
+
let id;
|
161
160
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
162
|
-
|
161
|
+
id = read_signedLEB128(y.slice(1));
|
163
162
|
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
164
163
|
|
165
164
|
// remove throw inst
|
@@ -167,6 +166,8 @@ const compile = async (file, _funcs) => {
|
|
167
166
|
} else {
|
168
167
|
n[1]--;
|
169
168
|
}
|
169
|
+
|
170
|
+
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name} (${exceptions[id].constructor}: ${exceptions[id].message})`);
|
170
171
|
}
|
171
172
|
|
172
173
|
if (n[0] === Opcodes.catch) {
|