porffor 0.17.0-f43ba190c โ†’ 0.18.3

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/README.md CHANGED
@@ -148,41 +148,42 @@ These include some early (stage 1/0) and/or dead (last commit years ago) proposa
148
148
  - Array constructor (`Array(5)`, `new Array(1, 2, 3)`)
149
149
  - Labelled statements (`foo: while (...)`)
150
150
  - `do...while` loops
151
+ - Optional parameters (`(foo = 'bar') => { ... }`)
151
152
 
152
153
  ### Built-ins
153
154
 
154
155
  - `NaN` and `Infinity`
155
156
  - `isNaN()` and `isFinite()`
156
157
  - Most of `Number` (`MAX_VALUE`, `MIN_VALUE`, `MAX_SAFE_INTEGER`, `MIN_SAFE_INTEGER`, `POSITIVE_INFINITY`, `NEGATIVE_INFINITY`, `EPSILON`, `NaN`, `isNaN`, `isFinite`, `isInteger`, `isSafeInteger`)
157
- - Some `Math` funcs (`sqrt`, `abs`, `floor`, `sign`, `round`, `trunc`, `clz32`, `fround`, `random`)
158
+ - Most `Math` funcs (`sqrt`, `abs`, `floor`, `sign`, `round`, `trunc`, `clz32`, `fround`, `random`, `exp`, `log`, `log2`, `log10`, `pow`, `expm1`, `log1p`, `sqrt`, `cbrt`, `hypot`, `sin`, `cos`, `tan`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `asin`, `acos`, `atan`, `atan2`)
158
159
  - Basic `globalThis` support
159
160
  - Basic `Boolean` and `Number`
160
161
  - Basic `eval` for literals
161
162
  - `Math.random()` using self-made xorshift128+ PRNG
162
163
  - Some of `performance` (`now()`, `timeOrigin`)
163
- - Some of `Array.prototype` (`at`, `push`, `pop`, `shift`, `fill`, `slice`, `indexOf`, `lastIndexOf`, `includes`, `with`, `reverse`, `toReversed`)
164
- - Some of `Array` (`of`, `isArray`)
165
- - Most of `String.prototype` (`at`, `charAt`, `charCodeAt`, `toUpperCase`, `toLowerCase`, `startsWith`, `endsWith`, `indexOf`, `lastIndexOf`, `includes`, `padStart`, `padEnd`, `substring`, `substr`, `slice`, `trimStart`, `trimEnd`, `trim`, `toString`, `big`, `blink`, `bold`, `fixed`, `italics`, `small`, `strike`, `sub`, `sup`, `trimLeft`, `trimRight`, )
164
+ - Most of `Array.prototype` (`at`, `push`, `pop`, `shift`, `fill`, `slice`, `indexOf`, `lastIndexOf`, `includes`, `with`, `reverse`, `toReversed`, `forEach`, `filter`, `map`, `find`, `findLast`, `findIndex`, `findLastIndex`, `every`, `some`, `reduce`, `reduceRight`, `join`, `toString`)
165
+ - Most of `Array` (`of`, `isArray`)
166
+ - Most of `String.prototype` (`at`, `charAt`, `charCodeAt`, `toUpperCase`, `toLowerCase`, `startsWith`, `endsWith`, `indexOf`, `lastIndexOf`, `includes`, `padStart`, `padEnd`, `substring`, `substr`, `slice`, `trimStart`, `trimEnd`, `trim`, `toString`, `big`, `blink`, `bold`, `fixed`, `italics`, `small`, `strike`, `sub`, `sup`, `trimLeft`, `trimRight`, `trim`)
166
167
  - Some of `crypto` (`randomUUID`)
167
168
  - `escape`
168
169
  - `btoa`
169
170
  - Most of `Number.prototype` (`toString`, `toFixed`, `toExponential`)
170
171
  - `parseInt`
171
172
  - Spec-compliant `Date`
173
+ - WIP typed arrays (`Uint8Array`, `Int32Array`, etc)
172
174
 
173
175
  ### Custom
