porffor 0.57.24 → 0.57.26
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/builtins/_internal_object.ts +301 -39
- package/compiler/builtins_precompiled.js +570 -552
- package/compiler/codegen.js +74 -34
- package/compiler/precompile.js +5 -0
- package/compiler/prefs.js +2 -7
- package/package.json +1 -1
- package/runtime/index.js +1 -1
- package/foo.js +0 -1
- package/foo.ts +0 -12
@@ -20,9 +20,11 @@ import type {} from './porffor.d.ts';
|
|
20
20
|
|
21
21
|
// hash key for hashmap
|
22
22
|
export const __Porffor_object_hash = (key: any): i32 => {
|
23
|
-
if (Porffor.
|
24
|
-
|
25
|
-
|
23
|
+
if (Porffor.comptime.flag`hasType.symbol`) {
|
24
|
+
if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) {
|
25
|
+
// symbol, hash is unused so just return 0
|
26
|
+
return 0;
|
27
|
+
}
|
26
28
|
}
|
27
29
|
|
28
30
|
// bytestring or string, xxh32-based hash
|
@@ -110,8 +112,11 @@ export const __Porffor_object_writeKey = (ptr: i32, key: any, hash: i32): void =
|
|
110
112
|
|
111
113
|
// set MSB 1 if regular string
|
112
114
|
if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.string) keyEnc |= 0x80000000;
|
113
|
-
|
114
|
-
|
115
|
+
|
116
|
+
// set MSB 1&2 if symbol
|
117
|
+
if (Porffor.comptime.flag`hasType.symbol`) {
|
118
|
+
if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) keyEnc |= 0xc0000000;
|
119
|
+
}
|
115
120
|
|
116
121
|
// write encoded key to ptr + 4
|
117
122
|
Porffor.wasm.i32.store(ptr, keyEnc, 0, 4);
|
@@ -415,43 +420,23 @@ export const __Porffor_object_lookup = (obj: any, target: any, targetHash: i32):
|
|
415
420
|
let ptr: i32 = Porffor.wasm`local.get ${obj}` + 8;
|
416
421
|
const endPtr: i32 = ptr + Porffor.wasm.i32.load16_u(obj, 0, 0) * 18;
|
417
422
|
|
418
|
-
if (Porffor.
|
419
|
-
|
420
|
-
|
421
|
-
if ((key >>> 30) == 3) { // MSB 1 and 2 set, symbol (unset MSB x2)
|
422
|
-
// todo: remove casts once weird bug which breaks unrelated things is fixed (https://github.com/CanadaHonk/porffor/commit/5747f0c1f3a4af95283ebef175cdacb21e332a52)
|
423
|
-
if ((key & 0x3FFFFFFF) as symbol == target as symbol) return ptr;
|
424
|
-
}
|
425
|
-
}
|
426
|
-
} else {
|
427
|
-
for (; ptr < endPtr; ptr += 18) {
|
428
|
-
if (Porffor.wasm.i32.load(ptr, 0, 0) == targetHash) {
|
423
|
+
if (Porffor.comptime.flag`hasType.symbol`) {
|
424
|
+
if (Porffor.wasm`local.get ${target+1}` == Porffor.TYPES.symbol) {
|
425
|
+
for (; ptr < endPtr; ptr += 18) {
|
429
426
|
const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
|
427
|
+
if ((key >>> 30) == 3) { // MSB 1 and 2 set, symbol (unset MSB x2)
|
428
|
+
// todo: remove casts once weird bug which breaks unrelated things is fixed (https://github.com/CanadaHonk/porffor/commit/5747f0c1f3a4af95283ebef175cdacb21e332a52)
|
429
|
+
if ((key & 0x3FFFFFFF) as symbol == target as symbol) return ptr;
|
430
|
+
}
|
431
|
+
}
|
430
432
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
// slow path: strcmp
|
435
|
-
Porffor.wasm`
|
436
|
-
local.get ${key}
|
437
|
-
i32.const 2147483647
|
438
|
-
i32.and
|
433
|
+
return -1;
|
434
|
+
}
|
435
|
+
}
|
439
436
|
|
440
|
-
|
441
|
-
i32.
|
442
|
-
|
443
|
-
i32.const 30
|
444
|
-
i32.shr_u
|
445
|
-
select
|
446
|
-
|
447
|
-
local.get ${target}
|
448
|
-
local.get ${target+1}
|
449
|
-
call __Porffor_strcmp
|
450
|
-
if 64
|
451
|
-
local.get ${ptr}
|
452
|
-
return
|
453
|
-
end`;
|
454
|
-
}
|
437
|
+
for (; ptr < endPtr; ptr += 18) {
|
438
|
+
if (Porffor.wasm.i32.load(ptr, 0, 0) == targetHash) {
|
439
|
+
return ptr;
|
455
440
|
}
|
456
441
|
}
|
457
442
|
|
@@ -556,6 +541,84 @@ i32.shr_u
|
|
556
541
|
return`;
|
557
542
|
};
|
558
543
|
|
544
|
+
export const __Porffor_object_get_withHash = (obj: any, key: any, hash: i32): any => {
|
545
|
+
const trueType: i32 = Porffor.wasm`local.get ${obj+1}`;
|
546
|
+
if (trueType != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
|
547
|
+
|
548
|
+
if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot get property of null');
|
549
|
+
|
550
|
+
let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
|
551
|
+
if (entryPtr == -1) {
|
552
|
+
// check prototype chain
|
553
|
+
if (trueType == Porffor.TYPES.object) {
|
554
|
+
// opt: inline get object prototype
|
555
|
+
Porffor.wasm`
|
556
|
+
local.get ${obj}
|
557
|
+
local.get ${obj}
|
558
|
+
i32.load 0 4
|
559
|
+
local.set ${obj}
|
560
|
+
i32.load8_u 0 3
|
561
|
+
local.set ${obj+1}`;
|
562
|
+
|
563
|
+
// if empty, prototype is object.prototype
|
564
|
+
if (Porffor.type(obj) == Porffor.TYPES.empty) obj = __Object_prototype;
|
565
|
+
} else obj = __Porffor_object_getHiddenPrototype(trueType);
|
566
|
+
|
567
|
+
if (Porffor.type(obj) != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
|
568
|
+
let lastProto: any = obj;
|
569
|
+
while (true) {
|
570
|
+
if ((entryPtr = __Porffor_object_lookup(obj, key, hash)) != -1) break;
|
571
|
+
|
572
|
+
// inline get prototype
|
573
|
+
if (Porffor.type(obj) == Porffor.TYPES.object) {
|
574
|
+
Porffor.wasm`
|
575
|
+
local.get ${obj}
|
576
|
+
local.get ${obj}
|
577
|
+
i32.load 0 4
|
578
|
+
local.set ${obj}
|
579
|
+
i32.load8_u 0 3
|
580
|
+
local.set ${obj+1}`;
|
581
|
+
} else obj = __Porffor_object_getPrototype(obj);
|
582
|
+
if (Porffor.type(obj) != Porffor.TYPES.object) obj = __Porffor_object_underlying(obj);
|
583
|
+
|
584
|
+
if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
|
585
|
+
lastProto = obj;
|
586
|
+
}
|
587
|
+
|
588
|
+
if (entryPtr == -1) {
|
589
|
+
Porffor.wasm`
|
590
|
+
f64.const 0
|
591
|
+
i32.const 128
|
592
|
+
return`;
|
593
|
+
}
|
594
|
+
}
|
595
|
+
|
596
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
|
597
|
+
if (tail & 0b0001) {
|
598
|
+
// accessor descriptor
|
599
|
+
const get: Function = __Porffor_object_accessorGet(entryPtr);
|
600
|
+
|
601
|
+
// no getter, return undefined
|
602
|
+
if (Porffor.wasm`local.get ${get}` == 0) {
|
603
|
+
Porffor.wasm`
|
604
|
+
f64.const 0
|
605
|
+
i32.const 128
|
606
|
+
return`;
|
607
|
+
}
|
608
|
+
|
609
|
+
return get.call(obj);
|
610
|
+
}
|
611
|
+
|
612
|
+
// data descriptor
|
613
|
+
Porffor.wasm`
|
614
|
+
local.get ${entryPtr}
|
615
|
+
f64.load 0 8
|
616
|
+
local.get ${tail}
|
617
|
+
i32.const 8
|
618
|
+
i32.shr_u
|
619
|
+
return`;
|
620
|
+
};
|
621
|
+
|
559
622
|
export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
|
560
623
|
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
|
561
624
|
obj = __Porffor_object_underlying(obj);
|
@@ -662,6 +725,105 @@ export const __Porffor_object_set = (obj: any, key: any, value: any): any => {
|
|
662
725
|
return value;
|
663
726
|
};
|
664
727
|
|
728
|
+
export const __Porffor_object_set_withHash = (obj: any, key: any, value: any, hash: i32): any => {
|
729
|
+
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
|
730
|
+
obj = __Porffor_object_underlying(obj);
|
731
|
+
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return value;
|
732
|
+
}
|
733
|
+
|
734
|
+
if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot set property of null');
|
735
|
+
|
736
|
+
let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
|
737
|
+
let flags: i32;
|
738
|
+
if (entryPtr == -1) {
|
739
|
+
// todo/opt: skip if no setters used
|
740
|
+
// check prototype chain for setter
|
741
|
+
let proto: any = __Porffor_object_getPrototype(obj);
|
742
|
+
if (proto != null) {
|
743
|
+
if (Porffor.type(proto) != Porffor.TYPES.object) proto = __Porffor_object_underlying(proto);
|
744
|
+
let lastProto: any = proto;
|
745
|
+
while (true) {
|
746
|
+
if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
|
747
|
+
|
748
|
+
proto = __Porffor_object_getPrototype(proto);
|
749
|
+
if (Porffor.type(proto) != Porffor.TYPES.object) proto = __Porffor_object_underlying(proto);
|
750
|
+
if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
|
751
|
+
lastProto = proto;
|
752
|
+
}
|
753
|
+
|
754
|
+
if (entryPtr != -1) {
|
755
|
+
// found possible setter
|
756
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
|
757
|
+
if (tail & 0b0001) {
|
758
|
+
// accessor descriptor
|
759
|
+
const set: Function = __Porffor_object_accessorSet(entryPtr);
|
760
|
+
|
761
|
+
// no setter, return early
|
762
|
+
if (Porffor.wasm`local.get ${set}` == 0) {
|
763
|
+
return value;
|
764
|
+
}
|
765
|
+
|
766
|
+
set.call(obj, value);
|
767
|
+
return value;
|
768
|
+
}
|
769
|
+
}
|
770
|
+
}
|
771
|
+
|
772
|
+
// add new entry
|
773
|
+
// check if object is inextensible
|
774
|
+
if (__Porffor_object_isInextensible(obj)) {
|
775
|
+
return value;
|
776
|
+
}
|
777
|
+
|
778
|
+
// bump size +1
|
779
|
+
const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
|
780
|
+
Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
|
781
|
+
|
782
|
+
// entryPtr = current end of object
|
783
|
+
entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
|
784
|
+
|
785
|
+
__Porffor_object_writeKey(entryPtr, key, hash);
|
786
|
+
|
787
|
+
// flags = writable, enumerable, configurable, not accessor
|
788
|
+
flags = 0b1110;
|
789
|
+
} else {
|
790
|
+
// existing entry, modify it
|
791
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
|
792
|
+
|
793
|
+
if (tail & 0b0001) {
|
794
|
+
// accessor descriptor
|
795
|
+
const set: Function = __Porffor_object_accessorSet(entryPtr);
|
796
|
+
|
797
|
+
// no setter, return early
|
798
|
+
if (Porffor.wasm`local.get ${set}` == 0) {
|
799
|
+
return value;
|
800
|
+
}
|
801
|
+
|
802
|
+
set.call(obj, value);
|
803
|
+
return value;
|
804
|
+
}
|
805
|
+
|
806
|
+
// data descriptor
|
807
|
+
if (!(tail & 0b1000)) {
|
808
|
+
// not writable, return now
|
809
|
+
return value;
|
810
|
+
}
|
811
|
+
|
812
|
+
// flags = same flags as before
|
813
|
+
flags = tail & 0xff;
|
814
|
+
}
|
815
|
+
|
816
|
+
// write new value value
|
817
|
+
Porffor.wasm.f64.store(entryPtr, value, 0, 8);
|
818
|
+
|
819
|
+
// write new tail (value type + flags)
|
820
|
+
Porffor.wasm.i32.store16(entryPtr,
|
821
|
+
flags + (Porffor.wasm`local.get ${value+1}` << 8),
|
822
|
+
0, 16);
|
823
|
+
|
824
|
+
return value;
|
825
|
+
};
|
826
|
+
|
665
827
|
export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any => {
|
666
828
|
if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot set property of null');
|
667
829
|
|
@@ -769,6 +931,106 @@ export const __Porffor_object_setStrict = (obj: any, key: any, value: any): any
|
|
769
931
|
return value;
|
770
932
|
};
|
771
933
|
|
934
|
+
export const __Porffor_object_setStrict_withHash = (obj: any, key: any, value: any, hash: i32): any => {
|
935
|
+
if (Porffor.wasm`local.get ${obj}` == 0) throw new TypeError('Cannot set property of null');
|
936
|
+
|
937
|
+
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
|
938
|
+
obj = __Porffor_object_underlying(obj);
|
939
|
+
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return value;
|
940
|
+
}
|
941
|
+
|
942
|
+
let entryPtr: i32 = __Porffor_object_lookup(obj, key, hash);
|
943
|
+
let flags: i32;
|
944
|
+
if (entryPtr == -1) {
|
945
|
+
// todo/opt: skip if no setters used
|
946
|
+
// check prototype chain for setter
|
947
|
+
let proto: any = __Porffor_object_getPrototype(obj);
|
948
|
+
if (proto != null) {
|
949
|
+
if (Porffor.type(proto) != Porffor.TYPES.object) proto = __Porffor_object_underlying(proto);
|
950
|
+
|
951
|
+
let lastProto: any = proto;
|
952
|
+
while (true) {
|
953
|
+
if ((entryPtr = __Porffor_object_lookup(proto, key, hash)) != -1) break;
|
954
|
+
|
955
|
+
proto = __Porffor_object_getPrototype(proto);
|
956
|
+
if (Porffor.type(proto) != Porffor.TYPES.object) proto = __Porffor_object_underlying(proto);
|
957
|
+
if (Porffor.fastOr(proto == null, Porffor.wasm`local.get ${proto}` == Porffor.wasm`local.get ${lastProto}`)) break;
|
958
|
+
lastProto = proto;
|
959
|
+
}
|
960
|
+
|
961
|
+
if (entryPtr != -1) {
|
962
|
+
// found possible setter
|
963
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
|
964
|
+
if (tail & 0b0001) {
|
965
|
+
// accessor descriptor
|
966
|
+
const set: Function = __Porffor_object_accessorSet(entryPtr);
|
967
|
+
|
968
|
+
// no setter, return early
|
969
|
+
if (Porffor.wasm`local.get ${set}` == 0) {
|
970
|
+
return value;
|
971
|
+
}
|
972
|
+
|
973
|
+
set.call(obj, value);
|
974
|
+
return value;
|
975
|
+
}
|
976
|
+
}
|
977
|
+
}
|
978
|
+
|
979
|
+
// add new entry
|
980
|
+
// check if object is inextensible
|
981
|
+
if (__Porffor_object_isInextensible(obj)) {
|
982
|
+
throw new TypeError('Cannot add property to inextensible object');
|
983
|
+
}
|
984
|
+
|
985
|
+
// bump size +1
|
986
|
+
const size: i32 = Porffor.wasm.i32.load16_u(obj, 0, 0);
|
987
|
+
Porffor.wasm.i32.store16(obj, size + 1, 0, 0);
|
988
|
+
|
989
|
+
// entryPtr = current end of object
|
990
|
+
entryPtr = Porffor.wasm`local.get ${obj}` + 8 + size * 18;
|
991
|
+
|
992
|
+
__Porffor_object_writeKey(entryPtr, key, hash);
|
993
|
+
|
994
|
+
// flags = writable, enumerable, configurable, not accessor
|
995
|
+
flags = 0b1110;
|
996
|
+
} else {
|
997
|
+
// existing entry, modify it
|
998
|
+
const tail: i32 = Porffor.wasm.i32.load16_u(entryPtr, 0, 16);
|
999
|
+
|
1000
|
+
if (tail & 0b0001) {
|
1001
|
+
// accessor descriptor
|
1002
|
+
const set: Function = __Porffor_object_accessorSet(entryPtr);
|
1003
|
+
|
1004
|
+
// no setter, return early
|
1005
|
+
if (Porffor.wasm`local.get ${set}` == 0) {
|
1006
|
+
throw new TypeError('Cannot set property with no setter of object');
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
set.call(obj, value);
|
1010
|
+
return value;
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
// data descriptor
|
1014
|
+
if (!(tail & 0b1000)) {
|
1015
|
+
// not writable, return now
|
1016
|
+
throw new TypeError('Cannot modify read-only property of object');
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
// flags = same flags as before
|
1020
|
+
flags = tail & 0xff;
|
1021
|
+
}
|
1022
|
+
|
1023
|
+
// write new value value (lol)
|
1024
|
+
Porffor.wasm.f64.store(entryPtr, value, 0, 8);
|
1025
|
+
|
1026
|
+
// write new tail (value type + flags)
|
1027
|
+
Porffor.wasm.i32.store16(entryPtr,
|
1028
|
+
flags + (Porffor.wasm`local.get ${value+1}` << 8),
|
1029
|
+
0, 16);
|
1030
|
+
|
1031
|
+
return value;
|
1032
|
+
};
|
1033
|
+
|
772
1034
|
export const __Porffor_object_define = (obj: any, key: any, value: any, flags: i32): void => {
|
773
1035
|
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) {
|
774
1036
|
obj = __Porffor_object_underlying(obj);
|