porffor 0.2.0-fde989a → 0.14.0-032e4ad08
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 +262 -0
- package/LICENSE +20 -20
- package/README.md +135 -94
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +216 -0
- package/compiler/2c.js +66 -54
- package/compiler/{sections.js → assemble.js} +109 -21
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +19 -0
- package/compiler/builtins/array.ts +225 -0
- package/compiler/builtins/base64.ts +77 -0
- package/compiler/builtins/boolean.ts +20 -0
- package/compiler/builtins/crypto.ts +121 -0
- package/compiler/builtins/date.ts +2069 -0
- package/compiler/builtins/error.js +22 -0
- package/compiler/builtins/escape.ts +140 -0
- package/compiler/builtins/function.ts +7 -0
- package/compiler/builtins/int.ts +147 -0
- package/compiler/builtins/math.ts +410 -0
- package/compiler/builtins/number.ts +531 -0
- package/compiler/builtins/object.ts +6 -0
- package/compiler/builtins/porffor.d.ts +60 -0
- package/compiler/builtins/set.ts +199 -0
- package/compiler/builtins/string.ts +1081 -0
- package/compiler/builtins/symbol.ts +62 -0
- package/compiler/builtins.js +466 -284
- package/compiler/{codeGen.js → codegen.js} +1573 -656
- package/compiler/decompile.js +3 -4
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +94 -10
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +2110 -0
- package/compiler/index.js +29 -44
- package/compiler/log.js +6 -3
- package/compiler/opt.js +55 -41
- package/compiler/parse.js +38 -30
- package/compiler/precompile.js +121 -0
- package/compiler/prefs.js +31 -0
- package/compiler/prototype.js +209 -201
- package/compiler/types.js +38 -0
- package/compiler/wasmSpec.js +33 -8
- package/compiler/wrap.js +154 -89
- package/package.json +9 -5
- package/porf +2 -0
- package/porffor_tmp.c +202 -0
- package/rhemyn/compile.js +46 -27
- package/rhemyn/parse.js +322 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +33 -34
- package/runner/debug.js +117 -0
- package/runner/index.js +80 -12
- package/runner/profiler.js +75 -0
- package/runner/repl.js +58 -15
- package/runner/sizes.js +37 -37
- package/runner/version.js +10 -8
- package/compiler/builtins/base64.js +0 -92
- package/filesize.cmd +0 -2
- package/runner/info.js +0 -89
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
- package/runner/transform.js +0 -15
- package/tmp.c +0 -661
- package/util/enum.js +0 -20
@@ -0,0 +1,31 @@
|
|
1
|
+
const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls', 'optUnused' ];
|
2
|
+
|
3
|
+
let cache = {};
|
4
|
+
const obj = new Proxy({}, {
|
5
|
+
get(_, p) {
|
6
|
+
// intentionally misses with undefined values cached
|
7
|
+
if (cache[p]) return cache[p];
|
8
|
+
|
9
|
+
const ret = (() => {
|
10
|
+
// fooBar -> foo-bar
|
11
|
+
const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
12
|
+
const prefix = name.length === 1 ? '-' : '--';
|
13
|
+
if (process.argv.includes(prefix + name)) return true;
|
14
|
+
if (process.argv.includes(prefix + 'no-' + name)) return false;
|
15
|
+
|
16
|
+
const valArg = process.argv.find(x => x.startsWith(`${prefix}${name}=`));
|
17
|
+
if (valArg) return valArg.slice(name.length + 1 + prefix.length);
|
18
|
+
|
19
|
+
if (onByDefault.includes(p)) return true;
|
20
|
+
return undefined;
|
21
|
+
})();
|
22
|
+
|
23
|
+
// do not cache in web demo as args are changed live
|
24
|
+
if (!globalThis.document) cache[p] = ret;
|
25
|
+
return ret;
|
26
|
+
}
|
27
|
+
});
|
28
|
+
|
29
|
+
obj.uncache = () => cache = {};
|
30
|
+
|
31
|
+
export default obj;
|
package/compiler/prototype.js
CHANGED
@@ -1,36 +1,22 @@
|
|
1
|
-
import { Opcodes, Blocktype, Valtype, ValtypeSize
|
2
|
-
import { number } from
|
3
|
-
import { unsignedLEB128 } from
|
4
|
-
import { UNDEFINED } from
|
5
|
-
|
6
|
-
|
7
|
-
const TYPES = {
|
8
|
-
number: 0x00,
|
9
|
-
boolean: 0x01,
|
10
|
-
string: 0x02,
|
11
|
-
undefined: 0x03,
|
12
|
-
object: 0x04,
|
13
|
-
function: 0x05,
|
14
|
-
symbol: 0x06,
|
15
|
-
bigint: 0x07,
|
16
|
-
|
17
|
-
// these are not "typeof" types but tracked internally
|
18
|
-
_array: 0x10,
|
19
|
-
_regexp: 0x11,
|
20
|
-
_bytestring: 0x12
|
21
|
-
};
|
1
|
+
import { Opcodes, Blocktype, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
+
import { number } from './embedding.js';
|
3
|
+
import { unsignedLEB128 } from './encoding.js';
|
4
|
+
import { UNDEFINED } from './builtins.js';
|
5
|
+
import { TYPES } from './types.js';
|
6
|
+
import Prefs from './prefs.js';
|
22
7
|
|
23
8
|
// todo: turn these into built-ins once arrays and these become less hacky
|
24
9
|
|
25
10
|
export const PrototypeFuncs = function() {
|
26
|
-
const noUnlikelyChecks =
|
27
|
-
|
28
|
-
|
11
|
+
const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
|
12
|
+
|
13
|
+
let zeroChecks;
|
14
|
+
if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
|
29
15
|
else zeroChecks = {};
|
30
16
|
|
31
|
-
this[TYPES.
|
17
|
+
this[TYPES.array] = {
|
32
18
|
// lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
|
33
|
-
at: (pointer, length, wIndex, iTmp) => [
|
19
|
+
at: (pointer, length, wIndex, wType, iTmp) => [
|
34
20
|
...wIndex,
|
35
21
|
Opcodes.i32_to,
|
36
22
|
[ Opcodes.local_tee, iTmp ],
|
@@ -61,31 +47,39 @@ export const PrototypeFuncs = function() {
|
|
61
47
|
[ Opcodes.end ],
|
62
48
|
|
63
49
|
[ Opcodes.local_get, iTmp ],
|
64
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
50
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
65
51
|
[ Opcodes.i32_mul ],
|
66
|
-
|
67
52
|
...pointer,
|
68
53
|
[ Opcodes.i32_add ],
|
54
|
+
[ Opcodes.local_set, iTmp ],
|
69
55
|
|
70
56
|
// read from memory
|
71
|
-
[ Opcodes.
|
57
|
+
[ Opcodes.local_get, iTmp ],
|
58
|
+
[ Opcodes.load, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
59
|
+
|
60
|
+
[ Opcodes.local_get, iTmp ],
|
61
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
72
62
|
],
|
73
63
|
|
74
64
|
// todo: only for 1 argument
|
75
|
-
push: (pointer, length, wNewMember,
|
65
|
+
push: (pointer, length, wNewMember, wType, iTmp, _2, _3, unusedValue) => [
|
76
66
|
// get memory offset of array at last index (length)
|
77
67
|
...length.getCachedI32(),
|
78
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
68
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
79
69
|
[ Opcodes.i32_mul ],
|
80
|
-
|
81
70
|
...pointer,
|
82
71
|
[ Opcodes.i32_add ],
|
72
|
+
[ Opcodes.local_set, iTmp ],
|
83
73
|
|
84
|
-
//
|
74
|
+
// store value
|
75
|
+
[ Opcodes.local_get, iTmp ],
|
85
76
|
...wNewMember,
|
77
|
+
[ Opcodes.store, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
86
78
|
|
87
|
-
// store
|
88
|
-
[ Opcodes.
|
79
|
+
// store type
|
80
|
+
[ Opcodes.local_get, iTmp ],
|
81
|
+
...wType,
|
82
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize[valtype]) ],
|
89
83
|
|
90
84
|
// bump array length by 1 and return it
|
91
85
|
...length.setI32([
|
@@ -107,7 +101,7 @@ export const PrototypeFuncs = function() {
|
|
107
101
|
// ...length.get()
|
108
102
|
],
|
109
103
|
|
110
|
-
pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
|
104
|
+
pop: (pointer, length, _1, _2, iTmp, _3, _4, unusedValue) => [
|
111
105
|
// if length == 0, noop
|
112
106
|
...length.getCachedI32(),
|
113
107
|
[ Opcodes.i32_eqz ],
|
@@ -135,20 +129,25 @@ export const PrototypeFuncs = function() {
|
|
135
129
|
// load last element
|
136
130
|
...(unusedValue() ? [] : [
|
137
131
|
...length.getCachedI32(),
|
138
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
132
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
139
133
|
[ Opcodes.i32_mul ],
|
140
134
|
|
141
135
|
...pointer,
|
142
136
|
[ Opcodes.i32_add ],
|
137
|
+
[ Opcodes.local_set, iTmp ],
|
143
138
|
|
144
|
-
[ Opcodes.
|
139
|
+
[ Opcodes.local_get, iTmp ],
|
140
|
+
[ Opcodes.load, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
141
|
+
|
142
|
+
[ Opcodes.local_get, iTmp ],
|
143
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize[valtype]) ]
|
145
144
|
])
|
146
145
|
],
|
147
146
|
|
148
147
|
shift: (pointer, length) => [
|
149
148
|
// if length == 0, noop
|
150
149
|
...length.getCachedI32(),
|
151
|
-
Opcodes.i32_eqz,
|
150
|
+
[ Opcodes.i32_eqz ],
|
152
151
|
[ Opcodes.if, Blocktype.void ],
|
153
152
|
...number(UNDEFINED),
|
154
153
|
[ Opcodes.br, 1 ],
|
@@ -167,8 +166,12 @@ export const PrototypeFuncs = function() {
|
|
167
166
|
]),
|
168
167
|
|
169
168
|
// load first element
|
169
|
+
// todo/perf: unusedValue opt
|
170
|
+
...pointer,
|
171
|
+
[ Opcodes.load, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
172
|
+
|
170
173
|
...pointer,
|
171
|
-
[ Opcodes.
|
174
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize[valtype]) ],
|
172
175
|
|
173
176
|
// offset page by -1 ind
|
174
177
|
// ...number(pointer + ValtypeSize.i32, Valtype.i32), // dst = base array index + length size
|
@@ -184,13 +187,13 @@ export const PrototypeFuncs = function() {
|
|
184
187
|
[ Opcodes.i32_add ],
|
185
188
|
|
186
189
|
// src = base array index + length size + an index
|
187
|
-
...number(ValtypeSize.i32 + ValtypeSize[valtype], Valtype.i32),
|
190
|
+
...number(ValtypeSize.i32 + ValtypeSize[valtype] + 1, Valtype.i32),
|
188
191
|
...pointer,
|
189
192
|
[ Opcodes.i32_add ],
|
190
193
|
|
191
194
|
// size = new length * sizeof element
|
192
195
|
...length.getCachedI32(),
|
193
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
196
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
194
197
|
[ Opcodes.i32_mul ],
|
195
198
|
[ ...Opcodes.memory_copy, 0x00, 0x00 ]
|
196
199
|
|
@@ -208,7 +211,7 @@ export const PrototypeFuncs = function() {
|
|
208
211
|
// ]),
|
209
212
|
],
|
210
213
|
|
211
|
-
fill: (pointer, length, wElement, iTmp) => [
|
214
|
+
fill: (pointer, length, wElement, wType, iTmp, iTmp2) => [
|
212
215
|
...wElement,
|
213
216
|
[ Opcodes.local_set, iTmp ],
|
214
217
|
|
@@ -220,7 +223,7 @@ export const PrototypeFuncs = function() {
|
|
220
223
|
[ Opcodes.i32_sub ],
|
221
224
|
|
222
225
|
// * sizeof value
|
223
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
226
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
224
227
|
[ Opcodes.i32_mul ],
|
225
228
|
|
226
229
|
...length.setCachedI32(),
|
@@ -238,17 +241,25 @@ export const PrototypeFuncs = function() {
|
|
238
241
|
|
239
242
|
[ Opcodes.loop, Blocktype.void ],
|
240
243
|
|
241
|
-
//
|
244
|
+
// calculate offset
|
242
245
|
...length.getCachedI32(),
|
243
246
|
...pointer,
|
244
247
|
[ Opcodes.i32_add ],
|
248
|
+
[ Opcodes.local_set, iTmp2 ],
|
245
249
|
|
250
|
+
// store value
|
251
|
+
[ Opcodes.local_get, iTmp2 ],
|
246
252
|
[ Opcodes.local_get, iTmp ],
|
247
|
-
[ Opcodes.store,
|
253
|
+
[ Opcodes.store, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
254
|
+
|
255
|
+
// store type
|
256
|
+
[ Opcodes.local_get, iTmp2 ],
|
257
|
+
...wType,
|
258
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize[valtype]) ],
|
248
259
|
|
249
260
|
// pointer - sizeof value
|
250
261
|
...length.getCachedI32(),
|
251
|
-
...number(ValtypeSize[valtype], Valtype.i32),
|
262
|
+
...number(ValtypeSize[valtype] + 1, Valtype.i32),
|
252
263
|
[ Opcodes.i32_sub ],
|
253
264
|
|
254
265
|
...length.setCachedI32(),
|
@@ -267,13 +278,17 @@ export const PrototypeFuncs = function() {
|
|
267
278
|
]
|
268
279
|
};
|
269
280
|
|
270
|
-
this[TYPES.
|
271
|
-
this[TYPES.
|
272
|
-
this[TYPES.
|
273
|
-
this[TYPES.
|
281
|
+
this[TYPES.array].at.local = Valtype.i32;
|
282
|
+
this[TYPES.array].push.returnType = TYPES.number;
|
283
|
+
this[TYPES.array].push.noArgRetLength = true;
|
284
|
+
this[TYPES.array].push.local = Valtype.i32;
|
285
|
+
this[TYPES.array].pop.local = Valtype.i32;
|
286
|
+
this[TYPES.array].fill.local = valtypeBinary;
|
287
|
+
this[TYPES.array].fill.local2 = Valtype.i32;
|
288
|
+
this[TYPES.array].fill.returnType = TYPES.array;
|
274
289
|
|
275
290
|
this[TYPES.string] = {
|
276
|
-
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
291
|
+
at: (pointer, length, wIndex, wType, iTmp, _, arrayShell) => {
|
277
292
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
278
293
|
|
279
294
|
return [
|
@@ -331,7 +346,7 @@ export const PrototypeFuncs = function() {
|
|
331
346
|
},
|
332
347
|
|
333
348
|
// todo: out of bounds properly
|
334
|
-
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
349
|
+
charAt: (pointer, length, wIndex, wType, _1, _2, arrayShell) => {
|
335
350
|
const [ newOut, newPointer ] = arrayShell(1, 'i16');
|
336
351
|
|
337
352
|
return [
|
@@ -342,8 +357,8 @@ export const PrototypeFuncs = function() {
|
|
342
357
|
...number(0, Valtype.i32), // base 0 for store later
|
343
358
|
|
344
359
|
...wIndex,
|
345
|
-
|
346
360
|
Opcodes.i32_to,
|
361
|
+
|
347
362
|
...number(ValtypeSize.i16, Valtype.i32),
|
348
363
|
[ Opcodes.i32_mul ],
|
349
364
|
|
@@ -361,127 +376,124 @@ export const PrototypeFuncs = function() {
|
|
361
376
|
];
|
362
377
|
},
|
363
378
|
|
364
|
-
charCodeAt: (pointer, length, wIndex, iTmp) =>
|
365
|
-
|
366
|
-
|
367
|
-
Opcodes.i32_to,
|
368
|
-
|
369
|
-
...(zeroChecks.charcodeat ? [] : [
|
370
|
-
[ Opcodes.local_set, iTmp ],
|
379
|
+
charCodeAt: (pointer, length, wIndex, wType, iTmp) => [
|
380
|
+
...wIndex,
|
381
|
+
Opcodes.i32_to,
|
371
382
|
|
372
|
-
|
373
|
-
|
374
|
-
[ Opcodes.local_get, iTmp ],
|
375
|
-
...number(0, Valtype.i32),
|
376
|
-
[ Opcodes.i32_lt_s ],
|
377
|
-
]),
|
383
|
+
...(zeroChecks.charcodeat ? [] : [
|
384
|
+
[ Opcodes.local_set, iTmp ],
|
378
385
|
|
379
|
-
|
386
|
+
// index < 0
|
387
|
+
...(noUnlikelyChecks ? [] : [
|
380
388
|
[ Opcodes.local_get, iTmp ],
|
381
|
-
...
|
382
|
-
[ Opcodes.
|
389
|
+
...number(0, Valtype.i32),
|
390
|
+
[ Opcodes.i32_lt_s ],
|
391
|
+
]),
|
383
392
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
[ Opcodes.end ],
|
393
|
+
// index >= length
|
394
|
+
[ Opcodes.local_get, iTmp ],
|
395
|
+
...length.getCachedI32(),
|
396
|
+
[ Opcodes.i32_ge_s ],
|
389
397
|
|
390
|
-
|
391
|
-
]
|
398
|
+
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
399
|
+
[ Opcodes.if, Blocktype.void ],
|
400
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
401
|
+
[ Opcodes.br, 1 ],
|
402
|
+
[ Opcodes.end ],
|
392
403
|
|
393
|
-
|
394
|
-
|
404
|
+
[ Opcodes.local_get, iTmp ],
|
405
|
+
]),
|
395
406
|
|
396
|
-
|
397
|
-
|
407
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
408
|
+
[ Opcodes.i32_mul ],
|
398
409
|
|
399
|
-
|
400
|
-
|
401
|
-
Opcodes.i32_from_u
|
402
|
-
];
|
403
|
-
},
|
410
|
+
...pointer,
|
411
|
+
[ Opcodes.i32_add ],
|
404
412
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
[ Opcodes.local_set, iTmp ],
|
413
|
+
// load current string ind {arg}
|
414
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
415
|
+
Opcodes.i32_from_u
|
416
|
+
],
|
410
417
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
...pointer,
|
416
|
-
[ Opcodes.i32_add ],
|
417
|
-
...length.setCachedI32(),
|
418
|
+
isWellFormed: (pointer, length, _1, _2, iTmp, iTmp2) => [
|
419
|
+
// note: we cannot presume it begins as 0 in case it was used previously
|
420
|
+
...pointer,
|
421
|
+
[ Opcodes.local_set, iTmp ],
|
418
422
|
|
419
|
-
|
423
|
+
// use cached length as end pointer
|
424
|
+
...length.getCachedI32(),
|
425
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
426
|
+
[ Opcodes.i32_mul ],
|
427
|
+
...pointer,
|
428
|
+
[ Opcodes.i32_add ],
|
429
|
+
...length.setCachedI32(),
|
420
430
|
|
421
|
-
|
431
|
+
[ Opcodes.loop, Blocktype.void ],
|
422
432
|
|
423
|
-
|
424
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
425
|
-
[ Opcodes.local_set, iTmp2 ],
|
426
|
-
|
427
|
-
// if not surrogate, continue
|
428
|
-
[ Opcodes.local_get, iTmp2 ],
|
429
|
-
...number(0xF800, Valtype.i32),
|
430
|
-
[ Opcodes.i32_and ],
|
431
|
-
...number(0xD800, Valtype.i32),
|
432
|
-
[ Opcodes.i32_ne ],
|
433
|
-
[ Opcodes.br_if, 0 ],
|
434
|
-
|
435
|
-
// if not leading surrogate, return false
|
436
|
-
[ Opcodes.local_get, iTmp2 ],
|
437
|
-
...number(0xDC00, Valtype.i32),
|
438
|
-
[ Opcodes.i32_ge_s ],
|
439
|
-
[ Opcodes.if, Blocktype.void ],
|
440
|
-
...number(0),
|
441
|
-
[ Opcodes.br, 3 ],
|
442
|
-
[ Opcodes.end ],
|
433
|
+
[ Opcodes.block, Blocktype.void ],
|
443
434
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
435
|
+
[ Opcodes.local_get, iTmp ],
|
436
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
437
|
+
[ Opcodes.local_set, iTmp2 ],
|
438
|
+
|
439
|
+
// if not surrogate, continue
|
440
|
+
[ Opcodes.local_get, iTmp2 ],
|
441
|
+
...number(0xF800, Valtype.i32),
|
442
|
+
[ Opcodes.i32_and ],
|
443
|
+
...number(0xD800, Valtype.i32),
|
444
|
+
[ Opcodes.i32_ne ],
|
445
|
+
[ Opcodes.br_if, 0 ],
|
455
446
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
447
|
+
// if not leading surrogate, return false
|
448
|
+
[ Opcodes.local_get, iTmp2 ],
|
449
|
+
...number(0xDC00, Valtype.i32),
|
450
|
+
[ Opcodes.i32_ge_s ],
|
451
|
+
[ Opcodes.if, Blocktype.void ],
|
452
|
+
...number(0),
|
453
|
+
[ Opcodes.br, 3 ],
|
454
|
+
[ Opcodes.end ],
|
461
455
|
|
462
|
-
|
456
|
+
// if not followed by trailing surrogate, return false
|
457
|
+
[ Opcodes.local_get, iTmp ],
|
458
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32 + ValtypeSize.i16) ],
|
459
|
+
...number(0xFC00, Valtype.i32),
|
460
|
+
[ Opcodes.i32_and ],
|
461
|
+
...number(0xDC00, Valtype.i32),
|
462
|
+
[ Opcodes.i32_ne ],
|
463
|
+
[ Opcodes.if, Blocktype.void ],
|
464
|
+
...number(0),
|
465
|
+
[ Opcodes.br, 3 ],
|
466
|
+
[ Opcodes.end ],
|
463
467
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
468
|
+
// bump index again since gone through two valid chars
|
469
|
+
[ Opcodes.local_get, iTmp ],
|
470
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
471
|
+
[ Opcodes.i32_add ],
|
472
|
+
[ Opcodes.local_set, iTmp ],
|
473
|
+
|
474
|
+
[ Opcodes.end ],
|
469
475
|
|
470
|
-
|
471
|
-
|
472
|
-
|
476
|
+
// bump pointer and loop if not at the end
|
477
|
+
[ Opcodes.local_get, iTmp ],
|
478
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
479
|
+
[ Opcodes.i32_add ],
|
480
|
+
[ Opcodes.local_tee, iTmp ],
|
473
481
|
|
474
|
-
|
482
|
+
...length.getCachedI32(), // end pointer
|
483
|
+
[ Opcodes.i32_ne ],
|
484
|
+
[ Opcodes.br_if, 0 ],
|
475
485
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
486
|
+
[ Opcodes.end ],
|
487
|
+
|
488
|
+
// return true
|
489
|
+
...number(1)
|
490
|
+
]
|
480
491
|
};
|
481
492
|
|
482
493
|
this[TYPES.string].at.local = Valtype.i32;
|
483
494
|
this[TYPES.string].at.returnType = TYPES.string;
|
484
495
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
496
|
+
this[TYPES.string].charCodeAt.returnType = TYPES.number;
|
485
497
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
486
498
|
this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
487
499
|
|
@@ -489,10 +501,10 @@ export const PrototypeFuncs = function() {
|
|
489
501
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
490
502
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
491
503
|
|
492
|
-
if (
|
493
|
-
this[TYPES.
|
494
|
-
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
495
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
504
|
+
if (Prefs.bytestring) {
|
505
|
+
this[TYPES.bytestring] = {
|
506
|
+
at: (pointer, length, wIndex, wType, iTmp, _, arrayShell) => {
|
507
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
496
508
|
|
497
509
|
return [
|
498
510
|
// setup new/out array
|
@@ -547,8 +559,8 @@ export const PrototypeFuncs = function() {
|
|
547
559
|
},
|
548
560
|
|
549
561
|
// todo: out of bounds properly
|
550
|
-
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
551
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
562
|
+
charAt: (pointer, length, wIndex, wType, _1, _2, arrayShell) => {
|
563
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
552
564
|
|
553
565
|
return [
|
554
566
|
// setup new/out array
|
@@ -558,7 +570,6 @@ export const PrototypeFuncs = function() {
|
|
558
570
|
...number(0, Valtype.i32), // base 0 for store later
|
559
571
|
|
560
572
|
...wIndex,
|
561
|
-
|
562
573
|
Opcodes.i32_to,
|
563
574
|
|
564
575
|
...pointer,
|
@@ -575,60 +586,57 @@ export const PrototypeFuncs = function() {
|
|
575
586
|
];
|
576
587
|
},
|
577
588
|
|
578
|
-
charCodeAt: (pointer, length, wIndex, iTmp) =>
|
579
|
-
|
580
|
-
|
581
|
-
Opcodes.i32_to,
|
582
|
-
|
583
|
-
...(zeroChecks.charcodeat ? [] : [
|
584
|
-
[ Opcodes.local_set, iTmp ],
|
589
|
+
charCodeAt: (pointer, length, wIndex, wType, iTmp) => [
|
590
|
+
...wIndex,
|
591
|
+
Opcodes.i32_to,
|
585
592
|
|
586
|
-
|
587
|
-
|
588
|
-
[ Opcodes.local_get, iTmp ],
|
589
|
-
...number(0, Valtype.i32),
|
590
|
-
[ Opcodes.i32_lt_s ],
|
591
|
-
]),
|
593
|
+
...(zeroChecks.charcodeat ? [] : [
|
594
|
+
[ Opcodes.local_set, iTmp ],
|
592
595
|
|
593
|
-
|
596
|
+
// index < 0
|
597
|
+
...(noUnlikelyChecks ? [] : [
|
594
598
|
[ Opcodes.local_get, iTmp ],
|
595
|
-
...
|
596
|
-
[ Opcodes.
|
599
|
+
...number(0, Valtype.i32),
|
600
|
+
[ Opcodes.i32_lt_s ],
|
601
|
+
]),
|
597
602
|
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
[ Opcodes.end ],
|
603
|
+
// index >= length
|
604
|
+
[ Opcodes.local_get, iTmp ],
|
605
|
+
...length.getCachedI32(),
|
606
|
+
[ Opcodes.i32_ge_s ],
|
603
607
|
|
604
|
-
|
605
|
-
]
|
608
|
+
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
609
|
+
[ Opcodes.if, Blocktype.void ],
|
610
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
611
|
+
[ Opcodes.br, 1 ],
|
612
|
+
[ Opcodes.end ],
|
606
613
|
|
607
|
-
|
608
|
-
|
614
|
+
[ Opcodes.local_get, iTmp ],
|
615
|
+
]),
|
609
616
|
|
610
|
-
|
611
|
-
|
612
|
-
Opcodes.i32_from_u
|
613
|
-
];
|
614
|
-
},
|
617
|
+
...pointer,
|
618
|
+
[ Opcodes.i32_add ],
|
615
619
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
620
|
+
// load current string ind {arg}
|
621
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
622
|
+
Opcodes.i32_from_u
|
623
|
+
],
|
624
|
+
|
625
|
+
isWellFormed: () => [
|
626
|
+
// we know it must be true as it is a bytestring lol
|
627
|
+
...number(1)
|
628
|
+
]
|
622
629
|
};
|
623
630
|
|
624
|
-
this[TYPES.
|
625
|
-
this[TYPES.
|
626
|
-
this[TYPES.
|
627
|
-
this[TYPES.
|
628
|
-
this[TYPES.
|
631
|
+
this[TYPES.bytestring].at.local = Valtype.i32;
|
632
|
+
this[TYPES.bytestring].at.returnType = TYPES.bytestring;
|
633
|
+
this[TYPES.bytestring].charAt.returnType = TYPES.bytestring;
|
634
|
+
this[TYPES.bytestring].charCodeAt.returnType = TYPES.number;
|
635
|
+
this[TYPES.bytestring].charCodeAt.local = Valtype.i32;
|
636
|
+
this[TYPES.bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
629
637
|
|
630
|
-
this[TYPES.
|
631
|
-
this[TYPES.
|
632
|
-
this[TYPES.
|
638
|
+
this[TYPES.bytestring].isWellFormed.local = Valtype.i32;
|
639
|
+
this[TYPES.bytestring].isWellFormed.local2 = Valtype.i32;
|
640
|
+
this[TYPES.bytestring].isWellFormed.returnType = TYPES.boolean;
|
633
641
|
}
|
634
642
|
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
export const TYPES = {
|
2
|
+
number: 0x00,
|
3
|
+
boolean: 0x01,
|
4
|
+
string: 0x02,
|
5
|
+
undefined: 0x03,
|
6
|
+
object: 0x04,
|
7
|
+
function: 0x05,
|
8
|
+
symbol: 0x06,
|
9
|
+
bigint: 0x07
|
10
|
+
};
|
11
|
+
|
12
|
+
export const TYPE_NAMES = {
|
13
|
+
[TYPES.number]: 'Number',
|
14
|
+
[TYPES.boolean]: 'Boolean',
|
15
|
+
[TYPES.string]: 'String',
|
16
|
+
[TYPES.undefined]: 'undefined',
|
17
|
+
[TYPES.object]: 'Object',
|
18
|
+
[TYPES.function]: 'Function',
|
19
|
+
[TYPES.symbol]: 'Symbol',
|
20
|
+
[TYPES.bigint]: 'BigInt'
|
21
|
+
};
|
22
|
+
|
23
|
+
export const INTERNAL_TYPE_BASE = 0x10;
|
24
|
+
let internalTypeIndex = INTERNAL_TYPE_BASE;
|
25
|
+
const registerInternalType = name => {
|
26
|
+
const n = internalTypeIndex++;
|
27
|
+
TYPES[name.toLowerCase()] = n;
|
28
|
+
TYPE_NAMES[n] = name;
|
29
|
+
};
|
30
|
+
|
31
|
+
// note: when adding a new internal type, please also add a deserializer to wrap.js
|
32
|
+
// (it is okay to add a throw todo deserializer for wips)
|
33
|
+
|
34
|
+
registerInternalType('Array');
|
35
|
+
registerInternalType('RegExp');
|
36
|
+
registerInternalType('ByteString');
|
37
|
+
registerInternalType('Date');
|
38
|
+
registerInternalType('Set');
|