porffor 0.20.5 → 0.20.7
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 +1 -1
- package/compiler/builtins/array.ts +7 -0
- package/compiler/builtins/object.ts +136 -1
- package/compiler/builtins/porffor.d.ts +1 -0
- package/compiler/builtins/set.ts +2 -5
- package/compiler/builtins/symbol.ts +1 -6
- package/compiler/builtins/weakref.ts +1 -1
- package/compiler/builtins/z_ecma262.ts +16 -0
- package/compiler/builtins/z_map.ts +8 -9
- package/compiler/builtins/z_weakmap.ts +3 -5
- package/compiler/builtins/z_weakset.ts +2 -5
- package/compiler/codegen.js +59 -32
- package/compiler/generated_builtins.js +181 -120
- package/compiler/precompile.js +1 -1
- package/compiler/types.js +10 -16
- package/compiler/wrap.js +3 -3
- package/package.json +1 -1
- package/runner/index.js +2 -2
package/compiler/assemble.js
CHANGED
@@ -154,7 +154,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
154
154
|
encodeVector([ [
|
155
155
|
0x00,
|
156
156
|
Opcodes.i32_const, 0, Opcodes.end,
|
157
|
-
...encodeVector(funcs.map(x => x.index))
|
157
|
+
...encodeVector(funcs.map(x => unsignedLEB128(x.index)))
|
158
158
|
] ])
|
159
159
|
);
|
160
160
|
|
@@ -36,6 +36,13 @@ export const __Array_from = (arg: any, mapFn: any): any[] => {
|
|
36
36
|
return out;
|
37
37
|
};
|
38
38
|
|
39
|
+
export const __Porffor_fastPush = (_this: any[], el: any) => {
|
40
|
+
let len: i32 = _this.length;
|
41
|
+
_this[len] = el;
|
42
|
+
_this.length = ++len;
|
43
|
+
return len;
|
44
|
+
};
|
45
|
+
|
39
46
|
export const __Array_prototype_push = (_this: any[], ...items: any[]) => {
|
40
47
|
let len: i32 = _this.length;
|
41
48
|
const itemsLen: i32 = items.length;
|
@@ -1,8 +1,143 @@
|
|
1
1
|
import type {} from './porffor.d.ts';
|
2
2
|
|
3
|
+
export const __Object_keys = (obj: any): any[] => {
|
4
|
+
if (obj == null) throw new TypeError('Argument is nullish, expected object');
|
5
|
+
|
6
|
+
const out: any[] = Porffor.allocate();
|
7
|
+
|
8
|
+
const t: i32 = Porffor.rawType(obj);
|
9
|
+
if (t == Porffor.TYPES.object) {
|
10
|
+
const keys: Set = Porffor.wasm.i32.load(obj, 0, 0);
|
11
|
+
const size: i32 = Porffor.wasm.i32.load(keys, 0, 0);
|
12
|
+
out.length = size;
|
13
|
+
|
14
|
+
for (let i: i32 = 0; i < size; i++) {
|
15
|
+
out[i] = Porffor.set.read(keys, i);
|
16
|
+
}
|
17
|
+
} else if (Porffor.fastOr(
|
18
|
+
t == Porffor.TYPES.array,
|
19
|
+
t == Porffor.TYPES.bytestring,
|
20
|
+
t == Porffor.TYPES.string
|
21
|
+
)) {
|
22
|
+
const len: i32 = obj.length;
|
23
|
+
out.length = len;
|
24
|
+
|
25
|
+
for (let i: i32 = 0; i < len; i++) {
|
26
|
+
out[i] = __Number_prototype_toString(i);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
return out;
|
31
|
+
};
|
32
|
+
|
33
|
+
export const __Object_values = (obj: any): any[] => {
|
34
|
+
if (obj == null) throw new TypeError('Argument is nullish, expected object');
|
35
|
+
|
36
|
+
const out: any[] = Porffor.allocate();
|
37
|
+
|
38
|
+
const t: i32 = Porffor.rawType(obj);
|
39
|
+
if (t == Porffor.TYPES.object) {
|
40
|
+
const size: i32 = Porffor.wasm.i32.load(Porffor.wasm.i32.load(obj, 0, 0), 0, 0);
|
41
|
+
const vals: any[] = Porffor.wasm.i32.load(obj, 0, 4);
|
42
|
+
|
43
|
+
out.length = size;
|
44
|
+
for (let i: i32 = 0; i < size; i++) {
|
45
|
+
out[i] = vals[i];
|
46
|
+
}
|
47
|
+
} else if (Porffor.fastOr(
|
48
|
+
t == Porffor.TYPES.array,
|
49
|
+
t == Porffor.TYPES.bytestring,
|
50
|
+
t == Porffor.TYPES.string
|
51
|
+
)) {
|
52
|
+
const len: i32 = obj.length;
|
53
|
+
out.length = len;
|
54
|
+
|
55
|
+
for (let i: i32 = 0; i < len; i++) {
|
56
|
+
out[i] = obj[i];
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
return out;
|
61
|
+
};
|
62
|
+
|
63
|
+
export const __Object_entries = (obj: any): any[] => {
|
64
|
+
const out: any[] = Porffor.allocate();
|
65
|
+
|
66
|
+
const keys: any[] = __Object_keys(obj);
|
67
|
+
const vals: any[] = __Object_values(obj);
|
68
|
+
|
69
|
+
const size: i32 = keys.length;
|
70
|
+
out.length = size;
|
71
|
+
|
72
|
+
for (let i: i32 = 0; i < size; i++) {
|
73
|
+
// what is memory efficiency anyway?
|
74
|
+
const entry: any[] = Porffor.allocate();
|
75
|
+
|
76
|
+
entry.length = 2;
|
77
|
+
entry[0] = keys[i];
|
78
|
+
entry[1] = vals[i];
|
79
|
+
|
80
|
+
out[i] = entry;
|
81
|
+
}
|
82
|
+
|
83
|
+
return out;
|
84
|
+
};
|
85
|
+
|
86
|
+
export const __Object_fromEntries = (iterable: any): object => {
|
87
|
+
const out: object = {};
|
88
|
+
|
89
|
+
for (const x of iterable) {
|
90
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
91
|
+
out[ecma262.ToPropertyKey(x[0])] = x[1];
|
92
|
+
}
|
93
|
+
|
94
|
+
return out;
|
95
|
+
};
|
96
|
+
|
97
|
+
|
98
|
+
export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
|
99
|
+
const p: any = ecma262.ToPropertyKey(prop);
|
100
|
+
|
101
|
+
const t: i32 = Porffor.rawType(_this);
|
102
|
+
if (t == Porffor.TYPES.object) {
|
103
|
+
const keys: Set = Porffor.wasm.i32.load(_this, 0, 0);
|
104
|
+
return __Set_prototype_has(keys, p);
|
105
|
+
}
|
106
|
+
|
107
|
+
const keys: any[] = __Object_keys(_this);
|
108
|
+
return __Array_prototype_includes(keys, p);
|
109
|
+
};
|
110
|
+
|
111
|
+
export const __Object_hasOwn = (obj: any, prop: any) => {
|
112
|
+
// todo: not spec compliant lol
|
113
|
+
return __Object_prototype_hasOwnProperty(obj, prop);
|
114
|
+
};
|
115
|
+
|
116
|
+
|
117
|
+
export const __Object_assign = (target: any, ...sources: any[]) => {
|
118
|
+
if (target == null) throw new TypeError('Argument is nullish, expected object');
|
119
|
+
|
120
|
+
for (const x of sources) {
|
121
|
+
const keys: any[] = __Object_keys(x);
|
122
|
+
const vals: any[] = __Object_values(x);
|
123
|
+
|
124
|
+
const len: i32 = keys.length;
|
125
|
+
for (let i: i32 = 0; i < len; i++) {
|
126
|
+
target[keys[i]] = vals[i];
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
return target;
|
131
|
+
};
|
132
|
+
|
133
|
+
|
3
134
|
export const __Object_prototype_toString = (_this: object) => {
|
4
135
|
let out: bytestring = '[object Object]';
|
5
136
|
return out;
|
6
137
|
};
|
7
138
|
|
8
|
-
export const __Object_prototype_toLocaleString = (_this: object) => __Object_prototype_toLocaleString(_this);
|
139
|
+
export const __Object_prototype_toLocaleString = (_this: object) => __Object_prototype_toLocaleString(_this);
|
140
|
+
|
141
|
+
export const __Object_prototype_valueOf = (_this: object) => {
|
142
|
+
return _this;
|
143
|
+
};
|
package/compiler/builtins/set.ts
CHANGED
@@ -76,7 +76,7 @@ export const __Set_prototype_values = (_this: Set) => {
|
|
76
76
|
const out: any[] = __Porffor_allocate();
|
77
77
|
for (let i: number = 0; i < size; i++) {
|
78
78
|
const val: any = __Porffor_set_read(_this, i);
|
79
|
-
|
79
|
+
Porffor.fastPush(out, val);
|
80
80
|
}
|
81
81
|
|
82
82
|
return out;
|
@@ -184,10 +184,7 @@ export const Set = function (iterable: any): Set {
|
|
184
184
|
|
185
185
|
const out: Set = __Porffor_allocate();
|
186
186
|
|
187
|
-
if (
|
188
|
-
Porffor.rawType(iterable) != Porffor.TYPES.undefined,
|
189
|
-
iterable !== null
|
190
|
-
)) for (const x of iterable) {
|
187
|
+
if (iterable != null) for (const x of iterable) {
|
191
188
|
__Set_prototype_add(out, x);
|
192
189
|
}
|
193
190
|
|
@@ -17,12 +17,7 @@ export const Symbol = (description: any): Symbol => {
|
|
17
17
|
}
|
18
18
|
|
19
19
|
// 4. Return a new Symbol whose [[Description]] is descString.
|
20
|
-
|
21
|
-
descStore[len] = descString;
|
22
|
-
descStore.length = ++len;
|
23
|
-
|
24
|
-
// 1-based so always truthy as numeric value
|
25
|
-
const sym: Symbol = len;
|
20
|
+
const sym: Symbol = Porffor.fastPush(descStore, descString);
|
26
21
|
return sym;
|
27
22
|
};
|
28
23
|
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const WeakRef = function (target: any): WeakRef {
|
4
4
|
if (!new.target) throw new TypeError("Constructor WeakRef requires 'new'");
|
5
5
|
|
6
|
-
if (Porffor.rawType(target) <
|
6
|
+
if (Porffor.rawType(target) < 0x05) throw new TypeError('Target for WeakRef needs to be an object or symbol');
|
7
7
|
|
8
8
|
const out: WeakRef = Porffor.allocateBytes(9);
|
9
9
|
|
@@ -62,4 +62,20 @@ export const __ecma262_ToString = (argument: unknown): bytestring => {
|
|
62
62
|
// 11. Assert: primValue is not an Object.
|
63
63
|
// 12. Return ? ToString(primValue).
|
64
64
|
return argument.toString();
|
65
|
+
};
|
66
|
+
|
67
|
+
// 7.1.19 ToPropertyKey (argument)
|
68
|
+
// https://tc39.es/ecma262/#sec-topropertykey
|
69
|
+
export const __ecma262_ToPropertyKey = (argument: any): any => {
|
70
|
+
// 1. Let key be ? ToPrimitive(argument, string).
|
71
|
+
const key: any = argument;
|
72
|
+
|
73
|
+
// 2. If key is a Symbol, then
|
74
|
+
if (Porffor.rawType(key) == Porffor.TYPES.symbol) {
|
75
|
+
// a. Return key.
|
76
|
+
return key;
|
77
|
+
}
|
78
|
+
|
79
|
+
// 3. Return ! ToString(key).
|
80
|
+
return __ecma262_ToString(key);
|
65
81
|
};
|
@@ -40,7 +40,7 @@ export const __Map_prototype_set = (_this: Map, key: any, value: any) => {
|
|
40
40
|
Porffor.wasm.i32.store(keys, size + 1, 0, 0);
|
41
41
|
|
42
42
|
// write new key at end
|
43
|
-
|
43
|
+
Porffor.set.write(keys, size, key);
|
44
44
|
|
45
45
|
// write new value at end
|
46
46
|
vals[size] = value;
|
@@ -97,10 +97,8 @@ export const Map = function (iterable: any): Map {
|
|
97
97
|
const vals: any[] = Porffor.allocate();
|
98
98
|
Porffor.wasm.i32.store(out, vals, 0, 4);
|
99
99
|
|
100
|
-
if (
|
101
|
-
Porffor.rawType(
|
102
|
-
iterable !== null
|
103
|
-
)) for (const x of iterable) {
|
100
|
+
if (iterable != null) for (const x of iterable) {
|
101
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
104
102
|
__Map_prototype_set(out, x[0], x[1]);
|
105
103
|
}
|
106
104
|
|
@@ -112,18 +110,19 @@ export const __Map_prototype_keys = (_this: Map) => {
|
|
112
110
|
const out: any[] = Porffor.allocate();
|
113
111
|
|
114
112
|
for (const x of keys) {
|
115
|
-
|
113
|
+
Porffor.fastPush(out, x);
|
116
114
|
}
|
117
115
|
|
118
116
|
return out;
|
119
117
|
};
|
120
118
|
|
121
119
|
export const __Map_prototype_values = (_this: Map) => {
|
122
|
-
const
|
120
|
+
const size: i32 = Porffor.wasm.i32.load(Porffor.wasm.i32.load(_this, 0, 0), 0, 0);
|
121
|
+
const vals: any[] = Porffor.wasm.i32.load(_this, 0, 4);
|
123
122
|
const out: any[] = Porffor.allocate();
|
124
123
|
|
125
|
-
for (
|
126
|
-
|
124
|
+
for (let i: i32 = 0; i < size; i++) {
|
125
|
+
Porffor.fastPush(out, vals[i]);
|
127
126
|
}
|
128
127
|
|
129
128
|
return out;
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const __WeakMap_prototype_has = (_this: WeakMap, key: any) => __Map_prototype_has(_this, key);
|
4
4
|
|
5
5
|
export const __WeakMap_prototype_set = (_this: WeakMap, key: any, value: any) => {
|
6
|
-
if (Porffor.rawType(key) <
|
6
|
+
if (Porffor.rawType(key) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
|
7
7
|
|
8
8
|
__Map_prototype_set(_this, key, value);
|
9
9
|
return _this;
|
@@ -22,10 +22,8 @@ export const WeakMap = function (iterable: any): WeakMap {
|
|
22
22
|
const vals: any[] = Porffor.allocate();
|
23
23
|
Porffor.wasm.i32.store(out, vals, 0, 4);
|
24
24
|
|
25
|
-
if (
|
26
|
-
Porffor.rawType(
|
27
|
-
iterable !== null
|
28
|
-
)) for (const x of iterable) {
|
25
|
+
if (iterable != null) for (const x of iterable) {
|
26
|
+
if (Porffor.rawType(x) < 0x06) throw new TypeError('Iterator contains non-object');
|
29
27
|
__WeakMap_prototype_set(out, x[0], x[1]);
|
30
28
|
}
|
31
29
|
|
@@ -3,7 +3,7 @@ import type {} from './porffor.d.ts';
|
|
3
3
|
export const __WeakSet_prototype_has = (_this: WeakSet, value: any) => __Set_prototype_has(_this, value);
|
4
4
|
|
5
5
|
export const __WeakSet_prototype_add = (_this: WeakSet, value: any) => {
|
6
|
-
if (Porffor.rawType(value) <
|
6
|
+
if (Porffor.rawType(value) < 0x05) throw new TypeError('Value in WeakSet needs to be an object or symbol');
|
7
7
|
|
8
8
|
__Set_prototype_add(_this, value);
|
9
9
|
return _this;
|
@@ -16,10 +16,7 @@ export const WeakSet = function (iterable: any): WeakSet {
|
|
16
16
|
|
17
17
|
const out: WeakSet = __Porffor_allocate();
|
18
18
|
|
19
|
-
if (
|
20
|
-
Porffor.rawType(iterable) != Porffor.TYPES.undefined,
|
21
|
-
iterable !== null
|
22
|
-
)) for (const x of iterable) {
|
19
|
+
if (iterable != null) for (const x of iterable) {
|
23
20
|
__WeakSet_prototype_add(out, x);
|
24
21
|
}
|
25
22
|
|
package/compiler/codegen.js
CHANGED
@@ -713,7 +713,7 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
|
|
713
713
|
if (truthyMode === 'full') return [
|
714
714
|
// if value != 0 or NaN
|
715
715
|
...(!useTmp ? [] : [ [ Opcodes.local_get, tmp ] ]),
|
716
|
-
...(intIn ? [
|
716
|
+
...(intIn ? [] : [ Opcodes.i32_to ]),
|
717
717
|
|
718
718
|
[ Opcodes.i32_eqz ],
|
719
719
|
[ Opcodes.i32_eqz ],
|
@@ -820,6 +820,7 @@ const nullish = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
820
820
|
...typeSwitch(scope, type, {
|
821
821
|
[TYPES.undefined]: [
|
822
822
|
// undefined
|
823
|
+
...(!useTmp ? [ [ Opcodes.drop ] ] : []),
|
823
824
|
...number(1, intOut ? Valtype.i32 : valtypeBinary)
|
824
825
|
],
|
825
826
|
[TYPES.object]: [
|
@@ -831,6 +832,7 @@ const nullish = (scope, wasm, type, intIn = false, intOut = false) => {
|
|
831
832
|
],
|
832
833
|
default: [
|
833
834
|
// not
|
835
|
+
...(!useTmp ? [ [ Opcodes.drop ] ] : []),
|
834
836
|
...number(0, intOut ? Valtype.i32 : valtypeBinary)
|
835
837
|
]
|
836
838
|
}, intOut ? Valtype.i32 : valtypeBinary)
|
@@ -1082,6 +1084,13 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1082
1084
|
]);
|
1083
1085
|
};
|
1084
1086
|
|
1087
|
+
const knownNullish = decl => {
|
1088
|
+
if (decl.type === 'Literal' && decl.value === null) return true;
|
1089
|
+
if (decl.type === 'Identifier' && decl.name === 'undefined') return true;
|
1090
|
+
|
1091
|
+
return false;
|
1092
|
+
};
|
1093
|
+
|
1085
1094
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
1086
1095
|
if (decl.operator === 'instanceof') {
|
1087
1096
|
// very hacky basic instanceof
|
@@ -1110,8 +1119,24 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
|
|
1110
1119
|
return out;
|
1111
1120
|
}
|
1112
1121
|
|
1113
|
-
|
1122
|
+
// opt: == null|undefined -> nullish
|
1123
|
+
if (decl.operator === '==' || decl.operator === '!=') {
|
1124
|
+
if (knownNullish(decl.right)) {
|
1125
|
+
const out = nullish(scope, generate(scope, decl.left), getNodeType(scope, decl.left), false, true);
|
1126
|
+
if (decl.operator === '!=') out.push([ Opcodes.i32_eqz ]);
|
1127
|
+
out.push(Opcodes.i32_from_u);
|
1128
|
+
return out;
|
1129
|
+
}
|
1114
1130
|
|
1131
|
+
if (knownNullish(decl.left)) {
|
1132
|
+
const out = nullish(scope, generate(scope, decl.right), getNodeType(scope, decl.right), false, true);
|
1133
|
+
if (decl.operator === '!=') out.push([ Opcodes.i32_eqz ]);
|
1134
|
+
out.push(Opcodes.i32_from_u);
|
1135
|
+
return out;
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
|
1115
1140
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
1116
1141
|
|
1117
1142
|
return out;
|
@@ -1307,7 +1332,7 @@ const isExistingProtoFunc = name => {
|
|
1307
1332
|
const getType = (scope, _name) => {
|
1308
1333
|
const name = mapName(_name);
|
1309
1334
|
|
1310
|
-
|
1335
|
+
if (Object.hasOwn(builtinVars, name)) return number(builtinVars[name].type ?? TYPES.number, Valtype.i32);
|
1311
1336
|
|
1312
1337
|
if (typedInput && scope.locals[name]?.metadata?.type != null) return number(scope.locals[name].metadata.type, Valtype.i32);
|
1313
1338
|
if (Object.hasOwn(scope.locals, name)) return [ [ Opcodes.local_get, scope.locals[name + '#type'].idx ] ];
|
@@ -1315,13 +1340,13 @@ const getType = (scope, _name) => {
|
|
1315
1340
|
if (typedInput && globals[name]?.metadata?.type != null) return number(globals[name].metadata.type, Valtype.i32);
|
1316
1341
|
if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name + '#type'].idx ] ];
|
1317
1342
|
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1343
|
+
if (Object.hasOwn(builtinFuncs, name) || Object.hasOwn(importedFuncs, name) ||
|
1344
|
+
Object.hasOwn(funcIndex, name) || Object.hasOwn(internalConstrs, name))
|
1345
|
+
return number(TYPES.function, Valtype.i32);
|
1321
1346
|
|
1322
|
-
if (isExistingProtoFunc(name))
|
1347
|
+
if (isExistingProtoFunc(name)) return number(TYPES.function, Valtype.i32);
|
1323
1348
|
|
1324
|
-
return number(
|
1349
|
+
return number(TYPES.undefined, Valtype.i32);
|
1325
1350
|
};
|
1326
1351
|
|
1327
1352
|
const setType = (scope, _name, type) => {
|
@@ -1563,7 +1588,6 @@ const generateLiteral = (scope, decl, global, name) => {
|
|
1563
1588
|
return number(decl.value);
|
1564
1589
|
|
1565
1590
|
case 'boolean':
|
1566
|
-
// hack: bool as int (1/0)
|
1567
1591
|
return number(decl.value ? 1 : 0);
|
1568
1592
|
|
1569
1593
|
case 'string':
|
@@ -2839,9 +2863,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2839
2863
|
value: decl.left.property.name
|
2840
2864
|
};
|
2841
2865
|
|
2842
|
-
includeBuiltin(scope, '__Map_prototype_get');
|
2843
|
-
includeBuiltin(scope, '__Map_prototype_set');
|
2844
|
-
|
2845
2866
|
return [
|
2846
2867
|
...typeSwitch(scope, getNodeType(scope, decl.left.object), {
|
2847
2868
|
[TYPES.array]: [
|
@@ -2879,23 +2900,26 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
2879
2900
|
...getNodeType(scope, object),
|
2880
2901
|
|
2881
2902
|
...generate(scope, property),
|
2882
|
-
...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_property') ] ]),
|
2883
2903
|
...getNodeType(scope, property),
|
2904
|
+
...toPropertyKey(scope),
|
2905
|
+
...(op === '=' ? [] : [ [ Opcodes.local_set, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2906
|
+
...(op === '=' ? [] : [ [ Opcodes.local_tee, localTmp(scope, '#objset_property') ] ]),
|
2907
|
+
...(op === '=' ? [] : [ [ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ] ]),
|
2884
2908
|
|
2885
2909
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
2886
2910
|
[ Opcodes.local_get, localTmp(scope, '#objset_object') ],
|
2887
2911
|
...getNodeType(scope, object),
|
2888
2912
|
|
2889
2913
|
[ Opcodes.local_get, localTmp(scope, '#objset_property') ],
|
2890
|
-
|
2914
|
+
[ Opcodes.local_get, localTmp(scope, '#objset_property_type', Valtype.i32) ],
|
2891
2915
|
|
2892
|
-
[ Opcodes.call, ...unsignedLEB128(
|
2916
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_get').index) ],
|
2893
2917
|
...setLastType(scope)
|
2894
2918
|
], generate(scope, decl.right), getLastType(scope), getNodeType(scope, decl.right), false, name, true)),
|
2895
2919
|
[ Opcodes.local_tee, newValueTmp ],
|
2896
2920
|
...getNodeType(scope, decl),
|
2897
2921
|
|
2898
|
-
[ Opcodes.call, ...unsignedLEB128(
|
2922
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_set').index) ],
|
2899
2923
|
[ Opcodes.drop ],
|
2900
2924
|
|
2901
2925
|
...setLastType(scope, getNodeType(scope, decl)),
|
@@ -3406,16 +3430,22 @@ const generateForOf = (scope, decl) => {
|
|
3406
3430
|
// get length
|
3407
3431
|
[ Opcodes.local_get, pointer ],
|
3408
3432
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
3409
|
-
[ Opcodes.
|
3433
|
+
[ Opcodes.local_tee, length ],
|
3434
|
+
|
3435
|
+
[ Opcodes.if, Blocktype.void ]
|
3410
3436
|
);
|
3411
3437
|
|
3438
|
+
depth.push('if');
|
3412
3439
|
depth.push('forof');
|
3440
|
+
depth.push('block');
|
3441
|
+
depth.push('block');
|
3413
3442
|
|
3414
3443
|
// setup local for left
|
3415
3444
|
generate(scope, decl.left);
|
3416
3445
|
|
3417
3446
|
let leftName = decl.left.declarations?.[0]?.id?.name;
|
3418
3447
|
if (!leftName && decl.left.name) {
|
3448
|
+
// todo: should be sloppy mode only
|
3419
3449
|
leftName = decl.left.name;
|
3420
3450
|
|
3421
3451
|
generateVar(scope, { kind: 'var', _bare: true, declarations: [ { id: { name: leftName } } ] })
|
@@ -3426,9 +3456,6 @@ const generateForOf = (scope, decl) => {
|
|
3426
3456
|
const [ local, isGlobal ] = lookupName(scope, leftName);
|
3427
3457
|
if (!local) return todo(scope, 'for of failed to get left local (probably destructure)');
|
3428
3458
|
|
3429
|
-
depth.push('block');
|
3430
|
-
depth.push('block');
|
3431
|
-
|
3432
3459
|
// // todo: we should only do this for strings but we don't know at compile-time :(
|
3433
3460
|
// hack: this is naughty and will break things!
|
3434
3461
|
let newOut = number(0, Valtype.i32), newPointer = number(0, Valtype.i32);
|
@@ -3571,12 +3598,6 @@ const generateForOf = (scope, decl) => {
|
|
3571
3598
|
...generate(scope, decl.body),
|
3572
3599
|
[ Opcodes.end ],
|
3573
3600
|
|
3574
|
-
// increment iter pointer
|
3575
|
-
// [ Opcodes.local_get, pointer ],
|
3576
|
-
// ...number(1, Valtype.i32),
|
3577
|
-
// [ Opcodes.i32_add ],
|
3578
|
-
// [ Opcodes.local_set, pointer ],
|
3579
|
-
|
3580
3601
|
// increment counter by 1
|
3581
3602
|
[ Opcodes.local_get, counter ],
|
3582
3603
|
...number(1, Valtype.i32),
|
@@ -3734,6 +3755,8 @@ const generateForOf = (scope, decl) => {
|
|
3734
3755
|
default: internalThrow(scope, 'TypeError', `Tried for..of on non-iterable type`)
|
3735
3756
|
}, Blocktype.void));
|
3736
3757
|
|
3758
|
+
out.push([ Opcodes.end ]); // end if
|
3759
|
+
|
3737
3760
|
depth.pop();
|
3738
3761
|
depth.pop();
|
3739
3762
|
depth.pop();
|
@@ -4310,9 +4333,12 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
|
|
4310
4333
|
return makeArray(scope, decl, global, name, initEmpty, valtype, false, true)[0];
|
4311
4334
|
};
|
4312
4335
|
|
4336
|
+
const toPropertyKey = scope => Prefs.fastObject ? [] : [
|
4337
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__ecma262_ToPropertyKey').index) ]
|
4338
|
+
];
|
4339
|
+
|
4313
4340
|
const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
4314
4341
|
includeBuiltin(scope, 'Map');
|
4315
|
-
includeBuiltin(scope, '__Map_prototype_set');
|
4316
4342
|
|
4317
4343
|
// todo: optimize const objects
|
4318
4344
|
const tmp = localTmp(scope, `#objectexpr${randId()}`);
|
@@ -4332,7 +4358,8 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
4332
4358
|
const { method, shorthand, computed, kind, key, value } = x;
|
4333
4359
|
if (kind !== 'init') return todo(scope, 'complex objects are not supported yet', true);
|
4334
4360
|
|
4335
|
-
|
4361
|
+
let k = key;
|
4362
|
+
if (!computed && key.type !== 'Literal') k = {
|
4336
4363
|
type: 'Literal',
|
4337
4364
|
value: key.name
|
4338
4365
|
};
|
@@ -4343,11 +4370,12 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
4343
4370
|
|
4344
4371
|
...generate(scope, k),
|
4345
4372
|
...getNodeType(scope, k),
|
4373
|
+
...toPropertyKey(scope),
|
4346
4374
|
|
4347
4375
|
...generate(scope, value),
|
4348
4376
|
...getNodeType(scope, value),
|
4349
4377
|
|
4350
|
-
[ Opcodes.call, ...unsignedLEB128(
|
4378
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_set').index) ],
|
4351
4379
|
|
4352
4380
|
[ Opcodes.drop ],
|
4353
4381
|
[ Opcodes.drop ]
|
@@ -4503,8 +4531,6 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4503
4531
|
}, _global, _name, true, 'i16', true);
|
4504
4532
|
}
|
4505
4533
|
|
4506
|
-
includeBuiltin(scope, '__Map_prototype_get');
|
4507
|
-
|
4508
4534
|
const out = typeSwitch(scope, getNodeType(scope, object), {
|
4509
4535
|
[TYPES.array]: [
|
4510
4536
|
...loadArray(scope, objectWasm, propertyWasm),
|
@@ -4580,8 +4606,9 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
4580
4606
|
|
4581
4607
|
...propertyWasm,
|
4582
4608
|
...getNodeType(scope, property),
|
4609
|
+
...toPropertyKey(scope),
|
4583
4610
|
|
4584
|
-
[ Opcodes.call, ...unsignedLEB128(
|
4611
|
+
[ Opcodes.call, ...unsignedLEB128(includeBuiltin(scope, '__Map_prototype_get').index) ],
|
4585
4612
|
...setLastType(scope)
|
4586
4613
|
],
|
4587
4614
|
|