174
176
 
175
177
  - Supports i32, i64, and f64 for valtypes
176
- - Start of a SIMD api (docs needed)
177
178
  - Intrinsic functions (see below)
178
179
  - Inlining wasm via ``asm`...``\` "macro"
179
180
 
180
181
  ## Versioning
181
- Porffor uses a unique versioning system, here's an example: `0.14.0-15cb49f07`. Let's break it down:
182
+ Porffor uses a unique versioning system, here's an example: `0.18.2+2aa3f0589`. Let's break it down:
182
183
  1. `0` - major, always `0` as Porffor is not ready yet
183
- 2. `14` - minor, total Test262 pass percentage (floored to nearest int)
184
- 3. `0` - micro, always `0` as unused
185
- 4. `15cb49f07` - commit hash
184
+ 2. `18` - minor, total Test262 pass percentage (floored to nearest int)
185
+ 3. `2` - micro, build number for that minor (incremented each publish/git push)
186
+ 4. `2aa3f0589` - commit hash
186
187
 
187
188
  ## Performance
188
189
  *For the features it supports most of the time*, Porffor is *blazingly fast* compared to most interpreters and common engines running without JIT. For those with JIT, it is usually slower by default, but can catch up with compiler arguments and typed input, even more so when compiling to native binaries.
package/bf ADDED
Binary file
package/compiler/2c.js CHANGED
@@ -171,9 +171,6 @@ const removeBrackets = str => {
171
171
  };
172
172
 
173
173
  export default ({ funcs, globals, tags, data, exceptions, pages }) => {
174
- // fix declaring order for c
175
- funcs.reverse();
176
-
177
174
  const invOperatorOpcode = Object.values(operatorOpcode).reduce((acc, x) => {
178
175
  for (const k in x) {
179
176
  acc[x[k]] = k;
@@ -201,7 +198,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
201
198
 
202
199
  includes.set('stdint.h', true);
203
200
 
204
- let out = ``;
201
+ globalThis.out = ``;
205
202
 
206
203
  for (const x in globals) {
207
204
  const g = globals[x];
@@ -231,15 +228,12 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
231
228
 
232
229
  if (out) out += '\n';
233
230
 
234
- let depth = 1;
235
- let brDepth = 0;
236
- const line = (str, semi = true) => out += `${' '.repeat((depth + brDepth) * 2)}${str}${semi ? ';' : ''}\n`;
231
+ const line = (str, semi = true) => out += `${str}${semi ? ';' : ''}\n`;
237
232
  const lines = lines => {
238
233
  for (const x of lines) {
239
- out += `${' '.repeat((depth + brDepth) * 2)}${x}\n`;
234
+ out += x + '\n';
240
235
  }
241
236
  };
242
-
243
237
  const platformSpecific = (win, unix, add = true) => {
244
238
  let tmp = '';
245
239
 
@@ -268,11 +262,46 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
268
262
 
269
263
  let brId = 0;
270
264
 
271
- for (const f of funcs) {
272
- depth = 1;
273
- brDepth = 0;
265
+ const cified = new Set();
266
+ const cify = f => {
267
+ let out = '';
268
+
269
+ let depth = 1;
270
+ let brDepth = 0;
271
+ const line = (str, semi = true) => out += `${' '.repeat((depth + brDepth) * 2)}${str}${semi ? ';' : ''}\n`;
272
+ const lines = lines => {
273
+ for (const x of lines) {
274
+ out += `${' '.repeat((depth + brDepth) * 2)}${x}\n`;
275
+ }
276
+ };
277
+ const platformSpecific = (win, unix, add = true) => {
278
+ let tmp = '';
279
+
280
+ if (win) {
281
+ if (add) out += '#ifdef _WIN32\n';
282
+ else tmp += '#ifdef _WIN32\n';
283
+
284
+ if (add) lines(win.split('\n'));
285
+ else tmp += win + (win.endsWith('\n') ? '' : '\n');
286
+ }
287
+
288
+ if (unix) {
289
+ if (add) out += (win ? '#else' : '#ifndef _WIN32') + '\n';
290
+ else tmp += (win ? '#else' : '#ifndef _WIN32') + '\n';
291
+
292
+ if (add) lines(unix.split('\n'));
293
+ else tmp += unix + (unix.endsWith('\n') ? '' : '\n');
294
+ }
295
+
296
+ if (win || unix)
297
+ if (add) out += '#endif\n';
298
+ else tmp += '#endif\n';
299
+
300
+ return tmp;
301
+ };
274
302
 
275
303
  let retTmpId = 0;
304
+ let tmpId = 0;
276
305
 
277
306
  const invLocals = inv(f.locals, x => x.idx);
278
307
 
@@ -598,6 +627,11 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
598
627
  break;
599
628
  }
600
629
 
630
+ if (!cified.has(func.name) && func.name !== f.name) {
631
+ cify(func);
632
+ cified.add(func.name);
633
+ }
634
+
601
635
  let args = [];
602
636
  for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
603
637
 
@@ -663,6 +697,53 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
663
697
  break;
664
698
  }
665
699
 
700
+ case Opcodes.f64_abs: {
701
+ break;
702
+ }
703
+ case Opcodes.f64_neg: {
704
+ break;
705
+ }
706
+
707
+ case Opcodes.f64_ceil: {
708
+ break;
709
+ }
710
+ case Opcodes.f64_floor: {
711
+ break;
712
+ }
713
+ case Opcodes.f64_trunc: {
714
+ break;
715
+ }
716
+ case Opcodes.f64_nearest: {
717
+ break;
718
+ }
719
+
720
+ case Opcodes.f64_sqrt: {
721
+ break;
722
+ }
723
+ case Opcodes.f64_min: {
724
+ const b = vals.pop();
725
+ const a = vals.pop();
726
+
727
+ const id = tmpId++;
728
+ line(`const f64 _tmp${id}a = ${a}`);
729
+ line(`const f64 _tmp${id}b = ${b}`);
730
+ vals.push(`(_tmp${id}a > _tmp${id}b ? _tmp${id}b : _tmp${id}a)`);
731
+ break;
732
+ }
733
+ case Opcodes.f64_max: {
734
+ const b = vals.pop();
735
+ const a = vals.pop();
736
+
737
+ const id = tmpId++;
738
+ line(`const f64 _tmp${id}a = ${a}`);
739
+ line(`const f64 _tmp${id}b = ${b}`);
740
+ vals.push(`(_tmp${id}a > _tmp${id}b ? _tmp${id}a : _tmp${id}b)`);
741
+ break;
742
+ }
743
+ case Opcodes.f64_copysign: {
744
+ break;
745
+ }
746
+
666
747
  default:
667
748
  if (CMemFuncs[i[0]]) {
668
749
  const name = invOpcodes[i[0]];
@@ -698,12 +779,14 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
698
779
  }
699
780
 
700
781
  out += '}\n\n';
701
- }
702
782
 
703
- depth = 0;
783
+ globalThis.out = globalThis.out + out;
784
+ };
785
+
786
+ cify(funcs.find(x => x.name === 'main'));
704
787
 
705
788
  const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
706
789
  out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
707
790
 
708
- return out.trim();
791
+ return `// generated by porffor ${globalThis.version ?? '0.17.0'}\n` + out.trim();
709
792
  };
