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.
@@ -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
- for (let i: i32 = 0; i < len; i++) {
73
- out[i] = (arg as object)[i];
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 += `export const ${name} = function (message: any): ${name} {
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
 
@@ -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 === key) return true;
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] === key) return vals[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] === key) {
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] === key) {
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 (const x of sources) {
209
- // todo: switch to for..in once it supports non-pure-object
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
- const len: i32 = keys.length;
214
- for (let i: i32 = 0; i < len; i++) {
215
- target[keys[i]] = vals[i];
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
+ };
@@ -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] === value) return true;
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] === value) return _this;
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] === value) {
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;