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.
@@ -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.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) {
24
- // symbol, hash is unused so just return 0
25
- return 0;
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
- // set MSB 1&2 if symbol
114
- else if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) keyEnc |= 0xc0000000;
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.wasm`local.get ${target+1}` == Porffor.TYPES.symbol) {
419
- for (; ptr < endPtr; ptr += 18) {
420
- const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
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
- // fast path: check if same pointer first
432
- if (key == Porffor.wasm`local.get ${target}`) return ptr;
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
- i32.const 67 ;; bytestring
441
- i32.const 195 ;; string
442
- local.get ${key}
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);