porffor 0.58.19 → 0.59.0
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/AGENT.md +16 -7
- package/compiler/assemble.js +2 -13
- package/compiler/builtins/regexp.ts +47 -7
- package/compiler/builtins/string.ts +0 -35
- package/compiler/builtins/string_f64.ts +97 -0
- package/compiler/builtins.js +30 -37
- package/compiler/builtins_precompiled.js +379 -367
- package/compiler/codegen.js +60 -15
- package/compiler/pgo.js +21 -43
- package/compiler/wrap.js +3 -8
- package/fuzz/index.js +1 -1
- package/package.json +1 -1
- package/runtime/debug.js +1 -1
- package/runtime/index.js +1 -1
- package/runtime/profile.js +1 -1
- package/runtime/repl.js +1 -1
- package/wow.js +0 -1
package/AGENT.md
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
-
you are an assistant coder for Porffor -
|
1
|
+
you are an assistant coder for Porffor - an early javascript and typescript to webassembly and native ahead-of-time compiler. the codebase is written in js and ts.
|
2
2
|
|
3
3
|
IMPORTANT:
|
4
4
|
- built-ins apis (Date, String.prototype, etc) are written in ts inside `compiler/builtins`
|
5
5
|
- once you update a file inside that directory, you MUST run `./porf precompile` to compile to make your changes effective
|
6
6
|
|
7
|
-
|
7
|
+
Test your work using the test262 tools available, iterate independently but do not get stuck on one chain of thought or approach. Paths for test262 tools should be relative to the 'test262/test' directory (e.g., 'built-ins/RegExp' NOT 'test262/test/built-ins/RegExp').
|
8
8
|
|
9
|
-
|
10
|
-
-
|
11
|
-
-
|
12
|
-
|
13
|
-
|
9
|
+
You can also do the following via bash/shell commands:
|
10
|
+
- To get an overview of the most failing directories, use the command: `node test262/fails.cjs`
|
11
|
+
- To just evaluate code in the engine, use the command: `./porf -p "..."`
|
12
|
+
|
13
|
+
## Code Style
|
14
|
+
- After finishing, check if your work/diff could be simplified
|
15
|
+
- Always use single quotes (unless double is required)
|
16
|
+
- 2-space indentation, LF line endings, no trailing whitespace
|
17
|
+
- Built-in APIs in `compiler/builtins/` written in TypeScript
|
18
|
+
- Inline code in built-ins, avoid helper functions
|
19
|
+
- Use semicolons
|
20
|
+
- Do not use trailing commas
|
21
|
+
- Use const/let, avoid var
|
22
|
+
- Follow existing naming: camelCase for variables, PascalCase for types
|
package/compiler/assemble.js
CHANGED
@@ -208,20 +208,9 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
208
208
|
const bytesPerFunc = funcs.bytesPerFuncLut();
|
209
209
|
for (let i = 0; i < indirectFuncs.length; i++) {
|
210
210
|
const func = indirectFuncs[i].wrapperOf;
|
211
|
-
let name = func.name;
|
212
211
|
|
213
212
|
// userland exposed .length
|
214
|
-
|
215
|
-
if (length == null) {
|
216
|
-
length = func.params.length;
|
217
|
-
if (func.constr) length -= 4;
|
218
|
-
if (func.method) length -= 2;
|
219
|
-
if (!func.internal || func.typedParams) length = Math.floor(length / 2);
|
220
|
-
|
221
|
-
// remove _this from internal prototype funcs
|
222
|
-
if (func.internal && name.includes('_prototype_')) length--;
|
223
|
-
}
|
224
|
-
|
213
|
+
const length = func.jsLength;
|
225
214
|
bytes.push(length % 256, (length / 256 | 0) % 256);
|
226
215
|
|
227
216
|
let flags = 0b00000000; // 8 flag bits
|
@@ -229,8 +218,8 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
229
218
|
if (func.constr) flags |= 0b10;
|
230
219
|
bytes.push(flags);
|
231
220
|
|
221
|
+
let name = func.name;
|
232
222
|
if (name.startsWith('#')) name = '';
|
233
|
-
|
234
223
|
// eg: __String_prototype_toLowerCase -> toLowerCase
|
235
224
|
if (name.startsWith('__')) name = name.split('_').pop();
|
236
225
|
|
@@ -787,11 +787,11 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
787
787
|
const inputLen: i32 = Porffor.wasm.i32.load(input, 0, 0);
|
788
788
|
let searchStart: i32 = 0;
|
789
789
|
if (global || sticky) {
|
790
|
-
searchStart = Porffor.wasm.i32.
|
790
|
+
searchStart = Porffor.wasm.i32.load16_u(regexp, 0, 8);
|
791
791
|
}
|
792
792
|
|
793
793
|
if (searchStart > inputLen) {
|
794
|
-
if (global || sticky) Porffor.wasm.i32.
|
794
|
+
if (global || sticky) Porffor.wasm.i32.store16(regexp, 0, 0, 8);
|
795
795
|
return null;
|
796
796
|
}
|
797
797
|
|
@@ -919,7 +919,7 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
919
919
|
backtrack = true;
|
920
920
|
} else {
|
921
921
|
const classId: i32 = Porffor.wasm.i32.load8_u(pc, 0, 1);
|
922
|
-
const char: i32 = Porffor.wasm.i32.load8_u(input +
|
922
|
+
const char: i32 = Porffor.wasm.i32.load8_u(input + sp, 0, 4);
|
923
923
|
let isMatch: boolean = false;
|
924
924
|
if (classId == 1) isMatch = char >= 48 && char <= 57;
|
925
925
|
else if (classId == 2) isMatch = !(char >= 48 && char <= 57);
|
@@ -948,16 +948,56 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
948
948
|
backtrack = true;
|
949
949
|
}
|
950
950
|
} else if (op == 0x07) { // word boundary
|
951
|
-
|
952
|
-
|
951
|
+
let prevIsWord: boolean = false;
|
952
|
+
if (sp > 0) {
|
953
|
+
const prevChar: i32 = Porffor.wasm.i32.load8_u(input + sp, 0, 3);
|
954
|
+
prevIsWord = Porffor.fastOr(
|
955
|
+
prevChar >= 65 && prevChar <= 90, // A-Z
|
956
|
+
prevChar >= 97 && prevChar <= 122, // a-z
|
957
|
+
prevChar >= 48 && prevChar <= 57, // 0-9
|
958
|
+
prevChar == 95 // _
|
959
|
+
);
|
960
|
+
}
|
961
|
+
|
962
|
+
let nextIsWord: boolean = false;
|
963
|
+
if (sp < inputLen) {
|
964
|
+
const nextChar: i32 = Porffor.wasm.i32.load8_u(input + sp, 0, 4);
|
965
|
+
nextIsWord = Porffor.fastOr(
|
966
|
+
nextChar >= 65 && nextChar <= 90, // A-Z
|
967
|
+
nextChar >= 97 && nextChar <= 122, // a-z
|
968
|
+
nextChar >= 48 && nextChar <= 57, // 0-9
|
969
|
+
nextChar == 95 // _
|
970
|
+
);
|
971
|
+
}
|
972
|
+
|
953
973
|
if (prevIsWord != nextIsWord) {
|
954
974
|
pc += 1;
|
955
975
|
} else {
|
956
976
|
backtrack = true;
|
957
977
|
}
|
958
978
|
} else if (op == 0x08) { // non-word boundary
|
959
|
-
|
960
|
-
|
979
|
+
let prevIsWord: boolean = false;
|
980
|
+
if (sp > 0) {
|
981
|
+
const prevChar: i32 = Porffor.wasm.i32.load8_u(input + sp, 0, 3);
|
982
|
+
prevIsWord = Porffor.fastOr(
|
983
|
+
prevChar >= 65 && prevChar <= 90, // A-Z
|
984
|
+
prevChar >= 97 && prevChar <= 122, // a-z
|
985
|
+
prevChar >= 48 && prevChar <= 57, // 0-9
|
986
|
+
prevChar == 95 // _
|
987
|
+
);
|
988
|
+
}
|
989
|
+
|
990
|
+
let nextIsWord: boolean = false;
|
991
|
+
if (sp < inputLen) {
|
992
|
+
const nextChar: i32 = Porffor.wasm.i32.load8_u(input + sp, 0, 4);
|
993
|
+
nextIsWord = Porffor.fastOr(
|
994
|
+
nextChar >= 65 && nextChar <= 90, // A-Z
|
995
|
+
nextChar >= 97 && nextChar <= 122, // a-z
|
996
|
+
nextChar >= 48 && nextChar <= 57, // 0-9
|
997
|
+
nextChar == 95 // _
|
998
|
+
);
|
999
|
+
}
|
1000
|
+
|
961
1001
|
if (prevIsWord == nextIsWord) {
|
962
1002
|
pc += 1;
|
963
1003
|
} else {
|
@@ -353,11 +353,9 @@ export const __Porffor_strcat = (a: any, b: any): any => {
|
|
353
353
|
};
|
354
354
|
|
355
355
|
|
356
|
-
|
357
356
|
export const __String_prototype_at = (_this: string, index: number) => {
|
358
357
|
const len: i32 = _this.length;
|
359
358
|
|
360
|
-
index |= 0;
|
361
359
|
if (index < 0) index = len + index;
|
362
360
|
if (Porffor.fastOr(index < 0, index >= len)) return undefined;
|
363
361
|
|
@@ -375,7 +373,6 @@ export const __String_prototype_at = (_this: string, index: number) => {
|
|
375
373
|
export const __ByteString_prototype_at = (_this: bytestring, index: number) => {
|
376
374
|
const len: i32 = _this.length;
|
377
375
|
|
378
|
-
index |= 0;
|
379
376
|
if (index < 0) index = len + index;
|
380
377
|
if (Porffor.fastOr(index < 0, index >= len)) return undefined;
|
381
378
|
|
@@ -393,7 +390,6 @@ export const __ByteString_prototype_at = (_this: bytestring, index: number) => {
|
|
393
390
|
export const __String_prototype_charAt = (_this: string, index: number) => {
|
394
391
|
const len: i32 = _this.length;
|
395
392
|
|
396
|
-
index |= 0;
|
397
393
|
if (Porffor.fastOr(index < 0, index >= len)) return '';
|
398
394
|
|
399
395
|
let out: string = Porffor.allocateBytes(8);
|
@@ -410,7 +406,6 @@ export const __String_prototype_charAt = (_this: string, index: number) => {
|
|
410
406
|
export const __ByteString_prototype_charAt = (_this: bytestring, index: number) => {
|
411
407
|
const len: i32 = _this.length;
|
412
408
|
|
413
|
-
index |= 0;
|
414
409
|
if (Porffor.fastOr(index < 0, index >= len)) return '';
|
415
410
|
|
416
411
|
let out: bytestring = Porffor.allocateBytes(8);
|
@@ -522,7 +517,6 @@ export const __ByteString_prototype_toLocaleLowerCase = (_this: bytestring) => _
|
|
522
517
|
export const __String_prototype_codePointAt = (_this: string, index: number) => {
|
523
518
|
const len: i32 = _this.length;
|
524
519
|
|
525
|
-
index |= 0;
|
526
520
|
if (Porffor.fastOr(index < 0, index >= len)) return undefined;
|
527
521
|
|
528
522
|
index *= 2;
|
@@ -545,7 +539,6 @@ export const __String_prototype_codePointAt = (_this: string, index: number) =>
|
|
545
539
|
export const __ByteString_prototype_codePointAt = (_this: bytestring, index: number) => {
|
546
540
|
const len: i32 = _this.length;
|
547
541
|
|
548
|
-
index |= 0;
|
549
542
|
if (Porffor.fastOr(index < 0, index >= len)) return undefined;
|
550
543
|
|
551
544
|
// bytestrings cannot have surrogates, so just do charCodeAt
|
@@ -565,7 +558,6 @@ export const __String_prototype_startsWith = (_this: string, searchString: strin
|
|
565
558
|
const len: i32 = _this.length;
|
566
559
|
if (position > 0) {
|
567
560
|
if (position > len) position = len;
|
568
|
-
else position |= 0;
|
569
561
|
} else position = 0;
|
570
562
|
|
571
563
|
thisPtr += position * 2;
|
@@ -595,7 +587,6 @@ export const __ByteString_prototype_startsWith = (_this: bytestring, searchStrin
|
|
595
587
|
const len: i32 = _this.length;
|
596
588
|
if (position > 0) {
|
597
589
|
if (position > len) position = len;
|
598
|
-
else position |= 0;
|
599
590
|
} else position = 0;
|
600
591
|
|
601
592
|
thisPtr += position;
|
@@ -628,7 +619,6 @@ export const __String_prototype_endsWith = (_this: string, searchString: string,
|
|
628
619
|
|
629
620
|
if (endPosition > 0) {
|
630
621
|
if (endPosition > len) endPosition = len;
|
631
|
-
else endPosition |= 0;
|
632
622
|
} else endPosition = 0;
|
633
623
|
|
634
624
|
endPosition -= searchLen;
|
@@ -669,7 +659,6 @@ export const __ByteString_prototype_endsWith = (_this: bytestring, searchString:
|
|
669
659
|
|
670
660
|
if (endPosition > 0) {
|
671
661
|
if (endPosition > len) endPosition = len;
|
672
|
-
else endPosition |= 0;
|
673
662
|
} else endPosition = 0;
|
674
663
|
|
675
664
|
endPosition -= searchLen;
|
@@ -702,7 +691,6 @@ export const __String_prototype_indexOf = (_this: string, searchString: string,
|
|
702
691
|
const len: i32 = _this.length;
|
703
692
|
if (position > 0) {
|
704
693
|
if (position > len) position = len;
|
705
|
-
else position |= 0;
|
706
694
|
} else position = 0;
|
707
695
|
|
708
696
|
const thisPtrEnd: i32 = thisPtr + (len * 2) - searchLenX2;
|
@@ -743,7 +731,6 @@ export const __ByteString_prototype_indexOf = (_this: bytestring, searchString:
|
|
743
731
|
const len: i32 = _this.length;
|
744
732
|
if (position > 0) {
|
745
733
|
if (position > len) position = len;
|
746
|
-
else position |= 0;
|
747
734
|
} else position = 0;
|
748
735
|
|
749
736
|
const thisPtrEnd: i32 = thisPtr + len - searchLen;
|
@@ -789,7 +776,6 @@ export const __String_prototype_lastIndexOf = (_this: string, searchString: stri
|
|
789
776
|
if (position > 0) {
|
790
777
|
const max: i32 = len - searchLen;
|
791
778
|
if (position > max) position = max;
|
792
|
-
else position |= 0;
|
793
779
|
} else position = 0;
|
794
780
|
|
795
781
|
const thisPtrStart: i32 = thisPtr;
|
@@ -835,7 +821,6 @@ export const __ByteString_prototype_lastIndexOf = (_this: bytestring, searchStri
|
|
835
821
|
if (position > 0) {
|
836
822
|
const max: i32 = len - searchLen;
|
837
823
|
if (position > max) position = max;
|
838
|
-
else position |= 0;
|
839
824
|
} else position = 0;
|
840
825
|
|
841
826
|
const thisPtrStart: i32 = thisPtr;
|
@@ -875,7 +860,6 @@ export const __String_prototype_includes = (_this: string, searchString: string,
|
|
875
860
|
const len: i32 = _this.length;
|
876
861
|
if (position > 0) {
|
877
862
|
if (position > len) position = len;
|
878
|
-
else position |= 0;
|
879
863
|
} else position = 0;
|
880
864
|
|
881
865
|
const thisPtrEnd: i32 = thisPtr + (len * 2) - searchLenX2;
|
@@ -916,7 +900,6 @@ export const __ByteString_prototype_includes = (_this: bytestring, searchString:
|
|
916
900
|
const len: i32 = _this.length;
|
917
901
|
if (position > 0) {
|
918
902
|
if (position > len) position = len;
|
919
|
-
else position |= 0;
|
920
903
|
} else position = 0;
|
921
904
|
|
922
905
|
const thisPtrEnd: i32 = thisPtr + len - searchLen;
|
@@ -952,7 +935,6 @@ export const __String_prototype_padStart = (_this: string, targetLength: number,
|
|
952
935
|
|
953
936
|
const len: i32 = _this.length;
|
954
937
|
|
955
|
-
targetLength |= 0;
|
956
938
|
|
957
939
|
const todo: i32 = targetLength - len;
|
958
940
|
if (todo > 0) {
|
@@ -997,7 +979,6 @@ export const __ByteString_prototype_padStart = (_this: bytestring, targetLength:
|
|
997
979
|
|
998
980
|
const len: i32 = _this.length;
|
999
981
|
|
1000
|
-
targetLength |= 0;
|
1001
982
|
|
1002
983
|
const todo: i32 = targetLength - len;
|
1003
984
|
if (todo > 0) {
|
@@ -1046,7 +1027,6 @@ export const __String_prototype_padEnd = (_this: string, targetLength: number, p
|
|
1046
1027
|
outPtr += 2;
|
1047
1028
|
}
|
1048
1029
|
|
1049
|
-
targetLength |= 0;
|
1050
1030
|
|
1051
1031
|
const todo: i32 = targetLength - len;
|
1052
1032
|
if (todo > 0) {
|
@@ -1088,7 +1068,6 @@ export const __ByteString_prototype_padEnd = (_this: bytestring, targetLength: n
|
|
1088
1068
|
Porffor.wasm.i32.store8(outPtr++, Porffor.wasm.i32.load8_u(thisPtr++, 0, 4), 0, 4);
|
1089
1069
|
}
|
1090
1070
|
|
1091
|
-
targetLength |= 0;
|
1092
1071
|
|
1093
1072
|
const todo: i32 = targetLength - len;
|
1094
1073
|
if (todo > 0) {
|
@@ -1123,8 +1102,6 @@ export const __String_prototype_substring = (_this: string, start: number, end:
|
|
1123
1102
|
start = tmp;
|
1124
1103
|
}
|
1125
1104
|
|
1126
|
-
start |= 0;
|
1127
|
-
end |= 0;
|
1128
1105
|
|
1129
1106
|
if (start < 0) start = 0;
|
1130
1107
|
if (start > len) start = len;
|
@@ -1161,8 +1138,6 @@ export const __ByteString_prototype_substring = (_this: bytestring, start: numbe
|
|
1161
1138
|
start = tmp;
|
1162
1139
|
}
|
1163
1140
|
|
1164
|
-
start |= 0;
|
1165
|
-
end |= 0;
|
1166
1141
|
|
1167
1142
|
if (start < 0) start = 0;
|
1168
1143
|
if (start > len) start = len;
|
@@ -1191,7 +1166,6 @@ export const __ByteString_prototype_substring = (_this: bytestring, start: numbe
|
|
1191
1166
|
export const __String_prototype_substr = (_this: string, start: number, length: number) => {
|
1192
1167
|
const len: i32 = _this.length;
|
1193
1168
|
|
1194
|
-
start |= 0;
|
1195
1169
|
|
1196
1170
|
if (start < 0) {
|
1197
1171
|
start = len + start;
|
@@ -1200,7 +1174,6 @@ export const __String_prototype_substr = (_this: string, start: number, length:
|
|
1200
1174
|
|
1201
1175
|
if (Porffor.wasm`local.get ${length+1}` == Porffor.TYPES.undefined) length = len - start;
|
1202
1176
|
|
1203
|
-
length |= 0;
|
1204
1177
|
|
1205
1178
|
if (start + length > len) length = len - start;
|
1206
1179
|
|
@@ -1228,7 +1201,6 @@ export const __String_prototype_substr = (_this: string, start: number, length:
|
|
1228
1201
|
export const __ByteString_prototype_substr = (_this: bytestring, start: number, length: number) => {
|
1229
1202
|
const len: i32 = _this.length;
|
1230
1203
|
|
1231
|
-
start |= 0;
|
1232
1204
|
|
1233
1205
|
if (start < 0) {
|
1234
1206
|
start = len + start;
|
@@ -1237,7 +1209,6 @@ export const __ByteString_prototype_substr = (_this: bytestring, start: number,
|
|
1237
1209
|
|
1238
1210
|
if (Porffor.wasm`local.get ${length+1}` == Porffor.TYPES.undefined) length = len - start;
|
1239
1211
|
|
1240
|
-
length |= 0;
|
1241
1212
|
|
1242
1213
|
if (start + length > len) length = len - start;
|
1243
1214
|
|
@@ -1264,8 +1235,6 @@ export const __String_prototype_slice = (_this: string, start: number, end: numb
|
|
1264
1235
|
const len: i32 = _this.length;
|
1265
1236
|
if (Porffor.wasm`local.get ${end+1}` == Porffor.TYPES.undefined) end = len;
|
1266
1237
|
|
1267
|
-
start |= 0;
|
1268
|
-
end |= 0;
|
1269
1238
|
|
1270
1239
|
if (start < 0) {
|
1271
1240
|
start = len + start;
|
@@ -1305,8 +1274,6 @@ export const __ByteString_prototype_slice = (_this: bytestring, start: number, e
|
|
1305
1274
|
const len: i32 = _this.length;
|
1306
1275
|
if (Porffor.wasm`local.get ${end+1}` == Porffor.TYPES.undefined) end = len;
|
1307
1276
|
|
1308
|
-
start |= 0;
|
1309
|
-
end |= 0;
|
1310
1277
|
|
1311
1278
|
if (start < 0) {
|
1312
1279
|
start = len + start;
|
@@ -1644,7 +1611,6 @@ export const __String_prototype_split = (_this: string, separator: any, limit: a
|
|
1644
1611
|
let out: any[] = Porffor.allocate(), outLen: i32 = 0;
|
1645
1612
|
|
1646
1613
|
if (Porffor.wasm`local.get ${limit+1}` == Porffor.TYPES.undefined) limit = Number.MAX_SAFE_INTEGER;
|
1647
|
-
limit |= 0;
|
1648
1614
|
if (limit < 0) limit = Number.MAX_SAFE_INTEGER;
|
1649
1615
|
|
1650
1616
|
if (separator == null) {
|
@@ -1822,7 +1788,6 @@ i32.store8 0 12`;
|
|
1822
1788
|
}
|
1823
1789
|
|
1824
1790
|
if (Porffor.wasm`local.get ${limit+1}` == Porffor.TYPES.undefined) limit = Number.MAX_SAFE_INTEGER;
|
1825
|
-
limit |= 0;
|
1826
1791
|
if (limit < 0) limit = Number.MAX_SAFE_INTEGER;
|
1827
1792
|
|
1828
1793
|
let tmp: bytestring = Porffor.allocate(), tmpLen: i32 = 0;
|
@@ -105,6 +105,58 @@ export const __String_fromCharCode = (...codes: any[]): bytestring|string => {
|
|
105
105
|
return out;
|
106
106
|
};
|
107
107
|
|
108
|
+
export const __String_fromCodePoint = (...codePoints: any[]): string => {
|
109
|
+
let out: string = Porffor.allocate();
|
110
|
+
|
111
|
+
const len: i32 = codePoints.length;
|
112
|
+
let outLength: i32 = 0;
|
113
|
+
|
114
|
+
for (let i: i32 = 0; i < len; i++) {
|
115
|
+
const codepoint: number = ecma262.ToNumber(codePoints[i]);
|
116
|
+
|
117
|
+
if (codepoint != (codepoint | 0)) {
|
118
|
+
throw new RangeError('Invalid code point');
|
119
|
+
}
|
120
|
+
|
121
|
+
// Check if code point is valid (0 to 0x10FFFF)
|
122
|
+
if (Porffor.fastOr(codepoint < 0, codepoint > 0x10FFFF)) {
|
123
|
+
throw new RangeError('Invalid code point');
|
124
|
+
}
|
125
|
+
|
126
|
+
if (codepoint <= 0xFFFF) {
|
127
|
+
// BMP code point - single 16-bit unit
|
128
|
+
outLength++;
|
129
|
+
} else {
|
130
|
+
// Supplementary code point - surrogate pair (2 units)
|
131
|
+
outLength += 2;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
out.length = outLength;
|
136
|
+
let outIndex: i32 = 0;
|
137
|
+
|
138
|
+
for (let i: i32 = 0; i < len; i++) {
|
139
|
+
const codepoint: number = ecma262.ToNumber(codePoints[i]);
|
140
|
+
|
141
|
+
if (codepoint <= 0xFFFF) {
|
142
|
+
// BMP code point
|
143
|
+
Porffor.wasm.i32.store16(Porffor.wasm`local.get ${out}` + outIndex * 2, codepoint, 0, 4);
|
144
|
+
outIndex++;
|
145
|
+
} else {
|
146
|
+
// Supplementary code point - encode as surrogate pair
|
147
|
+
const cpMinusBase: i32 = codepoint - 0x10000;
|
148
|
+
const highSurrogate: i32 = 0xD800 + (cpMinusBase >> 10);
|
149
|
+
const lowSurrogate: i32 = 0xDC00 + (cpMinusBase & 0x3FF);
|
150
|
+
|
151
|
+
Porffor.wasm.i32.store16(Porffor.wasm`local.get ${out}` + outIndex * 2, highSurrogate, 0, 4);
|
152
|
+
Porffor.wasm.i32.store16(Porffor.wasm`local.get ${out}` + outIndex * 2, lowSurrogate, 0, 6);
|
153
|
+
outIndex += 2;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
return out;
|
158
|
+
};
|
159
|
+
|
108
160
|
// in f64 file as returns NaN which returns 0 in i32
|
109
161
|
export const __String_prototype_charCodeAt = (_this: string, index: number) => {
|
110
162
|
const len: i32 = _this.length;
|
@@ -122,4 +174,49 @@ export const __ByteString_prototype_charCodeAt = (_this: bytestring, index: numb
|
|
122
174
|
if (Porffor.fastOr(index < 0, index >= len)) return NaN;
|
123
175
|
|
124
176
|
return Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${_this}` + index, 0, 4);
|
177
|
+
};
|
178
|
+
|
179
|
+
// 22.1.2.4 String.raw ( template, ...substitutions )
|
180
|
+
// https://tc39.es/ecma262/#sec-string.raw
|
181
|
+
export const __String_raw = (template: any, ...substitutions: any[]): string => {
|
182
|
+
// 1. Let substitutionCount be the number of elements in substitutions.
|
183
|
+
const substitutionCount: i32 = substitutions.length;
|
184
|
+
|
185
|
+
// 2. Let cooked be ? ToObject(template).
|
186
|
+
// 3. Let literals be ? ToObject(? Get(cooked, "raw")).
|
187
|
+
const literals: any = template.raw;
|
188
|
+
|
189
|
+
// 4. Let literalCount be ? LengthOfArrayLike(literals).
|
190
|
+
const literalCount: number = ecma262.ToIntegerOrInfinity(Porffor.type(literals) == Porffor.TYPES.object ? (literals as object)['length'] : literals.length);
|
191
|
+
|
192
|
+
// 5. If literalCount ≤ 0, return the empty String.
|
193
|
+
if (literalCount <= 0) return '';
|
194
|
+
|
195
|
+
// 6. Let R be the empty String.
|
196
|
+
let R: string = '';
|
197
|
+
|
198
|
+
// 7. Let nextIndex be 0.
|
199
|
+
let nextIndex: i32 = 0;
|
200
|
+
|
201
|
+
// 8. Repeat,
|
202
|
+
while (true) {
|
203
|
+
// a. Let nextLiteralVal be ? Get(literals, ! ToString(𝔽(nextIndex))).
|
204
|
+
// b. Let nextLiteral be ? ToString(nextLiteralVal).
|
205
|
+
// c. Set R to the string-concatenation of R and nextLiteral.
|
206
|
+
R = __Porffor_concatStrings(R, literals[nextIndex]);
|
207
|
+
|
208
|
+
// d. If nextIndex + 1 = literalCount, return R.
|
209
|
+
if (nextIndex + 1 == literalCount) return R;
|
210
|
+
|
211
|
+
// e. If nextIndex < substitutionCount, then
|
212
|
+
if (nextIndex < substitutionCount) {
|
213
|
+
// i. Let nextSubVal be substitutions[nextIndex].
|
214
|
+
// ii. Let nextSub be ? ToString(nextSubVal).
|
215
|
+
// iii. Set R to the string-concatenation of R and nextSub.
|
216
|
+
R = __Porffor_concatStrings(R, substitutions[nextIndex]);
|
217
|
+
}
|
218
|
+
|
219
|
+
// f. Set nextIndex to nextIndex + 1.
|
220
|
+
nextIndex += 1;
|
221
|
+
}
|
125
222
|
};
|
package/compiler/builtins.js
CHANGED
@@ -5,8 +5,11 @@ import { TYPES, TYPE_NAMES } from './types.js';
|
|
5
5
|
import { number, unsignedLEB128 } from './encoding.js';
|
6
6
|
import './prefs.js';
|
7
7
|
|
8
|
-
export
|
9
|
-
|
8
|
+
export let importedFuncs;
|
9
|
+
export const setImports = (v = null) => {
|
10
|
+
importedFuncs = v ?? { length: 0 };
|
11
|
+
};
|
12
|
+
setImports();
|
10
13
|
|
11
14
|
/**
|
12
15
|
* Create an import function for the Porffor world to use.
|
@@ -18,51 +21,41 @@ Object.defineProperty(importedFuncs, 'length', { configurable: true, writable: t
|
|
18
21
|
* @param {string} c - C source code to compile as import implementation
|
19
22
|
*/
|
20
23
|
export const createImport = (name, params, returns, js = null, c = null) => {
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
if (!globalThis.valtypeBinary) {
|
25
|
+
globalThis.valtype ??= Prefs.valtype ?? 'f64';
|
26
|
+
globalThis.valtypeBinary = Valtype[valtype];
|
27
|
+
}
|
28
|
+
|
29
|
+
if (typeof params === 'number') params = new Array(params).fill(valtypeBinary);
|
30
|
+
if (typeof returns === 'number') returns = new Array(returns).fill(valtypeBinary);
|
27
31
|
|
28
32
|
if (name in importedFuncs) {
|
29
33
|
// overwrite existing import
|
30
34
|
const existing = importedFuncs[name];
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
const call = +existing;
|
36
|
+
const replacement = new Number(call);
|
37
|
+
replacement.name = name;
|
38
|
+
replacement.import = existing.import;
|
39
|
+
replacement.params = params;
|
40
|
+
replacement.returns = returns;
|
41
|
+
replacement.js = js;
|
42
|
+
replacement.c = c;
|
43
|
+
|
44
|
+
importedFuncs[name] = replacement;
|
37
45
|
return;
|
38
46
|
}
|
39
47
|
|
40
48
|
const call = importedFuncs.length;
|
41
49
|
const ident = String.fromCharCode(97 + importedFuncs.length);
|
42
|
-
let obj;
|
43
|
-
const get = () => {
|
44
|
-
if (obj) return obj;
|
45
|
-
lazy();
|
46
|
-
|
47
|
-
obj = new Number(call);
|
48
|
-
obj.name = name;
|
49
|
-
obj.import = ident;
|
50
|
-
obj.params = params;
|
51
|
-
obj.returns = returns;
|
52
|
-
obj.js = js;
|
53
|
-
obj.c = c;
|
54
|
-
return obj;
|
55
|
-
};
|
56
50
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
});
|
51
|
+
const obj = importedFuncs[name] = importedFuncs[call] = new Number(call);
|
52
|
+
obj.name = name;
|
53
|
+
obj.import = ident;
|
54
|
+
obj.params = params;
|
55
|
+
obj.returns = returns;
|
56
|
+
obj.js = js;
|
57
|
+
obj.c = c;
|
58
|
+
|
66
59
|
importedFuncs.length = call + 1;
|
67
60
|
};
|
68
61
|
|