porffor 0.30.14 → 0.33.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.
- package/compiler/allocators.js +1 -0
- package/compiler/assemble.js +12 -5
- package/compiler/builtins/_internal_object.ts +41 -15
- package/compiler/builtins/arraybuffer.ts +5 -1
- package/compiler/builtins/object.ts +24 -11
- package/compiler/builtins_objects.js +20 -5
- package/compiler/builtins_precompiled.js +528 -520
- package/compiler/codegen.js +247 -72
- package/compiler/precompile.js +2 -5
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -37,7 +37,8 @@ const todo = (scope, msg, expectsValue = undefined) => {
|
|
37
37
|
};
|
38
38
|
|
39
39
|
const isFuncType = type =>
|
40
|
-
type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression'
|
40
|
+
type === 'FunctionDeclaration' || type === 'FunctionExpression' || type === 'ArrowFunctionExpression' ||
|
41
|
+
type === 'ClassDeclaration' || type === 'ClassExpression';
|
41
42
|
const hasFuncWithName = name =>
|
42
43
|
Object.hasOwn(funcIndex, name) || Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) || Object.hasOwn(internalConstrs, name);
|
43
44
|
|
@@ -70,7 +71,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
70
71
|
|
71
72
|
case 'ArrowFunctionExpression':
|
72
73
|
case 'FunctionDeclaration':
|
73
|
-
case 'FunctionExpression':
|
74
|
+
case 'FunctionExpression': {
|
74
75
|
const func = generateFunc(scope, decl);
|
75
76
|
|
76
77
|
if (decl.type.endsWith('Expression')) {
|
@@ -78,6 +79,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
78
79
|
}
|
79
80
|
|
80
81
|
return cacheAst(decl, []);
|
82
|
+
}
|
81
83
|
|
82
84
|
case 'BlockStatement':
|
83
85
|
return cacheAst(decl, generateCode(scope, decl));
|
@@ -175,6 +177,10 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
175
177
|
case 'MemberExpression':
|
176
178
|
return cacheAst(decl, generateMember(scope, decl, global, name));
|
177
179
|
|
180
|
+
case 'ClassExpression':
|
181
|
+
case 'ClassDeclaration':
|
182
|
+
return cacheAst(decl, generateClass(scope, decl));
|
183
|
+
|
178
184
|
case 'ExportNamedDeclaration':
|
179
185
|
if (!decl.declaration) return todo(scope, 'unsupported export declaration');
|
180
186
|
|
@@ -1218,7 +1224,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
|
|
1218
1224
|
type: 'CallExpression',
|
1219
1225
|
callee: {
|
1220
1226
|
type: 'Identifier',
|
1221
|
-
name: '
|
1227
|
+
name: '__Porffor_object_in'
|
1222
1228
|
},
|
1223
1229
|
arguments: [
|
1224
1230
|
decl.right,
|
@@ -1327,12 +1333,8 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1327
1333
|
locals[nameParam(i)] = { idx: i, type: allLocals[i] };
|
1328
1334
|
}
|
1329
1335
|
|
1330
|
-
for (const x
|
1331
|
-
|
1332
|
-
if (offset != null) offset += pages.size * pageSize;
|
1333
|
-
|
1334
|
-
const bytes = x[1];
|
1335
|
-
data.push({ offset, bytes });
|
1336
|
+
for (const x in _data) {
|
1337
|
+
data.push({ page: x, bytes: _data[x] });
|
1336
1338
|
}
|
1337
1339
|
|
1338
1340
|
const func = {
|
@@ -1515,6 +1517,7 @@ const setLastType = (scope, type = []) => [
|
|
1515
1517
|
|
1516
1518
|
const getNodeType = (scope, node) => {
|
1517
1519
|
const ret = (() => {
|
1520
|
+
if (node._type) return node._type;
|
1518
1521
|
if (node.type === 'Literal') {
|
1519
1522
|
if (node.regex) return TYPES.regexp;
|
1520
1523
|
|
@@ -1675,10 +1678,7 @@ const getNodeType = (scope, node) => {
|
|
1675
1678
|
|
1676
1679
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1677
1680
|
if (objectKnownType != null) {
|
1678
|
-
if (name === 'length')
|
1679
|
-
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1680
|
-
else return TYPES.undefined;
|
1681
|
-
}
|
1681
|
+
if (name === 'length' && typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1682
1682
|
|
1683
1683
|
if (node.computed) {
|
1684
1684
|
if (objectKnownType === TYPES.string) return TYPES.string;
|
@@ -1702,12 +1702,12 @@ const getNodeType = (scope, node) => {
|
|
1702
1702
|
}
|
1703
1703
|
}
|
1704
1704
|
|
1705
|
-
if (node.type
|
1705
|
+
if (node.type === 'ThisExpression') {
|
1706
1706
|
if (!scope.constr) return getType(scope, 'globalThis');
|
1707
1707
|
return [ [ Opcodes.local_get, '#this#type' ] ];
|
1708
1708
|
}
|
1709
1709
|
|
1710
|
-
if (node.type
|
1710
|
+
if (node.type === 'MetaProperty') {
|
1711
1711
|
switch (`${node.meta.name}.${node.property.name}`) {
|
1712
1712
|
case 'new.target': {
|
1713
1713
|
return [ [ Opcodes.local_get, '#newtarget#type' ] ];
|
@@ -3221,12 +3221,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
3221
3221
|
},
|
3222
3222
|
arguments: [
|
3223
3223
|
{ type: 'Identifier', name: tmpName },
|
3224
|
-
{ type: 'Literal', value: i }
|
3225
|
-
{
|
3226
|
-
type: 'MemberExpression',
|
3227
|
-
object: { type: 'Identifier', name: tmpName, },
|
3228
|
-
property: { type: 'Identifier', name: 'length', }
|
3229
|
-
}
|
3224
|
+
{ type: 'Literal', value: i }
|
3230
3225
|
],
|
3231
3226
|
_protoInternalCall: true
|
3232
3227
|
}, undefined, global)
|
@@ -3419,15 +3414,16 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3419
3414
|
const op = decl.operator.slice(0, -1) || '=';
|
3420
3415
|
|
3421
3416
|
// hack: .length setter
|
3422
|
-
if (type === 'MemberExpression' && decl.left.property.name === 'length') {
|
3417
|
+
if (type === 'MemberExpression' && decl.left.property.name === 'length' && !decl._internalAssign) {
|
3423
3418
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
3424
|
-
const pointerTmp =
|
3419
|
+
const pointerTmp = localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
3425
3420
|
|
3426
|
-
|
3421
|
+
const out = [
|
3427
3422
|
...generate(scope, decl.left.object),
|
3428
|
-
Opcodes.i32_to_u
|
3429
|
-
|
3423
|
+
Opcodes.i32_to_u
|
3424
|
+
];
|
3430
3425
|
|
3426
|
+
const lengthTypeWasm = [
|
3431
3427
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3432
3428
|
[ Opcodes.local_get, pointerTmp ],
|
3433
3429
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
@@ -3440,6 +3436,33 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3440
3436
|
|
3441
3437
|
[ Opcodes.local_get, newValueTmp ]
|
3442
3438
|
];
|
3439
|
+
|
3440
|
+
const type = getNodeType(scope, decl.left.object);
|
3441
|
+
const known = knownType(scope, type);
|
3442
|
+
if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3443
|
+
...out,
|
3444
|
+
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3445
|
+
|
3446
|
+
...lengthTypeWasm
|
3447
|
+
];
|
3448
|
+
|
3449
|
+
return [
|
3450
|
+
...out,
|
3451
|
+
[ Opcodes.local_set, pointerTmp ],
|
3452
|
+
|
3453
|
+
...type,
|
3454
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3455
|
+
[ Opcodes.i32_and ],
|
3456
|
+
[ Opcodes.if, valtypeBinary ],
|
3457
|
+
[ Opcodes.local_get, pointerTmp ],
|
3458
|
+
...lengthTypeWasm,
|
3459
|
+
[ Opcodes.else ],
|
3460
|
+
...generate(scope, {
|
3461
|
+
...decl,
|
3462
|
+
_internalAssign: true
|
3463
|
+
}),
|
3464
|
+
[ Opcodes.end ]
|
3465
|
+
];
|
3443
3466
|
}
|
3444
3467
|
|
3445
3468
|
// arr[i]
|
@@ -4951,7 +4974,7 @@ const compileBytes = (val, itemType) => {
|
|
4951
4974
|
}
|
4952
4975
|
};
|
4953
4976
|
|
4954
|
-
const makeData = (scope, elements,
|
4977
|
+
const makeData = (scope, elements, page = null, itemType, initEmpty) => {
|
4955
4978
|
const length = elements.length;
|
4956
4979
|
|
4957
4980
|
// if length is 0 memory/data will just be 0000... anyway
|
@@ -4965,8 +4988,7 @@ const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
|
|
4965
4988
|
bytes.push(...compileBytes(elements[i], itemType));
|
4966
4989
|
}
|
4967
4990
|
|
4968
|
-
const obj = { bytes };
|
4969
|
-
if (offset != null) obj.offset = offset;
|
4991
|
+
const obj = { bytes, page };
|
4970
4992
|
|
4971
4993
|
const idx = data.push(obj) - 1;
|
4972
4994
|
|
@@ -5068,7 +5090,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
5068
5090
|
(!globalThis.precompile || !global)
|
5069
5091
|
) {
|
5070
5092
|
if (Prefs.activeData && firstAssign) {
|
5071
|
-
makeData(scope, elements,
|
5093
|
+
makeData(scope, elements, allocator.lastName, itemType, initEmpty);
|
5072
5094
|
|
5073
5095
|
// local value as pointer
|
5074
5096
|
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
@@ -5363,6 +5385,7 @@ const countLength = (func, name = undefined) => {
|
|
5363
5385
|
};
|
5364
5386
|
|
5365
5387
|
const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) => {
|
5388
|
+
let final = [], finalEnd, extraBC = {};
|
5366
5389
|
const name = decl.object.name;
|
5367
5390
|
|
5368
5391
|
// hack: .name
|
@@ -5375,6 +5398,12 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5375
5398
|
return withType(scope, makeString(scope, nameProp, _global, _name, true), TYPES.bytestring);
|
5376
5399
|
}
|
5377
5400
|
|
5401
|
+
const object = decl.object;
|
5402
|
+
const property = getMemberProperty(decl);
|
5403
|
+
|
5404
|
+
// generate now so type is gotten correctly later (it gets cached)
|
5405
|
+
generate(scope, object);
|
5406
|
+
|
5378
5407
|
// hack: .length
|
5379
5408
|
if (decl.property.name === 'length') {
|
5380
5409
|
// todo: support optional
|
@@ -5389,7 +5418,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5389
5418
|
}
|
5390
5419
|
|
5391
5420
|
const out = [
|
5392
|
-
...generate(scope,
|
5421
|
+
...generate(scope, object),
|
5393
5422
|
Opcodes.i32_to_u,
|
5394
5423
|
];
|
5395
5424
|
|
@@ -5403,25 +5432,21 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5403
5432
|
];
|
5404
5433
|
}
|
5405
5434
|
|
5406
|
-
const type = getNodeType(scope,
|
5435
|
+
const type = getNodeType(scope, object);
|
5407
5436
|
const known = knownType(scope, type);
|
5408
|
-
if (known != null && known
|
5409
|
-
|
5410
|
-
...out,
|
5411
|
-
|
5412
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
5413
|
-
Opcodes.i32_from_u
|
5414
|
-
];
|
5437
|
+
if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
|
5438
|
+
...out,
|
5415
5439
|
|
5416
|
-
|
5417
|
-
|
5440
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
5441
|
+
Opcodes.i32_from_u
|
5442
|
+
];
|
5418
5443
|
|
5419
5444
|
const tmp = localTmp(scope, '#length_tmp', Valtype.i32);
|
5420
|
-
|
5445
|
+
final = [
|
5421
5446
|
...out,
|
5422
5447
|
[ Opcodes.local_set, tmp ],
|
5423
5448
|
|
5424
|
-
...getNodeType(scope,
|
5449
|
+
...getNodeType(scope, object),
|
5425
5450
|
...number(TYPE_FLAGS.length, Valtype.i32),
|
5426
5451
|
[ Opcodes.i32_and ],
|
5427
5452
|
[ Opcodes.if, valtypeBinary ],
|
@@ -5431,22 +5456,14 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5431
5456
|
|
5432
5457
|
...setLastType(scope, TYPES.number),
|
5433
5458
|
[ Opcodes.else ],
|
5434
|
-
...getNodeType(scope, decl.object),
|
5435
|
-
...number(TYPES.function, Valtype.i32),
|
5436
|
-
[ Opcodes.i32_eq ],
|
5437
|
-
[ Opcodes.if, Blocktype.void ],
|
5438
|
-
[ Opcodes.local_get, tmp ],
|
5439
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_funcLut_length').index ],
|
5440
|
-
Opcodes.i32_from_u,
|
5441
|
-
|
5442
|
-
...setLastType(scope, TYPES.number),
|
5443
|
-
[ Opcodes.br, 1 ],
|
5444
|
-
[ Opcodes.end ],
|
5445
|
-
|
5446
|
-
...number(0),
|
5447
|
-
...setLastType(scope, TYPES.undefined),
|
5448
5459
|
[ Opcodes.end ]
|
5449
5460
|
];
|
5461
|
+
|
5462
|
+
if (known != null) {
|
5463
|
+
final = [];
|
5464
|
+
} else {
|
5465
|
+
finalEnd = final.pop();
|
5466
|
+
}
|
5450
5467
|
}
|
5451
5468
|
|
5452
5469
|
// todo: generate this array procedurally during builtinFuncs creation
|
@@ -5455,33 +5472,67 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5455
5472
|
const bc = {};
|
5456
5473
|
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
5457
5474
|
|
5475
|
+
localTmp(scope, '#member_obj');
|
5476
|
+
localTmp(scope, '#member_obj#type', Valtype.i32);
|
5477
|
+
|
5478
|
+
const known = knownType(scope, getNodeType(scope, object));
|
5458
5479
|
if (cands.length > 0) {
|
5459
5480
|
for (const x of cands) {
|
5460
5481
|
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
5461
5482
|
if (type == null) continue;
|
5462
5483
|
|
5484
|
+
if (type === known) return generateCall(scope, {
|
5485
|
+
callee: {
|
5486
|
+
type: 'Identifier',
|
5487
|
+
name: x
|
5488
|
+
},
|
5489
|
+
arguments: [ object ],
|
5490
|
+
_protoInternalCall: true
|
5491
|
+
});
|
5492
|
+
|
5463
5493
|
bc[type] = generateCall(scope, {
|
5464
5494
|
callee: {
|
5465
5495
|
type: 'Identifier',
|
5466
5496
|
name: x
|
5467
5497
|
},
|
5468
|
-
arguments: [
|
5498
|
+
arguments: [
|
5499
|
+
{ type: 'Identifier', name: '#member_obj' }
|
5500
|
+
],
|
5469
5501
|
_protoInternalCall: true
|
5470
5502
|
});
|
5471
5503
|
}
|
5472
5504
|
}
|
5473
5505
|
|
5474
|
-
|
5475
|
-
...bc,
|
5476
|
-
default: withType(scope, number(0), TYPES.undefined)
|
5477
|
-
}, valtypeBinary);
|
5506
|
+
if (known == null) extraBC = bc;
|
5478
5507
|
}
|
5479
5508
|
|
5480
|
-
|
5481
|
-
|
5509
|
+
if (decl.property.name === '__proto__') {
|
5510
|
+
// todo: support optional
|
5511
|
+
const bc = {};
|
5512
|
+
const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
|
5482
5513
|
|
5483
|
-
|
5484
|
-
|
5514
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
5515
|
+
for (const x of prototypes) {
|
5516
|
+
const type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
|
5517
|
+
if (type == null) continue;
|
5518
|
+
|
5519
|
+
// do not __proto__ primitive hack for objects
|
5520
|
+
if (type === TYPES.object) continue;
|
5521
|
+
|
5522
|
+
const ident = {
|
5523
|
+
type: 'Identifier',
|
5524
|
+
name: x
|
5525
|
+
};
|
5526
|
+
|
5527
|
+
bc[type] = [
|
5528
|
+
...generateIdent(scope, ident),
|
5529
|
+
...setLastType(scope, getNodeType(scope, ident))
|
5530
|
+
];
|
5531
|
+
if (type === known) return bc[type];
|
5532
|
+
}
|
5533
|
+
|
5534
|
+
if (known == null) extraBC = bc;
|
5535
|
+
}
|
5485
5536
|
|
5486
5537
|
// todo/perf: use i32 object (and prop?) locals
|
5487
5538
|
const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
|
@@ -5668,7 +5719,9 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5668
5719
|
default: [
|
5669
5720
|
...number(0),
|
5670
5721
|
...setLastType(scope, TYPES.undefined)
|
5671
|
-
]
|
5722
|
+
],
|
5723
|
+
|
5724
|
+
...extraBC
|
5672
5725
|
});
|
5673
5726
|
|
5674
5727
|
if (decl.optional) {
|
@@ -5676,6 +5729,10 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5676
5729
|
[ Opcodes.block, valtypeBinary ],
|
5677
5730
|
...(_objectWasm ? _objectWasm : generate(scope, object)),
|
5678
5731
|
[ Opcodes.local_tee, localTmp(scope, '#member_obj') ],
|
5732
|
+
...(scope.locals['#member_obj#type'] ? [
|
5733
|
+
...getNodeType(scope, object),
|
5734
|
+
[ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
|
5735
|
+
] : []),
|
5679
5736
|
|
5680
5737
|
...nullish(scope, [], getNodeType(scope, object), false, true),
|
5681
5738
|
[ Opcodes.if, Blocktype.void ],
|
@@ -5695,12 +5752,106 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5695
5752
|
out.unshift(
|
5696
5753
|
...(_objectWasm ? _objectWasm : generate(scope, object)),
|
5697
5754
|
[ Opcodes.local_set, localTmp(scope, '#member_obj') ],
|
5755
|
+
...(scope.locals['#member_obj#type'] ? [
|
5756
|
+
...getNodeType(scope, object),
|
5757
|
+
[ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
|
5758
|
+
] : []),
|
5698
5759
|
|
5699
5760
|
...generate(scope, property, false, '#member_prop'),
|
5700
5761
|
[ Opcodes.local_set, localTmp(scope, '#member_prop') ]
|
5701
5762
|
);
|
5702
5763
|
}
|
5703
5764
|
|
5765
|
+
if (final.length > 0) {
|
5766
|
+
final = final.concat(out);
|
5767
|
+
final.push(finalEnd);
|
5768
|
+
return final;
|
5769
|
+
}
|
5770
|
+
|
5771
|
+
return out;
|
5772
|
+
};
|
5773
|
+
|
5774
|
+
const generateClass = (scope, decl) => {
|
5775
|
+
const expr = decl.type === 'ClassExpression';
|
5776
|
+
if (decl.superClass) return todo(scope, 'class extends is not supported yet', expr);
|
5777
|
+
|
5778
|
+
const name = decl.id.name;
|
5779
|
+
if (name == null) return todo(scope, 'unknown name for class', expr);
|
5780
|
+
|
5781
|
+
const body = decl.body.body;
|
5782
|
+
const root = {
|
5783
|
+
type: 'Identifier',
|
5784
|
+
name
|
5785
|
+
};
|
5786
|
+
|
5787
|
+
const constr = body.find(x => x.kind === 'constructor')?.value ?? {
|
5788
|
+
type: 'FunctionExpression',
|
5789
|
+
id: root,
|
5790
|
+
params: [],
|
5791
|
+
body: {
|
5792
|
+
type: 'BlockStatement',
|
5793
|
+
body: []
|
5794
|
+
}
|
5795
|
+
};
|
5796
|
+
|
5797
|
+
const func = generateFunc(scope, {
|
5798
|
+
...constr,
|
5799
|
+
_onlyConstr: `Class constructor ${name} requires 'new'`,
|
5800
|
+
type: expr ? 'FunctionExpression' : 'FunctionDeclaration'
|
5801
|
+
});
|
5802
|
+
|
5803
|
+
const out = [];
|
5804
|
+
|
5805
|
+
for (const x of body) {
|
5806
|
+
let { type, key, value, kind, static: _static, computed } = x;
|
5807
|
+
if (type !== 'MethodDefinition' && type !== 'PropertyDefinition') return todo(scope, `class body type ${type} is not supported yet`, expr);
|
5808
|
+
|
5809
|
+
if (kind === 'constructor') continue;
|
5810
|
+
|
5811
|
+
const object = _static ? root : {
|
5812
|
+
type: 'MemberExpression',
|
5813
|
+
object: root,
|
5814
|
+
property: {
|
5815
|
+
type: 'Identifier',
|
5816
|
+
name: 'prototype'
|
5817
|
+
},
|
5818
|
+
computed: false,
|
5819
|
+
optional: false
|
5820
|
+
};
|
5821
|
+
|
5822
|
+
let k = key;
|
5823
|
+
if (!computed && key.type !== 'Literal') k = {
|
5824
|
+
type: 'Literal',
|
5825
|
+
value: key.name
|
5826
|
+
};
|
5827
|
+
|
5828
|
+
let initKind = 'init';
|
5829
|
+
if (kind === 'get' || kind === 'set') initKind = kind;
|
5830
|
+
|
5831
|
+
// default value to undefined
|
5832
|
+
value ??= DEFAULT_VALUE();
|
5833
|
+
|
5834
|
+
out.push(
|
5835
|
+
...generate(scope, object),
|
5836
|
+
Opcodes.i32_to_u,
|
5837
|
+
...getNodeType(scope, object),
|
5838
|
+
|
5839
|
+
...generate(scope, k),
|
5840
|
+
...getNodeType(scope, k),
|
5841
|
+
...toPropertyKey(scope, true),
|
5842
|
+
|
5843
|
+
...generate(scope, value),
|
5844
|
+
...(initKind !== 'init' ? [ Opcodes.i32_to_u ] : []),
|
5845
|
+
...getNodeType(scope, value),
|
5846
|
+
|
5847
|
+
[ Opcodes.call, includeBuiltin(scope, `__Porffor_object_expr_${initKind}`).index ],
|
5848
|
+
|
5849
|
+
[ Opcodes.drop ],
|
5850
|
+
[ Opcodes.drop ]
|
5851
|
+
);
|
5852
|
+
}
|
5853
|
+
|
5854
|
+
if (expr) out.push(funcRef(func.index, func.name));
|
5704
5855
|
return out;
|
5705
5856
|
};
|
5706
5857
|
|
@@ -5716,7 +5867,9 @@ const objectHack = node => {
|
|
5716
5867
|
if (node.computed || node.optional) return;
|
5717
5868
|
|
5718
5869
|
// hack: block these properties as they can be accessed on functions
|
5719
|
-
if (node.property.name
|
5870
|
+
if (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call') return;
|
5871
|
+
|
5872
|
+
if (node.property.name === '__proto__') return;
|
5720
5873
|
|
5721
5874
|
let objectName = node.object.name;
|
5722
5875
|
|
@@ -5914,17 +6067,39 @@ const generateFunc = (scope, decl) => {
|
|
5914
6067
|
);
|
5915
6068
|
}
|
5916
6069
|
|
6070
|
+
if (decl._onlyConstr) {
|
6071
|
+
wasm.unshift(
|
6072
|
+
// error if not being constructed
|
6073
|
+
[ Opcodes.local_get, '#newtarget' ],
|
6074
|
+
Opcodes.i32_to_u,
|
6075
|
+
[ Opcodes.i32_eqz ],
|
6076
|
+
[ Opcodes.if, Blocktype.void ],
|
6077
|
+
...internalThrow(func, 'TypeError', decl._onlyConstr),
|
6078
|
+
[ Opcodes.end ]
|
6079
|
+
);
|
6080
|
+
}
|
6081
|
+
|
5917
6082
|
if (name === 'main') {
|
5918
6083
|
func.gotLastType = true;
|
5919
6084
|
func.export = true;
|
5920
6085
|
func.returns = [ valtypeBinary, Valtype.i32 ];
|
5921
6086
|
|
6087
|
+
let finalStatement = decl.body.body[decl.body.body.length - 1];
|
6088
|
+
if (finalStatement?.type === 'EmptyStatement') finalStatement = decl.body.body[decl.body.body.length - 2];
|
6089
|
+
|
5922
6090
|
const lastInst = func.wasm[func.wasm.length - 1] ?? [ Opcodes.end ];
|
5923
6091
|
if (lastInst[0] === Opcodes.drop) {
|
5924
|
-
|
5925
|
-
|
5926
|
-
|
5927
|
-
|
6092
|
+
if (finalStatement.type.endsWith('Declaration')) {
|
6093
|
+
// final statement is decl, force undefined
|
6094
|
+
disposeLeftover(wasm);
|
6095
|
+
func.wasm.push(
|
6096
|
+
...number(UNDEFINED),
|
6097
|
+
...number(TYPES.undefined, Valtype.i32)
|
6098
|
+
);
|
6099
|
+
} else {
|
6100
|
+
func.wasm.splice(func.wasm.length - 1, 1);
|
6101
|
+
func.wasm.push(...getNodeType(func, finalStatement));
|
6102
|
+
}
|
5928
6103
|
}
|
5929
6104
|
|
5930
6105
|
if (lastInst[0] === Opcodes.end || lastInst[0] === Opcodes.local_set || lastInst[0] === Opcodes.global_set) {
|
package/compiler/precompile.js
CHANGED
@@ -66,10 +66,7 @@ const compile = async (file, _funcs) => {
|
|
66
66
|
const exports = funcs.filter(x => x.export && x.name !== 'main');
|
67
67
|
for (const x of exports) {
|
68
68
|
if (x.data) {
|
69
|
-
x.data = x.data.
|
70
|
-
for (const y in x.data) {
|
71
|
-
if (x.data[y].offset != null) x.data[y].offset -= x.data[0].offset;
|
72
|
-
}
|
69
|
+
x.data = x.data.reduce((acc, x) => { acc[data[x].page] = data[x].bytes; return acc; }, {});
|
73
70
|
}
|
74
71
|
|
75
72
|
if (x.exceptions) {
|
@@ -226,7 +223,7 @@ ${funcs.map(x => {
|
|
226
223
|
wasm:${rewriteWasm(x.wasm)},
|
227
224
|
params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)}` : 'typedReturns:1'},
|
228
225
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
229
|
-
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && x.data.length > 0 ? `data
|
226
|
+
${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)},` : ''}
|
230
227
|
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}
|
231
228
|
};`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
232
229
|
}).join('\n')}
|
package/package.json
CHANGED