@@ -82,7 +82,17 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
82
82
  params.push(valtypeBinary, Valtype.i32);
83
83
  }
84
84
 
85
- const returns = [ valtypeBinary, Valtype.i32 ];
85
+ if (inst.at(-1) === 'constr') {
86
+ inst.pop();
87
+ params.unshift(Valtype.i32);
88
+ }
89
+
90
+ let returns = [ valtypeBinary, Valtype.i32 ];
91
+ if (inst.at(-1) === 'no_type_return') {
92
+ inst.pop();
93
+ returns = [ valtypeBinary ];
94
+ }
95
+
86
96
  inst[1] = getType(params, returns);
87
97
  }
88
98
  }
@@ -116,16 +126,21 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
116
126
  ] ])
117
127
  );
118
128
 
119
- if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
120
- // generate func argc lut data
129
+ if (pages.has('func lut') && !data.addedFuncArgcLut) {
130
+ // generate func lut data
121
131
  const bytes = [];
122
132
  for (let i = 0; i < funcs.length; i++) {
123
133
  const argc = Math.floor(funcs[i].params.length / 2);
124
134
  bytes.push(argc % 256, (argc / 256 | 0) % 256);
135
+
136
+ let flags = 0b00000000; // 8 flag bits
137
+ if (funcs[i].returnType != null) flags |= 0b1;
138
+ if (funcs[i].constr) flags |= 0b10;
139
+ bytes.push(flags);
125
140
  }
126
141
 
127
142
  data.push({
128
- offset: pages.get('func argc lut').ind * pageSize,
143
+ offset: pages.get('func lut').ind * pageSize,
129
144
  bytes
130
145
  });
131
146
  data.addedFuncArgcLut = true;
@@ -4,6 +4,7 @@ export const __Array_isArray = (x: unknown): boolean =>
4
4
  // Porffor.wasm`local.get ${x+1}` == Porffor.TYPES.array;
5
5
  Porffor.rawType(x) == Porffor.TYPES.array;
6
6
 
7
+
7
8
  export const __Array_prototype_slice = (_this: any[], start: number, end: number) => {
8
9
  const len: i32 = _this.length;
9
10
  if (Porffor.rawType(end) == Porffor.TYPES.undefined) end = len;
@@ -22,7 +23,7 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
22
23
  }
23
24
  if (end > len) end = len;
24
25
 
25
- let out: any[] = [];
26
+ let out: any[] = Porffor.allocate();
26
27
 
27
28
  if (start > end) return out;
28
29
 
@@ -42,10 +43,38 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
42
43
  }
