porffor 0.14.0-f67c123a1 → 0.16.0-08983b6b1
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/CONTRIBUTING.md +16 -10
- package/README.md +14 -30
- package/asur/index.js +1 -1
- package/compiler/2c.js +172 -59
- package/compiler/allocators.js +128 -0
- package/compiler/assemble.js +37 -5
- package/compiler/builtins/annexb_string.ts +1 -0
- package/compiler/builtins/array.ts +154 -7
- package/compiler/builtins/base64.ts +1 -0
- package/compiler/builtins/boolean.ts +3 -1
- package/compiler/builtins/console.ts +6 -0
- package/compiler/builtins/crypto.ts +1 -0
- package/compiler/builtins/date.ts +5 -30
- package/compiler/builtins/error.js +22 -0
- package/compiler/builtins/escape.ts +1 -2
- package/compiler/builtins/function.ts +2 -0
- package/compiler/builtins/int.ts +2 -0
- package/compiler/builtins/math.ts +410 -0
- package/compiler/builtins/number.ts +12 -21
- package/compiler/builtins/object.ts +2 -0
- package/compiler/builtins/porffor.d.ts +18 -0
- package/compiler/builtins/set.ts +22 -12
- package/compiler/builtins/string.ts +1 -0
- package/compiler/builtins/string_f64.ts +10 -0
- package/compiler/builtins/symbol.ts +62 -0
- package/compiler/builtins/z_ecma262.ts +62 -0
- package/compiler/builtins.js +50 -12
- package/compiler/codegen.js +826 -552
- package/compiler/cyclone.js +535 -0
- package/compiler/decompile.js +7 -1
- package/compiler/generated_builtins.js +635 -84
- package/compiler/havoc.js +93 -0
- package/compiler/index.js +108 -15
- package/compiler/opt.js +10 -44
- package/compiler/parse.js +3 -9
- package/compiler/pgo.js +212 -0
- package/compiler/precompile.js +17 -11
- package/compiler/prefs.js +13 -5
- package/compiler/prototype.js +200 -186
- package/compiler/wasmSpec.js +2 -2
- package/compiler/wrap.js +128 -44
- package/package.json +3 -5
- package/runner/index.js +31 -15
- package/runner/repl.js +18 -2
- /package/runner/{profiler.js → profile.js} +0 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
import { Opcodes, PageSize, Valtype } from './wasmSpec.js';
|
2
|
+
import { number } from './embedding.js';
|
3
|
+
import Prefs from './prefs.js';
|
4
|
+
|
5
|
+
// we currently have 3 allocators:
|
6
|
+
// - static (default): a static/compile-time allocator. fast (no grow/run-time alloc needed) but can break some code
|
7
|
+
// - grow: perform a memory.grow every allocation. simple but maybe slow?
|
8
|
+
// - chunk: perform large memory.grow's in chunks when needed. needs investigation
|
9
|
+
|
10
|
+
export default name => {
|
11
|
+
switch (name) {
|
12
|
+
case 'static': return new StaticAllocator();
|
13
|
+
case 'grow': return new GrowAllocator();
|
14
|
+
case 'chunk': return new ChunkAllocator();
|
15
|
+
default: throw new Error(`unknown allocator: ${name}`);
|
16
|
+
}
|
17
|
+
};
|
18
|
+
|
19
|
+
export class StaticAllocator {
|
20
|
+
constructor() {
|
21
|
+
}
|
22
|
+
|
23
|
+
allocType(itemType) {
|
24
|
+
switch (itemType) {
|
25
|
+
case 'i8': return 'bytestring';
|
26
|
+
case 'i16': return 'string';
|
27
|
+
|
28
|
+
default: return 'array';
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
ptr(ind) {
|
33
|
+
if (ind === 0) return 4;
|
34
|
+
return ind * PageSize;
|
35
|
+
}
|
36
|
+
|
37
|
+
alloc({ scope, pages }, name, { itemType }) {
|
38
|
+
const reason = `${this.allocType(itemType)}: ${Prefs.scopedPageNames ? (scope.name + '/') : ''}${name}`;
|
39
|
+
|
40
|
+
if (pages.has(reason)) return number(this.ptr(pages.get(reason).ind), Valtype.i32);
|
41
|
+
|
42
|
+
if (reason.startsWith('array:')) pages.hasArray = true;
|
43
|
+
if (reason.startsWith('string:')) pages.hasString = true;
|
44
|
+
if (reason.startsWith('bytestring:')) pages.hasByteString = true;
|
45
|
+
if (reason.includes('string:')) pages.hasAnyString = true;
|
46
|
+
|
47
|
+
let ind = pages.size;
|
48
|
+
pages.set(reason, { ind, type: itemType });
|
49
|
+
|
50
|
+
scope.pages ??= new Map();
|
51
|
+
scope.pages.set(reason, { ind, type: itemType });
|
52
|
+
|
53
|
+
return number(this.ptr(ind), Valtype.i32);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
export class GrowAllocator {
|
58
|
+
constructor() {
|
59
|
+
Prefs.rmUnusedTypes = false;
|
60
|
+
}
|
61
|
+
|
62
|
+
alloc() {
|
63
|
+
return [
|
64
|
+
// grow by 1 page
|
65
|
+
[ Opcodes.i32_const, 1 ],
|
66
|
+
[ Opcodes.memory_grow, 0 ], // returns old page count
|
67
|
+
|
68
|
+
// get ptr (page count * page size)
|
69
|
+
number(65536, Valtype.i32)[0],
|
70
|
+
[ Opcodes.i32_mul ]
|
71
|
+
];
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
export class ChunkAllocator {
|
76
|
+
constructor(chunkSize) {
|
77
|
+
Prefs.rmUnusedTypes = false;
|
78
|
+
|
79
|
+
// 64KiB * chunk size each growth
|
80
|
+
// 16: 1MiB chunks
|
81
|
+
this.chunkSize = chunkSize ?? Prefs.chunkAllocatorSize ?? 16;
|
82
|
+
}
|
83
|
+
|
84
|
+
alloc({ asmFunc, funcIndex }) {
|
85
|
+
const func = funcIndex['#chunkallocator_alloc'] ?? asmFunc('#chunkallocator_alloc', {
|
86
|
+
wasm: [
|
87
|
+
[ Opcodes.global_get, 0 ],
|
88
|
+
[ Opcodes.global_get, 1 ],
|
89
|
+
[ Opcodes.i32_ge_s ],
|
90
|
+
[ Opcodes.if, Valtype.i32 ], // ptr >= next
|
91
|
+
// grow by chunk size pages
|
92
|
+
[ Opcodes.i32_const, this.chunkSize ],
|
93
|
+
[ Opcodes.memory_grow, 0 ],
|
94
|
+
|
95
|
+
// ptr = prev memory size * PageSize
|
96
|
+
number(65536, Valtype.i32)[0],
|
97
|
+
[ Opcodes.i32_mul ],
|
98
|
+
[ Opcodes.global_set, 0 ],
|
99
|
+
|
100
|
+
// next = ptr + ((chunkSize - 1) * PageSize)
|
101
|
+
[ Opcodes.global_get, 0 ],
|
102
|
+
number(65536 * (this.chunkSize - 1), Valtype.i32)[0],
|
103
|
+
[ Opcodes.i32_add ],
|
104
|
+
[ Opcodes.global_set, 1 ],
|
105
|
+
|
106
|
+
// return ptr
|
107
|
+
[ Opcodes.global_get, 0 ],
|
108
|
+
[ Opcodes.else ],
|
109
|
+
// return ptr = ptr + PageSize
|
110
|
+
[ Opcodes.global_get, 0 ],
|
111
|
+
number(65536, Valtype.i32)[0],
|
112
|
+
[ Opcodes.i32_add ],
|
113
|
+
[ Opcodes.global_set, 0 ],
|
114
|
+
[ Opcodes.global_get, 0 ],
|
115
|
+
[ Opcodes.end ],
|
116
|
+
],
|
117
|
+
params: [],
|
118
|
+
locals: [],
|
119
|
+
globals: [ Valtype.i32, Valtype.i32 ],
|
120
|
+
globalNames: ['#chunkallocator_ptr', '#chunkallocator_next'],
|
121
|
+
returns: [ Valtype.i32 ],
|
122
|
+
}).index;
|
123
|
+
|
124
|
+
return [
|
125
|
+
[ Opcodes.call, func ]
|
126
|
+
];
|
127
|
+
}
|
128
|
+
}
|
package/compiler/assemble.js
CHANGED
@@ -21,7 +21,7 @@ const chHint = (topTier, baselineTier, strategy) => {
|
|
21
21
|
return (strategy | (baselineTier << 2) | (topTier << 4));
|
22
22
|
};
|
23
23
|
|
24
|
-
export default (funcs, globals, tags, pages, data, flags) => {
|
24
|
+
export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) => {
|
25
25
|
const types = [], typeCache = {};
|
26
26
|
|
27
27
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
@@ -44,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
44
44
|
|
45
45
|
let importFuncs = [];
|
46
46
|
|
47
|
-
if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
|
47
|
+
if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
|
48
48
|
importFuncs = importedFuncs;
|
49
49
|
} else {
|
50
50
|
let imports = new Map();
|
@@ -65,6 +65,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
65
65
|
importFuncs = [...imports.values()];
|
66
66
|
|
67
67
|
// fix call indexes for non-imports
|
68
|
+
// also fix call_indirect types
|
68
69
|
const delta = importedFuncs.length - importFuncs.length;
|
69
70
|
for (const f of funcs) {
|
70
71
|
f.originalIndex = f.index;
|
@@ -74,6 +75,16 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
74
75
|
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
|
75
76
|
inst[1] -= delta;
|
76
77
|
}
|
78
|
+
|
79
|
+
if (inst[0] === Opcodes.call_indirect) {
|
80
|
+
const params = [];
|
81
|
+
for (let i = 0; i < inst[1]; i++) {
|
82
|
+
params.push(valtypeBinary, Valtype.i32);
|
83
|
+
}
|
84
|
+
|
85
|
+
const returns = [ valtypeBinary, Valtype.i32 ];
|
86
|
+
inst[1] = getType(params, returns);
|
87
|
+
}
|
77
88
|
}
|
78
89
|
}
|
79
90
|
}
|
@@ -83,7 +94,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
83
94
|
|
84
95
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
85
96
|
Section.import,
|
86
|
-
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(
|
97
|
+
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(typeof x.params === 'object' ? x.params : new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
87
98
|
);
|
88
99
|
|
89
100
|
const funcSection = createSection(
|
@@ -101,10 +112,25 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
101
112
|
encodeVector([ [
|
102
113
|
0x00,
|
103
114
|
Opcodes.i32_const, 0, Opcodes.end,
|
104
|
-
encodeVector(funcs.map(x => x.index))
|
115
|
+
...encodeVector(funcs.map(x => x.index))
|
105
116
|
] ])
|
106
117
|
);
|
107
118
|
|
119
|
+
if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
|
120
|
+
// generate func argc lut data
|
121
|
+
const bytes = [];
|
122
|
+
for (let i = 0; i < funcs.length; i++) {
|
123
|
+
const argc = Math.floor(funcs[i].params.length / 2);
|
124
|
+
bytes.push(argc % 256, (argc / 256 | 0) % 256);
|
125
|
+
}
|
126
|
+
|
127
|
+
data.push({
|
128
|
+
offset: pages.get('func argc lut').ind * pageSize,
|
129
|
+
bytes
|
130
|
+
});
|
131
|
+
data.addedFuncArgcLut = true;
|
132
|
+
}
|
133
|
+
|
108
134
|
// const t0 = performance.now();
|
109
135
|
|
110
136
|
// specially optimized assembly for globals as this version is much (>5x) faster than traditional createSection()
|
@@ -214,7 +240,13 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
214
240
|
|
215
241
|
const dataSection = data.length === 0 ? [] : createSection(
|
216
242
|
Section.data,
|
217
|
-
encodeVector(data.map(x =>
|
243
|
+
encodeVector(data.map(x => {
|
244
|
+
// type: active
|
245
|
+
if (x.offset != null) return [ 0x00, Opcodes.i32_const, ...signedLEB128(x.offset), Opcodes.end, ...encodeVector(x.bytes) ];
|
246
|
+
|
247
|
+
// type: passive
|
248
|
+
return [ 0x01, ...encodeVector(x.bytes) ];
|
249
|
+
}))
|
218
250
|
);
|
219
251
|
|
220
252
|
const dataCountSection = data.length === 0 ? [] : createSection(
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import type {} from './porffor.d.ts';
|
2
|
+
|
1
3
|
export const __Array_isArray = (x: unknown): boolean =>
|
2
4
|
// Porffor.wasm`local.get ${x+1}` == Porffor.TYPES.array;
|
3
5
|
Porffor.rawType(x) == Porffor.TYPES.array;
|
@@ -27,14 +29,16 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
|
|
27
29
|
let outPtr: i32 = Porffor.wasm`local.get ${out}`;
|
28
30
|
let thisPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
29
31
|
|
30
|
-
const thisPtrEnd: i32 = thisPtr + end *
|
32
|
+
const thisPtrEnd: i32 = thisPtr + end * 9;
|
31
33
|
|
32
|
-
thisPtr += start *
|
34
|
+
thisPtr += start * 9;
|
33
35
|
|
34
36
|
while (thisPtr < thisPtrEnd) {
|
35
37
|
Porffor.wasm.f64.store(outPtr, Porffor.wasm.f64.load(thisPtr, 0, 4), 0, 4);
|
36
|
-
thisPtr
|
37
|
-
|
38
|
+
Porffor.wasm.i32.store8(outPtr + 8, Porffor.wasm.i32.load8_u(thisPtr + 8, 0, 4), 0, 4);
|
39
|
+
|
40
|
+
thisPtr += 9;
|
41
|
+
outPtr += 9;
|
38
42
|
}
|
39
43
|
|
40
44
|
out.length = end - start;
|
@@ -50,7 +54,7 @@ export const __Array_prototype_indexOf = (_this: any[], searchElement: any, posi
|
|
50
54
|
} else position = 0;
|
51
55
|
|
52
56
|
for (let i: i32 = position; i < len; i++) {
|
53
|
-
if (_this[i]
|
57
|
+
if (_this[i] === searchElement) return i;
|
54
58
|
}
|
55
59
|
|
56
60
|
return -1;
|
@@ -64,7 +68,7 @@ export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any,
|
|
64
68
|
} else position = 0;
|
65
69
|
|
66
70
|
for (let i: i32 = len - 1; i >= position; i--) {
|
67
|
-
if (_this[i]
|
71
|
+
if (_this[i] === searchElement) return i;
|
68
72
|
}
|
69
73
|
|
70
74
|
return -1;
|
@@ -78,7 +82,7 @@ export const __Array_prototype_includes = (_this: any[], searchElement: any, pos
|
|
78
82
|
} else position = 0;
|
79
83
|
|
80
84
|
for (let i: i32 = position; i < len; i++) {
|
81
|
-
if (_this[i]
|
85
|
+
if (_this[i] === searchElement) return true;
|
82
86
|
}
|
83
87
|
|
84
88
|
return false;
|
@@ -142,4 +146,147 @@ export const __Array_prototype_toReversed = (_this: any[]) => {
|
|
142
146
|
|
143
147
|
export const __Array_prototype_valueOf = (_this: any[]) => {
|
144
148
|
return _this;
|
149
|
+
};
|
150
|
+
|
151
|
+
|
152
|
+
export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
|
153
|
+
const len: i32 = _this.length;
|
154
|
+
let i: i32 = 0;
|
155
|
+
while (i < len) {
|
156
|
+
callbackFn(_this[i], i++, _this);
|
157
|
+
}
|
158
|
+
};
|
159
|
+
|
160
|
+
export const __Array_prototype_filter = (_this: any[], callbackFn: any) => {
|
161
|
+
const out: any[] = [];
|
162
|
+
|
163
|
+
const len: i32 = _this.length;
|
164
|
+
let i: i32 = 0;
|
165
|
+
while (i < len) {
|
166
|
+
const el: any = _this[i];
|
167
|
+
if (Boolean(callbackFn(el, i++, _this))) out.push(el);
|
168
|
+
}
|
169
|
+
|
170
|
+
return out;
|
171
|
+
};
|
172
|
+
|
173
|
+
export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
|
174
|
+
const len: i32 = _this.length;
|
175
|
+
const out: any[] = [];
|
176
|
+
out.length = len;
|
177
|
+
|
178
|
+
let i: i32 = 0;
|
179
|
+
while (i < len) {
|
180
|
+
out[i] = callbackFn(_this[i], i++, _this);
|
181
|
+
}
|
182
|
+
|
183
|
+
return out;
|
184
|
+
};
|
185
|
+
|
186
|
+
export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
|
187
|
+
const len: i32 = _this.length;
|
188
|
+
let i: i32 = 0;
|
189
|
+
while (i < len) {
|
190
|
+
const el: any = _this[i];
|
191
|
+
if (Boolean(callbackFn(el, i++, _this))) return el;
|
192
|
+
}
|
193
|
+
};
|
194
|
+
|
195
|
+
export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
|
196
|
+
let i: i32 = _this.length;
|
197
|
+
while (i > 0) {
|
198
|
+
const el: any = _this[--i];
|
199
|
+
if (Boolean(callbackFn(el, i, _this))) return el;
|
200
|
+
}
|
201
|
+
};
|
202
|
+
|
203
|
+
export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
|
204
|
+
const len: i32 = _this.length;
|
205
|
+
let i: i32 = 0;
|
206
|
+
while (i < len) {
|
207
|
+
if (Boolean(callbackFn(_this[i], i++, _this))) return i;
|
208
|
+
}
|
209
|
+
};
|
210
|
+
|
211
|
+
export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) => {
|
212
|
+
let i: i32 = _this.length;
|
213
|
+
while (i > 0) {
|
214
|
+
if (Boolean(callbackFn(_this[--i], i, _this))) return i;
|
215
|
+
}
|
216
|
+
};
|
217
|
+
|
218
|
+
export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
|
219
|
+
const len: i32 = _this.length;
|
220
|
+
let i: i32 = 0;
|
221
|
+
while (i < len) {
|
222
|
+
if (!Boolean(callbackFn(_this[i], i++, _this))) return false;
|
223
|
+
}
|
224
|
+
|
225
|
+
return true;
|
226
|
+
};
|
227
|
+
|
228
|
+
export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialValue: any) => {
|
229
|
+
let acc: any = initialValue ?? _this[0];
|
230
|
+
|
231
|
+
const len: i32 = _this.length;
|
232
|
+
let i: i32 = 0;
|
233
|
+
while (i < len) {
|
234
|
+
acc = callbackFn(acc, _this[i], i++, _this);
|
235
|
+
}
|
236
|
+
|
237
|
+
return acc;
|
238
|
+
};
|
239
|
+
|
240
|
+
export const __Array_prototype_toString = (_this: any[]) => {
|
241
|
+
// todo: this is bytestring only!
|
242
|
+
|
243
|
+
let out: bytestring = '';
|
244
|
+
out.length = 0;
|
245
|
+
|
246
|
+
const len: i32 = _this.length;
|
247
|
+
let i: i32 = 0;
|
248
|
+
while (i < len) {
|
249
|
+
if (i > 0) Porffor.bytestring.appendChar(out, 44);
|
250
|
+
|
251
|
+
const element: any = _this[i++];
|
252
|
+
const type: i32 = Porffor.rawType(element);
|
253
|
+
if (element != 0 || Porffor.fastAnd(
|
254
|
+
type != Porffor.TYPES.undefined, // undefined
|
255
|
+
type != Porffor.TYPES.object // null
|
256
|
+
)) {
|
257
|
+
Porffor.bytestring.appendStr(out, ecma262.ToString(element));
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
return out;
|
262
|
+
};
|
263
|
+
|
264
|
+
export const __Array_prototype_join = (_this: any[], _separator: any) => {
|
265
|
+
// todo: this is bytestring only!
|
266
|
+
// todo/perf: optimize single char separators
|
267
|
+
// todo/perf: optimize default separator (?)
|
268
|
+
|
269
|
+
let separator: bytestring = ',';
|
270
|
+
if (Porffor.rawType(_separator) != Porffor.TYPES.undefined)
|
271
|
+
separator = ecma262.ToString(_separator);
|
272
|
+
|
273
|
+
let out: bytestring = '';
|
274
|
+
out.length = 0;
|
275
|
+
|
276
|
+
const len: i32 = _this.length;
|
277
|
+
let i: i32 = 0;
|
278
|
+
while (i < len) {
|
279
|
+
if (i > 0) Porffor.bytestring.appendStr(out, separator);
|
280
|
+
|
281
|
+
const element: any = _this[i++];
|
282
|
+
const type: i32 = Porffor.rawType(element);
|
283
|
+
if (element != 0 || Porffor.fastAnd(
|
284
|
+
type != Porffor.TYPES.undefined, // undefined
|
285
|
+
type != Porffor.TYPES.object // null
|
286
|
+
)) {
|
287
|
+
Porffor.bytestring.appendStr(out, ecma262.ToString(element));
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
return out;
|
145
292
|
};
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import type {} from './porffor.d.ts';
|
2
|
+
|
1
3
|
// 20.3.3.2 Boolean.prototype.toString ()
|
2
4
|
// https://tc39.es/ecma262/#sec-boolean.prototype.tostring
|
3
5
|
export const __Boolean_prototype_toString = (_this: boolean) => {
|
@@ -15,4 +17,4 @@ export const __Boolean_prototype_toString = (_this: boolean) => {
|
|
15
17
|
export const __Boolean_prototype_valueOf = (_this: boolean) => {
|
16
18
|
// 1. Return ? ThisBooleanValue(this value).
|
17
19
|
return _this;
|
18
|
-
};
|
20
|
+
};
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import type {} from './porffor.d.ts';
|
2
|
+
|
1
3
|
// 21.4.1.3 Day (t)
|
2
4
|
// https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-day
|
3
5
|
// 1. Return 𝔽(floor(ℝ(t / msPerDay))).
|
@@ -251,29 +253,6 @@ export const __ecma262_UTC = (t: number): number => {
|
|
251
253
|
return t;
|
252
254
|
};
|
253
255
|
|
254
|
-
|
255
|
-
// todo: move this somewhere generic?
|
256
|
-
// 7.1.5 ToIntegerOrInfinity (argument)
|
257
|
-
// https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tointegerorinfinity
|
258
|
-
export const __ecma262_ToIntegerOrInfinity = (argument: unknown): number => {
|
259
|
-
// 1. Let number be ? ToNumber(argument).
|
260
|
-
let number: number = Number(argument);
|
261
|
-
|
262
|
-
// 2. If number is one of NaN, +0𝔽, or -0𝔽, return 0.
|
263
|
-
if (Number.isNaN(number)) return 0;
|
264
|
-
|
265
|
-
// 3. If number is +∞𝔽, return +∞.
|
266
|
-
// 4. If number is -∞𝔽, return -∞.
|
267
|
-
if (!Number.isFinite(number)) return number;
|
268
|
-
|
269
|
-
// 5. Return truncate(ℝ(number)).
|
270
|
-
number = Math.trunc(number);
|
271
|
-
|
272
|
-
// return 0 for -0
|
273
|
-
if (number == 0) return 0;
|
274
|
-
return number;
|
275
|
-
};
|
276
|
-
|
277
256
|
// 21.4.1.27 MakeTime (hour, min, sec, ms)
|
278
257
|
// https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-maketime
|
279
258
|
export const __ecma262_MakeTime = (hour: number, min: number, sec: number, ms: number): number => {
|
@@ -720,12 +699,9 @@ export const __Porffor_date_allocate = (): Date => {
|
|
720
699
|
const hack: bytestring = '';
|
721
700
|
|
722
701
|
if (hack.length == 0) {
|
723
|
-
hack.length = Porffor.wasm`
|
724
|
-
memory.grow 0
|
725
|
-
drop
|
726
|
-
memory.size 0
|
702
|
+
hack.length = Porffor.wasm`
|
727
703
|
i32.const 1
|
728
|
-
|
704
|
+
memory.grow 0
|
729
705
|
i32.const 65536
|
730
706
|
i32.mul
|
731
707
|
i32.from_u`;
|
@@ -1892,8 +1868,7 @@ export const __ecma262_ToDateString = (tv: number) => {
|
|
1892
1868
|
|
1893
1869
|
// 1. If tv is NaN, return "Invalid Date".
|
1894
1870
|
if (Number.isNaN(tv)) {
|
1895
|
-
out = 'Invalid Date';
|
1896
|
-
return out;
|
1871
|
+
return out = 'Invalid Date';
|
1897
1872
|
}
|
1898
1873
|
|
1899
1874
|
// 2. Let t be LocalTime(tv).
|
@@ -0,0 +1,22 @@
|
|
1
|
+
export default () => {
|
2
|
+
let out = '';
|
3
|
+
|
4
|
+
const error = name => out += `export const ${name} = (message: bytestring) => {
|
5
|
+
return {};
|
6
|
+
};
|
7
|
+
|
8
|
+
export const ${name}$constructor = (message: bytestring) => {
|
9
|
+
return {};
|
10
|
+
};`;
|
11
|
+
|
12
|
+
error('Error');
|
13
|
+
error('AggregateError');
|
14
|
+
error('TypeError');
|
15
|
+
error('ReferenceError');
|
16
|
+
error('SyntaxError');
|
17
|
+
error('RangeError');
|
18
|
+
error('EvalError');
|
19
|
+
error('URIError');
|
20
|
+
|
21
|
+
return out;
|
22
|
+
};
|
package/compiler/builtins/int.ts
CHANGED