porffor 0.61.4 → 0.61.6
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/array.ts +12 -4
- package/compiler/builtins/error.js +11 -1
- package/compiler/builtins/map.ts +4 -4
- package/compiler/builtins/number.ts +12 -1
- package/compiler/builtins/object.ts +68 -14
- package/compiler/builtins/promise.ts +3 -4
- package/compiler/builtins/set.ts +3 -3
- package/compiler/builtins/stringtonumber.ts +46 -1
- package/compiler/builtins_precompiled.js +813 -807
- package/compiler/codegen.js +276 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/runtime/index.js +1 -1
|
@@ -35,7 +35,7 @@ export const Array = function (...args: any[]): any[] {
|
|
|
35
35
|
export const __Array_isArray = (x: unknown): boolean =>
|
|
36
36
|
Porffor.type(x) == Porffor.TYPES.array;
|
|
37
37
|
|
|
38
|
-
export const __Array_from = (arg: any, mapFn: any): any[] => {
|
|
38
|
+
export const __Array_from = (arg: any, mapFn: any, thisArg: any = undefined): any[] => {
|
|
39
39
|
if (arg == null) throw new TypeError('Argument cannot be nullish');
|
|
40
40
|
|
|
41
41
|
let out: any[] = Porffor.malloc();
|
|
@@ -51,7 +51,7 @@ export const __Array_from = (arg: any, mapFn: any): any[] => {
|
|
|
51
51
|
if (Porffor.type(mapFn) != Porffor.TYPES.function) throw new TypeError('Called Array.from with a non-function mapFn');
|
|
52
52
|
|
|
53
53
|
for (const x of arg) {
|
|
54
|
-
out[i] = mapFn(x, i);
|
|
54
|
+
out[i] = mapFn.call(thisArg, x, i);
|
|
55
55
|
i++;
|
|
56
56
|
}
|
|
57
57
|
} else {
|
|
@@ -69,8 +69,16 @@ export const __Array_from = (arg: any, mapFn: any): any[] => {
|
|
|
69
69
|
if (len > 4294967295) throw new RangeError('Invalid array length');
|
|
70
70
|
if (len < 0) len = 0;
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
if (Porffor.type(mapFn) != Porffor.TYPES.undefined) {
|
|
73
|
+
if (Porffor.type(mapFn) != Porffor.TYPES.function) throw new TypeError('Called Array.from with a non-function mapFn');
|
|
74
|
+
|
|
75
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
76
|
+
out[i] = mapFn.call(thisArg, (arg as object)[i], i);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
80
|
+
out[i] = (arg as object)[i];
|
|
81
|
+
}
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
out.length = len;
|
|
@@ -4,7 +4,10 @@ export default () => {
|
|
|
4
4
|
const errors = [];
|
|
5
5
|
const error = name => {
|
|
6
6
|
errors.push(name);
|
|
7
|
-
out += `
|
|
7
|
+
out += `
|
|
8
|
+
export const ${name} = function (
|
|
9
|
+
${name === 'AggregateError' ? 'errors: any,' : ''} message: any
|
|
10
|
+
): ${name} {
|
|
8
11
|
if (message === undefined) message = '';
|
|
9
12
|
else message = ecma262.ToString(message);
|
|
10
13
|
|
|
@@ -12,6 +15,13 @@ export default () => {
|
|
|
12
15
|
Porffor.wasm.i32.store(obj, message, 0, 0);
|
|
13
16
|
Porffor.wasm.i32.store8(obj, Porffor.type(message), 0, 4);
|
|
14
17
|
|
|
18
|
+
// https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-aggregate-error
|
|
19
|
+
${name === 'AggregateError' ? `
|
|
20
|
+
const errorsList: any[] = __Array_from(errors);
|
|
21
|
+
// TODO: should not be enumerable
|
|
22
|
+
obj.errors = errorsList;
|
|
23
|
+
` : ''}
|
|
24
|
+
|
|
15
25
|
return obj;
|
|
16
26
|
};
|
|
17
27
|
|
package/compiler/builtins/map.ts
CHANGED
|
@@ -7,7 +7,7 @@ export const __Map_prototype_size$get = (_this: Map) => {
|
|
|
7
7
|
export const __Map_prototype_has = (_this: Map, key: any) => {
|
|
8
8
|
const keys: any[] = Porffor.wasm.i32.load(_this, 0, 0);
|
|
9
9
|
for (const x of keys) {
|
|
10
|
-
if (x
|
|
10
|
+
if (__ecma262_SameValueZero(x, key)) return true;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
return false;
|
|
@@ -19,7 +19,7 @@ export const __Map_prototype_get = (_this: Map, key: any) => {
|
|
|
19
19
|
|
|
20
20
|
const size: i32 = Porffor.wasm.i32.load(keys, 0, 0);
|
|
21
21
|
for (let i: i32 = 0; i < size; i++) {
|
|
22
|
-
if (keys[i]
|
|
22
|
+
if (__ecma262_SameValueZero(keys[i], key)) return vals[i];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return undefined;
|
|
@@ -31,7 +31,7 @@ export const __Map_prototype_set = (_this: Map, key: any, value: any) => {
|
|
|
31
31
|
|
|
32
32
|
const size: i32 = keys.length;
|
|
33
33
|
for (let i: i32 = 0; i < size; i++) {
|
|
34
|
-
if (keys[i]
|
|
34
|
+
if (__ecma262_SameValueZero(keys[i], key)) {
|
|
35
35
|
vals[i] = value;
|
|
36
36
|
return _this;
|
|
37
37
|
}
|
|
@@ -54,7 +54,7 @@ export const __Map_prototype_delete = (_this: Map, key: any) => {
|
|
|
54
54
|
|
|
55
55
|
const size: i32 = keys.length;
|
|
56
56
|
for (let i: i32 = 0; i < size; i++) {
|
|
57
|
-
if (keys[i]
|
|
57
|
+
if (__ecma262_SameValueZero(keys[i], key)) {
|
|
58
58
|
Porffor.array.fastRemove(keys, i, size);
|
|
59
59
|
Porffor.array.fastRemove(vals, i, size);
|
|
60
60
|
return true;
|
|
@@ -687,7 +687,6 @@ export const parseInt = (input: any, radix: any): f64 => {
|
|
|
687
687
|
export const __Number_parseInt = (input: any, radix: any): f64 => parseInt(input, radix);
|
|
688
688
|
|
|
689
689
|
export const parseFloat = (input: any): f64 => {
|
|
690
|
-
// todo: handle exponents
|
|
691
690
|
input = ecma262.ToString(input).trim();
|
|
692
691
|
|
|
693
692
|
let n: f64 = NaN;
|
|
@@ -740,6 +739,18 @@ export const parseFloat = (input: any): f64 => {
|
|
|
740
739
|
} else if (chr == 46) { // .
|
|
741
740
|
if (dec) break;
|
|
742
741
|
dec = 1;
|
|
742
|
+
} else if (chr == 101 || chr == 69) { // e or E
|
|
743
|
+
if (Number.isNaN(n)) break; // No mantissa before exponent
|
|
744
|
+
|
|
745
|
+
const exp: f64 = __Porffor_parseExp(input, i, len, false);
|
|
746
|
+
if (!Number.isNaN(exp)) {
|
|
747
|
+
if (exp < 0) {
|
|
748
|
+
n = n / (10 ** -exp);
|
|
749
|
+
} else {
|
|
750
|
+
n = n * (10 ** exp);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
break;
|
|
743
754
|
} else {
|
|
744
755
|
break;
|
|
745
756
|
}
|
|
@@ -28,9 +28,12 @@ export const __Object_keys = (obj: any): any[] => {
|
|
|
28
28
|
for (; ptr < endPtr; ptr += 18) {
|
|
29
29
|
if (!Porffor.object.isEnumerable(ptr)) continue;
|
|
30
30
|
|
|
31
|
+
// if key is a symbol skip it
|
|
32
|
+
const rawKey: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
|
|
33
|
+
if ((rawKey >>> 30) == 3) continue;
|
|
34
|
+
|
|
31
35
|
let key: any;
|
|
32
36
|
Porffor.wasm`local raw i32
|
|
33
|
-
local msb i32
|
|
34
37
|
local.get ${ptr}
|
|
35
38
|
i32.to_u
|
|
36
39
|
i32.load 0 4
|
|
@@ -39,14 +42,8 @@ local.set raw
|
|
|
39
42
|
local.get raw
|
|
40
43
|
i32.const 30
|
|
41
44
|
i32.shr_u
|
|
42
|
-
local.tee msb
|
|
43
45
|
if 127
|
|
44
|
-
i32.const 5 ;; symbol
|
|
45
46
|
i32.const 67 ;; string
|
|
46
|
-
local.get msb
|
|
47
|
-
i32.const 3
|
|
48
|
-
i32.eq
|
|
49
|
-
select
|
|
50
47
|
local.set ${key+1}
|
|
51
48
|
|
|
52
49
|
local.get raw
|
|
@@ -84,6 +81,10 @@ export const __Object_values = (obj: any): any[] => {
|
|
|
84
81
|
const tail: i32 = Porffor.wasm.i32.load16_u(ptr, 0, 16);
|
|
85
82
|
if (!(tail & 0b0100)) continue; // not enumerable
|
|
86
83
|
|
|
84
|
+
// if key is a symbol skip it
|
|
85
|
+
const rawKey: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
|
|
86
|
+
if ((rawKey >>> 30) == 3) continue;
|
|
87
|
+
|
|
87
88
|
if (tail & 0b0001) {
|
|
88
89
|
// accessor
|
|
89
90
|
const get: Function = Porffor.object.accessorGet(ptr);
|
|
@@ -205,14 +206,67 @@ export const __Porffor_object_instanceof = (obj: any, constr: any, checkProto: a
|
|
|
205
206
|
export const __Object_assign = (target: any, ...sources: any[]): any => {
|
|
206
207
|
if (target == null) throw new TypeError('Argument is nullish, expected object');
|
|
207
208
|
|
|
208
|
-
for (
|
|
209
|
-
|
|
210
|
-
const keys: any[] = __Object_keys(x);
|
|
211
|
-
const vals: any[] = __Object_values(x);
|
|
209
|
+
for (let src of sources) {
|
|
210
|
+
if (src == null) continue;
|
|
212
211
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
|
|
213
|
+
src = __Porffor_object_underlying(src);
|
|
214
|
+
if (Porffor.type(src) == Porffor.TYPES.object) {
|
|
215
|
+
let ptr: i32 = Porffor.wasm`local.get ${src}` + 8;
|
|
216
|
+
const endPtr: i32 = ptr + Porffor.wasm.i32.load16_u(src, 0, 0) * 18;
|
|
217
|
+
|
|
218
|
+
for (; ptr < endPtr; ptr += 18) {
|
|
219
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(ptr, 0, 16);
|
|
220
|
+
if (!(tail & 0b0100)) continue; // not enumerable
|
|
221
|
+
|
|
222
|
+
let key: any;
|
|
223
|
+
Porffor.wasm`local raw i32
|
|
224
|
+
local msb i32
|
|
225
|
+
local.get ${ptr}
|
|
226
|
+
i32.to_u
|
|
227
|
+
i32.load 0 4
|
|
228
|
+
local.set raw
|
|
229
|
+
|
|
230
|
+
local.get raw
|
|
231
|
+
i32.const 30
|
|
232
|
+
i32.shr_u
|
|
233
|
+
local.tee msb
|
|
234
|
+
if 127
|
|
235
|
+
i32.const 5 ;; symbol
|
|
236
|
+
i32.const 67 ;; string
|
|
237
|
+
local.get msb
|
|
238
|
+
i32.const 3
|
|
239
|
+
i32.eq
|
|
240
|
+
select
|
|
241
|
+
local.set ${key+1}
|
|
242
|
+
|
|
243
|
+
local.get raw
|
|
244
|
+
i32.const 1073741823
|
|
245
|
+
i32.and ;; unset 2 MSBs
|
|
246
|
+
else
|
|
247
|
+
i32.const 195
|
|
248
|
+
local.set ${key+1}
|
|
249
|
+
|
|
250
|
+
local.get raw
|
|
251
|
+
end
|
|
252
|
+
i32.from_u
|
|
253
|
+
local.set ${key}`;
|
|
254
|
+
|
|
255
|
+
let value: any;
|
|
256
|
+
if (tail & 0b0001) {
|
|
257
|
+
// accessor - call getter
|
|
258
|
+
const get: Function = Porffor.object.accessorGet(ptr);
|
|
259
|
+
if (Porffor.wasm`local.get ${get}` == 0) {
|
|
260
|
+
value = undefined;
|
|
261
|
+
} else {
|
|
262
|
+
value = get.call(src);
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
value = Porffor.object.readValue(ptr);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
target[key] = value;
|
|
269
|
+
}
|
|
216
270
|
}
|
|
217
271
|
}
|
|
218
272
|
|
|
@@ -414,7 +414,6 @@ export const __Promise_allSettled = (promises: any): Promise => {
|
|
|
414
414
|
};
|
|
415
415
|
|
|
416
416
|
export const __Promise_any = (promises: any): Promise => {
|
|
417
|
-
// todo: use new AggregateError(_allOut, msg) instead of new AggregateError(msg) when supported
|
|
418
417
|
_allPromises = promises;
|
|
419
418
|
|
|
420
419
|
return new Promise((res, rej) => {
|
|
@@ -430,7 +429,7 @@ export const __Promise_any = (promises: any): Promise => {
|
|
|
430
429
|
x.then(r => {
|
|
431
430
|
_allRes(r);
|
|
432
431
|
}, r => {
|
|
433
|
-
if (Porffor.array.fastPush(_allOut, r) == _allLen) _allRes(new AggregateError());
|
|
432
|
+
if (Porffor.array.fastPush(_allOut, r) == _allLen) _allRes(new AggregateError(_allOut));
|
|
434
433
|
});
|
|
435
434
|
} else {
|
|
436
435
|
return _allRes(x);
|
|
@@ -439,7 +438,7 @@ export const __Promise_any = (promises: any): Promise => {
|
|
|
439
438
|
|
|
440
439
|
if (_allLen == 0) {
|
|
441
440
|
// empty iterable: immediately reject
|
|
442
|
-
_allRej(new AggregateError());
|
|
441
|
+
_allRej(new AggregateError(_allOut));
|
|
443
442
|
}
|
|
444
443
|
});
|
|
445
444
|
};
|
|
@@ -487,4 +486,4 @@ export const __Porffor_promise_await = (value: any): any => {
|
|
|
487
486
|
|
|
488
487
|
// rejected
|
|
489
488
|
throw result;
|
|
490
|
-
};
|
|
489
|
+
};
|
package/compiler/builtins/set.ts
CHANGED
|
@@ -24,7 +24,7 @@ export const __Set_prototype_has = (_this: Set, value: any) => {
|
|
|
24
24
|
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
|
25
25
|
|
|
26
26
|
for (let i: number = 0; i < size; i++) {
|
|
27
|
-
if ((_this as any[])[i]
|
|
27
|
+
if (__ecma262_SameValueZero((_this as any[])[i], value)) return true;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
return false;
|
|
@@ -35,7 +35,7 @@ export const __Set_prototype_add = (_this: Set, value: any) => {
|
|
|
35
35
|
|
|
36
36
|
// check if already in set
|
|
37
37
|
for (let i: number = 0; i < size; i++) {
|
|
38
|
-
if ((_this as any[])[i]
|
|
38
|
+
if (__ecma262_SameValueZero((_this as any[])[i], value)) return _this;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// not, add it
|
|
@@ -52,7 +52,7 @@ export const __Set_prototype_delete = (_this: Set, value: any) => {
|
|
|
52
52
|
// check if already in set
|
|
53
53
|
const size: number = Porffor.wasm.i32.load(_this, 0, 0);
|
|
54
54
|
for (let i: number = 0; i < size; i++) {
|
|
55
|
-
if ((_this as any[])[i]
|
|
55
|
+
if (__ecma262_SameValueZero((_this as any[])[i], value)) {
|
|
56
56
|
// found, delete
|
|
57
57
|
Porffor.array.fastRemove(_this, i, size);
|
|
58
58
|
return true;
|
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
// Parse exponent part after 'e' or 'E'
|
|
2
|
+
// Returns the exponent value (can be negative), or NaN on failure
|
|
3
|
+
// strict: if true, returns NaN on any non-digit char; if false, stops at non-digit
|
|
4
|
+
export const __Porffor_parseExp = (str: unknown, i: i32, len: i32, strict: boolean): f64 => {
|
|
5
|
+
let expNeg: boolean = false;
|
|
6
|
+
let exp: i32 = 0;
|
|
7
|
+
let hasDigit: boolean = false;
|
|
8
|
+
|
|
9
|
+
// Check for +/- after E
|
|
10
|
+
if (i < len) {
|
|
11
|
+
const sign: i32 = str.charCodeAt(i);
|
|
12
|
+
if (sign == 43) { // +
|
|
13
|
+
i++;
|
|
14
|
+
} else if (sign == 45) { // -
|
|
15
|
+
expNeg = true;
|
|
16
|
+
i++;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Must have at least one digit
|
|
21
|
+
if (strict && i >= len) return NaN;
|
|
22
|
+
|
|
23
|
+
// Parse exponent digits
|
|
24
|
+
while (i < len) {
|
|
25
|
+
const chr: i32 = str.charCodeAt(i);
|
|
26
|
+
if (chr >= 48 && chr <= 57) { // 0-9
|
|
27
|
+
exp = (exp * 10) + chr - 48;
|
|
28
|
+
hasDigit = true;
|
|
29
|
+
i++;
|
|
30
|
+
} else {
|
|
31
|
+
if (strict) return NaN;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!hasDigit) return NaN;
|
|
37
|
+
|
|
38
|
+
if (expNeg) return -exp;
|
|
39
|
+
return exp;
|
|
40
|
+
};
|
|
41
|
+
|
|
1
42
|
export const __Porffor_stn_int = (str: unknown, radix: i32, i: i32): f64 => {
|
|
2
43
|
let nMax: i32 = 58;
|
|
3
44
|
if (radix < 10) nMax = 48 + radix;
|
|
@@ -46,6 +87,11 @@ export const __Porffor_stn_float = (str: unknown, i: i32): f64 => {
|
|
|
46
87
|
} else if (chr == 46) { // .
|
|
47
88
|
if (dec) return NaN;
|
|
48
89
|
dec = 1;
|
|
90
|
+
} else if (chr == 69 || chr == 101) { // E or e
|
|
91
|
+
const exp: f64 = __Porffor_parseExp(str, i, len, true);
|
|
92
|
+
if (Number.isNaN(exp)) return NaN;
|
|
93
|
+
if (exp < 0) return n / (10 ** -exp);
|
|
94
|
+
return n * (10 ** exp);
|
|
49
95
|
} else {
|
|
50
96
|
return NaN;
|
|
51
97
|
}
|
|
@@ -116,7 +162,6 @@ export const __ecma262_StringToNumber = (str: unknown): number => {
|
|
|
116
162
|
return NaN;
|
|
117
163
|
}
|
|
118
164
|
|
|
119
|
-
// todo: handle exponents
|
|
120
165
|
const n: f64 = __Porffor_stn_float(str, i);
|
|
121
166
|
|
|
122
167
|
if (negative) return -n;
|