porffor 0.61.2 → 0.61.4
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/2c.js +6 -68
- package/compiler/assemble.js +2 -4
- package/compiler/builtins/annexb_string.js +1 -1
- package/compiler/builtins/array.ts +9 -1
- package/compiler/builtins/console.ts +1 -0
- package/compiler/builtins/function.ts +1 -2
- package/compiler/builtins/json.ts +8 -1
- package/compiler/builtins/map.ts +4 -2
- package/compiler/builtins/math.ts +49 -13
- package/compiler/builtins/number.ts +23 -4
- package/compiler/builtins/object.ts +5 -1
- package/compiler/builtins/porffor.d.ts +1 -4
- package/compiler/builtins/regexp.ts +166 -190
- package/compiler/builtins/set.ts +4 -2
- package/compiler/builtins/string.ts +96 -108
- package/compiler/builtins/string_f64.ts +4 -3
- package/compiler/builtins/stringtonumber.ts +4 -3
- package/compiler/builtins/typedarray.js +11 -10
- package/compiler/builtins/z_ecma262.ts +9 -0
- package/compiler/builtins.js +16 -8
- package/compiler/builtins_precompiled.js +574 -569
- package/compiler/codegen.js +97 -30
- package/compiler/opt.js +2 -2
- package/compiler/precompile.js +4 -2
- package/compiler/semantic.js +1 -5
- package/compiler/wasmSpec.js +1 -0
- package/compiler/wrap.js +6 -26
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/runtime/index.js +1 -1
- package/bun.lock +0 -84
- package/deno.lock +0 -18
package/compiler/2c.js
CHANGED
|
@@ -2,7 +2,6 @@ import { read_unsignedLEB128 } from './encoding.js';
|
|
|
2
2
|
import { Blocktype, Opcodes, Valtype, PageSize } from './wasmSpec.js';
|
|
3
3
|
import { operatorOpcode } from './expression.js';
|
|
4
4
|
import { log } from './log.js';
|
|
5
|
-
import './prefs.js';
|
|
6
5
|
|
|
7
6
|
const CValtype = {
|
|
8
7
|
i8: 'u8',
|
|
@@ -209,7 +208,7 @@ export default ({ funcs, globals, data, pages }) => {
|
|
|
209
208
|
|
|
210
209
|
includes.set('stdint.h', true);
|
|
211
210
|
|
|
212
|
-
|
|
211
|
+
let out = '';
|
|
213
212
|
|
|
214
213
|
for (const x in globals) {
|
|
215
214
|
const g = globals[x];
|
|
@@ -281,6 +280,7 @@ export default ({ funcs, globals, data, pages }) => {
|
|
|
281
280
|
if (cified.has(f.name)) return '';
|
|
282
281
|
cified.add(f.name);
|
|
283
282
|
|
|
283
|
+
let topOfOut = '';
|
|
284
284
|
let out = '';
|
|
285
285
|
|
|
286
286
|
let depth = 1;
|
|
@@ -358,8 +358,7 @@ export default ({ funcs, globals, data, pages }) => {
|
|
|
358
358
|
|
|
359
359
|
if (f.name === '__Porffor_promise_runJobs') {
|
|
360
360
|
out += '}';
|
|
361
|
-
|
|
362
|
-
return;
|
|
361
|
+
return topOfOut + out;
|
|
363
362
|
}
|
|
364
363
|
|
|
365
364
|
if (f.name === '#main') {
|
|
@@ -661,66 +660,6 @@ f64 _time_out${id} = (f64)_ts${id}.tv_sec * 1000.0 + (f64)_ts${id}.tv_nsec / 1.0
|
|
|
661
660
|
break;
|
|
662
661
|
}
|
|
663
662
|
|
|
664
|
-
case '__Porffor_readArgv': {
|
|
665
|
-
prepend.set('__Porffor_readArgv',
|
|
666
|
-
`i32 __Porffor_readArgv(u32 index, u32 outPtr) {
|
|
667
|
-
if (index >= _argc) {
|
|
668
|
-
return -1;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
char* arg = _argv[index];
|
|
672
|
-
|
|
673
|
-
u32 read = 0;
|
|
674
|
-
char* out = _memory + outPtr + 4;
|
|
675
|
-
char ch;
|
|
676
|
-
while ((ch = *(arg++)) != 0) {
|
|
677
|
-
out[read++] = ch;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
*((i32*)(_memory + outPtr)) = (i32)read;
|
|
681
|
-
return read;
|
|
682
|
-
}`);
|
|
683
|
-
|
|
684
|
-
const outPtr = vals.pop();
|
|
685
|
-
const index = vals.pop();
|
|
686
|
-
vals.push(`(f64)__Porffor_readArgv((u32)(${index}), (u32)(${outPtr}))`);
|
|
687
|
-
break;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
case '__Porffor_readFile': {
|
|
691
|
-
includes.set('stdio.h', true);
|
|
692
|
-
|
|
693
|
-
prepend.set('__Porffor_readFile',
|
|
694
|
-
`i32 __Porffor_readFile(u32 pathPtr, u32 outPtr) {
|
|
695
|
-
FILE* fp;
|
|
696
|
-
if (pathPtr == 0) {
|
|
697
|
-
fp = stdin;
|
|
698
|
-
} else {
|
|
699
|
-
char* path = _memory + pathPtr + 4;
|
|
700
|
-
fp = fopen(path, "r");
|
|
701
|
-
if (fp == NULL) {
|
|
702
|
-
return -1;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
u32 read = 0;
|
|
707
|
-
char* out = _memory + outPtr + 4;
|
|
708
|
-
char ch;
|
|
709
|
-
while ((ch = fgetc(fp)) != EOF) {
|
|
710
|
-
out[read++] = ch;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
fclose(fp);
|
|
714
|
-
|
|
715
|
-
*((i32*)(_memory + outPtr)) = (i32)read;
|
|
716
|
-
return read;
|
|
717
|
-
}`);
|
|
718
|
-
const outPtr = vals.pop();
|
|
719
|
-
const pathPtr = vals.pop();
|
|
720
|
-
vals.push(`(f64)__Porffor_readFile((u32)(${pathPtr}), (u32)(${outPtr}))`);
|
|
721
|
-
break;
|
|
722
|
-
}
|
|
723
|
-
|
|
724
663
|
default:
|
|
725
664
|
log.warning('2c', `unimplemented import: ${importFunc.name}`);
|
|
726
665
|
break;
|
|
@@ -730,7 +669,7 @@ f64 _time_out${id} = (f64)_ts${id}.tv_sec * 1000.0 + (f64)_ts${id}.tv_nsec / 1.0
|
|
|
730
669
|
}
|
|
731
670
|
|
|
732
671
|
if (!cified.has(func.name) && !ffiFuncs[func.name]) {
|
|
733
|
-
cify(func);
|
|
672
|
+
topOfOut += cify(func);
|
|
734
673
|
}
|
|
735
674
|
|
|
736
675
|
let args = [];
|
|
@@ -951,12 +890,11 @@ f64 _time_out${id} = (f64)_ts${id}.tv_sec * 1000.0 + (f64)_ts${id}.tv_nsec / 1.0
|
|
|
951
890
|
}
|
|
952
891
|
|
|
953
892
|
out += '}\n\n';
|
|
954
|
-
|
|
955
|
-
globalThis.out = globalThis.out + out;
|
|
893
|
+
return topOfOut + out;
|
|
956
894
|
};
|
|
957
895
|
|
|
958
896
|
for (const x of funcs) {
|
|
959
|
-
if (x.export || x.name === '#main') cify(x);
|
|
897
|
+
if (x.export || x.name === '#main') out += cify(x);
|
|
960
898
|
}
|
|
961
899
|
|
|
962
900
|
const rawParams = f => {
|
package/compiler/assemble.js
CHANGED
|
@@ -25,14 +25,12 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
|
25
25
|
if (f.usesImports) for (let j = 0; j < f.wasm.length; j++) {
|
|
26
26
|
const x = f.wasm[j];
|
|
27
27
|
if (x[0] === Opcodes.call && x[1] < importedFuncs.length) {
|
|
28
|
-
const
|
|
29
|
-
const func = importedFuncs[idx];
|
|
30
|
-
|
|
28
|
+
const func = importedFuncs[x[1]];
|
|
31
29
|
if (!remap.has(func)) {
|
|
32
30
|
remap.set(func, importFuncs.length);
|
|
33
31
|
importFuncs.push(func);
|
|
34
32
|
}
|
|
35
|
-
|
|
33
|
+
f.wasm[j] = [ x[0], remap.get(func) ];
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
}
|
|
@@ -22,7 +22,7 @@ export const __ByteString_prototype_${a0} = (_this: bytestring) =>
|
|
|
22
22
|
export const __String_prototype_${name} = (_this: string, arg: any) => {
|
|
23
23
|
arg = ecma262.ToString(arg);
|
|
24
24
|
const len: i32 = arg.length;
|
|
25
|
-
const escaped: bytestring = Porffor.malloc(
|
|
25
|
+
const escaped: bytestring = Porffor.malloc(6 + len * 6); // overallocate in case of "s
|
|
26
26
|
for (let i: i32 = 0; i < len; i++) {
|
|
27
27
|
const c: i32 = arg.charCodeAt(i);
|
|
28
28
|
if (c != 34) {
|
|
@@ -371,6 +371,8 @@ export const __Array_prototype_fill = (_this: any[], value: any, _start: any, _e
|
|
|
371
371
|
// @porf-typed-array
|
|
372
372
|
export const __Array_prototype_indexOf = (_this: any[], searchElement: any, _position: any) => {
|
|
373
373
|
const len: i32 = _this.length;
|
|
374
|
+
if (len == 0) return -1;
|
|
375
|
+
|
|
374
376
|
let position: i32 = ecma262.ToIntegerOrInfinity(_position);
|
|
375
377
|
if (position >= 0) {
|
|
376
378
|
if (position > len) position = len;
|
|
@@ -389,6 +391,8 @@ export const __Array_prototype_indexOf = (_this: any[], searchElement: any, _pos
|
|
|
389
391
|
// @porf-typed-array
|
|
390
392
|
export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any, _position: any) => {
|
|
391
393
|
const len: i32 = _this.length;
|
|
394
|
+
if (len == 0) return -1;
|
|
395
|
+
|
|
392
396
|
let position: i32 = _position == null ? len - 1 : ecma262.ToIntegerOrInfinity(_position);
|
|
393
397
|
if (position >= 0) {
|
|
394
398
|
if (position > len - 1) position = len - 1;
|
|
@@ -406,6 +410,8 @@ export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any,
|
|
|
406
410
|
// @porf-typed-array
|
|
407
411
|
export const __Array_prototype_includes = (_this: any[], searchElement: any, _position: any) => {
|
|
408
412
|
const len: i32 = _this.length;
|
|
413
|
+
if (len == 0) return false;
|
|
414
|
+
|
|
409
415
|
let position: i32 = ecma262.ToIntegerOrInfinity(_position);
|
|
410
416
|
if (position >= 0) {
|
|
411
417
|
if (position > len) position = len;
|
|
@@ -415,7 +421,7 @@ export const __Array_prototype_includes = (_this: any[], searchElement: any, _po
|
|
|
415
421
|
}
|
|
416
422
|
|
|
417
423
|
for (let i: i32 = position; i < len; i++) {
|
|
418
|
-
if (_this[i]
|
|
424
|
+
if (__ecma262_SameValueZero(_this[i], searchElement)) return true;
|
|
419
425
|
}
|
|
420
426
|
|
|
421
427
|
return false;
|
|
@@ -612,6 +618,7 @@ export const __Array_prototype_findIndex = (_this: any[], callbackFn: any, thisA
|
|
|
612
618
|
if (!!callbackFn.call(thisArg, _this[i], i, _this)) return i;
|
|
613
619
|
i++;
|
|
614
620
|
}
|
|
621
|
+
return -1;
|
|
615
622
|
};
|
|
616
623
|
|
|
617
624
|
// @porf-typed-array
|
|
@@ -621,6 +628,7 @@ export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any, t
|
|
|
621
628
|
while (i > 0) {
|
|
622
629
|
if (!!callbackFn.call(thisArg, _this[--i], i, _this)) return i;
|
|
623
630
|
}
|
|
631
|
+
return -1;
|
|
624
632
|
};
|
|
625
633
|
|
|
626
634
|
// @porf-typed-array
|
|
@@ -59,6 +59,7 @@ export const __Porffor_print = (arg: any, colors: boolean = true, depth: number
|
|
|
59
59
|
return;
|
|
60
60
|
|
|
61
61
|
case Porffor.TYPES.boolean:
|
|
62
|
+
case Porffor.TYPES.booleanobject:
|
|
62
63
|
if (colors) Porffor.printStatic('\x1b[33m'); // yellow
|
|
63
64
|
if (arg) {
|
|
64
65
|
Porffor.printStatic('true');
|
|
@@ -21,8 +21,7 @@ export const __Function_prototype_toString = (_this: Function) => {
|
|
|
21
21
|
export const __Function_prototype_toLocaleString = (_this: Function) => __Function_prototype_toString(_this);
|
|
22
22
|
|
|
23
23
|
export const __Function_prototype_apply = (_this: Function, thisArg: any, argsArray: any) => {
|
|
24
|
-
|
|
25
|
-
return Porffor.call(_this, argsArray, thisArg, null);
|
|
24
|
+
return Porffor.call(_this, Array.from(argsArray ?? []) as any[], thisArg, null);
|
|
26
25
|
};
|
|
27
26
|
|
|
28
27
|
export const __Function_prototype_bind = (_this: Function, thisArg: any, argsArray: any) => {
|
|
@@ -39,6 +39,7 @@ export const __Porffor_json_canSerialize = (value: any): boolean => {
|
|
|
39
39
|
Porffor.type(value) == Porffor.TYPES.stringobject,
|
|
40
40
|
Porffor.type(value) == Porffor.TYPES.number,
|
|
41
41
|
Porffor.type(value) == Porffor.TYPES.numberobject,
|
|
42
|
+
Porffor.type(value) == Porffor.TYPES.booleanobject,
|
|
42
43
|
Porffor.type(value) == Porffor.TYPES.array,
|
|
43
44
|
Porffor.type(value) > Porffor.TYPES.function
|
|
44
45
|
)) return true;
|
|
@@ -57,6 +58,12 @@ export const __Porffor_json_serialize = (_buffer: i32, value: any, depth: i32, s
|
|
|
57
58
|
if (value === true) return __Porffor_bytestring_bufferStr(buffer, 'true');
|
|
58
59
|
if (value === false) return __Porffor_bytestring_bufferStr(buffer, 'false');
|
|
59
60
|
|
|
61
|
+
// Handle Boolean objects by extracting [[BooleanData]]
|
|
62
|
+
if (Porffor.type(value) == Porffor.TYPES.booleanobject) {
|
|
63
|
+
if (value.valueOf()) return __Porffor_bytestring_bufferStr(buffer, 'true');
|
|
64
|
+
return __Porffor_bytestring_bufferStr(buffer, 'false');
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
if (Porffor.fastOr(
|
|
61
68
|
(Porffor.type(value) | 0b10000000) == Porffor.TYPES.bytestring,
|
|
62
69
|
Porffor.type(value) == Porffor.TYPES.stringobject
|
|
@@ -240,7 +247,7 @@ export const __JSON_stringify = (value: any, replacer: any, space: any) => {
|
|
|
240
247
|
if (space < 1) {
|
|
241
248
|
space = undefined;
|
|
242
249
|
} else {
|
|
243
|
-
const spaceStr: bytestring = Porffor.malloc(
|
|
250
|
+
const spaceStr: bytestring = Porffor.malloc(6 + space);
|
|
244
251
|
for (let i: i32 = 0; i < space; i++) Porffor.bytestring.appendChar(spaceStr, 32);
|
|
245
252
|
|
|
246
253
|
space = spaceStr;
|
package/compiler/builtins/map.ts
CHANGED
|
@@ -72,7 +72,9 @@ export const __Map_prototype_clear = (_this: Map) => {
|
|
|
72
72
|
vals.length = 0;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
export const __Map_prototype_forEach = (_this: Map, callbackFn: any) => {
|
|
75
|
+
export const __Map_prototype_forEach = (_this: Map, callbackFn: any, thisArg: any = undefined) => {
|
|
76
|
+
if (Porffor.type(callbackFn) != Porffor.TYPES.function) throw new TypeError('callbackFn is not a function');
|
|
77
|
+
|
|
76
78
|
const keys: any[] = Porffor.wasm.i32.load(_this, 0, 0);
|
|
77
79
|
const vals: any[] = Porffor.wasm.i32.load(_this, 0, 4);
|
|
78
80
|
|
|
@@ -80,7 +82,7 @@ export const __Map_prototype_forEach = (_this: Map, callbackFn: any) => {
|
|
|
80
82
|
|
|
81
83
|
let i: i32 = 0;
|
|
82
84
|
while (i < size) {
|
|
83
|
-
callbackFn(vals[i], keys[i++], _this);
|
|
85
|
+
callbackFn.call(thisArg, vals[i], keys[i++], _this);
|
|
84
86
|
}
|
|
85
87
|
};
|
|
86
88
|
|
|
@@ -154,7 +154,7 @@ export const __Math_pow = (base: number, exponent: number): number => {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// 5. If base is -∞𝔽, then
|
|
157
|
-
const isOdd = exponent % 2 == 1;
|
|
157
|
+
const isOdd = Math.abs(exponent) % 2 == 1;
|
|
158
158
|
|
|
159
159
|
// a. If exponent > +0𝔽, then
|
|
160
160
|
if (exponent > 0) {
|
|
@@ -178,7 +178,7 @@ export const __Math_pow = (base: number, exponent: number): number => {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
// 7. If base is -0𝔽, then
|
|
181
|
-
const isOdd = exponent % 2 == 1;
|
|
181
|
+
const isOdd = Math.abs(exponent) % 2 == 1;
|
|
182
182
|
|
|
183
183
|
// a. If exponent > +0𝔽, then
|
|
184
184
|
if (exponent > 0) {
|
|
@@ -246,7 +246,7 @@ export const __Math_pow = (base: number, exponent: number): number => {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
currentBase *= currentBase;
|
|
249
|
-
currentExponent
|
|
249
|
+
currentExponent = Math.trunc(currentExponent / 2);
|
|
250
250
|
} else {
|
|
251
251
|
// Handle fractional part
|
|
252
252
|
result *= Math.exp(currentExponent * Math.log(Math.abs(currentBase)));
|
|
@@ -282,7 +282,10 @@ export const __Math_expm1 = (x: number): number => {
|
|
|
282
282
|
};
|
|
283
283
|
|
|
284
284
|
export const __Math_log1p = (x: number): number => {
|
|
285
|
+
// log1p(0) = 0 (preserve sign)
|
|
286
|
+
if (x == 0) return x;
|
|
285
287
|
if (x == -1) return -Infinity; // log(0) = -inf
|
|
288
|
+
if (x < -1) return NaN; // log of negative is NaN
|
|
286
289
|
if (!Number.isFinite(x)) return x;
|
|
287
290
|
|
|
288
291
|
// opt: use exp(x) - 1 for large x
|
|
@@ -305,7 +308,7 @@ export const __Math_log1p = (x: number): number => {
|
|
|
305
308
|
|
|
306
309
|
export const __Math_sqrt = (y: number): number => {
|
|
307
310
|
if (y <= 0) {
|
|
308
|
-
if (y == 0) return 0
|
|
311
|
+
if (y == 0) return y; // sqrt(0) = 0 (preserve sign)
|
|
309
312
|
return NaN;
|
|
310
313
|
}
|
|
311
314
|
if (!Number.isFinite(y)) return y;
|
|
@@ -323,7 +326,7 @@ export const __Math_sqrt = (y: number): number => {
|
|
|
323
326
|
};
|
|
324
327
|
|
|
325
328
|
export const __Math_cbrt = (y: number): number => {
|
|
326
|
-
if (y == 0) return
|
|
329
|
+
if (y == 0) return y; // cbrt(0) = 0 (preserves sign)
|
|
327
330
|
if (!Number.isFinite(y)) return y;
|
|
328
331
|
|
|
329
332
|
// Babylonian method
|
|
@@ -341,9 +344,16 @@ export const __Math_cbrt = (y: number): number => {
|
|
|
341
344
|
|
|
342
345
|
|
|
343
346
|
// todo: varargs
|
|
344
|
-
export const __Math_hypot = (x: number, y: number): number =>
|
|
347
|
+
export const __Math_hypot = (x: number, y: number): number => {
|
|
348
|
+
// If any argument is ±Infinity, return +Infinity (even if other args are NaN)
|
|
349
|
+
if (x == Infinity || x == -Infinity || y == Infinity || y == -Infinity) return Infinity;
|
|
350
|
+
return Math.sqrt(x * x + y * y);
|
|
351
|
+
};
|
|
345
352
|
|
|
346
353
|
export const __Math_sin = (x: number): number => {
|
|
354
|
+
// sin(0) = 0 (preserve sign)
|
|
355
|
+
if (x == 0) return x;
|
|
356
|
+
|
|
347
357
|
// -inf <= x <= inf -> 0 <= x <= 2pi
|
|
348
358
|
const piX2: number = Math.PI * 2;
|
|
349
359
|
x %= piX2;
|
|
@@ -381,21 +391,47 @@ export const __Math_sin = (x: number): number => {
|
|
|
381
391
|
// );
|
|
382
392
|
};
|
|
383
393
|
|
|
384
|
-
export const __Math_cos = (x: number): number =>
|
|
385
|
-
|
|
394
|
+
export const __Math_cos = (x: number): number => {
|
|
395
|
+
if (x == 0) return 1;
|
|
396
|
+
return Math.sin(x + Math.PI / 2);
|
|
397
|
+
};
|
|
398
|
+
export const __Math_tan = (x: number): number => {
|
|
399
|
+
// tan(0) = 0 (preserve sign)
|
|
400
|
+
if (x == 0) return x;
|
|
401
|
+
return Math.sin(x) / Math.cos(x);
|
|
402
|
+
};
|
|
386
403
|
|
|
387
|
-
export const __Math_sinh = (x: number): number =>
|
|
404
|
+
export const __Math_sinh = (x: number): number => {
|
|
405
|
+
// sinh(0) = 0 (preserve sign)
|
|
406
|
+
if (x == 0) return x;
|
|
407
|
+
return (Math.exp(x) - Math.exp(-x)) / 2;
|
|
408
|
+
};
|
|
388
409
|
export const __Math_cosh = (x: number): number => (Math.exp(x) + Math.exp(-x)) / 2;
|
|
389
|
-
export const __Math_tanh = (x: number): number =>
|
|
410
|
+
export const __Math_tanh = (x: number): number => {
|
|
411
|
+
// tanh(0) = 0 (preserve sign)
|
|
412
|
+
if (x == 0) return x;
|
|
413
|
+
if (x == Infinity) return 1;
|
|
414
|
+
if (x == -Infinity) return -1;
|
|
415
|
+
return Math.sinh(x) / Math.cosh(x);
|
|
416
|
+
};
|
|
390
417
|
|
|
391
418
|
|
|
392
|
-
export const __Math_asinh = (x: number): number =>
|
|
419
|
+
export const __Math_asinh = (x: number): number => {
|
|
420
|
+
// asinh(0) = 0 (preserve sign)
|
|
421
|
+
if (x == 0) return x;
|
|
422
|
+
if (!Number.isFinite(x)) return x;
|
|
423
|
+
return Math.log(x + Math.sqrt(x * x + 1));
|
|
424
|
+
};
|
|
393
425
|
export const __Math_acosh = (x: number): number => {
|
|
394
426
|
if (x < 1) return NaN;
|
|
395
427
|
return Math.log(x + Math.sqrt(x * x - 1));
|
|
396
428
|
};
|
|
397
429
|
export const __Math_atanh = (x: number): number => {
|
|
398
|
-
|
|
430
|
+
// atanh(0) = 0 (preserve sign)
|
|
431
|
+
if (x == 0) return x;
|
|
432
|
+
if (x == 1) return Infinity;
|
|
433
|
+
if (x == -1) return -Infinity;
|
|
434
|
+
if (Math.abs(x) > 1) return NaN;
|
|
399
435
|
return 0.5 * Math.log((1 + x) / (1 - x));
|
|
400
436
|
};
|
|
401
437
|
|
|
@@ -424,7 +460,7 @@ export const __Math_asin = (x: number): number => {
|
|
|
424
460
|
return sum;
|
|
425
461
|
};
|
|
426
462
|
|
|
427
|
-
export const __Math_acos = (x: number): number => Math.
|
|
463
|
+
export const __Math_acos = (x: number): number => Math.PI / 2 - Math.asin(x);
|
|
428
464
|
|
|
429
465
|
export const __Math_atan = (x: number): number => {
|
|
430
466
|
if (x == Infinity) return Math.PI / 2;
|
|
@@ -40,7 +40,7 @@ export const __Number_prototype_toString = (_this: number, radix: number|any) =>
|
|
|
40
40
|
radix = 10;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
radix
|
|
43
|
+
radix = Math.trunc(radix);
|
|
44
44
|
if (radix < 2 || radix > 36) {
|
|
45
45
|
throw new RangeError('toString() radix argument must be between 2 and 36');
|
|
46
46
|
}
|
|
@@ -268,7 +268,7 @@ export const __Number_prototype_toString = (_this: number, radix: number|any) =>
|
|
|
268
268
|
};
|
|
269
269
|
|
|
270
270
|
export const __Number_prototype_toFixed = (_this: number, fractionDigits: number) => {
|
|
271
|
-
fractionDigits
|
|
271
|
+
fractionDigits = Math.trunc(fractionDigits);
|
|
272
272
|
if (fractionDigits < 0 || fractionDigits > 100) {
|
|
273
273
|
throw new RangeError('toFixed() fractionDigits argument must be between 0 and 100');
|
|
274
274
|
}
|
|
@@ -367,7 +367,7 @@ export const __Number_prototype_toExponential = (_this: number, fractionDigits:
|
|
|
367
367
|
// todo: string to number
|
|
368
368
|
fractionDigits = undefined;
|
|
369
369
|
} else {
|
|
370
|
-
fractionDigits
|
|
370
|
+
fractionDigits = Math.trunc(fractionDigits);
|
|
371
371
|
if (fractionDigits < 0 || fractionDigits > 100) {
|
|
372
372
|
throw new RangeError('toExponential() fractionDigits argument must be between 0 and 100');
|
|
373
373
|
}
|
|
@@ -695,6 +695,10 @@ export const parseFloat = (input: any): f64 => {
|
|
|
695
695
|
let negative: boolean = false;
|
|
696
696
|
|
|
697
697
|
let i: i32 = 0;
|
|
698
|
+
const len: i32 = input.length;
|
|
699
|
+
|
|
700
|
+
if (len == 0) return NaN;
|
|
701
|
+
|
|
698
702
|
const start: i32 = input.charCodeAt(0);
|
|
699
703
|
|
|
700
704
|
// +, ignore
|
|
@@ -708,7 +712,22 @@ export const parseFloat = (input: any): f64 => {
|
|
|
708
712
|
negative = true;
|
|
709
713
|
}
|
|
710
714
|
|
|
711
|
-
|
|
715
|
+
// Check for "Infinity"
|
|
716
|
+
if (len - i >= 8) {
|
|
717
|
+
// Check if remaining string starts with "Infinity"
|
|
718
|
+
if (input.charCodeAt(i) == 73 && // I
|
|
719
|
+
input.charCodeAt(i + 1) == 110 && // n
|
|
720
|
+
input.charCodeAt(i + 2) == 102 && // f
|
|
721
|
+
input.charCodeAt(i + 3) == 105 && // i
|
|
722
|
+
input.charCodeAt(i + 4) == 110 && // n
|
|
723
|
+
input.charCodeAt(i + 5) == 105 && // i
|
|
724
|
+
input.charCodeAt(i + 6) == 116 && // t
|
|
725
|
+
input.charCodeAt(i + 7) == 121) { // y
|
|
726
|
+
if (negative) return -Infinity;
|
|
727
|
+
return Infinity;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
712
731
|
while (i < len) {
|
|
713
732
|
const chr: i32 = input.charCodeAt(i++);
|
|
714
733
|
|
|
@@ -643,7 +643,11 @@ export const __Object_setPrototypeOf = (obj: any, proto: any): any => {
|
|
|
643
643
|
if (obj == null) throw new TypeError('Object is nullish, expected object');
|
|
644
644
|
if (!Porffor.object.isObjectOrNull(proto)) throw new TypeError('Prototype should be an object or null');
|
|
645
645
|
|
|
646
|
-
//
|
|
646
|
+
// If object is inextensible, throw if new proto is different from current
|
|
647
|
+
if (Porffor.object.isObject(obj) && Porffor.object.isInextensible(obj)) {
|
|
648
|
+
const currentProto: any = Porffor.object.getPrototypeWithHidden(obj, Porffor.type(obj));
|
|
649
|
+
if (proto !== currentProto) throw new TypeError('Cannot set prototype of non-extensible object');
|
|
650
|
+
}
|
|
647
651
|
|
|
648
652
|
Porffor.object.setPrototype(obj, proto);
|
|
649
653
|
return obj;
|
|
@@ -96,6 +96,7 @@ type PorfforGlobal = {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
print(x: any): i32;
|
|
99
|
+
printStatic(str: string): void;
|
|
99
100
|
|
|
100
101
|
randomByte(): i32;
|
|
101
102
|
|
|
@@ -127,10 +128,6 @@ type PorfforGlobal = {
|
|
|
127
128
|
|
|
128
129
|
s(...args: any): string;
|
|
129
130
|
bs(...args: any): bytestring;
|
|
130
|
-
|
|
131
|
-
printStatic(str: string): void;
|
|
132
|
-
readArgv(index: i32, out: bytestring): i32;
|
|
133
|
-
readFile(path: bytestring, out: bytestring): i32;
|
|
134
131
|
};
|
|
135
132
|
|
|
136
133
|
declare global {
|