porffor 0.55.35 → 0.56.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/builtins/bigint.ts +4 -4
- package/compiler/builtins/object.ts +1 -1
- package/compiler/builtins.js +0 -55
- package/compiler/builtins_precompiled.js +112 -112
- package/compiler/codegen.js +41 -37
- package/compiler/expression.js +55 -3
- package/package.json +1 -1
- package/r.cjs +102 -3
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -809,12 +809,23 @@ const compareStrings = (scope, left, right, leftType, rightType, noConv = false)
|
|
809
809
|
};
|
810
810
|
|
811
811
|
const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode = undefined) => {
|
812
|
+
const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
|
812
813
|
if (isIntToFloatOp(wasm[wasm.length - 1])) return [
|
813
814
|
...wasm,
|
814
|
-
...(
|
815
|
+
...(truthyMode === 'full' ? [
|
816
|
+
[ Opcodes.f64_const, 0 ],
|
817
|
+
[ Opcodes.f64_ne ],
|
818
|
+
...(!intOut ? [ Opcodes.i32_from_u ] : [])
|
819
|
+
] : [
|
820
|
+
...(!intIn && intOut ? [ Opcodes.i32_to_u ] : [])
|
821
|
+
])
|
815
822
|
];
|
816
823
|
if (isIntOp(wasm[wasm.length - 1])) return [
|
817
824
|
...wasm,
|
825
|
+
...(truthyMode === 'full' ? [
|
826
|
+
[ Opcodes.i32_eqz ],
|
827
|
+
[ Opcodes.i32_eqz ]
|
828
|
+
] : []),
|
818
829
|
...(intOut ? [] : [ Opcodes.i32_from ]),
|
819
830
|
];
|
820
831
|
|
@@ -822,8 +833,6 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
|
|
822
833
|
|
823
834
|
const useTmp = knownType(scope, type) == null;
|
824
835
|
const tmp = useTmp && localTmp(scope, `#logicinner_tmp${intIn ? '_int' : ''}`, intIn ? Valtype.i32 : valtypeBinary);
|
825
|
-
|
826
|
-
const truthyMode = forceTruthyMode ?? Prefs.truthy ?? 'full';
|
827
836
|
const def = (() => {
|
828
837
|
if (truthyMode === 'full') return [
|
829
838
|
// if value != 0 or NaN
|
@@ -995,22 +1004,29 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
|
|
995
1004
|
const finalize = out => startOut.concat(out, endOut);
|
996
1005
|
|
997
1006
|
// if strict (in)equal check types match, skip if known
|
998
|
-
if (strictOp
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
[ Opcodes.
|
1009
|
-
|
1010
|
-
|
1011
|
-
[ Opcodes.i32_or ]
|
1012
|
-
|
1013
|
-
|
1007
|
+
if (strictOp) {
|
1008
|
+
if (knownLeft != null && knownRight != null) {
|
1009
|
+
if ((knownLeft | TYPE_FLAGS.parity) !== (knownRight | TYPE_FLAGS.parity)) endOut.push(
|
1010
|
+
number(op === '===' ? 0 : 1, Valtype.i32),
|
1011
|
+
[ op === '===' ? Opcodes.i32_and : Opcodes.i32_or ]
|
1012
|
+
);
|
1013
|
+
} else {
|
1014
|
+
endOut.push(
|
1015
|
+
...leftType,
|
1016
|
+
number(TYPE_FLAGS.parity, Valtype.i32),
|
1017
|
+
[ Opcodes.i32_or ],
|
1018
|
+
...rightType,
|
1019
|
+
number(TYPE_FLAGS.parity, Valtype.i32),
|
1020
|
+
[ Opcodes.i32_or ],
|
1021
|
+
...(op === '===' ? [
|
1022
|
+
[ Opcodes.i32_eq ],
|
1023
|
+
[ Opcodes.i32_and ]
|
1024
|
+
] : [
|
1025
|
+
[ Opcodes.i32_ne ],
|
1026
|
+
[ Opcodes.i32_or ]
|
1027
|
+
])
|
1028
|
+
);
|
1029
|
+
}
|
1014
1030
|
}
|
1015
1031
|
|
1016
1032
|
if (!eqOp && (knownLeft === TYPES.bigint || knownRight === TYPES.bigint) && !(knownLeft === TYPES.bigint && knownRight === TYPES.bigint)) {
|
@@ -1041,10 +1057,10 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
|
|
1041
1057
|
|
1042
1058
|
// string comparison
|
1043
1059
|
if (op === '===' || op === '==' || op === '!==' || op === '!=') {
|
1044
|
-
return [
|
1060
|
+
return finalize([
|
1045
1061
|
...compareStrings(scope, left, right, leftType, rightType, knownLeftStr && knownRightStr),
|
1046
1062
|
...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
|
1047
|
-
];
|
1063
|
+
]);
|
1048
1064
|
}
|
1049
1065
|
|
1050
1066
|
// todo: proper >|>=|<|<=
|
@@ -1052,21 +1068,9 @@ const performOp = (scope, op, left, right, leftType, rightType) => {
|
|
1052
1068
|
|
1053
1069
|
let ops = operatorOpcode[valtype][op];
|
1054
1070
|
|
1055
|
-
// some complex ops are implemented
|
1056
|
-
|
1057
|
-
if (!ops && builtinFuncs[builtinName]) {
|
1058
|
-
includeBuiltin(scope, builtinName);
|
1059
|
-
const idx = funcIndex[builtinName];
|
1060
|
-
|
1061
|
-
return finalize([
|
1062
|
-
...left,
|
1063
|
-
...right,
|
1064
|
-
[ Opcodes.call, idx ]
|
1065
|
-
]);
|
1066
|
-
}
|
1067
|
-
|
1071
|
+
// some complex ops are implemented in funcs
|
1072
|
+
if (typeof ops === 'function') return finalize(asmFuncToAsm(scope, ops, { left, right }));
|
1068
1073
|
if (!ops) return todo(scope, `operator ${op} not implemented yet`, true);
|
1069
|
-
|
1070
1074
|
if (!Array.isArray(ops)) ops = [ ops ];
|
1071
1075
|
ops = [ ops ];
|
1072
1076
|
|
@@ -1237,7 +1241,7 @@ const generateBinaryExp = (scope, decl) => {
|
|
1237
1241
|
return out;
|
1238
1242
|
};
|
1239
1243
|
|
1240
|
-
const asmFuncToAsm = (scope, func) => {
|
1244
|
+
const asmFuncToAsm = (scope, func, extra) => {
|
1241
1245
|
return func(scope, {
|
1242
1246
|
Valtype, Opcodes, TYPES, TYPE_NAMES, usedTypes, typeSwitch, makeString, internalThrow,
|
1243
1247
|
getNodeType, generate, generateIdent,
|
@@ -1318,7 +1322,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1318
1322
|
return wasm;
|
1319
1323
|
},
|
1320
1324
|
allocPage: (scope, name) => allocPage({ scope, pages }, name)
|
1321
|
-
});
|
1325
|
+
}, extra);
|
1322
1326
|
};
|
1323
1327
|
|
1324
1328
|
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usesImports = false, usedTypes = [] } = {}) => {
|
package/compiler/expression.js
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
import { Opcodes } from './wasmSpec.js';
|
1
|
+
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
|
+
import { TYPES } from './types.js';
|
3
|
+
|
4
|
+
const f64ifyBitwise = op => (_1, _2, { left, right }) => [
|
5
|
+
...left,
|
6
|
+
Opcodes.i32_trunc_sat_f64_s,
|
7
|
+
...right,
|
8
|
+
Opcodes.i32_trunc_sat_f64_s,
|
9
|
+
[ op ],
|
10
|
+
[ Opcodes.f64_convert_i32_s ]
|
11
|
+
];
|
2
12
|
|
3
13
|
export const operatorOpcode = {
|
4
14
|
i32: {
|
@@ -23,7 +33,17 @@ export const operatorOpcode = {
|
|
23
33
|
'>': Opcodes.i32_gt_s,
|
24
34
|
'>=': Opcodes.i32_ge_s,
|
25
35
|
'<': Opcodes.i32_lt_s,
|
26
|
-
'<=': Opcodes.i32_le_s
|
36
|
+
'<=': Opcodes.i32_le_s,
|
37
|
+
|
38
|
+
'**': (_, { builtin }, { left, right }) => [
|
39
|
+
...left,
|
40
|
+
[ Opcodes.f64_convert_i32_s ],
|
41
|
+
[ Opcodes.i32_const, TYPES.number ],
|
42
|
+
...right,
|
43
|
+
[ Opcodes.f64_convert_i32_s ],
|
44
|
+
[ Opcodes.i32_const, TYPES.number ],
|
45
|
+
[ Opcodes.call, builtin('__Math_pow') ]
|
46
|
+
]
|
27
47
|
},
|
28
48
|
|
29
49
|
i64: {
|
@@ -65,6 +85,38 @@ export const operatorOpcode = {
|
|
65
85
|
'>': Opcodes.f64_gt,
|
66
86
|
'>=': Opcodes.f64_ge,
|
67
87
|
'<': Opcodes.f64_lt,
|
68
|
-
'<=': Opcodes.f64_le
|
88
|
+
'<=': Opcodes.f64_le,
|
89
|
+
|
90
|
+
'**': (_, { builtin }, { left, right }) => [
|
91
|
+
...left,
|
92
|
+
[ Opcodes.i32_const, TYPES.number ],
|
93
|
+
...right,
|
94
|
+
[ Opcodes.i32_const, TYPES.number ],
|
95
|
+
[ Opcodes.call, builtin('__Math_pow') ]
|
96
|
+
],
|
97
|
+
|
98
|
+
'%': (_, { builtin, loc }, { left, right }) => [
|
99
|
+
// a - truncf(a / b) * b
|
100
|
+
...left,
|
101
|
+
[ Opcodes.local_tee, loc('#math_a', Valtype.f64) ],
|
102
|
+
...right,
|
103
|
+
[ Opcodes.local_tee, loc('#math_b', Valtype.f64) ],
|
104
|
+
|
105
|
+
[ Opcodes.local_get, loc('#math_a', Valtype.f64) ],
|
106
|
+
[ Opcodes.local_get, loc('#math_b', Valtype.f64) ],
|
107
|
+
[ Opcodes.f64_div ],
|
108
|
+
[ Opcodes.f64_trunc ],
|
109
|
+
|
110
|
+
[ Opcodes.f64_mul ],
|
111
|
+
[ Opcodes.f64_sub ]
|
112
|
+
],
|
113
|
+
|
114
|
+
// add bitwise ops by converting operands to i32 first
|
115
|
+
'&': f64ifyBitwise(Opcodes.i32_and),
|
116
|
+
'|': f64ifyBitwise(Opcodes.i32_or),
|
117
|
+
'^': f64ifyBitwise(Opcodes.i32_xor),
|
118
|
+
'<<': f64ifyBitwise(Opcodes.i32_shl),
|
119
|
+
'>>': f64ifyBitwise(Opcodes.i32_shr_s),
|
120
|
+
'>>>': f64ifyBitwise(Opcodes.i32_shr_u)
|
69
121
|
}
|
70
122
|
};
|
package/package.json
CHANGED
package/r.cjs
CHANGED
@@ -1,8 +1,107 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
var assert = mustBeTrue => {
|
2
|
+
if (mustBeTrue === true) {
|
3
|
+
return;
|
4
|
+
}
|
5
|
+
|
6
|
+
throw new Test262Error('assert failed');
|
7
|
+
};
|
8
|
+
|
9
|
+
function isConfigurable(obj, name) {
|
10
|
+
if (Object.hasOwn(obj, name)) return Object.getOwnPropertyDescriptor(obj, name).configurable;
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
|
14
|
+
function isEnumerable(obj, name) {
|
15
|
+
return Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).enumerable;
|
16
|
+
}
|
17
|
+
|
18
|
+
function isSameValue(a, b) {
|
19
|
+
if (a === 0 && b === 0) return 1 / a === 1 / b;
|
20
|
+
if (a !== a && b !== b) return true;
|
21
|
+
|
22
|
+
return a === b;
|
23
|
+
}
|
24
|
+
|
25
|
+
function isWritable(obj, name, verifyProp, value) {
|
26
|
+
if (Object.hasOwn(obj, name) && Object.getOwnPropertyDescriptor(obj, name).writable != null) return Object.getOwnPropertyDescriptor(obj, name).writable;
|
27
|
+
if (!Object.hasOwn(obj, name) && Object.isExtensible(obj)) return true;
|
28
|
+
|
29
|
+
var unlikelyValue = Array.isArray(obj) && name === "length" ?
|
30
|
+
Math.pow(2, 32) - 1 :
|
31
|
+
"unlikelyValue";
|
32
|
+
var newValue = value || unlikelyValue;
|
33
|
+
var hadValue = Object.hasOwn(obj, name);
|
34
|
+
var oldValue = obj[name];
|
35
|
+
var writeSucceeded;
|
36
|
+
|
37
|
+
try {
|
38
|
+
obj[name] = newValue;
|
39
|
+
} catch {}
|
40
|
+
|
41
|
+
writeSucceeded = isSameValue(obj[verifyProp || name], newValue);
|
42
|
+
|
43
|
+
if (writeSucceeded) {
|
44
|
+
if (hadValue) {
|
45
|
+
obj[name] = oldValue;
|
46
|
+
} else {
|
47
|
+
delete obj[name];
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
return writeSucceeded;
|
3
52
|
}
|
4
53
|
|
5
|
-
|
54
|
+
function verifyProperty(obj, name, desc, options) {
|
55
|
+
var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
|
56
|
+
|
57
|
+
if (desc === undefined) {
|
58
|
+
if (originalDesc !== undefined) {
|
59
|
+
throw new Test262Error('verifyProperty: expected undefined descriptor');
|
60
|
+
}
|
61
|
+
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
|
65
|
+
if (!Object.hasOwn(obj, name)) throw new Test262Error('verifyProperty: obj should have own property');
|
66
|
+
|
67
|
+
if (Object.hasOwn(desc, 'value')) {
|
68
|
+
const v = desc.value;
|
69
|
+
if (!isSameValue(originalDesc.value, v)) throw new Test262Error('verifyProperty: descriptor value mismatch');
|
70
|
+
// if (!isSameValue(obj[name], v)) throw new Test262Error('verifyProperty: object value mismatch');
|
71
|
+
}
|
72
|
+
|
73
|
+
if (Object.hasOwn(desc, 'enumerable')) {
|
74
|
+
if (desc.enumerable !== originalDesc.enumerable ||
|
75
|
+
desc.enumerable !== isEnumerable(obj, name)) {
|
76
|
+
throw new Test262Error('enumerable fail');
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
if (Object.hasOwn(desc, 'writable')) {
|
81
|
+
if (desc.writable !== originalDesc.writable ||
|
82
|
+
desc.writable !== isWritable(obj, name)) {
|
83
|
+
throw new Test262Error('writable fail');
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
if (Object.hasOwn(desc, 'configurable')) {
|
88
|
+
if (desc.configurable !== originalDesc.configurable ||
|
89
|
+
desc.configurable !== isConfigurable(obj, name)) {
|
90
|
+
throw new Test262Error('configurable fail');
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
if (options && options.restore) {
|
95
|
+
Object.defineProperty(obj, name, originalDesc);
|
96
|
+
}
|
97
|
+
|
98
|
+
return true;
|
99
|
+
}
|
100
|
+
|
101
|
+
const desc = { enumerable: true, configurable: true, writable: true };
|
102
|
+
const obj = Object.defineProperty({}, 'wow', desc);
|
103
|
+
assert(verifyProperty(obj, 'wow', desc));
|
104
|
+
|
6
105
|
|
7
106
|
// var EQUAL = 1;
|
8
107
|
// var NOT_EQUAL = -1;
|