43
44
 
44
45
  out.length = end - start;
45
-
46
46
  return out;
47
47
  };
48
48
 
49
+ // @porf-typed-array
50
+ export const __Array_prototype_fill = (_this: any[], value: any, start: any, end: any) => {
51
+ const len: i32 = _this.length;
52
+
53
+ if (Porffor.rawType(start) == Porffor.TYPES.undefined) start = 0;
54
+ if (Porffor.rawType(end) == Porffor.TYPES.undefined) end = len;
55
+
56
+ start |= 0;
57
+ end |= 0;
58
+
59
+ if (start < 0) {
60
+ start = len + start;
61
+ if (start < 0) start = 0;
62
+ }
63
+ if (start > len) start = len;
64
+ if (end < 0) {
65
+ end = len + end;
66
+ if (end < 0) end = 0;
67
+ }
68
+ if (end > len) end = len;
69
+
70
+ for (let i: i32 = start; i < end; i++) {
71
+ _this[i] = value;
72
+ }
73
+
74
+ return _this;
75
+ };
76
+
77
+ // @porf-typed-array
49
78
  export const __Array_prototype_indexOf = (_this: any[], searchElement: any, position: number) => {
50
79
  const len: i32 = _this.length;
51
80
  if (position > 0) {
@@ -60,6 +89,7 @@ export const __Array_prototype_indexOf = (_this: any[], searchElement: any, posi
60
89
  return -1;
61
90
  };
62
91
 
92
+ // @porf-typed-array
63
93
  export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any, position: number) => {
64
94
  const len: i32 = _this.length;
65
95
  if (position > 0) {
@@ -74,6 +104,7 @@ export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any,
74
104
  return -1;
75
105
  };
76
106
 
107
+ // @porf-typed-array
77
108
  export const __Array_prototype_includes = (_this: any[], searchElement: any, position: number) => {
78
109
  const len: i32 = _this.length;
79
110
  if (position > 0) {
@@ -88,6 +119,7 @@ export const __Array_prototype_includes = (_this: any[], searchElement: any, pos
88
119
  return false;
89
120
  };
90
121
 
122
+ // @porf-typed-array
91
123
  export const __Array_prototype_with = (_this: any[], index: number, value: any) => {
92
124
  const len: i32 = _this.length;
93
125
  if (index < 0) {
@@ -101,8 +133,7 @@ export const __Array_prototype_with = (_this: any[], index: number, value: any)
101
133
  throw new RangeError('Invalid index');
102
134
  }
103
135
 
104
- // todo: allocator is bad here?
105
- let out: any[] = [];
136
+ let out: any[] = Porffor.allocate();
106
137
 
107
138
  Porffor.clone(_this, out);
108
139
 
@@ -111,6 +142,7 @@ export const __Array_prototype_with = (_this: any[], index: number, value: any)
111
142
  return out;
112
143
  };
113
144
 
145
+ // @porf-typed-array
114
146
  export const __Array_prototype_reverse = (_this: any[]) => {
115
147
  const len: i32 = _this.length;
116
148
 
@@ -126,14 +158,14 @@ export const __Array_prototype_reverse = (_this: any[]) => {
126
158
  return _this;
127
159
  };
128
160
 
129
- // todo: this has memory/allocation bugs so sometimes crashes :(
161
+ // @porf-typed-array
130
162
  export const __Array_prototype_toReversed = (_this: any[]) => {
131
163
  const len: i32 = _this.length;
132
164
 
133
165
  let start: i32 = 0;
134
166
  let end: i32 = len - 1;
135
167
 
136
- let out: any[] = [];
168
+ let out: any[] = Porffor.allocate();
137
169
  out.length = len;
138
170
 
139
171
  while (start < end) {
@@ -144,11 +176,13 @@ export const __Array_prototype_toReversed = (_this: any[]) => {
144
176
  return out;
145
177
  };
146
178
 
179
+ // @porf-typed-array
147
180
  export const __Array_prototype_valueOf = (_this: any[]) => {
148
181
  return _this;
149
182
  };
150
183
 
151
184
 
185
+ // @porf-typed-array
152
186
  export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
153
187
  const len: i32 = _this.length;
154
188
  let i: i32 = 0;
@@ -157,22 +191,26 @@ export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
157
191
  }
158
192
  };
159
193
 
194
+ // @porf-typed-array
160
195
  export const __Array_prototype_filter = (_this: any[], callbackFn: any) => {
161
- const out: any[] = [];
196
+ const out: any[] = Porffor.allocate();
162
197
 
163
198
  const len: i32 = _this.length;
164
199
  let i: i32 = 0;
200
+ let j: i32 = 0;
165
201
  while (i < len) {
166
202
  const el: any = _this[i];
167
- if (Boolean(callbackFn(el, i++, _this))) out.push(el);
203
+ if (Boolean(callbackFn(el, i++, _this))) out[j++] = el;
168
204
  }
169
205
 
206
+ out.length = j;
170
207
  return out;
171
208
  };
172
209
 
210
+ // @porf-typed-array
173
211
  export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
174
212
  const len: i32 = _this.length;
175
- const out: any[] = [];
213
+ const out: any[] = Porffor.allocate();
176
214
  out.length = len;
177
215
 
178
216
  let i: i32 = 0;
@@ -183,6 +221,7 @@ export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
183
221
  return out;
184
222
  };
185
223
 
224
+ // @porf-typed-array
186
225
  export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
187
226
  const len: i32 = _this.length;
188
227
  let i: i32 = 0;
@@ -192,6 +231,7 @@ export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
192
231
  }
193
232
  };
194
233
 
234
+ // @porf-typed-array
195
235
  export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
196
236
  let i: i32 = _this.length;
197
237
  while (i > 0) {
@@ -200,6 +240,7 @@ export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
200
240
  }
201
241
  };
202
242
 
243
+ // @porf-typed-array
203
244
  export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
204
245
  const len: i32 = _this.length;
205
246
  let i: i32 = 0;
@@ -208,6 +249,7 @@ export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
208
249
  }
209
250
  };
210
251
 
252
+ // @porf-typed-array
211
253
  export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) => {
212
254
  let i: i32 = _this.length;
213
255
  while (i > 0) {
@@ -215,6 +257,7 @@ export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) =
215
257
  }
216
258
  };
217
259
 
260
+ // @porf-typed-array
218
261
  export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
219
262
  const len: i32 = _this.length;
220
263
  let i: i32 = 0;
@@ -225,6 +268,7 @@ export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
225
268
  return true;
226
269
  };
227
270
 
271
+ // @porf-typed-array
228
272
  export const __Array_prototype_some = (_this: any[], callbackFn: any) => {
229
273
  const len: i32 = _this.length;
230
274
  let i: i32 = 0;
@@ -235,6 +279,7 @@ export const __Array_prototype_some = (_this: any[], callbackFn: any) => {
235
279
  return false;
236
280
  };
237
281
 
282
+ // @porf-typed-array
238
283
  export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialValue: any) => {
239
284
  let acc: any = initialValue ?? _this[0];
240
285
 
@@ -247,6 +292,7 @@ export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialV
247
292
  return acc;
248
293
  };
249
294
 
295
+ // @porf-typed-array
250
296
  export const __Array_prototype_reduceRight = (_this: any[], callbackFn: any, initialValue: any) => {
251
297
  const len: i32 = _this.length;
252
298
  let acc: any = initialValue ?? _this[len - 1];
@@ -259,6 +305,52 @@ export const __Array_prototype_reduceRight = (_this: any[], callbackFn: any, ini
259
305
  return acc;
260
306
  };
261
307
 
308
+ // @porf-typed-array
309
+ export const __Array_prototype_sort = (_this: any[], callbackFn: any) => {
310
+ // todo: default callbackFn
311
+
312
+ // insertion sort, i guess
313
+ const len: i32 = _this.length;
314
+ for (let i: i32 = 0; i < len; i++) {
315
+ const x: any = _this[i];
316
+ let j: i32 = i;
317
+ while (j > 0) {
318
+ const y: any = _this[j - 1];
319
+
320
+ // 23.1.3.30.2 CompareArrayElements (x, y, comparefn)
321
+ // https://tc39.es/ecma262/#sec-comparearrayelements
322
+ const xt: i32 = Porffor.rawType(x);
323
+ const yt: i32 = Porffor.rawType(y);
324
+ let v: number;
325
+
326
+ // 1. If x and y are both undefined, return +0๐”ฝ.
327
+ if (xt == Porffor.TYPES.undefined && yt == Porffor.TYPES.undefined) v = 0;
328
+ // 2. If x is undefined, return 1๐”ฝ.
329
+ else if (xt == Porffor.TYPES.undefined) v = 1;
330
+ // 3. If y is undefined, return -1๐”ฝ.
331
+ else if (yt == Porffor.TYPES.undefined) v = -1;
332
+ else {
333
+ // 4. If comparefn is not undefined, then
334
+ // a. Let v be ? ToNumber(? Call(comparefn, undefined, ยซ x, y ยป)).
335
+ v = callbackFn(x, y);
336
+
337
+ // b. If v is NaN, return +0๐”ฝ.
338
+ // if (Number.isNaN(v)) v = 0;
339
+
340
+ // c. Return v.
341
+ }
342
+
343
+ if (v >= 0) break;
344
+ _this[j--] = y;
345
+ }
346
+
347
+ _this[j] = x;
348
+ }
349
+
350
+ return _this;
351
+ };
352
+
353
+ // @porf-typed-array
262
354
  export const __Array_prototype_toString = (_this: any[]) => {
263
355
  // todo: this is bytestring only!
264
356
 
@@ -283,6 +375,7 @@ export const __Array_prototype_toString = (_this: any[]) => {
283
375
  return out;
284
376
  };
285
377
 
378
+ // @porf-typed-array
286
379
  export const __Array_prototype_join = (_this: any[], _separator: any) => {
287
380
  // todo: this is bytestring only!
288
381
  // todo/perf: optimize single char separators