@kokimoki/app 1.13.0 → 1.15.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/dist/kokimoki-client.d.ts +6 -0
- package/dist/kokimoki-client.js +14 -0
- package/dist/kokimoki.min.d.ts +6 -0
- package/dist/kokimoki.min.js +1729 -1191
- package/dist/kokimoki.min.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -3
- package/dist/fields.d.ts +0 -95
- package/dist/fields.js +0 -152
- package/dist/kokimoki-schema.d.ts +0 -84
- package/dist/kokimoki-schema.js +0 -163
package/dist/kokimoki.min.js
CHANGED
|
@@ -486,7 +486,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
|
|
|
486
486
|
var eventsExports = events.exports;
|
|
487
487
|
var EventEmitter$1 = /*@__PURE__*/getDefaultExportFromCjs(eventsExports);
|
|
488
488
|
|
|
489
|
-
const KOKIMOKI_APP_VERSION = "1.
|
|
489
|
+
const KOKIMOKI_APP_VERSION = "1.15.0";
|
|
490
490
|
|
|
491
491
|
/**
|
|
492
492
|
* Utility module to work with key-value stores.
|
|
@@ -508,9 +508,9 @@ const create$5 = () => new Map();
|
|
|
508
508
|
* Copy a Map object into a fresh Map object.
|
|
509
509
|
*
|
|
510
510
|
* @function
|
|
511
|
-
* @template
|
|
512
|
-
* @param {Map<
|
|
513
|
-
* @return {Map<
|
|
511
|
+
* @template K,V
|
|
512
|
+
* @param {Map<K,V>} m
|
|
513
|
+
* @return {Map<K,V>}
|
|
514
514
|
*/
|
|
515
515
|
const copy = m => {
|
|
516
516
|
const r = create$5();
|
|
@@ -527,12 +527,12 @@ const copy = m => {
|
|
|
527
527
|
* ```
|
|
528
528
|
*
|
|
529
529
|
* @function
|
|
530
|
-
* @template
|
|
531
|
-
* @template {Map<
|
|
530
|
+
* @template {Map<any, any>} MAP
|
|
531
|
+
* @template {MAP extends Map<any,infer V> ? function():V : unknown} CF
|
|
532
532
|
* @param {MAP} map
|
|
533
|
-
* @param {K} key
|
|
534
|
-
* @param {
|
|
535
|
-
* @return {
|
|
533
|
+
* @param {MAP extends Map<infer K,any> ? K : unknown} key
|
|
534
|
+
* @param {CF} createT
|
|
535
|
+
* @return {ReturnType<CF>}
|
|
536
536
|
*/
|
|
537
537
|
const setIfUndefined = (map, key, createT) => {
|
|
538
538
|
let set = map.get(key);
|
|
@@ -640,44 +640,52 @@ const isArray = Array.isArray;
|
|
|
640
640
|
|
|
641
641
|
/**
|
|
642
642
|
* Handles named events.
|
|
643
|
+
* @experimental
|
|
644
|
+
*
|
|
645
|
+
* This is basically a (better typed) duplicate of Observable, which will replace Observable in the
|
|
646
|
+
* next release.
|
|
643
647
|
*
|
|
644
|
-
* @template
|
|
648
|
+
* @template {{[key in keyof EVENTS]: function(...any):void}} EVENTS
|
|
645
649
|
*/
|
|
646
|
-
class
|
|
650
|
+
class ObservableV2 {
|
|
647
651
|
constructor () {
|
|
648
652
|
/**
|
|
649
653
|
* Some desc.
|
|
650
|
-
* @type {Map<
|
|
654
|
+
* @type {Map<string, Set<any>>}
|
|
651
655
|
*/
|
|
652
656
|
this._observers = create$5();
|
|
653
657
|
}
|
|
654
658
|
|
|
655
659
|
/**
|
|
656
|
-
* @
|
|
657
|
-
* @param {
|
|
660
|
+
* @template {keyof EVENTS & string} NAME
|
|
661
|
+
* @param {NAME} name
|
|
662
|
+
* @param {EVENTS[NAME]} f
|
|
658
663
|
*/
|
|
659
664
|
on (name, f) {
|
|
660
|
-
setIfUndefined(this._observers, name, create$4).add(f);
|
|
665
|
+
setIfUndefined(this._observers, /** @type {string} */ (name), create$4).add(f);
|
|
666
|
+
return f
|
|
661
667
|
}
|
|
662
668
|
|
|
663
669
|
/**
|
|
664
|
-
* @
|
|
665
|
-
* @param {
|
|
670
|
+
* @template {keyof EVENTS & string} NAME
|
|
671
|
+
* @param {NAME} name
|
|
672
|
+
* @param {EVENTS[NAME]} f
|
|
666
673
|
*/
|
|
667
674
|
once (name, f) {
|
|
668
675
|
/**
|
|
669
676
|
* @param {...any} args
|
|
670
677
|
*/
|
|
671
678
|
const _f = (...args) => {
|
|
672
|
-
this.off(name, _f);
|
|
679
|
+
this.off(name, /** @type {any} */ (_f));
|
|
673
680
|
f(...args);
|
|
674
681
|
};
|
|
675
|
-
this.on(name, _f);
|
|
682
|
+
this.on(name, /** @type {any} */ (_f));
|
|
676
683
|
}
|
|
677
684
|
|
|
678
685
|
/**
|
|
679
|
-
* @
|
|
680
|
-
* @param {
|
|
686
|
+
* @template {keyof EVENTS & string} NAME
|
|
687
|
+
* @param {NAME} name
|
|
688
|
+
* @param {EVENTS[NAME]} f
|
|
681
689
|
*/
|
|
682
690
|
off (name, f) {
|
|
683
691
|
const observers = this._observers.get(name);
|
|
@@ -695,8 +703,9 @@ class Observable {
|
|
|
695
703
|
*
|
|
696
704
|
* @todo This should catch exceptions
|
|
697
705
|
*
|
|
698
|
-
* @
|
|
699
|
-
* @param {
|
|
706
|
+
* @template {keyof EVENTS & string} NAME
|
|
707
|
+
* @param {NAME} name The event name.
|
|
708
|
+
* @param {Parameters<EVENTS[NAME]>} args The arguments that are applied to the event listener.
|
|
700
709
|
*/
|
|
701
710
|
emit (name, args) {
|
|
702
711
|
// copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
|
|
@@ -707,6 +716,7 @@ class Observable {
|
|
|
707
716
|
this._observers = create$5();
|
|
708
717
|
}
|
|
709
718
|
}
|
|
719
|
+
/* c8 ignore end */
|
|
710
720
|
|
|
711
721
|
/**
|
|
712
722
|
* Common Math expressions.
|
|
@@ -739,6 +749,46 @@ const max$3 = (a, b) => a > b ? a : b;
|
|
|
739
749
|
*/
|
|
740
750
|
const isNegativeZero = n => n !== 0 ? n < 0 : 1 / n < 0;
|
|
741
751
|
|
|
752
|
+
/* eslint-env browser */
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Binary data constants.
|
|
756
|
+
*
|
|
757
|
+
* @module binary
|
|
758
|
+
*/
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* n-th bit activated.
|
|
762
|
+
*
|
|
763
|
+
* @type {number}
|
|
764
|
+
*/
|
|
765
|
+
const BIT1 = 1;
|
|
766
|
+
const BIT2 = 2;
|
|
767
|
+
const BIT3 = 4;
|
|
768
|
+
const BIT4 = 8;
|
|
769
|
+
const BIT6 = 32;
|
|
770
|
+
const BIT7 = 64;
|
|
771
|
+
const BIT8 = 128;
|
|
772
|
+
const BITS5 = 31;
|
|
773
|
+
const BITS6 = 63;
|
|
774
|
+
const BITS7 = 127;
|
|
775
|
+
/**
|
|
776
|
+
* @type {number}
|
|
777
|
+
*/
|
|
778
|
+
const BITS31 = 0x7FFFFFFF;
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Utility helpers for working with numbers.
|
|
782
|
+
*
|
|
783
|
+
* @module number
|
|
784
|
+
*/
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
|
788
|
+
|
|
789
|
+
/* c8 ignore next */
|
|
790
|
+
const isInteger = Number.isInteger || (num => typeof num === 'number' && isFinite(num) && floor$2(num) === num);
|
|
791
|
+
|
|
742
792
|
/**
|
|
743
793
|
* @param {string} s
|
|
744
794
|
* @return {string}
|
|
@@ -807,342 +857,650 @@ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
|
|
|
807
857
|
}
|
|
808
858
|
|
|
809
859
|
/**
|
|
810
|
-
*
|
|
860
|
+
* Efficient schema-less binary encoding with support for variable length encoding.
|
|
811
861
|
*
|
|
812
|
-
*
|
|
813
|
-
*/
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* @template T
|
|
817
|
-
* @param {T|null|undefined} v
|
|
818
|
-
* @return {T|null}
|
|
819
|
-
*/
|
|
820
|
-
/* c8 ignore next */
|
|
821
|
-
const undefinedToNull = v => v === undefined ? null : v;
|
|
822
|
-
|
|
823
|
-
/* eslint-env browser */
|
|
824
|
-
|
|
825
|
-
/**
|
|
826
|
-
* Isomorphic variable storage.
|
|
862
|
+
* Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
|
|
827
863
|
*
|
|
828
|
-
*
|
|
864
|
+
* Encodes numbers in little-endian order (least to most significant byte order)
|
|
865
|
+
* and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
|
|
866
|
+
* which is also used in Protocol Buffers.
|
|
829
867
|
*
|
|
830
|
-
*
|
|
868
|
+
* ```js
|
|
869
|
+
* // encoding step
|
|
870
|
+
* const encoder = encoding.createEncoder()
|
|
871
|
+
* encoding.writeVarUint(encoder, 256)
|
|
872
|
+
* encoding.writeVarString(encoder, 'Hello world!')
|
|
873
|
+
* const buf = encoding.toUint8Array(encoder)
|
|
874
|
+
* ```
|
|
875
|
+
*
|
|
876
|
+
* ```js
|
|
877
|
+
* // decoding step
|
|
878
|
+
* const decoder = decoding.createDecoder(buf)
|
|
879
|
+
* decoding.readVarUint(decoder) // => 256
|
|
880
|
+
* decoding.readVarString(decoder) // => 'Hello world!'
|
|
881
|
+
* decoding.hasContent(decoder) // => false - all data is read
|
|
882
|
+
* ```
|
|
883
|
+
*
|
|
884
|
+
* @module encoding
|
|
831
885
|
*/
|
|
832
886
|
|
|
833
|
-
/* c8 ignore start */
|
|
834
|
-
class VarStoragePolyfill {
|
|
835
|
-
constructor () {
|
|
836
|
-
this.map = new Map();
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
/**
|
|
840
|
-
* @param {string} key
|
|
841
|
-
* @param {any} newValue
|
|
842
|
-
*/
|
|
843
|
-
setItem (key, newValue) {
|
|
844
|
-
this.map.set(key, newValue);
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
/**
|
|
848
|
-
* @param {string} key
|
|
849
|
-
*/
|
|
850
|
-
getItem (key) {
|
|
851
|
-
return this.map.get(key)
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
/* c8 ignore stop */
|
|
855
887
|
|
|
856
888
|
/**
|
|
857
|
-
*
|
|
889
|
+
* A BinaryEncoder handles the encoding to an Uint8Array.
|
|
858
890
|
*/
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
usePolyfill = false;
|
|
891
|
+
class Encoder {
|
|
892
|
+
constructor () {
|
|
893
|
+
this.cpos = 0;
|
|
894
|
+
this.cbuf = new Uint8Array(100);
|
|
895
|
+
/**
|
|
896
|
+
* @type {Array<Uint8Array>}
|
|
897
|
+
*/
|
|
898
|
+
this.bufs = [];
|
|
868
899
|
}
|
|
869
|
-
}
|
|
870
|
-
/* c8 ignore stop */
|
|
900
|
+
}
|
|
871
901
|
|
|
872
902
|
/**
|
|
873
|
-
*
|
|
903
|
+
* @function
|
|
904
|
+
* @return {Encoder}
|
|
874
905
|
*/
|
|
875
|
-
|
|
876
|
-
const varStorage = _localStorage;
|
|
906
|
+
const createEncoder = () => new Encoder();
|
|
877
907
|
|
|
878
908
|
/**
|
|
879
|
-
*
|
|
909
|
+
* The current length of the encoded data.
|
|
880
910
|
*
|
|
881
|
-
* @
|
|
911
|
+
* @function
|
|
912
|
+
* @param {Encoder} encoder
|
|
913
|
+
* @return {number}
|
|
882
914
|
*/
|
|
883
|
-
|
|
915
|
+
const length = encoder => {
|
|
916
|
+
let len = encoder.cpos;
|
|
917
|
+
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
918
|
+
len += encoder.bufs[i].length;
|
|
919
|
+
}
|
|
920
|
+
return len
|
|
921
|
+
};
|
|
884
922
|
|
|
885
923
|
/**
|
|
886
|
-
*
|
|
924
|
+
* Transform to Uint8Array.
|
|
925
|
+
*
|
|
926
|
+
* @function
|
|
927
|
+
* @param {Encoder} encoder
|
|
928
|
+
* @return {Uint8Array} The created ArrayBuffer.
|
|
887
929
|
*/
|
|
888
|
-
const
|
|
930
|
+
const toUint8Array = encoder => {
|
|
931
|
+
const uint8arr = new Uint8Array(length(encoder));
|
|
932
|
+
let curPos = 0;
|
|
933
|
+
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
934
|
+
const d = encoder.bufs[i];
|
|
935
|
+
uint8arr.set(d, curPos);
|
|
936
|
+
curPos += d.length;
|
|
937
|
+
}
|
|
938
|
+
uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
|
|
939
|
+
return uint8arr
|
|
940
|
+
};
|
|
889
941
|
|
|
890
942
|
/**
|
|
891
|
-
*
|
|
943
|
+
* Verify that it is possible to write `len` bytes wtihout checking. If
|
|
944
|
+
* necessary, a new Buffer with the required length is attached.
|
|
945
|
+
*
|
|
946
|
+
* @param {Encoder} encoder
|
|
947
|
+
* @param {number} len
|
|
892
948
|
*/
|
|
893
|
-
const
|
|
949
|
+
const verifyLen = (encoder, len) => {
|
|
950
|
+
const bufferLen = encoder.cbuf.length;
|
|
951
|
+
if (bufferLen - encoder.cpos < len) {
|
|
952
|
+
encoder.bufs.push(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos));
|
|
953
|
+
encoder.cbuf = new Uint8Array(max$3(bufferLen, len) * 2);
|
|
954
|
+
encoder.cpos = 0;
|
|
955
|
+
}
|
|
956
|
+
};
|
|
894
957
|
|
|
895
958
|
/**
|
|
896
|
-
*
|
|
897
|
-
*
|
|
898
|
-
* @
|
|
959
|
+
* Write one byte to the encoder.
|
|
960
|
+
*
|
|
961
|
+
* @function
|
|
962
|
+
* @param {Encoder} encoder
|
|
963
|
+
* @param {number} num The byte that is to be encoded.
|
|
899
964
|
*/
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
|
|
965
|
+
const write = (encoder, num) => {
|
|
966
|
+
const bufferLen = encoder.cbuf.length;
|
|
967
|
+
if (encoder.cpos === bufferLen) {
|
|
968
|
+
encoder.bufs.push(encoder.cbuf);
|
|
969
|
+
encoder.cbuf = new Uint8Array(bufferLen * 2);
|
|
970
|
+
encoder.cpos = 0;
|
|
903
971
|
}
|
|
972
|
+
encoder.cbuf[encoder.cpos++] = num;
|
|
904
973
|
};
|
|
905
974
|
|
|
906
975
|
/**
|
|
907
|
-
*
|
|
908
|
-
*
|
|
976
|
+
* Write one byte as an unsigned integer.
|
|
977
|
+
*
|
|
978
|
+
* @function
|
|
979
|
+
* @param {Encoder} encoder
|
|
980
|
+
* @param {number} num The number that is to be encoded.
|
|
909
981
|
*/
|
|
910
|
-
const
|
|
982
|
+
const writeUint8 = write;
|
|
911
983
|
|
|
912
984
|
/**
|
|
913
|
-
*
|
|
985
|
+
* Write a variable length unsigned integer. Max encodable integer is 2^53.
|
|
986
|
+
*
|
|
987
|
+
* @function
|
|
988
|
+
* @param {Encoder} encoder
|
|
989
|
+
* @param {number} num The number that is to be encoded.
|
|
914
990
|
*/
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
991
|
+
const writeVarUint = (encoder, num) => {
|
|
992
|
+
while (num > BITS7) {
|
|
993
|
+
write(encoder, BIT8 | (BITS7 & num));
|
|
994
|
+
num = floor$2(num / 128); // shift >>> 7
|
|
918
995
|
}
|
|
919
|
-
|
|
996
|
+
write(encoder, BITS7 & num);
|
|
920
997
|
};
|
|
921
998
|
|
|
922
999
|
/**
|
|
923
|
-
*
|
|
924
|
-
*
|
|
925
|
-
*
|
|
1000
|
+
* Write a variable length integer.
|
|
1001
|
+
*
|
|
1002
|
+
* We use the 7th bit instead for signaling that this is a negative number.
|
|
1003
|
+
*
|
|
1004
|
+
* @function
|
|
1005
|
+
* @param {Encoder} encoder
|
|
1006
|
+
* @param {number} num The number that is to be encoded.
|
|
926
1007
|
*/
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1008
|
+
const writeVarInt = (encoder, num) => {
|
|
1009
|
+
const isNegative = isNegativeZero(num);
|
|
1010
|
+
if (isNegative) {
|
|
1011
|
+
num = -num;
|
|
1012
|
+
}
|
|
1013
|
+
// |- whether to continue reading |- whether is negative |- number
|
|
1014
|
+
write(encoder, (num > BITS6 ? BIT8 : 0) | (isNegative ? BIT7 : 0) | (BITS6 & num));
|
|
1015
|
+
num = floor$2(num / 64); // shift >>> 6
|
|
1016
|
+
// We don't need to consider the case of num === 0 so we can use a different
|
|
1017
|
+
// pattern here than above.
|
|
1018
|
+
while (num > 0) {
|
|
1019
|
+
write(encoder, (num > BITS7 ? BIT8 : 0) | (BITS7 & num));
|
|
1020
|
+
num = floor$2(num / 128); // shift >>> 7
|
|
932
1021
|
}
|
|
933
|
-
return true
|
|
934
1022
|
};
|
|
935
1023
|
|
|
936
1024
|
/**
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
* @param {any} obj
|
|
940
|
-
* @param {string|symbol} key
|
|
941
|
-
* @return {boolean}
|
|
1025
|
+
* A cache to store strings temporarily
|
|
942
1026
|
*/
|
|
943
|
-
const
|
|
1027
|
+
const _strBuffer = new Uint8Array(30000);
|
|
1028
|
+
const _maxStrBSize = _strBuffer.length / 3;
|
|
944
1029
|
|
|
945
1030
|
/**
|
|
946
|
-
*
|
|
947
|
-
* @param {Object<string,any>} b
|
|
948
|
-
* @return {boolean}
|
|
949
|
-
*/
|
|
950
|
-
const equalFlat = (a, b) => a === b || (length$1(a) === length$1(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && b[key] === val));
|
|
951
|
-
|
|
952
|
-
/**
|
|
953
|
-
* Common functions and function call helpers.
|
|
1031
|
+
* Write a variable length string.
|
|
954
1032
|
*
|
|
955
|
-
* @
|
|
1033
|
+
* @function
|
|
1034
|
+
* @param {Encoder} encoder
|
|
1035
|
+
* @param {String} str The string that is to be encoded.
|
|
956
1036
|
*/
|
|
957
|
-
|
|
1037
|
+
const _writeVarStringNative = (encoder, str) => {
|
|
1038
|
+
if (str.length < _maxStrBSize) {
|
|
1039
|
+
// We can encode the string into the existing buffer
|
|
1040
|
+
/* c8 ignore next */
|
|
1041
|
+
const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
|
|
1042
|
+
writeVarUint(encoder, written);
|
|
1043
|
+
for (let i = 0; i < written; i++) {
|
|
1044
|
+
write(encoder, _strBuffer[i]);
|
|
1045
|
+
}
|
|
1046
|
+
} else {
|
|
1047
|
+
writeVarUint8Array(encoder, encodeUtf8(str));
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
958
1050
|
|
|
959
1051
|
/**
|
|
960
|
-
*
|
|
1052
|
+
* Write a variable length string.
|
|
961
1053
|
*
|
|
962
|
-
* @
|
|
963
|
-
* @param {
|
|
1054
|
+
* @function
|
|
1055
|
+
* @param {Encoder} encoder
|
|
1056
|
+
* @param {String} str The string that is to be encoded.
|
|
964
1057
|
*/
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
if (i < fs.length) {
|
|
972
|
-
callAll(fs, args, i + 1);
|
|
973
|
-
}
|
|
1058
|
+
const _writeVarStringPolyfill = (encoder, str) => {
|
|
1059
|
+
const encodedString = unescape(encodeURIComponent(str));
|
|
1060
|
+
const len = encodedString.length;
|
|
1061
|
+
writeVarUint(encoder, len);
|
|
1062
|
+
for (let i = 0; i < len; i++) {
|
|
1063
|
+
write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
|
|
974
1064
|
}
|
|
975
1065
|
};
|
|
976
1066
|
|
|
977
1067
|
/**
|
|
978
|
-
*
|
|
1068
|
+
* Write a variable length string.
|
|
979
1069
|
*
|
|
980
|
-
* @
|
|
981
|
-
* @
|
|
1070
|
+
* @function
|
|
1071
|
+
* @param {Encoder} encoder
|
|
1072
|
+
* @param {String} str The string that is to be encoded.
|
|
982
1073
|
*/
|
|
983
|
-
|
|
1074
|
+
/* c8 ignore next */
|
|
1075
|
+
const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
|
|
984
1076
|
|
|
985
1077
|
/**
|
|
986
|
-
*
|
|
987
|
-
* @template {V} OPTS
|
|
1078
|
+
* Append fixed-length Uint8Array to the encoder.
|
|
988
1079
|
*
|
|
989
|
-
* @
|
|
990
|
-
* @param {
|
|
1080
|
+
* @function
|
|
1081
|
+
* @param {Encoder} encoder
|
|
1082
|
+
* @param {Uint8Array} uint8Array
|
|
991
1083
|
*/
|
|
992
|
-
|
|
993
|
-
const
|
|
1084
|
+
const writeUint8Array = (encoder, uint8Array) => {
|
|
1085
|
+
const bufferLen = encoder.cbuf.length;
|
|
1086
|
+
const cpos = encoder.cpos;
|
|
1087
|
+
const leftCopyLen = min$2(bufferLen - cpos, uint8Array.length);
|
|
1088
|
+
const rightCopyLen = uint8Array.length - leftCopyLen;
|
|
1089
|
+
encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
|
|
1090
|
+
encoder.cpos += leftCopyLen;
|
|
1091
|
+
if (rightCopyLen > 0) {
|
|
1092
|
+
// Still something to write, write right half..
|
|
1093
|
+
// Append new buffer
|
|
1094
|
+
encoder.bufs.push(encoder.cbuf);
|
|
1095
|
+
// must have at least size of remaining buffer
|
|
1096
|
+
encoder.cbuf = new Uint8Array(max$3(bufferLen * 2, rightCopyLen));
|
|
1097
|
+
// copy array
|
|
1098
|
+
encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
|
|
1099
|
+
encoder.cpos = rightCopyLen;
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
994
1102
|
|
|
995
1103
|
/**
|
|
996
|
-
*
|
|
1104
|
+
* Append an Uint8Array to Encoder.
|
|
997
1105
|
*
|
|
998
|
-
* @
|
|
1106
|
+
* @function
|
|
1107
|
+
* @param {Encoder} encoder
|
|
1108
|
+
* @param {Uint8Array} uint8Array
|
|
999
1109
|
*/
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
const isNode = typeof process !== 'undefined' && process.release &&
|
|
1005
|
-
/node|io\.js/.test(process.release.name);
|
|
1110
|
+
const writeVarUint8Array = (encoder, uint8Array) => {
|
|
1111
|
+
writeVarUint(encoder, uint8Array.byteLength);
|
|
1112
|
+
writeUint8Array(encoder, uint8Array);
|
|
1113
|
+
};
|
|
1006
1114
|
|
|
1007
1115
|
/**
|
|
1008
|
-
*
|
|
1116
|
+
* Create an DataView of the next `len` bytes. Use it to write data after
|
|
1117
|
+
* calling this function.
|
|
1118
|
+
*
|
|
1119
|
+
* ```js
|
|
1120
|
+
* // write float32 using DataView
|
|
1121
|
+
* const dv = writeOnDataView(encoder, 4)
|
|
1122
|
+
* dv.setFloat32(0, 1.1)
|
|
1123
|
+
* // read float32 using DataView
|
|
1124
|
+
* const dv = readFromDataView(encoder, 4)
|
|
1125
|
+
* dv.getFloat32(0) // => 1.100000023841858 (leaving it to the reader to find out why this is the correct result)
|
|
1126
|
+
* ```
|
|
1127
|
+
*
|
|
1128
|
+
* @param {Encoder} encoder
|
|
1129
|
+
* @param {number} len
|
|
1130
|
+
* @return {DataView}
|
|
1009
1131
|
*/
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
if (isNode) {
|
|
1016
|
-
params = create$5();
|
|
1017
|
-
const pargs = process.argv;
|
|
1018
|
-
let currParamName = null;
|
|
1019
|
-
for (let i = 0; i < pargs.length; i++) {
|
|
1020
|
-
const parg = pargs[i];
|
|
1021
|
-
if (parg[0] === '-') {
|
|
1022
|
-
if (currParamName !== null) {
|
|
1023
|
-
params.set(currParamName, '');
|
|
1024
|
-
}
|
|
1025
|
-
currParamName = parg;
|
|
1026
|
-
} else {
|
|
1027
|
-
if (currParamName !== null) {
|
|
1028
|
-
params.set(currParamName, parg);
|
|
1029
|
-
currParamName = null;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
if (currParamName !== null) {
|
|
1034
|
-
params.set(currParamName, '');
|
|
1035
|
-
}
|
|
1036
|
-
// in ReactNative for example this would not be true (unless connected to the Remote Debugger)
|
|
1037
|
-
} else if (typeof location === 'object') {
|
|
1038
|
-
params = create$5(); // eslint-disable-next-line no-undef
|
|
1039
|
-
(location.search || '?').slice(1).split('&').forEach((kv) => {
|
|
1040
|
-
if (kv.length !== 0) {
|
|
1041
|
-
const [key, value] = kv.split('=');
|
|
1042
|
-
params.set(`--${fromCamelCase(key, '-')}`, value);
|
|
1043
|
-
params.set(`-${fromCamelCase(key, '-')}`, value);
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
} else {
|
|
1047
|
-
params = create$5();
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
return params
|
|
1132
|
+
const writeOnDataView = (encoder, len) => {
|
|
1133
|
+
verifyLen(encoder, len);
|
|
1134
|
+
const dview = new DataView(encoder.cbuf.buffer, encoder.cpos, len);
|
|
1135
|
+
encoder.cpos += len;
|
|
1136
|
+
return dview
|
|
1051
1137
|
};
|
|
1052
|
-
/* c8 ignore stop */
|
|
1053
1138
|
|
|
1054
1139
|
/**
|
|
1055
|
-
* @param {
|
|
1056
|
-
* @
|
|
1140
|
+
* @param {Encoder} encoder
|
|
1141
|
+
* @param {number} num
|
|
1057
1142
|
*/
|
|
1058
|
-
|
|
1059
|
-
const hasParam = (name) => computeParams().has(name);
|
|
1143
|
+
const writeFloat32 = (encoder, num) => writeOnDataView(encoder, 4).setFloat32(0, num, false);
|
|
1060
1144
|
|
|
1061
1145
|
/**
|
|
1062
|
-
* @param {
|
|
1063
|
-
* @
|
|
1146
|
+
* @param {Encoder} encoder
|
|
1147
|
+
* @param {number} num
|
|
1064
1148
|
*/
|
|
1065
|
-
|
|
1066
|
-
const getVariable = (name) =>
|
|
1067
|
-
isNode
|
|
1068
|
-
? undefinedToNull(process.env[name.toUpperCase()])
|
|
1069
|
-
: undefinedToNull(varStorage.getItem(name));
|
|
1149
|
+
const writeFloat64 = (encoder, num) => writeOnDataView(encoder, 8).setFloat64(0, num, false);
|
|
1070
1150
|
|
|
1071
1151
|
/**
|
|
1072
|
-
* @param {
|
|
1073
|
-
* @
|
|
1152
|
+
* @param {Encoder} encoder
|
|
1153
|
+
* @param {bigint} num
|
|
1074
1154
|
*/
|
|
1075
|
-
|
|
1076
|
-
const hasConf = (name) =>
|
|
1077
|
-
hasParam('--' + name) || getVariable(name) !== null;
|
|
1078
|
-
|
|
1079
|
-
/* c8 ignore next */
|
|
1080
|
-
hasConf('production');
|
|
1081
|
-
|
|
1082
|
-
/* c8 ignore next 2 */
|
|
1083
|
-
const forceColor = isNode &&
|
|
1084
|
-
isOneOf(process.env.FORCE_COLOR, ['true', '1', '2']);
|
|
1085
|
-
|
|
1086
|
-
/* c8 ignore start */
|
|
1087
|
-
const supportsColor = !hasParam('no-colors') &&
|
|
1088
|
-
(!isNode || process.stdout.isTTY || forceColor) && (
|
|
1089
|
-
!isNode || hasParam('color') || forceColor ||
|
|
1090
|
-
getVariable('COLORTERM') !== null ||
|
|
1091
|
-
(getVariable('TERM') || '').includes('color')
|
|
1092
|
-
);
|
|
1093
|
-
/* c8 ignore stop */
|
|
1094
|
-
|
|
1095
|
-
/* eslint-env browser */
|
|
1155
|
+
const writeBigInt64 = (encoder, num) => /** @type {any} */ (writeOnDataView(encoder, 8)).setBigInt64(0, num, false);
|
|
1096
1156
|
|
|
1157
|
+
const floatTestBed = new DataView(new ArrayBuffer(4));
|
|
1097
1158
|
/**
|
|
1098
|
-
*
|
|
1159
|
+
* Check if a number can be encoded as a 32 bit float.
|
|
1099
1160
|
*
|
|
1100
|
-
* @
|
|
1161
|
+
* @param {number} num
|
|
1162
|
+
* @return {boolean}
|
|
1101
1163
|
*/
|
|
1164
|
+
const isFloat32 = num => {
|
|
1165
|
+
floatTestBed.setFloat32(0, num);
|
|
1166
|
+
return floatTestBed.getFloat32(0) === num
|
|
1167
|
+
};
|
|
1102
1168
|
|
|
1103
1169
|
/**
|
|
1104
|
-
*
|
|
1170
|
+
* Encode data with efficient binary format.
|
|
1105
1171
|
*
|
|
1106
|
-
*
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
const BIT4 = 8;
|
|
1112
|
-
const BIT6 = 32;
|
|
1113
|
-
const BIT7 = 64;
|
|
1114
|
-
const BIT8 = 128;
|
|
1115
|
-
const BITS5 = 31;
|
|
1116
|
-
const BITS6 = 63;
|
|
1117
|
-
const BITS7 = 127;
|
|
1118
|
-
/**
|
|
1119
|
-
* @type {number}
|
|
1120
|
-
*/
|
|
1121
|
-
const BITS31 = 0x7FFFFFFF;
|
|
1122
|
-
|
|
1123
|
-
/**
|
|
1124
|
-
* Utility helpers for working with numbers.
|
|
1172
|
+
* Differences to JSON:
|
|
1173
|
+
* • Transforms data to a binary format (not to a string)
|
|
1174
|
+
* • Encodes undefined, NaN, and ArrayBuffer (these can't be represented in JSON)
|
|
1175
|
+
* • Numbers are efficiently encoded either as a variable length integer, as a
|
|
1176
|
+
* 32 bit float, as a 64 bit float, or as a 64 bit bigint.
|
|
1125
1177
|
*
|
|
1126
|
-
*
|
|
1127
|
-
*/
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
|
1131
|
-
|
|
1132
|
-
/* c8 ignore next */
|
|
1133
|
-
const isInteger = Number.isInteger || (num => typeof num === 'number' && isFinite(num) && floor$2(num) === num);
|
|
1134
|
-
|
|
1135
|
-
/**
|
|
1136
|
-
* Error helpers.
|
|
1178
|
+
* Encoding table:
|
|
1137
1179
|
*
|
|
1138
|
-
*
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1144
|
-
|
|
1145
|
-
|
|
1180
|
+
* | Data Type | Prefix | Encoding Method | Comment |
|
|
1181
|
+
* | ------------------- | -------- | ------------------ | ------- |
|
|
1182
|
+
* | undefined | 127 | | Functions, symbol, and everything that cannot be identified is encoded as undefined |
|
|
1183
|
+
* | null | 126 | | |
|
|
1184
|
+
* | integer | 125 | writeVarInt | Only encodes 32 bit signed integers |
|
|
1185
|
+
* | float32 | 124 | writeFloat32 | |
|
|
1186
|
+
* | float64 | 123 | writeFloat64 | |
|
|
1187
|
+
* | bigint | 122 | writeBigInt64 | |
|
|
1188
|
+
* | boolean (false) | 121 | | True and false are different data types so we save the following byte |
|
|
1189
|
+
* | boolean (true) | 120 | | - 0b01111000 so the last bit determines whether true or false |
|
|
1190
|
+
* | string | 119 | writeVarString | |
|
|
1191
|
+
* | object<string,any> | 118 | custom | Writes {length} then {length} key-value pairs |
|
|
1192
|
+
* | array<any> | 117 | custom | Writes {length} then {length} json values |
|
|
1193
|
+
* | Uint8Array | 116 | writeVarUint8Array | We use Uint8Array for any kind of binary data |
|
|
1194
|
+
*
|
|
1195
|
+
* Reasons for the decreasing prefix:
|
|
1196
|
+
* We need the first bit for extendability (later we may want to encode the
|
|
1197
|
+
* prefix with writeVarUint). The remaining 7 bits are divided as follows:
|
|
1198
|
+
* [0-30] the beginning of the data range is used for custom purposes
|
|
1199
|
+
* (defined by the function that uses this library)
|
|
1200
|
+
* [31-127] the end of the data range is used for data encoding by
|
|
1201
|
+
* lib0/encoding.js
|
|
1202
|
+
*
|
|
1203
|
+
* @param {Encoder} encoder
|
|
1204
|
+
* @param {undefined|null|number|bigint|boolean|string|Object<string,any>|Array<any>|Uint8Array} data
|
|
1205
|
+
*/
|
|
1206
|
+
const writeAny = (encoder, data) => {
|
|
1207
|
+
switch (typeof data) {
|
|
1208
|
+
case 'string':
|
|
1209
|
+
// TYPE 119: STRING
|
|
1210
|
+
write(encoder, 119);
|
|
1211
|
+
writeVarString(encoder, data);
|
|
1212
|
+
break
|
|
1213
|
+
case 'number':
|
|
1214
|
+
if (isInteger(data) && abs$2(data) <= BITS31) {
|
|
1215
|
+
// TYPE 125: INTEGER
|
|
1216
|
+
write(encoder, 125);
|
|
1217
|
+
writeVarInt(encoder, data);
|
|
1218
|
+
} else if (isFloat32(data)) {
|
|
1219
|
+
// TYPE 124: FLOAT32
|
|
1220
|
+
write(encoder, 124);
|
|
1221
|
+
writeFloat32(encoder, data);
|
|
1222
|
+
} else {
|
|
1223
|
+
// TYPE 123: FLOAT64
|
|
1224
|
+
write(encoder, 123);
|
|
1225
|
+
writeFloat64(encoder, data);
|
|
1226
|
+
}
|
|
1227
|
+
break
|
|
1228
|
+
case 'bigint':
|
|
1229
|
+
// TYPE 122: BigInt
|
|
1230
|
+
write(encoder, 122);
|
|
1231
|
+
writeBigInt64(encoder, data);
|
|
1232
|
+
break
|
|
1233
|
+
case 'object':
|
|
1234
|
+
if (data === null) {
|
|
1235
|
+
// TYPE 126: null
|
|
1236
|
+
write(encoder, 126);
|
|
1237
|
+
} else if (isArray(data)) {
|
|
1238
|
+
// TYPE 117: Array
|
|
1239
|
+
write(encoder, 117);
|
|
1240
|
+
writeVarUint(encoder, data.length);
|
|
1241
|
+
for (let i = 0; i < data.length; i++) {
|
|
1242
|
+
writeAny(encoder, data[i]);
|
|
1243
|
+
}
|
|
1244
|
+
} else if (data instanceof Uint8Array) {
|
|
1245
|
+
// TYPE 116: ArrayBuffer
|
|
1246
|
+
write(encoder, 116);
|
|
1247
|
+
writeVarUint8Array(encoder, data);
|
|
1248
|
+
} else {
|
|
1249
|
+
// TYPE 118: Object
|
|
1250
|
+
write(encoder, 118);
|
|
1251
|
+
const keys = Object.keys(data);
|
|
1252
|
+
writeVarUint(encoder, keys.length);
|
|
1253
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1254
|
+
const key = keys[i];
|
|
1255
|
+
writeVarString(encoder, key);
|
|
1256
|
+
writeAny(encoder, data[key]);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
break
|
|
1260
|
+
case 'boolean':
|
|
1261
|
+
// TYPE 120/121: boolean (true/false)
|
|
1262
|
+
write(encoder, data ? 120 : 121);
|
|
1263
|
+
break
|
|
1264
|
+
default:
|
|
1265
|
+
// TYPE 127: undefined
|
|
1266
|
+
write(encoder, 127);
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Now come a few stateful encoder that have their own classes.
|
|
1272
|
+
*/
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* Basic Run Length Encoder - a basic compression implementation.
|
|
1276
|
+
*
|
|
1277
|
+
* Encodes [1,1,1,7] to [1,3,7,1] (3 times 1, 1 time 7). This encoder might do more harm than good if there are a lot of values that are not repeated.
|
|
1278
|
+
*
|
|
1279
|
+
* It was originally used for image compression. Cool .. article http://csbruce.com/cbm/transactor/pdfs/trans_v7_i06.pdf
|
|
1280
|
+
*
|
|
1281
|
+
* @note T must not be null!
|
|
1282
|
+
*
|
|
1283
|
+
* @template T
|
|
1284
|
+
*/
|
|
1285
|
+
class RleEncoder extends Encoder {
|
|
1286
|
+
/**
|
|
1287
|
+
* @param {function(Encoder, T):void} writer
|
|
1288
|
+
*/
|
|
1289
|
+
constructor (writer) {
|
|
1290
|
+
super();
|
|
1291
|
+
/**
|
|
1292
|
+
* The writer
|
|
1293
|
+
*/
|
|
1294
|
+
this.w = writer;
|
|
1295
|
+
/**
|
|
1296
|
+
* Current state
|
|
1297
|
+
* @type {T|null}
|
|
1298
|
+
*/
|
|
1299
|
+
this.s = null;
|
|
1300
|
+
this.count = 0;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
* @param {T} v
|
|
1305
|
+
*/
|
|
1306
|
+
write (v) {
|
|
1307
|
+
if (this.s === v) {
|
|
1308
|
+
this.count++;
|
|
1309
|
+
} else {
|
|
1310
|
+
if (this.count > 0) {
|
|
1311
|
+
// flush counter, unless this is the first value (count = 0)
|
|
1312
|
+
writeVarUint(this, this.count - 1); // since count is always > 0, we can decrement by one. non-standard encoding ftw
|
|
1313
|
+
}
|
|
1314
|
+
this.count = 1;
|
|
1315
|
+
// write first value
|
|
1316
|
+
this.w(this, v);
|
|
1317
|
+
this.s = v;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
/**
|
|
1323
|
+
* @param {UintOptRleEncoder} encoder
|
|
1324
|
+
*/
|
|
1325
|
+
const flushUintOptRleEncoder = encoder => {
|
|
1326
|
+
if (encoder.count > 0) {
|
|
1327
|
+
// flush counter, unless this is the first value (count = 0)
|
|
1328
|
+
// case 1: just a single value. set sign to positive
|
|
1329
|
+
// case 2: write several values. set sign to negative to indicate that there is a length coming
|
|
1330
|
+
writeVarInt(encoder.encoder, encoder.count === 1 ? encoder.s : -encoder.s);
|
|
1331
|
+
if (encoder.count > 1) {
|
|
1332
|
+
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Optimized Rle encoder that does not suffer from the mentioned problem of the basic Rle encoder.
|
|
1339
|
+
*
|
|
1340
|
+
* Internally uses VarInt encoder to write unsigned integers. If the input occurs multiple times, we write
|
|
1341
|
+
* write it as a negative number. The UintOptRleDecoder then understands that it needs to read a count.
|
|
1342
|
+
*
|
|
1343
|
+
* Encodes [1,2,3,3,3] as [1,2,-3,3] (once 1, once 2, three times 3)
|
|
1344
|
+
*/
|
|
1345
|
+
class UintOptRleEncoder {
|
|
1346
|
+
constructor () {
|
|
1347
|
+
this.encoder = new Encoder();
|
|
1348
|
+
/**
|
|
1349
|
+
* @type {number}
|
|
1350
|
+
*/
|
|
1351
|
+
this.s = 0;
|
|
1352
|
+
this.count = 0;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* @param {number} v
|
|
1357
|
+
*/
|
|
1358
|
+
write (v) {
|
|
1359
|
+
if (this.s === v) {
|
|
1360
|
+
this.count++;
|
|
1361
|
+
} else {
|
|
1362
|
+
flushUintOptRleEncoder(this);
|
|
1363
|
+
this.count = 1;
|
|
1364
|
+
this.s = v;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Flush the encoded state and transform this to a Uint8Array.
|
|
1370
|
+
*
|
|
1371
|
+
* Note that this should only be called once.
|
|
1372
|
+
*/
|
|
1373
|
+
toUint8Array () {
|
|
1374
|
+
flushUintOptRleEncoder(this);
|
|
1375
|
+
return toUint8Array(this.encoder)
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/**
|
|
1380
|
+
* @param {IntDiffOptRleEncoder} encoder
|
|
1381
|
+
*/
|
|
1382
|
+
const flushIntDiffOptRleEncoder = encoder => {
|
|
1383
|
+
if (encoder.count > 0) {
|
|
1384
|
+
// 31 bit making up the diff | wether to write the counter
|
|
1385
|
+
// const encodedDiff = encoder.diff << 1 | (encoder.count === 1 ? 0 : 1)
|
|
1386
|
+
const encodedDiff = encoder.diff * 2 + (encoder.count === 1 ? 0 : 1);
|
|
1387
|
+
// flush counter, unless this is the first value (count = 0)
|
|
1388
|
+
// case 1: just a single value. set first bit to positive
|
|
1389
|
+
// case 2: write several values. set first bit to negative to indicate that there is a length coming
|
|
1390
|
+
writeVarInt(encoder.encoder, encodedDiff);
|
|
1391
|
+
if (encoder.count > 1) {
|
|
1392
|
+
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
/**
|
|
1398
|
+
* A combination of the IntDiffEncoder and the UintOptRleEncoder.
|
|
1399
|
+
*
|
|
1400
|
+
* The count approach is similar to the UintDiffOptRleEncoder, but instead of using the negative bitflag, it encodes
|
|
1401
|
+
* in the LSB whether a count is to be read. Therefore this Encoder only supports 31 bit integers!
|
|
1402
|
+
*
|
|
1403
|
+
* Encodes [1, 2, 3, 2] as [3, 1, 6, -1] (more specifically [(1 << 1) | 1, (3 << 0) | 0, -1])
|
|
1404
|
+
*
|
|
1405
|
+
* Internally uses variable length encoding. Contrary to normal UintVar encoding, the first byte contains:
|
|
1406
|
+
* * 1 bit that denotes whether the next value is a count (LSB)
|
|
1407
|
+
* * 1 bit that denotes whether this value is negative (MSB - 1)
|
|
1408
|
+
* * 1 bit that denotes whether to continue reading the variable length integer (MSB)
|
|
1409
|
+
*
|
|
1410
|
+
* Therefore, only five bits remain to encode diff ranges.
|
|
1411
|
+
*
|
|
1412
|
+
* Use this Encoder only when appropriate. In most cases, this is probably a bad idea.
|
|
1413
|
+
*/
|
|
1414
|
+
class IntDiffOptRleEncoder {
|
|
1415
|
+
constructor () {
|
|
1416
|
+
this.encoder = new Encoder();
|
|
1417
|
+
/**
|
|
1418
|
+
* @type {number}
|
|
1419
|
+
*/
|
|
1420
|
+
this.s = 0;
|
|
1421
|
+
this.count = 0;
|
|
1422
|
+
this.diff = 0;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
/**
|
|
1426
|
+
* @param {number} v
|
|
1427
|
+
*/
|
|
1428
|
+
write (v) {
|
|
1429
|
+
if (this.diff === v - this.s) {
|
|
1430
|
+
this.s = v;
|
|
1431
|
+
this.count++;
|
|
1432
|
+
} else {
|
|
1433
|
+
flushIntDiffOptRleEncoder(this);
|
|
1434
|
+
this.count = 1;
|
|
1435
|
+
this.diff = v - this.s;
|
|
1436
|
+
this.s = v;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
/**
|
|
1441
|
+
* Flush the encoded state and transform this to a Uint8Array.
|
|
1442
|
+
*
|
|
1443
|
+
* Note that this should only be called once.
|
|
1444
|
+
*/
|
|
1445
|
+
toUint8Array () {
|
|
1446
|
+
flushIntDiffOptRleEncoder(this);
|
|
1447
|
+
return toUint8Array(this.encoder)
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Optimized String Encoder.
|
|
1453
|
+
*
|
|
1454
|
+
* Encoding many small strings in a simple Encoder is not very efficient. The function call to decode a string takes some time and creates references that must be eventually deleted.
|
|
1455
|
+
* In practice, when decoding several million small strings, the GC will kick in more and more often to collect orphaned string objects (or maybe there is another reason?).
|
|
1456
|
+
*
|
|
1457
|
+
* This string encoder solves the above problem. All strings are concatenated and written as a single string using a single encoding call.
|
|
1458
|
+
*
|
|
1459
|
+
* The lengths are encoded using a UintOptRleEncoder.
|
|
1460
|
+
*/
|
|
1461
|
+
class StringEncoder {
|
|
1462
|
+
constructor () {
|
|
1463
|
+
/**
|
|
1464
|
+
* @type {Array<string>}
|
|
1465
|
+
*/
|
|
1466
|
+
this.sarr = [];
|
|
1467
|
+
this.s = '';
|
|
1468
|
+
this.lensE = new UintOptRleEncoder();
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* @param {string} string
|
|
1473
|
+
*/
|
|
1474
|
+
write (string) {
|
|
1475
|
+
this.s += string;
|
|
1476
|
+
if (this.s.length > 19) {
|
|
1477
|
+
this.sarr.push(this.s);
|
|
1478
|
+
this.s = '';
|
|
1479
|
+
}
|
|
1480
|
+
this.lensE.write(string.length);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
toUint8Array () {
|
|
1484
|
+
const encoder = new Encoder();
|
|
1485
|
+
this.sarr.push(this.s);
|
|
1486
|
+
this.s = '';
|
|
1487
|
+
writeVarString(encoder, this.sarr.join(''));
|
|
1488
|
+
writeUint8Array(encoder, this.lensE.toUint8Array());
|
|
1489
|
+
return toUint8Array(encoder)
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
/**
|
|
1494
|
+
* Error helpers.
|
|
1495
|
+
*
|
|
1496
|
+
* @module error
|
|
1497
|
+
*/
|
|
1498
|
+
|
|
1499
|
+
/**
|
|
1500
|
+
* @param {string} s
|
|
1501
|
+
* @return {Error}
|
|
1502
|
+
*/
|
|
1503
|
+
/* c8 ignore next */
|
|
1146
1504
|
const create$3 = s => new Error(s);
|
|
1147
1505
|
|
|
1148
1506
|
/**
|
|
@@ -1244,7 +1602,7 @@ const hasContent = decoder => decoder.pos !== decoder.arr.length;
|
|
|
1244
1602
|
* @return {Uint8Array}
|
|
1245
1603
|
*/
|
|
1246
1604
|
const readUint8Array = (decoder, len) => {
|
|
1247
|
-
const view =
|
|
1605
|
+
const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
|
|
1248
1606
|
decoder.pos += len;
|
|
1249
1607
|
return view
|
|
1250
1608
|
};
|
|
@@ -1564,729 +1922,430 @@ class IntDiffOptRleDecoder extends Decoder {
|
|
|
1564
1922
|
this.count--;
|
|
1565
1923
|
return this.s
|
|
1566
1924
|
}
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
class StringDecoder {
|
|
1570
|
-
/**
|
|
1571
|
-
* @param {Uint8Array} uint8Array
|
|
1572
|
-
*/
|
|
1573
|
-
constructor (uint8Array) {
|
|
1574
|
-
this.decoder = new UintOptRleDecoder(uint8Array);
|
|
1575
|
-
this.str = readVarString(this.decoder);
|
|
1576
|
-
/**
|
|
1577
|
-
* @type {number}
|
|
1578
|
-
*/
|
|
1579
|
-
this.spos = 0;
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
/**
|
|
1583
|
-
* @return {string}
|
|
1584
|
-
*/
|
|
1585
|
-
read () {
|
|
1586
|
-
const end = this.spos + this.decoder.read();
|
|
1587
|
-
const res = this.str.slice(this.spos, end);
|
|
1588
|
-
this.spos = end;
|
|
1589
|
-
return res
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
/**
|
|
1594
|
-
* Utility functions to work with buffers (Uint8Array).
|
|
1595
|
-
*
|
|
1596
|
-
* @module buffer
|
|
1597
|
-
*/
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
/**
|
|
1601
|
-
* @param {number} len
|
|
1602
|
-
*/
|
|
1603
|
-
const createUint8ArrayFromLen = len => new Uint8Array(len);
|
|
1604
|
-
|
|
1605
|
-
/**
|
|
1606
|
-
* Create Uint8Array with initial content from buffer
|
|
1607
|
-
*
|
|
1608
|
-
* @param {ArrayBuffer} buffer
|
|
1609
|
-
* @param {number} byteOffset
|
|
1610
|
-
* @param {number} length
|
|
1611
|
-
*/
|
|
1612
|
-
const createUint8ArrayViewFromArrayBuffer = (buffer, byteOffset, length) => new Uint8Array(buffer, byteOffset, length);
|
|
1613
|
-
|
|
1614
|
-
/**
|
|
1615
|
-
* Copy the content of an Uint8Array view to a new ArrayBuffer.
|
|
1616
|
-
*
|
|
1617
|
-
* @param {Uint8Array} uint8Array
|
|
1618
|
-
* @return {Uint8Array}
|
|
1619
|
-
*/
|
|
1620
|
-
const copyUint8Array = uint8Array => {
|
|
1621
|
-
const newBuf = createUint8ArrayFromLen(uint8Array.byteLength);
|
|
1622
|
-
newBuf.set(uint8Array);
|
|
1623
|
-
return newBuf
|
|
1624
|
-
};
|
|
1625
|
-
|
|
1626
|
-
/**
|
|
1627
|
-
* Efficient schema-less binary encoding with support for variable length encoding.
|
|
1628
|
-
*
|
|
1629
|
-
* Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
|
|
1630
|
-
*
|
|
1631
|
-
* Encodes numbers in little-endian order (least to most significant byte order)
|
|
1632
|
-
* and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
|
|
1633
|
-
* which is also used in Protocol Buffers.
|
|
1634
|
-
*
|
|
1635
|
-
* ```js
|
|
1636
|
-
* // encoding step
|
|
1637
|
-
* const encoder = encoding.createEncoder()
|
|
1638
|
-
* encoding.writeVarUint(encoder, 256)
|
|
1639
|
-
* encoding.writeVarString(encoder, 'Hello world!')
|
|
1640
|
-
* const buf = encoding.toUint8Array(encoder)
|
|
1641
|
-
* ```
|
|
1642
|
-
*
|
|
1643
|
-
* ```js
|
|
1644
|
-
* // decoding step
|
|
1645
|
-
* const decoder = decoding.createDecoder(buf)
|
|
1646
|
-
* decoding.readVarUint(decoder) // => 256
|
|
1647
|
-
* decoding.readVarString(decoder) // => 'Hello world!'
|
|
1648
|
-
* decoding.hasContent(decoder) // => false - all data is read
|
|
1649
|
-
* ```
|
|
1650
|
-
*
|
|
1651
|
-
* @module encoding
|
|
1652
|
-
*/
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
/**
|
|
1656
|
-
* A BinaryEncoder handles the encoding to an Uint8Array.
|
|
1657
|
-
*/
|
|
1658
|
-
class Encoder {
|
|
1659
|
-
constructor () {
|
|
1660
|
-
this.cpos = 0;
|
|
1661
|
-
this.cbuf = new Uint8Array(100);
|
|
1662
|
-
/**
|
|
1663
|
-
* @type {Array<Uint8Array>}
|
|
1664
|
-
*/
|
|
1665
|
-
this.bufs = [];
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
|
-
/**
|
|
1670
|
-
* @function
|
|
1671
|
-
* @return {Encoder}
|
|
1672
|
-
*/
|
|
1673
|
-
const createEncoder = () => new Encoder();
|
|
1674
|
-
|
|
1675
|
-
/**
|
|
1676
|
-
* The current length of the encoded data.
|
|
1677
|
-
*
|
|
1678
|
-
* @function
|
|
1679
|
-
* @param {Encoder} encoder
|
|
1680
|
-
* @return {number}
|
|
1681
|
-
*/
|
|
1682
|
-
const length = encoder => {
|
|
1683
|
-
let len = encoder.cpos;
|
|
1684
|
-
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
1685
|
-
len += encoder.bufs[i].length;
|
|
1686
|
-
}
|
|
1687
|
-
return len
|
|
1688
|
-
};
|
|
1689
|
-
|
|
1690
|
-
/**
|
|
1691
|
-
* Transform to Uint8Array.
|
|
1692
|
-
*
|
|
1693
|
-
* @function
|
|
1694
|
-
* @param {Encoder} encoder
|
|
1695
|
-
* @return {Uint8Array} The created ArrayBuffer.
|
|
1696
|
-
*/
|
|
1697
|
-
const toUint8Array = encoder => {
|
|
1698
|
-
const uint8arr = new Uint8Array(length(encoder));
|
|
1699
|
-
let curPos = 0;
|
|
1700
|
-
for (let i = 0; i < encoder.bufs.length; i++) {
|
|
1701
|
-
const d = encoder.bufs[i];
|
|
1702
|
-
uint8arr.set(d, curPos);
|
|
1703
|
-
curPos += d.length;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
class StringDecoder {
|
|
1928
|
+
/**
|
|
1929
|
+
* @param {Uint8Array} uint8Array
|
|
1930
|
+
*/
|
|
1931
|
+
constructor (uint8Array) {
|
|
1932
|
+
this.decoder = new UintOptRleDecoder(uint8Array);
|
|
1933
|
+
this.str = readVarString(this.decoder);
|
|
1934
|
+
/**
|
|
1935
|
+
* @type {number}
|
|
1936
|
+
*/
|
|
1937
|
+
this.spos = 0;
|
|
1704
1938
|
}
|
|
1705
|
-
uint8arr.set(createUint8ArrayViewFromArrayBuffer(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
|
|
1706
|
-
return uint8arr
|
|
1707
|
-
};
|
|
1708
1939
|
|
|
1709
|
-
/**
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
const bufferLen = encoder.cbuf.length;
|
|
1718
|
-
if (bufferLen - encoder.cpos < len) {
|
|
1719
|
-
encoder.bufs.push(createUint8ArrayViewFromArrayBuffer(encoder.cbuf.buffer, 0, encoder.cpos));
|
|
1720
|
-
encoder.cbuf = new Uint8Array(max$3(bufferLen, len) * 2);
|
|
1721
|
-
encoder.cpos = 0;
|
|
1940
|
+
/**
|
|
1941
|
+
* @return {string}
|
|
1942
|
+
*/
|
|
1943
|
+
read () {
|
|
1944
|
+
const end = this.spos + this.decoder.read();
|
|
1945
|
+
const res = this.str.slice(this.spos, end);
|
|
1946
|
+
this.spos = end;
|
|
1947
|
+
return res
|
|
1722
1948
|
}
|
|
1723
|
-
}
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
/* eslint-env browser */
|
|
1952
|
+
|
|
1953
|
+
const getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
1724
1954
|
|
|
1725
1955
|
/**
|
|
1726
|
-
*
|
|
1956
|
+
* Isomorphic module for true random numbers / buffers / uuids.
|
|
1727
1957
|
*
|
|
1728
|
-
*
|
|
1729
|
-
*
|
|
1730
|
-
* @
|
|
1958
|
+
* Attention: falls back to Math.random if the browser does not support crypto.
|
|
1959
|
+
*
|
|
1960
|
+
* @module random
|
|
1731
1961
|
*/
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
}
|
|
1739
|
-
encoder.cbuf[encoder.cpos++] = num;
|
|
1740
|
-
};
|
|
1962
|
+
|
|
1963
|
+
|
|
1964
|
+
const uint32 = () => getRandomValues(new Uint32Array(1))[0];
|
|
1965
|
+
|
|
1966
|
+
// @ts-ignore
|
|
1967
|
+
const uuidv4Template = [1e7] + -1e3 + -4e3 + -8e3 + -1e11;
|
|
1741
1968
|
|
|
1742
1969
|
/**
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1745
|
-
* @function
|
|
1746
|
-
* @param {Encoder} encoder
|
|
1747
|
-
* @param {number} num The number that is to be encoded.
|
|
1970
|
+
* @return {string}
|
|
1748
1971
|
*/
|
|
1749
|
-
const
|
|
1972
|
+
const uuidv4 = () => uuidv4Template.replace(/[018]/g, /** @param {number} c */ c =>
|
|
1973
|
+
(c ^ uint32() & 15 >> c / 4).toString(16)
|
|
1974
|
+
);
|
|
1750
1975
|
|
|
1751
1976
|
/**
|
|
1752
|
-
*
|
|
1977
|
+
* Utility helpers to work with promises.
|
|
1753
1978
|
*
|
|
1754
|
-
* @
|
|
1755
|
-
* @param {Encoder} encoder
|
|
1756
|
-
* @param {number} num The number that is to be encoded.
|
|
1979
|
+
* @module promise
|
|
1757
1980
|
*/
|
|
1758
|
-
|
|
1759
|
-
while (num > BITS7) {
|
|
1760
|
-
write(encoder, BIT8 | (BITS7 & num));
|
|
1761
|
-
num = floor$2(num / 128); // shift >>> 7
|
|
1762
|
-
}
|
|
1763
|
-
write(encoder, BITS7 & num);
|
|
1764
|
-
};
|
|
1981
|
+
|
|
1765
1982
|
|
|
1766
1983
|
/**
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
* @function
|
|
1772
|
-
* @param {Encoder} encoder
|
|
1773
|
-
* @param {number} num The number that is to be encoded.
|
|
1984
|
+
* @template T
|
|
1985
|
+
* @callback PromiseResolve
|
|
1986
|
+
* @param {T|PromiseLike<T>} [result]
|
|
1774
1987
|
*/
|
|
1775
|
-
const writeVarInt = (encoder, num) => {
|
|
1776
|
-
const isNegative = isNegativeZero(num);
|
|
1777
|
-
if (isNegative) {
|
|
1778
|
-
num = -num;
|
|
1779
|
-
}
|
|
1780
|
-
// |- whether to continue reading |- whether is negative |- number
|
|
1781
|
-
write(encoder, (num > BITS6 ? BIT8 : 0) | (isNegative ? BIT7 : 0) | (BITS6 & num));
|
|
1782
|
-
num = floor$2(num / 64); // shift >>> 6
|
|
1783
|
-
// We don't need to consider the case of num === 0 so we can use a different
|
|
1784
|
-
// pattern here than above.
|
|
1785
|
-
while (num > 0) {
|
|
1786
|
-
write(encoder, (num > BITS7 ? BIT8 : 0) | (BITS7 & num));
|
|
1787
|
-
num = floor$2(num / 128); // shift >>> 7
|
|
1788
|
-
}
|
|
1789
|
-
};
|
|
1790
1988
|
|
|
1791
1989
|
/**
|
|
1792
|
-
*
|
|
1990
|
+
* @template T
|
|
1991
|
+
* @param {function(PromiseResolve<T>,function(Error):void):any} f
|
|
1992
|
+
* @return {Promise<T>}
|
|
1793
1993
|
*/
|
|
1794
|
-
const
|
|
1795
|
-
const _maxStrBSize = _strBuffer.length / 3;
|
|
1994
|
+
const create$2 = f => /** @type {Promise<T>} */ (new Promise(f));
|
|
1796
1995
|
|
|
1797
1996
|
/**
|
|
1798
|
-
*
|
|
1997
|
+
* `Promise.all` wait for all promises in the array to resolve and return the result
|
|
1998
|
+
* @template {unknown[] | []} PS
|
|
1799
1999
|
*
|
|
1800
|
-
* @
|
|
1801
|
-
* @
|
|
1802
|
-
* @param {String} str The string that is to be encoded.
|
|
2000
|
+
* @param {PS} ps
|
|
2001
|
+
* @return {Promise<{ -readonly [P in keyof PS]: Awaited<PS[P]> }>}
|
|
1803
2002
|
*/
|
|
1804
|
-
|
|
1805
|
-
if (str.length < _maxStrBSize) {
|
|
1806
|
-
// We can encode the string into the existing buffer
|
|
1807
|
-
/* c8 ignore next */
|
|
1808
|
-
const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
|
|
1809
|
-
writeVarUint(encoder, written);
|
|
1810
|
-
for (let i = 0; i < written; i++) {
|
|
1811
|
-
write(encoder, _strBuffer[i]);
|
|
1812
|
-
}
|
|
1813
|
-
} else {
|
|
1814
|
-
writeVarUint8Array(encoder, encodeUtf8(str));
|
|
1815
|
-
}
|
|
1816
|
-
};
|
|
2003
|
+
Promise.all.bind(Promise);
|
|
1817
2004
|
|
|
1818
2005
|
/**
|
|
1819
|
-
*
|
|
2006
|
+
* Often used conditions.
|
|
1820
2007
|
*
|
|
1821
|
-
* @
|
|
1822
|
-
* @param {Encoder} encoder
|
|
1823
|
-
* @param {String} str The string that is to be encoded.
|
|
2008
|
+
* @module conditions
|
|
1824
2009
|
*/
|
|
1825
|
-
const _writeVarStringPolyfill = (encoder, str) => {
|
|
1826
|
-
const encodedString = unescape(encodeURIComponent(str));
|
|
1827
|
-
const len = encodedString.length;
|
|
1828
|
-
writeVarUint(encoder, len);
|
|
1829
|
-
for (let i = 0; i < len; i++) {
|
|
1830
|
-
write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
|
|
1831
|
-
}
|
|
1832
|
-
};
|
|
1833
2010
|
|
|
1834
2011
|
/**
|
|
1835
|
-
*
|
|
1836
|
-
*
|
|
1837
|
-
* @
|
|
1838
|
-
* @param {Encoder} encoder
|
|
1839
|
-
* @param {String} str The string that is to be encoded.
|
|
2012
|
+
* @template T
|
|
2013
|
+
* @param {T|null|undefined} v
|
|
2014
|
+
* @return {T|null}
|
|
1840
2015
|
*/
|
|
1841
2016
|
/* c8 ignore next */
|
|
1842
|
-
const
|
|
2017
|
+
const undefinedToNull = v => v === undefined ? null : v;
|
|
2018
|
+
|
|
2019
|
+
/* eslint-env browser */
|
|
1843
2020
|
|
|
1844
2021
|
/**
|
|
1845
|
-
*
|
|
2022
|
+
* Isomorphic variable storage.
|
|
1846
2023
|
*
|
|
1847
|
-
*
|
|
1848
|
-
*
|
|
1849
|
-
* @
|
|
2024
|
+
* Uses LocalStorage in the browser and falls back to in-memory storage.
|
|
2025
|
+
*
|
|
2026
|
+
* @module storage
|
|
1850
2027
|
*/
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
|
|
1857
|
-
encoder.cpos += leftCopyLen;
|
|
1858
|
-
if (rightCopyLen > 0) {
|
|
1859
|
-
// Still something to write, write right half..
|
|
1860
|
-
// Append new buffer
|
|
1861
|
-
encoder.bufs.push(encoder.cbuf);
|
|
1862
|
-
// must have at least size of remaining buffer
|
|
1863
|
-
encoder.cbuf = new Uint8Array(max$3(bufferLen * 2, rightCopyLen));
|
|
1864
|
-
// copy array
|
|
1865
|
-
encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
|
|
1866
|
-
encoder.cpos = rightCopyLen;
|
|
2028
|
+
|
|
2029
|
+
/* c8 ignore start */
|
|
2030
|
+
class VarStoragePolyfill {
|
|
2031
|
+
constructor () {
|
|
2032
|
+
this.map = new Map();
|
|
1867
2033
|
}
|
|
1868
|
-
|
|
2034
|
+
|
|
2035
|
+
/**
|
|
2036
|
+
* @param {string} key
|
|
2037
|
+
* @param {any} newValue
|
|
2038
|
+
*/
|
|
2039
|
+
setItem (key, newValue) {
|
|
2040
|
+
this.map.set(key, newValue);
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
/**
|
|
2044
|
+
* @param {string} key
|
|
2045
|
+
*/
|
|
2046
|
+
getItem (key) {
|
|
2047
|
+
return this.map.get(key)
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
/* c8 ignore stop */
|
|
1869
2051
|
|
|
1870
2052
|
/**
|
|
1871
|
-
*
|
|
1872
|
-
*
|
|
1873
|
-
* @function
|
|
1874
|
-
* @param {Encoder} encoder
|
|
1875
|
-
* @param {Uint8Array} uint8Array
|
|
2053
|
+
* @type {any}
|
|
1876
2054
|
*/
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2055
|
+
let _localStorage = new VarStoragePolyfill();
|
|
2056
|
+
let usePolyfill = true;
|
|
2057
|
+
|
|
2058
|
+
/* c8 ignore start */
|
|
2059
|
+
try {
|
|
2060
|
+
// if the same-origin rule is violated, accessing localStorage might thrown an error
|
|
2061
|
+
if (typeof localStorage !== 'undefined' && localStorage) {
|
|
2062
|
+
_localStorage = localStorage;
|
|
2063
|
+
usePolyfill = false;
|
|
2064
|
+
}
|
|
2065
|
+
} catch (e) { }
|
|
2066
|
+
/* c8 ignore stop */
|
|
1881
2067
|
|
|
1882
2068
|
/**
|
|
1883
|
-
*
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
* // write float32 using DataView
|
|
1888
|
-
* const dv = writeOnDataView(encoder, 4)
|
|
1889
|
-
* dv.setFloat32(0, 1.1)
|
|
1890
|
-
* // read float32 using DataView
|
|
1891
|
-
* const dv = readFromDataView(encoder, 4)
|
|
1892
|
-
* dv.getFloat32(0) // => 1.100000023841858 (leaving it to the reader to find out why this is the correct result)
|
|
1893
|
-
* ```
|
|
1894
|
-
*
|
|
1895
|
-
* @param {Encoder} encoder
|
|
1896
|
-
* @param {number} len
|
|
1897
|
-
* @return {DataView}
|
|
1898
|
-
*/
|
|
1899
|
-
const writeOnDataView = (encoder, len) => {
|
|
1900
|
-
verifyLen(encoder, len);
|
|
1901
|
-
const dview = new DataView(encoder.cbuf.buffer, encoder.cpos, len);
|
|
1902
|
-
encoder.cpos += len;
|
|
1903
|
-
return dview
|
|
1904
|
-
};
|
|
2069
|
+
* This is basically localStorage in browser, or a polyfill in nodejs
|
|
2070
|
+
*/
|
|
2071
|
+
/* c8 ignore next */
|
|
2072
|
+
const varStorage = _localStorage;
|
|
1905
2073
|
|
|
1906
2074
|
/**
|
|
1907
|
-
*
|
|
1908
|
-
*
|
|
2075
|
+
* Utility functions for working with EcmaScript objects.
|
|
2076
|
+
*
|
|
2077
|
+
* @module object
|
|
1909
2078
|
*/
|
|
1910
|
-
|
|
2079
|
+
|
|
1911
2080
|
|
|
1912
2081
|
/**
|
|
1913
|
-
*
|
|
1914
|
-
* @param {number} num
|
|
2082
|
+
* Object.assign
|
|
1915
2083
|
*/
|
|
1916
|
-
const
|
|
2084
|
+
const assign = Object.assign;
|
|
1917
2085
|
|
|
1918
2086
|
/**
|
|
1919
|
-
* @param {
|
|
1920
|
-
* @param {bigint} num
|
|
2087
|
+
* @param {Object<string,any>} obj
|
|
1921
2088
|
*/
|
|
1922
|
-
const
|
|
2089
|
+
const keys = Object.keys;
|
|
1923
2090
|
|
|
1924
|
-
const floatTestBed = new DataView(new ArrayBuffer(4));
|
|
1925
2091
|
/**
|
|
1926
|
-
*
|
|
1927
|
-
*
|
|
1928
|
-
* @param {
|
|
1929
|
-
* @return {boolean}
|
|
2092
|
+
* @template V
|
|
2093
|
+
* @param {{[k:string]:V}} obj
|
|
2094
|
+
* @param {function(V,string):any} f
|
|
1930
2095
|
*/
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1933
|
-
|
|
2096
|
+
const forEach$2 = (obj, f) => {
|
|
2097
|
+
for (const key in obj) {
|
|
2098
|
+
f(obj[key], key);
|
|
2099
|
+
}
|
|
1934
2100
|
};
|
|
1935
2101
|
|
|
1936
2102
|
/**
|
|
1937
|
-
*
|
|
1938
|
-
*
|
|
1939
|
-
* Differences to JSON:
|
|
1940
|
-
* • Transforms data to a binary format (not to a string)
|
|
1941
|
-
* • Encodes undefined, NaN, and ArrayBuffer (these can't be represented in JSON)
|
|
1942
|
-
* • Numbers are efficiently encoded either as a variable length integer, as a
|
|
1943
|
-
* 32 bit float, as a 64 bit float, or as a 64 bit bigint.
|
|
1944
|
-
*
|
|
1945
|
-
* Encoding table:
|
|
1946
|
-
*
|
|
1947
|
-
* | Data Type | Prefix | Encoding Method | Comment |
|
|
1948
|
-
* | ------------------- | -------- | ------------------ | ------- |
|
|
1949
|
-
* | undefined | 127 | | Functions, symbol, and everything that cannot be identified is encoded as undefined |
|
|
1950
|
-
* | null | 126 | | |
|
|
1951
|
-
* | integer | 125 | writeVarInt | Only encodes 32 bit signed integers |
|
|
1952
|
-
* | float32 | 124 | writeFloat32 | |
|
|
1953
|
-
* | float64 | 123 | writeFloat64 | |
|
|
1954
|
-
* | bigint | 122 | writeBigInt64 | |
|
|
1955
|
-
* | boolean (false) | 121 | | True and false are different data types so we save the following byte |
|
|
1956
|
-
* | boolean (true) | 120 | | - 0b01111000 so the last bit determines whether true or false |
|
|
1957
|
-
* | string | 119 | writeVarString | |
|
|
1958
|
-
* | object<string,any> | 118 | custom | Writes {length} then {length} key-value pairs |
|
|
1959
|
-
* | array<any> | 117 | custom | Writes {length} then {length} json values |
|
|
1960
|
-
* | Uint8Array | 116 | writeVarUint8Array | We use Uint8Array for any kind of binary data |
|
|
1961
|
-
*
|
|
1962
|
-
* Reasons for the decreasing prefix:
|
|
1963
|
-
* We need the first bit for extendability (later we may want to encode the
|
|
1964
|
-
* prefix with writeVarUint). The remaining 7 bits are divided as follows:
|
|
1965
|
-
* [0-30] the beginning of the data range is used for custom purposes
|
|
1966
|
-
* (defined by the function that uses this library)
|
|
1967
|
-
* [31-127] the end of the data range is used for data encoding by
|
|
1968
|
-
* lib0/encoding.js
|
|
1969
|
-
*
|
|
1970
|
-
* @param {Encoder} encoder
|
|
1971
|
-
* @param {undefined|null|number|bigint|boolean|string|Object<string,any>|Array<any>|Uint8Array} data
|
|
2103
|
+
* @param {Object<string,any>} obj
|
|
2104
|
+
* @return {number}
|
|
1972
2105
|
*/
|
|
1973
|
-
const
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
// TYPE 125: INTEGER
|
|
1983
|
-
write(encoder, 125);
|
|
1984
|
-
writeVarInt(encoder, data);
|
|
1985
|
-
} else if (isFloat32(data)) {
|
|
1986
|
-
// TYPE 124: FLOAT32
|
|
1987
|
-
write(encoder, 124);
|
|
1988
|
-
writeFloat32(encoder, data);
|
|
1989
|
-
} else {
|
|
1990
|
-
// TYPE 123: FLOAT64
|
|
1991
|
-
write(encoder, 123);
|
|
1992
|
-
writeFloat64(encoder, data);
|
|
1993
|
-
}
|
|
1994
|
-
break
|
|
1995
|
-
case 'bigint':
|
|
1996
|
-
// TYPE 122: BigInt
|
|
1997
|
-
write(encoder, 122);
|
|
1998
|
-
writeBigInt64(encoder, data);
|
|
1999
|
-
break
|
|
2000
|
-
case 'object':
|
|
2001
|
-
if (data === null) {
|
|
2002
|
-
// TYPE 126: null
|
|
2003
|
-
write(encoder, 126);
|
|
2004
|
-
} else if (isArray(data)) {
|
|
2005
|
-
// TYPE 117: Array
|
|
2006
|
-
write(encoder, 117);
|
|
2007
|
-
writeVarUint(encoder, data.length);
|
|
2008
|
-
for (let i = 0; i < data.length; i++) {
|
|
2009
|
-
writeAny(encoder, data[i]);
|
|
2010
|
-
}
|
|
2011
|
-
} else if (data instanceof Uint8Array) {
|
|
2012
|
-
// TYPE 116: ArrayBuffer
|
|
2013
|
-
write(encoder, 116);
|
|
2014
|
-
writeVarUint8Array(encoder, data);
|
|
2015
|
-
} else {
|
|
2016
|
-
// TYPE 118: Object
|
|
2017
|
-
write(encoder, 118);
|
|
2018
|
-
const keys = Object.keys(data);
|
|
2019
|
-
writeVarUint(encoder, keys.length);
|
|
2020
|
-
for (let i = 0; i < keys.length; i++) {
|
|
2021
|
-
const key = keys[i];
|
|
2022
|
-
writeVarString(encoder, key);
|
|
2023
|
-
writeAny(encoder, data[key]);
|
|
2024
|
-
}
|
|
2025
|
-
}
|
|
2026
|
-
break
|
|
2027
|
-
case 'boolean':
|
|
2028
|
-
// TYPE 120/121: boolean (true/false)
|
|
2029
|
-
write(encoder, data ? 120 : 121);
|
|
2030
|
-
break
|
|
2031
|
-
default:
|
|
2032
|
-
// TYPE 127: undefined
|
|
2033
|
-
write(encoder, 127);
|
|
2106
|
+
const size = obj => keys(obj).length;
|
|
2107
|
+
|
|
2108
|
+
/**
|
|
2109
|
+
* @param {Object|null|undefined} obj
|
|
2110
|
+
*/
|
|
2111
|
+
const isEmpty = obj => {
|
|
2112
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
2113
|
+
for (const _k in obj) {
|
|
2114
|
+
return false
|
|
2034
2115
|
}
|
|
2116
|
+
return true
|
|
2035
2117
|
};
|
|
2036
2118
|
|
|
2037
2119
|
/**
|
|
2038
|
-
*
|
|
2120
|
+
* @param {Object<string,any>} obj
|
|
2121
|
+
* @param {function(any,string):boolean} f
|
|
2122
|
+
* @return {boolean}
|
|
2039
2123
|
*/
|
|
2124
|
+
const every = (obj, f) => {
|
|
2125
|
+
for (const key in obj) {
|
|
2126
|
+
if (!f(obj[key], key)) {
|
|
2127
|
+
return false
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
return true
|
|
2131
|
+
};
|
|
2040
2132
|
|
|
2041
2133
|
/**
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2044
|
-
* Encodes [1,1,1,7] to [1,3,7,1] (3 times 1, 1 time 7). This encoder might do more harm than good if there are a lot of values that are not repeated.
|
|
2045
|
-
*
|
|
2046
|
-
* It was originally used for image compression. Cool .. article http://csbruce.com/cbm/transactor/pdfs/trans_v7_i06.pdf
|
|
2047
|
-
*
|
|
2048
|
-
* @note T must not be null!
|
|
2134
|
+
* Calls `Object.prototype.hasOwnProperty`.
|
|
2049
2135
|
*
|
|
2050
|
-
* @
|
|
2136
|
+
* @param {any} obj
|
|
2137
|
+
* @param {string|symbol} key
|
|
2138
|
+
* @return {boolean}
|
|
2051
2139
|
*/
|
|
2052
|
-
|
|
2053
|
-
/**
|
|
2054
|
-
* @param {function(Encoder, T):void} writer
|
|
2055
|
-
*/
|
|
2056
|
-
constructor (writer) {
|
|
2057
|
-
super();
|
|
2058
|
-
/**
|
|
2059
|
-
* The writer
|
|
2060
|
-
*/
|
|
2061
|
-
this.w = writer;
|
|
2062
|
-
/**
|
|
2063
|
-
* Current state
|
|
2064
|
-
* @type {T|null}
|
|
2065
|
-
*/
|
|
2066
|
-
this.s = null;
|
|
2067
|
-
this.count = 0;
|
|
2068
|
-
}
|
|
2140
|
+
const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
2069
2141
|
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
} else {
|
|
2077
|
-
if (this.count > 0) {
|
|
2078
|
-
// flush counter, unless this is the first value (count = 0)
|
|
2079
|
-
writeVarUint(this, this.count - 1); // since count is always > 0, we can decrement by one. non-standard encoding ftw
|
|
2080
|
-
}
|
|
2081
|
-
this.count = 1;
|
|
2082
|
-
// write first value
|
|
2083
|
-
this.w(this, v);
|
|
2084
|
-
this.s = v;
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2142
|
+
/**
|
|
2143
|
+
* @param {Object<string,any>} a
|
|
2144
|
+
* @param {Object<string,any>} b
|
|
2145
|
+
* @return {boolean}
|
|
2146
|
+
*/
|
|
2147
|
+
const equalFlat = (a, b) => a === b || (size(a) === size(b) && every(a, (val, key) => (val !== undefined || hasProperty(b, key)) && b[key] === val));
|
|
2088
2148
|
|
|
2089
2149
|
/**
|
|
2090
|
-
*
|
|
2150
|
+
* Make an object immutable. This hurts performance and is usually not needed if you perform good
|
|
2151
|
+
* coding practices.
|
|
2091
2152
|
*/
|
|
2092
|
-
const
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2153
|
+
const freeze = Object.freeze;
|
|
2154
|
+
|
|
2155
|
+
/**
|
|
2156
|
+
* Make an object and all its children immutable.
|
|
2157
|
+
* This *really* hurts performance and is usually not needed if you perform good coding practices.
|
|
2158
|
+
*
|
|
2159
|
+
* @template {any} T
|
|
2160
|
+
* @param {T} o
|
|
2161
|
+
* @return {Readonly<T>}
|
|
2162
|
+
*/
|
|
2163
|
+
const deepFreeze = (o) => {
|
|
2164
|
+
for (const key in o) {
|
|
2165
|
+
const c = o[key];
|
|
2166
|
+
if (typeof c === 'object' || typeof c === 'function') {
|
|
2167
|
+
deepFreeze(o[key]);
|
|
2100
2168
|
}
|
|
2101
2169
|
}
|
|
2170
|
+
return freeze(o)
|
|
2102
2171
|
};
|
|
2103
2172
|
|
|
2104
2173
|
/**
|
|
2105
|
-
*
|
|
2106
|
-
*
|
|
2107
|
-
* Internally uses VarInt encoder to write unsigned integers. If the input occurs multiple times, we write
|
|
2108
|
-
* write it as a negative number. The UintOptRleDecoder then understands that it needs to read a count.
|
|
2174
|
+
* Common functions and function call helpers.
|
|
2109
2175
|
*
|
|
2110
|
-
*
|
|
2176
|
+
* @module function
|
|
2111
2177
|
*/
|
|
2112
|
-
class UintOptRleEncoder {
|
|
2113
|
-
constructor () {
|
|
2114
|
-
this.encoder = new Encoder();
|
|
2115
|
-
/**
|
|
2116
|
-
* @type {number}
|
|
2117
|
-
*/
|
|
2118
|
-
this.s = 0;
|
|
2119
|
-
this.count = 0;
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
/**
|
|
2123
|
-
* @param {number} v
|
|
2124
|
-
*/
|
|
2125
|
-
write (v) {
|
|
2126
|
-
if (this.s === v) {
|
|
2127
|
-
this.count++;
|
|
2128
|
-
} else {
|
|
2129
|
-
flushUintOptRleEncoder(this);
|
|
2130
|
-
this.count = 1;
|
|
2131
|
-
this.s = v;
|
|
2132
|
-
}
|
|
2133
|
-
}
|
|
2134
2178
|
|
|
2135
|
-
toUint8Array () {
|
|
2136
|
-
flushUintOptRleEncoder(this);
|
|
2137
|
-
return toUint8Array(this.encoder)
|
|
2138
|
-
}
|
|
2139
|
-
}
|
|
2140
2179
|
|
|
2141
2180
|
/**
|
|
2142
|
-
*
|
|
2181
|
+
* Calls all functions in `fs` with args. Only throws after all functions were called.
|
|
2182
|
+
*
|
|
2183
|
+
* @param {Array<function>} fs
|
|
2184
|
+
* @param {Array<any>} args
|
|
2143
2185
|
*/
|
|
2144
|
-
const
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
writeVarInt(encoder.encoder, encodedDiff);
|
|
2153
|
-
if (encoder.count > 1) {
|
|
2154
|
-
writeVarUint(encoder.encoder, encoder.count - 2); // since count is always > 1, we can decrement by one. non-standard encoding ftw
|
|
2186
|
+
const callAll = (fs, args, i = 0) => {
|
|
2187
|
+
try {
|
|
2188
|
+
for (; i < fs.length; i++) {
|
|
2189
|
+
fs[i](...args);
|
|
2190
|
+
}
|
|
2191
|
+
} finally {
|
|
2192
|
+
if (i < fs.length) {
|
|
2193
|
+
callAll(fs, args, i + 1);
|
|
2155
2194
|
}
|
|
2156
2195
|
}
|
|
2157
2196
|
};
|
|
2158
2197
|
|
|
2159
2198
|
/**
|
|
2160
|
-
* A
|
|
2161
|
-
*
|
|
2162
|
-
* The count approach is similar to the UintDiffOptRleEncoder, but instead of using the negative bitflag, it encodes
|
|
2163
|
-
* in the LSB whether a count is to be read. Therefore this Encoder only supports 31 bit integers!
|
|
2164
|
-
*
|
|
2165
|
-
* Encodes [1, 2, 3, 2] as [3, 1, 6, -1] (more specifically [(1 << 1) | 1, (3 << 0) | 0, -1])
|
|
2199
|
+
* @template A
|
|
2166
2200
|
*
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
2169
|
-
|
|
2170
|
-
|
|
2201
|
+
* @param {A} a
|
|
2202
|
+
* @return {A}
|
|
2203
|
+
*/
|
|
2204
|
+
const id = a => a;
|
|
2205
|
+
|
|
2206
|
+
/**
|
|
2207
|
+
* @template V
|
|
2208
|
+
* @template {V} OPTS
|
|
2171
2209
|
*
|
|
2172
|
-
*
|
|
2210
|
+
* @param {V} value
|
|
2211
|
+
* @param {Array<OPTS>} options
|
|
2212
|
+
*/
|
|
2213
|
+
// @ts-ignore
|
|
2214
|
+
const isOneOf = (value, options) => options.includes(value);
|
|
2215
|
+
|
|
2216
|
+
/**
|
|
2217
|
+
* Isomorphic module to work access the environment (query params, env variables).
|
|
2173
2218
|
*
|
|
2174
|
-
*
|
|
2219
|
+
* @module environment
|
|
2175
2220
|
*/
|
|
2176
|
-
class IntDiffOptRleEncoder {
|
|
2177
|
-
constructor () {
|
|
2178
|
-
this.encoder = new Encoder();
|
|
2179
|
-
/**
|
|
2180
|
-
* @type {number}
|
|
2181
|
-
*/
|
|
2182
|
-
this.s = 0;
|
|
2183
|
-
this.count = 0;
|
|
2184
|
-
this.diff = 0;
|
|
2185
|
-
}
|
|
2186
2221
|
|
|
2187
|
-
/**
|
|
2188
|
-
* @param {number} v
|
|
2189
|
-
*/
|
|
2190
|
-
write (v) {
|
|
2191
|
-
if (this.diff === v - this.s) {
|
|
2192
|
-
this.s = v;
|
|
2193
|
-
this.count++;
|
|
2194
|
-
} else {
|
|
2195
|
-
flushIntDiffOptRleEncoder(this);
|
|
2196
|
-
this.count = 1;
|
|
2197
|
-
this.diff = v - this.s;
|
|
2198
|
-
this.s = v;
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
2222
|
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
}
|
|
2206
|
-
}
|
|
2223
|
+
/* c8 ignore next 2 */
|
|
2224
|
+
// @ts-ignore
|
|
2225
|
+
const isNode = typeof process !== 'undefined' && process.release && /node|io\.js/.test(process.release.name) && Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
|
|
2207
2226
|
|
|
2208
2227
|
/**
|
|
2209
|
-
*
|
|
2210
|
-
*
|
|
2211
|
-
* Encoding many small strings in a simple Encoder is not very efficient. The function call to decode a string takes some time and creates references that must be eventually deleted.
|
|
2212
|
-
* In practice, when decoding several million small strings, the GC will kick in more and more often to collect orphaned string objects (or maybe there is another reason?).
|
|
2213
|
-
*
|
|
2214
|
-
* This string encoder solves the above problem. All strings are concatenated and written as a single string using a single encoding call.
|
|
2215
|
-
*
|
|
2216
|
-
* The lengths are encoded using a UintOptRleEncoder.
|
|
2228
|
+
* @type {Map<string,string>}
|
|
2217
2229
|
*/
|
|
2218
|
-
|
|
2219
|
-
constructor () {
|
|
2220
|
-
/**
|
|
2221
|
-
* @type {Array<string>}
|
|
2222
|
-
*/
|
|
2223
|
-
this.sarr = [];
|
|
2224
|
-
this.s = '';
|
|
2225
|
-
this.lensE = new UintOptRleEncoder();
|
|
2226
|
-
}
|
|
2230
|
+
let params;
|
|
2227
2231
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2232
|
+
/* c8 ignore start */
|
|
2233
|
+
const computeParams = () => {
|
|
2234
|
+
if (params === undefined) {
|
|
2235
|
+
if (isNode) {
|
|
2236
|
+
params = create$5();
|
|
2237
|
+
const pargs = process.argv;
|
|
2238
|
+
let currParamName = null;
|
|
2239
|
+
for (let i = 0; i < pargs.length; i++) {
|
|
2240
|
+
const parg = pargs[i];
|
|
2241
|
+
if (parg[0] === '-') {
|
|
2242
|
+
if (currParamName !== null) {
|
|
2243
|
+
params.set(currParamName, '');
|
|
2244
|
+
}
|
|
2245
|
+
currParamName = parg;
|
|
2246
|
+
} else {
|
|
2247
|
+
if (currParamName !== null) {
|
|
2248
|
+
params.set(currParamName, parg);
|
|
2249
|
+
currParamName = null;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
if (currParamName !== null) {
|
|
2254
|
+
params.set(currParamName, '');
|
|
2255
|
+
}
|
|
2256
|
+
// in ReactNative for example this would not be true (unless connected to the Remote Debugger)
|
|
2257
|
+
} else if (typeof location === 'object') {
|
|
2258
|
+
params = create$5(); // eslint-disable-next-line no-undef
|
|
2259
|
+
(location.search || '?').slice(1).split('&').forEach((kv) => {
|
|
2260
|
+
if (kv.length !== 0) {
|
|
2261
|
+
const [key, value] = kv.split('=');
|
|
2262
|
+
params.set(`--${fromCamelCase(key, '-')}`, value);
|
|
2263
|
+
params.set(`-${fromCamelCase(key, '-')}`, value);
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
} else {
|
|
2267
|
+
params = create$5();
|
|
2236
2268
|
}
|
|
2237
|
-
this.lensE.write(string.length);
|
|
2238
2269
|
}
|
|
2270
|
+
return params
|
|
2271
|
+
};
|
|
2272
|
+
/* c8 ignore stop */
|
|
2239
2273
|
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
return toUint8Array(encoder)
|
|
2247
|
-
}
|
|
2248
|
-
}
|
|
2274
|
+
/**
|
|
2275
|
+
* @param {string} name
|
|
2276
|
+
* @return {boolean}
|
|
2277
|
+
*/
|
|
2278
|
+
/* c8 ignore next */
|
|
2279
|
+
const hasParam = (name) => computeParams().has(name);
|
|
2249
2280
|
|
|
2250
|
-
|
|
2281
|
+
/**
|
|
2282
|
+
* @param {string} name
|
|
2283
|
+
* @return {string|null}
|
|
2284
|
+
*/
|
|
2285
|
+
/* c8 ignore next 4 */
|
|
2286
|
+
const getVariable = (name) =>
|
|
2287
|
+
isNode
|
|
2288
|
+
? undefinedToNull(process.env[name.toUpperCase().replaceAll('-', '_')])
|
|
2289
|
+
: undefinedToNull(varStorage.getItem(name));
|
|
2251
2290
|
|
|
2252
|
-
|
|
2291
|
+
/**
|
|
2292
|
+
* @param {string} name
|
|
2293
|
+
* @return {boolean}
|
|
2294
|
+
*/
|
|
2295
|
+
/* c8 ignore next 2 */
|
|
2296
|
+
const hasConf = (name) =>
|
|
2297
|
+
hasParam('--' + name) || getVariable(name) !== null;
|
|
2253
2298
|
|
|
2254
|
-
|
|
2299
|
+
/* c8 ignore next */
|
|
2300
|
+
hasConf('production');
|
|
2255
2301
|
|
|
2256
|
-
|
|
2257
|
-
const
|
|
2258
|
-
|
|
2259
|
-
(c ^ uint32() & 15 >> c / 4).toString(16)
|
|
2260
|
-
);
|
|
2302
|
+
/* c8 ignore next 2 */
|
|
2303
|
+
const forceColor = isNode &&
|
|
2304
|
+
isOneOf(process.env.FORCE_COLOR, ['true', '1', '2']);
|
|
2261
2305
|
|
|
2306
|
+
/* c8 ignore start */
|
|
2262
2307
|
/**
|
|
2263
|
-
*
|
|
2308
|
+
* Color is enabled by default if the terminal supports it.
|
|
2264
2309
|
*
|
|
2265
|
-
*
|
|
2310
|
+
* Explicitly enable color using `--color` parameter
|
|
2311
|
+
* Disable color using `--no-color` parameter or using `NO_COLOR=1` environment variable.
|
|
2312
|
+
* `FORCE_COLOR=1` enables color and takes precedence over all.
|
|
2266
2313
|
*/
|
|
2267
|
-
|
|
2314
|
+
const supportsColor = forceColor || (
|
|
2315
|
+
!hasParam('--no-colors') && // @todo deprecate --no-colors
|
|
2316
|
+
!hasConf('no-color') &&
|
|
2317
|
+
(!isNode || process.stdout.isTTY) && (
|
|
2318
|
+
!isNode ||
|
|
2319
|
+
hasParam('--color') ||
|
|
2320
|
+
getVariable('COLORTERM') !== null ||
|
|
2321
|
+
(getVariable('TERM') || '').includes('color')
|
|
2322
|
+
)
|
|
2323
|
+
);
|
|
2324
|
+
/* c8 ignore stop */
|
|
2268
2325
|
|
|
2269
2326
|
/**
|
|
2270
|
-
*
|
|
2271
|
-
*
|
|
2272
|
-
* @
|
|
2327
|
+
* Utility functions to work with buffers (Uint8Array).
|
|
2328
|
+
*
|
|
2329
|
+
* @module buffer
|
|
2273
2330
|
*/
|
|
2274
2331
|
|
|
2332
|
+
|
|
2275
2333
|
/**
|
|
2276
|
-
* @
|
|
2277
|
-
* @param {function(PromiseResolve<T>,function(Error):void):any} f
|
|
2278
|
-
* @return {Promise<T>}
|
|
2334
|
+
* @param {number} len
|
|
2279
2335
|
*/
|
|
2280
|
-
const
|
|
2336
|
+
const createUint8ArrayFromLen = len => new Uint8Array(len);
|
|
2281
2337
|
|
|
2282
2338
|
/**
|
|
2283
|
-
*
|
|
2284
|
-
* @template {unknown[] | []} PS
|
|
2339
|
+
* Copy the content of an Uint8Array view to a new ArrayBuffer.
|
|
2285
2340
|
*
|
|
2286
|
-
* @param {
|
|
2287
|
-
* @return {
|
|
2341
|
+
* @param {Uint8Array} uint8Array
|
|
2342
|
+
* @return {Uint8Array}
|
|
2288
2343
|
*/
|
|
2289
|
-
|
|
2344
|
+
const copyUint8Array = uint8Array => {
|
|
2345
|
+
const newBuf = createUint8ArrayFromLen(uint8Array.byteLength);
|
|
2346
|
+
newBuf.set(uint8Array);
|
|
2347
|
+
return newBuf
|
|
2348
|
+
};
|
|
2290
2349
|
|
|
2291
2350
|
/**
|
|
2292
2351
|
* Working with value pairs.
|
|
@@ -2336,8 +2395,6 @@ const mapToStyleString = m => map(m, (value, key) => `${key}:${value};`).join(''
|
|
|
2336
2395
|
|
|
2337
2396
|
/**
|
|
2338
2397
|
* Return fresh symbol.
|
|
2339
|
-
*
|
|
2340
|
-
* @return {Symbol}
|
|
2341
2398
|
*/
|
|
2342
2399
|
const create = Symbol;
|
|
2343
2400
|
|
|
@@ -2353,17 +2410,36 @@ const UNCOLOR = create();
|
|
|
2353
2410
|
|
|
2354
2411
|
/* c8 ignore start */
|
|
2355
2412
|
/**
|
|
2356
|
-
* @param {Array<string|Symbol|Object|number>} args
|
|
2357
|
-
* @return {Array<string|object|number>}
|
|
2413
|
+
* @param {Array<undefined|string|Symbol|Object|number|function():any>} args
|
|
2414
|
+
* @return {Array<string|object|number|undefined>}
|
|
2358
2415
|
*/
|
|
2359
2416
|
const computeNoColorLoggingArgs = args => {
|
|
2417
|
+
if (args.length === 1 && args[0]?.constructor === Function) {
|
|
2418
|
+
args = /** @type {Array<string|Symbol|Object|number>} */ (/** @type {[function]} */ (args)[0]());
|
|
2419
|
+
}
|
|
2420
|
+
const strBuilder = [];
|
|
2360
2421
|
const logArgs = [];
|
|
2361
2422
|
// try with formatting until we find something unsupported
|
|
2362
2423
|
let i = 0;
|
|
2363
2424
|
for (; i < args.length; i++) {
|
|
2364
2425
|
const arg = args[i];
|
|
2365
|
-
if (arg
|
|
2366
|
-
|
|
2426
|
+
if (arg === undefined) {
|
|
2427
|
+
break
|
|
2428
|
+
} else if (arg.constructor === String || arg.constructor === Number) {
|
|
2429
|
+
strBuilder.push(arg);
|
|
2430
|
+
} else if (arg.constructor === Object) {
|
|
2431
|
+
break
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
if (i > 0) {
|
|
2435
|
+
// create logArgs with what we have so far
|
|
2436
|
+
logArgs.push(strBuilder.join(''));
|
|
2437
|
+
}
|
|
2438
|
+
// append the rest
|
|
2439
|
+
for (; i < args.length; i++) {
|
|
2440
|
+
const arg = args[i];
|
|
2441
|
+
if (!(arg instanceof Symbol)) {
|
|
2442
|
+
logArgs.push(arg);
|
|
2367
2443
|
}
|
|
2368
2444
|
}
|
|
2369
2445
|
return logArgs
|
|
@@ -2393,11 +2469,14 @@ const _browserStyleMap = {
|
|
|
2393
2469
|
};
|
|
2394
2470
|
|
|
2395
2471
|
/**
|
|
2396
|
-
* @param {Array<string|Symbol|Object|number>} args
|
|
2472
|
+
* @param {Array<string|Symbol|Object|number|function():any>} args
|
|
2397
2473
|
* @return {Array<string|object|number>}
|
|
2398
2474
|
*/
|
|
2399
2475
|
/* c8 ignore start */
|
|
2400
2476
|
const computeBrowserLoggingArgs = (args) => {
|
|
2477
|
+
if (args.length === 1 && args[0]?.constructor === Function) {
|
|
2478
|
+
args = /** @type {Array<string|Symbol|Object|number>} */ (/** @type {[function]} */ (args)[0]());
|
|
2479
|
+
}
|
|
2401
2480
|
const strBuilder = [];
|
|
2402
2481
|
const styles = [];
|
|
2403
2482
|
const currentStyle = create$5();
|
|
@@ -2414,6 +2493,9 @@ const computeBrowserLoggingArgs = (args) => {
|
|
|
2414
2493
|
if (style !== undefined) {
|
|
2415
2494
|
currentStyle.set(style.left, style.right);
|
|
2416
2495
|
} else {
|
|
2496
|
+
if (arg === undefined) {
|
|
2497
|
+
break
|
|
2498
|
+
}
|
|
2417
2499
|
if (arg.constructor === String || arg.constructor === Number) {
|
|
2418
2500
|
const style = mapToStyleString(currentStyle);
|
|
2419
2501
|
if (i > 0 || style.length > 0) {
|
|
@@ -2458,6 +2540,16 @@ const print = (...args) => {
|
|
|
2458
2540
|
vconsoles.forEach((vc) => vc.print(args));
|
|
2459
2541
|
};
|
|
2460
2542
|
|
|
2543
|
+
/* c8 ignore start */
|
|
2544
|
+
/**
|
|
2545
|
+
* @param {Array<string|Symbol|Object|number>} args
|
|
2546
|
+
*/
|
|
2547
|
+
const warn = (...args) => {
|
|
2548
|
+
console.warn(...computeLoggingArgs(args));
|
|
2549
|
+
args.unshift(ORANGE);
|
|
2550
|
+
vconsoles.forEach((vc) => vc.print(args));
|
|
2551
|
+
};
|
|
2552
|
+
|
|
2461
2553
|
const vconsoles = create$4();
|
|
2462
2554
|
|
|
2463
2555
|
/**
|
|
@@ -2551,9 +2643,12 @@ class DeleteSet {
|
|
|
2551
2643
|
const iterateDeletedStructs = (transaction, ds, f) =>
|
|
2552
2644
|
ds.clients.forEach((deletes, clientid) => {
|
|
2553
2645
|
const structs = /** @type {Array<GC|Item>} */ (transaction.doc.store.clients.get(clientid));
|
|
2554
|
-
|
|
2555
|
-
const
|
|
2556
|
-
|
|
2646
|
+
if (structs != null) {
|
|
2647
|
+
const lastStruct = structs[structs.length - 1];
|
|
2648
|
+
const clockState = lastStruct.id.clock + lastStruct.length;
|
|
2649
|
+
for (let i = 0, del = deletes[i]; i < deletes.length && del.clock < clockState; del = deletes[++i]) {
|
|
2650
|
+
iterateStructs(transaction, structs, del.clock, del.len, f);
|
|
2651
|
+
}
|
|
2557
2652
|
}
|
|
2558
2653
|
});
|
|
2559
2654
|
|
|
@@ -2825,6 +2920,7 @@ const readAndApplyDeleteSet = (decoder, transaction, store) => {
|
|
|
2825
2920
|
* @module Y
|
|
2826
2921
|
*/
|
|
2827
2922
|
|
|
2923
|
+
|
|
2828
2924
|
const generateNewClientId = uint32;
|
|
2829
2925
|
|
|
2830
2926
|
/**
|
|
@@ -2838,11 +2934,27 @@ const generateNewClientId = uint32;
|
|
|
2838
2934
|
* @property {boolean} [DocOpts.shouldLoad] Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
|
|
2839
2935
|
*/
|
|
2840
2936
|
|
|
2937
|
+
/**
|
|
2938
|
+
* @typedef {Object} DocEvents
|
|
2939
|
+
* @property {function(Doc):void} DocEvents.destroy
|
|
2940
|
+
* @property {function(Doc):void} DocEvents.load
|
|
2941
|
+
* @property {function(boolean, Doc):void} DocEvents.sync
|
|
2942
|
+
* @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.update
|
|
2943
|
+
* @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.updateV2
|
|
2944
|
+
* @property {function(Doc):void} DocEvents.beforeAllTransactions
|
|
2945
|
+
* @property {function(Transaction, Doc):void} DocEvents.beforeTransaction
|
|
2946
|
+
* @property {function(Transaction, Doc):void} DocEvents.beforeObserverCalls
|
|
2947
|
+
* @property {function(Transaction, Doc):void} DocEvents.afterTransaction
|
|
2948
|
+
* @property {function(Transaction, Doc):void} DocEvents.afterTransactionCleanup
|
|
2949
|
+
* @property {function(Doc, Array<Transaction>):void} DocEvents.afterAllTransactions
|
|
2950
|
+
* @property {function({ loaded: Set<Doc>, added: Set<Doc>, removed: Set<Doc> }, Doc, Transaction):void} DocEvents.subdocs
|
|
2951
|
+
*/
|
|
2952
|
+
|
|
2841
2953
|
/**
|
|
2842
2954
|
* A Yjs instance handles the state of shared data.
|
|
2843
|
-
* @extends
|
|
2955
|
+
* @extends ObservableV2<DocEvents>
|
|
2844
2956
|
*/
|
|
2845
|
-
class Doc extends
|
|
2957
|
+
class Doc extends ObservableV2 {
|
|
2846
2958
|
/**
|
|
2847
2959
|
* @param {DocOpts} opts configuration
|
|
2848
2960
|
*/
|
|
@@ -2893,8 +3005,9 @@ class Doc extends Observable {
|
|
|
2893
3005
|
* lost (with false as a parameter).
|
|
2894
3006
|
*/
|
|
2895
3007
|
this.isSynced = false;
|
|
3008
|
+
this.isDestroyed = false;
|
|
2896
3009
|
/**
|
|
2897
|
-
* Promise that resolves once the document has been loaded from a
|
|
3010
|
+
* Promise that resolves once the document has been loaded from a persistence provider.
|
|
2898
3011
|
*/
|
|
2899
3012
|
this.whenLoaded = create$2(resolve => {
|
|
2900
3013
|
this.on('load', () => {
|
|
@@ -2919,8 +3032,8 @@ class Doc extends Observable {
|
|
|
2919
3032
|
this.whenSynced = provideSyncedPromise();
|
|
2920
3033
|
}
|
|
2921
3034
|
this.isSynced = isSynced === undefined || isSynced === true;
|
|
2922
|
-
if (!this.isLoaded) {
|
|
2923
|
-
this.emit('load', []);
|
|
3035
|
+
if (this.isSynced && !this.isLoaded) {
|
|
3036
|
+
this.emit('load', [this]);
|
|
2924
3037
|
}
|
|
2925
3038
|
});
|
|
2926
3039
|
/**
|
|
@@ -2941,7 +3054,7 @@ class Doc extends Observable {
|
|
|
2941
3054
|
load () {
|
|
2942
3055
|
const item = this._item;
|
|
2943
3056
|
if (item !== null && !this.shouldLoad) {
|
|
2944
|
-
transact(/** @type {any} */ (item.parent).doc, transaction => {
|
|
3057
|
+
transact$1(/** @type {any} */ (item.parent).doc, transaction => {
|
|
2945
3058
|
transaction.subdocsLoaded.add(this);
|
|
2946
3059
|
}, null, true);
|
|
2947
3060
|
}
|
|
@@ -2970,36 +3083,37 @@ class Doc extends Observable {
|
|
|
2970
3083
|
* @public
|
|
2971
3084
|
*/
|
|
2972
3085
|
transact (f, origin = null) {
|
|
2973
|
-
return transact(this, f, origin)
|
|
3086
|
+
return transact$1(this, f, origin)
|
|
2974
3087
|
}
|
|
2975
3088
|
|
|
2976
3089
|
/**
|
|
2977
3090
|
* Define a shared data type.
|
|
2978
3091
|
*
|
|
2979
|
-
* Multiple calls of `
|
|
3092
|
+
* Multiple calls of `ydoc.get(name, TypeConstructor)` yield the same result
|
|
2980
3093
|
* and do not overwrite each other. I.e.
|
|
2981
|
-
* `
|
|
3094
|
+
* `ydoc.get(name, Y.Array) === ydoc.get(name, Y.Array)`
|
|
2982
3095
|
*
|
|
2983
|
-
* After this method is called, the type is also available on `
|
|
3096
|
+
* After this method is called, the type is also available on `ydoc.share.get(name)`.
|
|
2984
3097
|
*
|
|
2985
3098
|
* *Best Practices:*
|
|
2986
|
-
* Define all types right after the
|
|
3099
|
+
* Define all types right after the Y.Doc instance is created and store them in a separate object.
|
|
2987
3100
|
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
|
|
2988
3101
|
*
|
|
3102
|
+
* @template {typeof AbstractType<any>} Type
|
|
2989
3103
|
* @example
|
|
2990
|
-
* const
|
|
3104
|
+
* const ydoc = new Y.Doc(..)
|
|
2991
3105
|
* const appState = {
|
|
2992
|
-
* document:
|
|
2993
|
-
* comments:
|
|
3106
|
+
* document: ydoc.getText('document')
|
|
3107
|
+
* comments: ydoc.getArray('comments')
|
|
2994
3108
|
* }
|
|
2995
3109
|
*
|
|
2996
3110
|
* @param {string} name
|
|
2997
|
-
* @param {
|
|
2998
|
-
* @return {
|
|
3111
|
+
* @param {Type} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
|
|
3112
|
+
* @return {InstanceType<Type>} The created type. Constructed with TypeConstructor
|
|
2999
3113
|
*
|
|
3000
3114
|
* @public
|
|
3001
3115
|
*/
|
|
3002
|
-
get (name, TypeConstructor = AbstractType) {
|
|
3116
|
+
get (name, TypeConstructor = /** @type {any} */ (AbstractType)) {
|
|
3003
3117
|
const type = setIfUndefined(this.share, name, () => {
|
|
3004
3118
|
// @ts-ignore
|
|
3005
3119
|
const t = new TypeConstructor();
|
|
@@ -3025,12 +3139,12 @@ class Doc extends Observable {
|
|
|
3025
3139
|
t._length = type._length;
|
|
3026
3140
|
this.share.set(name, t);
|
|
3027
3141
|
t._integrate(this, null);
|
|
3028
|
-
return t
|
|
3142
|
+
return /** @type {InstanceType<Type>} */ (t)
|
|
3029
3143
|
} else {
|
|
3030
3144
|
throw new Error(`Type with the name ${name} has already been defined with a different constructor`)
|
|
3031
3145
|
}
|
|
3032
3146
|
}
|
|
3033
|
-
return type
|
|
3147
|
+
return /** @type {InstanceType<Type>} */ (type)
|
|
3034
3148
|
}
|
|
3035
3149
|
|
|
3036
3150
|
/**
|
|
@@ -3041,8 +3155,7 @@ class Doc extends Observable {
|
|
|
3041
3155
|
* @public
|
|
3042
3156
|
*/
|
|
3043
3157
|
getArray (name = '') {
|
|
3044
|
-
|
|
3045
|
-
return this.get(name, YArray)
|
|
3158
|
+
return /** @type {YArray<T>} */ (this.get(name, YArray))
|
|
3046
3159
|
}
|
|
3047
3160
|
|
|
3048
3161
|
/**
|
|
@@ -3052,7 +3165,6 @@ class Doc extends Observable {
|
|
|
3052
3165
|
* @public
|
|
3053
3166
|
*/
|
|
3054
3167
|
getText (name = '') {
|
|
3055
|
-
// @ts-ignore
|
|
3056
3168
|
return this.get(name, YText)
|
|
3057
3169
|
}
|
|
3058
3170
|
|
|
@@ -3064,8 +3176,17 @@ class Doc extends Observable {
|
|
|
3064
3176
|
* @public
|
|
3065
3177
|
*/
|
|
3066
3178
|
getMap (name = '') {
|
|
3067
|
-
|
|
3068
|
-
|
|
3179
|
+
return /** @type {YMap<T>} */ (this.get(name, YMap))
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
/**
|
|
3183
|
+
* @param {string} [name]
|
|
3184
|
+
* @return {YXmlElement}
|
|
3185
|
+
*
|
|
3186
|
+
* @public
|
|
3187
|
+
*/
|
|
3188
|
+
getXmlElement (name = '') {
|
|
3189
|
+
return /** @type {YXmlElement<{[key:string]:string}>} */ (this.get(name, YXmlElement))
|
|
3069
3190
|
}
|
|
3070
3191
|
|
|
3071
3192
|
/**
|
|
@@ -3075,7 +3196,6 @@ class Doc extends Observable {
|
|
|
3075
3196
|
* @public
|
|
3076
3197
|
*/
|
|
3077
3198
|
getXmlFragment (name = '') {
|
|
3078
|
-
// @ts-ignore
|
|
3079
3199
|
return this.get(name, YXmlFragment)
|
|
3080
3200
|
}
|
|
3081
3201
|
|
|
@@ -3104,6 +3224,7 @@ class Doc extends Observable {
|
|
|
3104
3224
|
* Emit `destroy` event and unregister all event handlers.
|
|
3105
3225
|
*/
|
|
3106
3226
|
destroy () {
|
|
3227
|
+
this.isDestroyed = true;
|
|
3107
3228
|
from(this.subdocs).forEach(subdoc => subdoc.destroy());
|
|
3108
3229
|
const item = this._item;
|
|
3109
3230
|
if (item !== null) {
|
|
@@ -3111,7 +3232,7 @@ class Doc extends Observable {
|
|
|
3111
3232
|
const content = /** @type {ContentDoc} */ (item.content);
|
|
3112
3233
|
content.doc = new Doc({ guid: this.guid, ...content.opts, shouldLoad: false });
|
|
3113
3234
|
content.doc._item = item;
|
|
3114
|
-
transact(/** @type {any} */ (item).parent.doc, transaction => {
|
|
3235
|
+
transact$1(/** @type {any} */ (item).parent.doc, transaction => {
|
|
3115
3236
|
const doc = content.doc;
|
|
3116
3237
|
if (!item.deleted) {
|
|
3117
3238
|
transaction.subdocsAdded.add(doc);
|
|
@@ -3119,26 +3240,11 @@ class Doc extends Observable {
|
|
|
3119
3240
|
transaction.subdocsRemoved.add(this);
|
|
3120
3241
|
}, null, true);
|
|
3121
3242
|
}
|
|
3122
|
-
|
|
3243
|
+
// @ts-ignore
|
|
3244
|
+
this.emit('destroyed', [true]); // DEPRECATED!
|
|
3123
3245
|
this.emit('destroy', [this]);
|
|
3124
3246
|
super.destroy();
|
|
3125
3247
|
}
|
|
3126
|
-
|
|
3127
|
-
/**
|
|
3128
|
-
* @param {string} eventName
|
|
3129
|
-
* @param {function(...any):any} f
|
|
3130
|
-
*/
|
|
3131
|
-
on (eventName, f) {
|
|
3132
|
-
super.on(eventName, f);
|
|
3133
|
-
}
|
|
3134
|
-
|
|
3135
|
-
/**
|
|
3136
|
-
* @param {string} eventName
|
|
3137
|
-
* @param {function} f
|
|
3138
|
-
*/
|
|
3139
|
-
off (eventName, f) {
|
|
3140
|
-
super.off(eventName, f);
|
|
3141
|
-
}
|
|
3142
3248
|
}
|
|
3143
3249
|
|
|
3144
3250
|
class DSDecoderV1 {
|
|
@@ -3579,7 +3685,7 @@ class UpdateEncoderV2 extends DSEncoderV2 {
|
|
|
3579
3685
|
*/
|
|
3580
3686
|
this.keyMap = new Map();
|
|
3581
3687
|
/**
|
|
3582
|
-
* Refers to the next
|
|
3688
|
+
* Refers to the next unique key-identifier to me used.
|
|
3583
3689
|
* See writeKey method for more information.
|
|
3584
3690
|
*
|
|
3585
3691
|
* @type {number}
|
|
@@ -3731,6 +3837,23 @@ class UpdateEncoderV2 extends DSEncoderV2 {
|
|
|
3731
3837
|
}
|
|
3732
3838
|
}
|
|
3733
3839
|
|
|
3840
|
+
/**
|
|
3841
|
+
* @module encoding
|
|
3842
|
+
*/
|
|
3843
|
+
/*
|
|
3844
|
+
* We use the first five bits in the info flag for determining the type of the struct.
|
|
3845
|
+
*
|
|
3846
|
+
* 0: GC
|
|
3847
|
+
* 1: Item with Deleted content
|
|
3848
|
+
* 2: Item with JSON content
|
|
3849
|
+
* 3: Item with Binary content
|
|
3850
|
+
* 4: Item with String content
|
|
3851
|
+
* 5: Item with Embed content (for richtext content)
|
|
3852
|
+
* 6: Item with Format content (a formatting marker for richtext content)
|
|
3853
|
+
* 7: Item with Type
|
|
3854
|
+
*/
|
|
3855
|
+
|
|
3856
|
+
|
|
3734
3857
|
/**
|
|
3735
3858
|
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
|
3736
3859
|
* @param {Array<GC|Item>} structs All structs by `client`
|
|
@@ -3839,7 +3962,7 @@ const readClientsStructRefs = (decoder, doc) => {
|
|
|
3839
3962
|
// @type {string|null}
|
|
3840
3963
|
const struct = new Item(
|
|
3841
3964
|
createID(client, clock),
|
|
3842
|
-
null, //
|
|
3965
|
+
null, // left
|
|
3843
3966
|
(info & BIT8) === BIT8 ? decoder.readLeftID() : null, // origin
|
|
3844
3967
|
null, // right
|
|
3845
3968
|
(info & BIT7) === BIT7 ? decoder.readRightID() : null, // right origin
|
|
@@ -3863,7 +3986,7 @@ const readClientsStructRefs = (decoder, doc) => {
|
|
|
3863
3986
|
|
|
3864
3987
|
const struct = new Item(
|
|
3865
3988
|
createID(client, clock),
|
|
3866
|
-
null, //
|
|
3989
|
+
null, // left
|
|
3867
3990
|
origin, // origin
|
|
3868
3991
|
null, // right
|
|
3869
3992
|
rightOrigin, // right origin
|
|
@@ -3896,7 +4019,7 @@ const readClientsStructRefs = (decoder, doc) => {
|
|
|
3896
4019
|
* then we start emptying the stack.
|
|
3897
4020
|
*
|
|
3898
4021
|
* It is not possible to have circles: i.e. struct1 (from client1) depends on struct2 (from client2)
|
|
3899
|
-
* depends on struct3 (from client1). Therefore the max stack size is
|
|
4022
|
+
* depends on struct3 (from client1). Therefore the max stack size is equal to `structReaders.length`.
|
|
3900
4023
|
*
|
|
3901
4024
|
* This method is implemented in a way so that we can resume computation if this update
|
|
3902
4025
|
* causally depends on another update.
|
|
@@ -3935,7 +4058,7 @@ const integrateStructs = (transaction, store, clientsStructRefs) => {
|
|
|
3935
4058
|
return nextStructsTarget
|
|
3936
4059
|
};
|
|
3937
4060
|
let curStructsTarget = getNextStructTarget();
|
|
3938
|
-
if (curStructsTarget === null
|
|
4061
|
+
if (curStructsTarget === null) {
|
|
3939
4062
|
return null
|
|
3940
4063
|
}
|
|
3941
4064
|
|
|
@@ -3964,14 +4087,14 @@ const integrateStructs = (transaction, store, clientsStructRefs) => {
|
|
|
3964
4087
|
const addStackToRestSS = () => {
|
|
3965
4088
|
for (const item of stack) {
|
|
3966
4089
|
const client = item.id.client;
|
|
3967
|
-
const
|
|
3968
|
-
if (
|
|
4090
|
+
const inapplicableItems = clientsStructRefs.get(client);
|
|
4091
|
+
if (inapplicableItems) {
|
|
3969
4092
|
// decrement because we weren't able to apply previous operation
|
|
3970
|
-
|
|
3971
|
-
restStructs.clients.set(client,
|
|
4093
|
+
inapplicableItems.i--;
|
|
4094
|
+
restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i));
|
|
3972
4095
|
clientsStructRefs.delete(client);
|
|
3973
|
-
|
|
3974
|
-
|
|
4096
|
+
inapplicableItems.i = 0;
|
|
4097
|
+
inapplicableItems.refs = [];
|
|
3975
4098
|
} else {
|
|
3976
4099
|
// item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
|
|
3977
4100
|
restStructs.clients.set(client, [item]);
|
|
@@ -4055,7 +4178,7 @@ const writeStructsFromTransaction = (encoder, transaction) => writeClientsStruct
|
|
|
4055
4178
|
/**
|
|
4056
4179
|
* Read and apply a document update.
|
|
4057
4180
|
*
|
|
4058
|
-
* This function has the same effect as `applyUpdate` but accepts
|
|
4181
|
+
* This function has the same effect as `applyUpdate` but accepts a decoder.
|
|
4059
4182
|
*
|
|
4060
4183
|
* @param {decoding.Decoder} decoder
|
|
4061
4184
|
* @param {Doc} ydoc
|
|
@@ -4065,7 +4188,7 @@ const writeStructsFromTransaction = (encoder, transaction) => writeClientsStruct
|
|
|
4065
4188
|
* @function
|
|
4066
4189
|
*/
|
|
4067
4190
|
const readUpdateV2 = (decoder, ydoc, transactionOrigin, structDecoder = new UpdateDecoderV2(decoder)) =>
|
|
4068
|
-
transact(ydoc, transaction => {
|
|
4191
|
+
transact$1(ydoc, transaction => {
|
|
4069
4192
|
// force that transaction.local is set to non-local
|
|
4070
4193
|
transaction.local = false;
|
|
4071
4194
|
let retry = false;
|
|
@@ -4670,7 +4793,8 @@ const iterateStructs = (transaction, structs, clockStart, len, f) => {
|
|
|
4670
4793
|
* possible. Here is an example to illustrate the advantages of bundling:
|
|
4671
4794
|
*
|
|
4672
4795
|
* @example
|
|
4673
|
-
* const
|
|
4796
|
+
* const ydoc = new Y.Doc()
|
|
4797
|
+
* const map = ydoc.getMap('map')
|
|
4674
4798
|
* // Log content when change is triggered
|
|
4675
4799
|
* map.observe(() => {
|
|
4676
4800
|
* console.log('change triggered')
|
|
@@ -4679,7 +4803,7 @@ const iterateStructs = (transaction, structs, clockStart, len, f) => {
|
|
|
4679
4803
|
* map.set('a', 0) // => "change triggered"
|
|
4680
4804
|
* map.set('b', 0) // => "change triggered"
|
|
4681
4805
|
* // When put in a transaction, it will trigger the log after the transaction:
|
|
4682
|
-
*
|
|
4806
|
+
* ydoc.transact(() => {
|
|
4683
4807
|
* map.set('a', 1)
|
|
4684
4808
|
* map.set('b', 1)
|
|
4685
4809
|
* }) // => "change triggered"
|
|
@@ -4855,7 +4979,7 @@ const tryGcDeleteSet = (ds, store, gcFilter) => {
|
|
|
4855
4979
|
*/
|
|
4856
4980
|
const tryMergeDeleteSet = (ds, store) => {
|
|
4857
4981
|
// try to merge deleted / gc'd items
|
|
4858
|
-
// merge from right to left for better
|
|
4982
|
+
// merge from right to left for better efficiency and so we don't miss any merge targets
|
|
4859
4983
|
ds.clients.forEach((deleteItems, client) => {
|
|
4860
4984
|
const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client));
|
|
4861
4985
|
for (let di = deleteItems.length - 1; di >= 0; di--) {
|
|
@@ -5025,7 +5149,7 @@ const cleanupTransactions = (transactionCleanups, i) => {
|
|
|
5025
5149
|
*
|
|
5026
5150
|
* @function
|
|
5027
5151
|
*/
|
|
5028
|
-
const transact = (doc, f, origin = null, local = true) => {
|
|
5152
|
+
const transact$1 = (doc, f, origin = null, local = true) => {
|
|
5029
5153
|
const transactionCleanups = doc._transactionCleanups;
|
|
5030
5154
|
let initialCall = false;
|
|
5031
5155
|
/**
|
|
@@ -5720,8 +5844,8 @@ const getPathTo = (parent, child) => {
|
|
|
5720
5844
|
let i = 0;
|
|
5721
5845
|
let c = /** @type {AbstractType<any>} */ (child._item.parent)._start;
|
|
5722
5846
|
while (c !== child._item && c !== null) {
|
|
5723
|
-
if (!c.deleted) {
|
|
5724
|
-
i
|
|
5847
|
+
if (!c.deleted && c.countable) {
|
|
5848
|
+
i += c.length;
|
|
5725
5849
|
}
|
|
5726
5850
|
c = c.right;
|
|
5727
5851
|
}
|
|
@@ -5732,6 +5856,11 @@ const getPathTo = (parent, child) => {
|
|
|
5732
5856
|
return path
|
|
5733
5857
|
};
|
|
5734
5858
|
|
|
5859
|
+
/**
|
|
5860
|
+
* https://docs.yjs.dev/getting-started/working-with-shared-types#caveats
|
|
5861
|
+
*/
|
|
5862
|
+
const warnPrematureAccess = () => { warn('Invalid access: Add Yjs type to a document before reading data.'); };
|
|
5863
|
+
|
|
5735
5864
|
const maxSearchMarker = 80;
|
|
5736
5865
|
|
|
5737
5866
|
/**
|
|
@@ -5863,11 +5992,11 @@ const findMarker = (yarray, index) => {
|
|
|
5863
5992
|
// }
|
|
5864
5993
|
// }
|
|
5865
5994
|
// if (marker) {
|
|
5866
|
-
// if (window.
|
|
5867
|
-
// window.
|
|
5868
|
-
// window.
|
|
5995
|
+
// if (window.lengths == null) {
|
|
5996
|
+
// window.lengths = []
|
|
5997
|
+
// window.getLengths = () => window.lengths.sort((a, b) => a - b)
|
|
5869
5998
|
// }
|
|
5870
|
-
// window.
|
|
5999
|
+
// window.lengths.push(marker.index - pindex)
|
|
5871
6000
|
// console.log('distance', marker.index - pindex, 'len', p && p.parent.length)
|
|
5872
6001
|
// }
|
|
5873
6002
|
if (marker !== null && abs$2(marker.index - pindex) < /** @type {YText|YArray<any>} */ (p.parent).length / maxSearchMarker) {
|
|
@@ -6014,6 +6143,10 @@ class AbstractType {
|
|
|
6014
6143
|
}
|
|
6015
6144
|
|
|
6016
6145
|
/**
|
|
6146
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
6147
|
+
*
|
|
6148
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
6149
|
+
*
|
|
6017
6150
|
* @return {AbstractType<EventType>}
|
|
6018
6151
|
*/
|
|
6019
6152
|
clone () {
|
|
@@ -6102,6 +6235,7 @@ class AbstractType {
|
|
|
6102
6235
|
* @function
|
|
6103
6236
|
*/
|
|
6104
6237
|
const typeListSlice = (type, start, end) => {
|
|
6238
|
+
type.doc ?? warnPrematureAccess();
|
|
6105
6239
|
if (start < 0) {
|
|
6106
6240
|
start = type._length + start;
|
|
6107
6241
|
}
|
|
@@ -6137,6 +6271,7 @@ const typeListSlice = (type, start, end) => {
|
|
|
6137
6271
|
* @function
|
|
6138
6272
|
*/
|
|
6139
6273
|
const typeListToArray = type => {
|
|
6274
|
+
type.doc ?? warnPrematureAccess();
|
|
6140
6275
|
const cs = [];
|
|
6141
6276
|
let n = type._start;
|
|
6142
6277
|
while (n !== null) {
|
|
@@ -6152,7 +6287,7 @@ const typeListToArray = type => {
|
|
|
6152
6287
|
};
|
|
6153
6288
|
|
|
6154
6289
|
/**
|
|
6155
|
-
* Executes a provided function on once on
|
|
6290
|
+
* Executes a provided function on once on every element of this YArray.
|
|
6156
6291
|
*
|
|
6157
6292
|
* @param {AbstractType<any>} type
|
|
6158
6293
|
* @param {function(any,number,any):void} f A function to execute on every element of this YArray.
|
|
@@ -6163,6 +6298,7 @@ const typeListToArray = type => {
|
|
|
6163
6298
|
const typeListForEach = (type, f) => {
|
|
6164
6299
|
let index = 0;
|
|
6165
6300
|
let n = type._start;
|
|
6301
|
+
type.doc ?? warnPrematureAccess();
|
|
6166
6302
|
while (n !== null) {
|
|
6167
6303
|
if (n.countable && !n.deleted) {
|
|
6168
6304
|
const c = n.content.getContent();
|
|
@@ -6252,6 +6388,7 @@ const typeListCreateIterator = type => {
|
|
|
6252
6388
|
* @function
|
|
6253
6389
|
*/
|
|
6254
6390
|
const typeListGet = (type, index) => {
|
|
6391
|
+
type.doc ?? warnPrematureAccess();
|
|
6255
6392
|
const marker = findMarker(type, index);
|
|
6256
6393
|
let n = type._start;
|
|
6257
6394
|
if (marker !== null) {
|
|
@@ -6332,7 +6469,7 @@ const typeListInsertGenericsAfter = (transaction, parent, referenceItem, content
|
|
|
6332
6469
|
packJsonContent();
|
|
6333
6470
|
};
|
|
6334
6471
|
|
|
6335
|
-
const lengthExceeded = create$3('Length exceeded!');
|
|
6472
|
+
const lengthExceeded = () => create$3('Length exceeded!');
|
|
6336
6473
|
|
|
6337
6474
|
/**
|
|
6338
6475
|
* @param {Transaction} transaction
|
|
@@ -6345,7 +6482,7 @@ const lengthExceeded = create$3('Length exceeded!');
|
|
|
6345
6482
|
*/
|
|
6346
6483
|
const typeListInsertGenerics = (transaction, parent, index, content) => {
|
|
6347
6484
|
if (index > parent._length) {
|
|
6348
|
-
throw lengthExceeded
|
|
6485
|
+
throw lengthExceeded()
|
|
6349
6486
|
}
|
|
6350
6487
|
if (index === 0) {
|
|
6351
6488
|
if (parent._searchMarker) {
|
|
@@ -6386,7 +6523,7 @@ const typeListInsertGenerics = (transaction, parent, index, content) => {
|
|
|
6386
6523
|
|
|
6387
6524
|
/**
|
|
6388
6525
|
* Pushing content is special as we generally want to push after the last item. So we don't have to update
|
|
6389
|
-
* the
|
|
6526
|
+
* the search marker.
|
|
6390
6527
|
*
|
|
6391
6528
|
* @param {Transaction} transaction
|
|
6392
6529
|
* @param {AbstractType<any>} parent
|
|
@@ -6447,7 +6584,7 @@ const typeListDelete = (transaction, parent, index, length) => {
|
|
|
6447
6584
|
n = n.right;
|
|
6448
6585
|
}
|
|
6449
6586
|
if (length > 0) {
|
|
6450
|
-
throw lengthExceeded
|
|
6587
|
+
throw lengthExceeded()
|
|
6451
6588
|
}
|
|
6452
6589
|
if (parent._searchMarker) {
|
|
6453
6590
|
updateMarkerChanges(parent._searchMarker, startIndex, -startLength + length /* in case we remove the above exception */);
|
|
@@ -6492,6 +6629,8 @@ const typeMapSet = (transaction, parent, key, value) => {
|
|
|
6492
6629
|
case Boolean:
|
|
6493
6630
|
case Array:
|
|
6494
6631
|
case String:
|
|
6632
|
+
case Date:
|
|
6633
|
+
case BigInt:
|
|
6495
6634
|
content = new ContentAny([value]);
|
|
6496
6635
|
break
|
|
6497
6636
|
case Uint8Array:
|
|
@@ -6520,6 +6659,7 @@ const typeMapSet = (transaction, parent, key, value) => {
|
|
|
6520
6659
|
* @function
|
|
6521
6660
|
*/
|
|
6522
6661
|
const typeMapGet = (parent, key) => {
|
|
6662
|
+
parent.doc ?? warnPrematureAccess();
|
|
6523
6663
|
const val = parent._map.get(key);
|
|
6524
6664
|
return val !== undefined && !val.deleted ? val.content.getContent()[val.length - 1] : undefined
|
|
6525
6665
|
};
|
|
@@ -6536,6 +6676,7 @@ const typeMapGetAll = (parent) => {
|
|
|
6536
6676
|
* @type {Object<string,any>}
|
|
6537
6677
|
*/
|
|
6538
6678
|
const res = {};
|
|
6679
|
+
parent.doc ?? warnPrematureAccess();
|
|
6539
6680
|
parent._map.forEach((value, key) => {
|
|
6540
6681
|
if (!value.deleted) {
|
|
6541
6682
|
res[key] = value.content.getContent()[value.length - 1];
|
|
@@ -6553,38 +6694,62 @@ const typeMapGetAll = (parent) => {
|
|
|
6553
6694
|
* @function
|
|
6554
6695
|
*/
|
|
6555
6696
|
const typeMapHas = (parent, key) => {
|
|
6697
|
+
parent.doc ?? warnPrematureAccess();
|
|
6556
6698
|
const val = parent._map.get(key);
|
|
6557
6699
|
return val !== undefined && !val.deleted
|
|
6558
6700
|
};
|
|
6559
6701
|
|
|
6560
6702
|
/**
|
|
6561
|
-
* @param {
|
|
6703
|
+
* @param {AbstractType<any>} parent
|
|
6704
|
+
* @param {Snapshot} snapshot
|
|
6705
|
+
* @return {Object<string,Object<string,any>|number|null|Array<any>|string|Uint8Array|AbstractType<any>|undefined>}
|
|
6706
|
+
*
|
|
6707
|
+
* @private
|
|
6708
|
+
* @function
|
|
6709
|
+
*/
|
|
6710
|
+
const typeMapGetAllSnapshot = (parent, snapshot) => {
|
|
6711
|
+
/**
|
|
6712
|
+
* @type {Object<string,any>}
|
|
6713
|
+
*/
|
|
6714
|
+
const res = {};
|
|
6715
|
+
parent._map.forEach((value, key) => {
|
|
6716
|
+
/**
|
|
6717
|
+
* @type {Item|null}
|
|
6718
|
+
*/
|
|
6719
|
+
let v = value;
|
|
6720
|
+
while (v !== null && (!snapshot.sv.has(v.id.client) || v.id.clock >= (snapshot.sv.get(v.id.client) || 0))) {
|
|
6721
|
+
v = v.left;
|
|
6722
|
+
}
|
|
6723
|
+
if (v !== null && isVisible(v, snapshot)) {
|
|
6724
|
+
res[key] = v.content.getContent()[v.length - 1];
|
|
6725
|
+
}
|
|
6726
|
+
});
|
|
6727
|
+
return res
|
|
6728
|
+
};
|
|
6729
|
+
|
|
6730
|
+
/**
|
|
6731
|
+
* @param {AbstractType<any> & { _map: Map<string, Item> }} type
|
|
6562
6732
|
* @return {IterableIterator<Array<any>>}
|
|
6563
6733
|
*
|
|
6564
6734
|
* @private
|
|
6565
6735
|
* @function
|
|
6566
6736
|
*/
|
|
6567
|
-
const createMapIterator =
|
|
6737
|
+
const createMapIterator = type => {
|
|
6738
|
+
type.doc ?? warnPrematureAccess();
|
|
6739
|
+
return iteratorFilter(type._map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
|
|
6740
|
+
};
|
|
6568
6741
|
|
|
6569
6742
|
/**
|
|
6570
6743
|
* @module YArray
|
|
6571
6744
|
*/
|
|
6572
6745
|
|
|
6746
|
+
|
|
6573
6747
|
/**
|
|
6574
6748
|
* Event that describes the changes on a YArray
|
|
6575
6749
|
* @template T
|
|
6576
6750
|
* @extends YEvent<YArray<T>>
|
|
6577
6751
|
*/
|
|
6578
|
-
class YArrayEvent extends YEvent {
|
|
6579
|
-
/**
|
|
6580
|
-
* @param {YArray<T>} yarray The changed type
|
|
6581
|
-
* @param {Transaction} transaction The transaction object
|
|
6582
|
-
*/
|
|
6583
|
-
constructor (yarray, transaction) {
|
|
6584
|
-
super(yarray, transaction);
|
|
6585
|
-
this._transaction = transaction;
|
|
6586
|
-
}
|
|
6587
|
-
}
|
|
6752
|
+
class YArrayEvent extends YEvent {}
|
|
6588
6753
|
|
|
6589
6754
|
/**
|
|
6590
6755
|
* A shared Array implementation.
|
|
@@ -6645,6 +6810,10 @@ class YArray extends AbstractType {
|
|
|
6645
6810
|
}
|
|
6646
6811
|
|
|
6647
6812
|
/**
|
|
6813
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
6814
|
+
*
|
|
6815
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
6816
|
+
*
|
|
6648
6817
|
* @return {YArray<T>}
|
|
6649
6818
|
*/
|
|
6650
6819
|
clone () {
|
|
@@ -6659,7 +6828,8 @@ class YArray extends AbstractType {
|
|
|
6659
6828
|
}
|
|
6660
6829
|
|
|
6661
6830
|
get length () {
|
|
6662
|
-
|
|
6831
|
+
this.doc ?? warnPrematureAccess();
|
|
6832
|
+
return this._length
|
|
6663
6833
|
}
|
|
6664
6834
|
|
|
6665
6835
|
/**
|
|
@@ -6691,7 +6861,7 @@ class YArray extends AbstractType {
|
|
|
6691
6861
|
*/
|
|
6692
6862
|
insert (index, content) {
|
|
6693
6863
|
if (this.doc !== null) {
|
|
6694
|
-
transact(this.doc, transaction => {
|
|
6864
|
+
transact$1(this.doc, transaction => {
|
|
6695
6865
|
typeListInsertGenerics(transaction, this, index, /** @type {any} */ (content));
|
|
6696
6866
|
});
|
|
6697
6867
|
} else {
|
|
@@ -6708,7 +6878,7 @@ class YArray extends AbstractType {
|
|
|
6708
6878
|
*/
|
|
6709
6879
|
push (content) {
|
|
6710
6880
|
if (this.doc !== null) {
|
|
6711
|
-
transact(this.doc, transaction => {
|
|
6881
|
+
transact$1(this.doc, transaction => {
|
|
6712
6882
|
typeListPushGenerics(transaction, this, /** @type {any} */ (content));
|
|
6713
6883
|
});
|
|
6714
6884
|
} else {
|
|
@@ -6717,9 +6887,9 @@ class YArray extends AbstractType {
|
|
|
6717
6887
|
}
|
|
6718
6888
|
|
|
6719
6889
|
/**
|
|
6720
|
-
*
|
|
6890
|
+
* Prepends content to this YArray.
|
|
6721
6891
|
*
|
|
6722
|
-
* @param {Array<T>} content Array of content to
|
|
6892
|
+
* @param {Array<T>} content Array of content to prepend.
|
|
6723
6893
|
*/
|
|
6724
6894
|
unshift (content) {
|
|
6725
6895
|
this.insert(0, content);
|
|
@@ -6733,7 +6903,7 @@ class YArray extends AbstractType {
|
|
|
6733
6903
|
*/
|
|
6734
6904
|
delete (index, length = 1) {
|
|
6735
6905
|
if (this.doc !== null) {
|
|
6736
|
-
transact(this.doc, transaction => {
|
|
6906
|
+
transact$1(this.doc, transaction => {
|
|
6737
6907
|
typeListDelete(transaction, this, index, length);
|
|
6738
6908
|
});
|
|
6739
6909
|
} else {
|
|
@@ -6761,7 +6931,8 @@ class YArray extends AbstractType {
|
|
|
6761
6931
|
}
|
|
6762
6932
|
|
|
6763
6933
|
/**
|
|
6764
|
-
*
|
|
6934
|
+
* Returns a portion of this YArray into a JavaScript Array selected
|
|
6935
|
+
* from start to end (end not included).
|
|
6765
6936
|
*
|
|
6766
6937
|
* @param {number} [start]
|
|
6767
6938
|
* @param {number} [end]
|
|
@@ -6794,7 +6965,7 @@ class YArray extends AbstractType {
|
|
|
6794
6965
|
}
|
|
6795
6966
|
|
|
6796
6967
|
/**
|
|
6797
|
-
* Executes a provided function once on
|
|
6968
|
+
* Executes a provided function once on every element of this YArray.
|
|
6798
6969
|
*
|
|
6799
6970
|
* @param {function(T,number,YArray<T>):void} f A function to execute on every element of this YArray.
|
|
6800
6971
|
*/
|
|
@@ -6825,6 +6996,11 @@ class YArray extends AbstractType {
|
|
|
6825
6996
|
*/
|
|
6826
6997
|
const readYArray = _decoder => new YArray();
|
|
6827
6998
|
|
|
6999
|
+
/**
|
|
7000
|
+
* @module YMap
|
|
7001
|
+
*/
|
|
7002
|
+
|
|
7003
|
+
|
|
6828
7004
|
/**
|
|
6829
7005
|
* @template T
|
|
6830
7006
|
* @extends YEvent<YMap<T>>
|
|
@@ -6847,7 +7023,7 @@ class YMapEvent extends YEvent {
|
|
|
6847
7023
|
* A shared Map implementation.
|
|
6848
7024
|
*
|
|
6849
7025
|
* @extends AbstractType<YMapEvent<MapType>>
|
|
6850
|
-
* @implements {Iterable<MapType>}
|
|
7026
|
+
* @implements {Iterable<[string, MapType]>}
|
|
6851
7027
|
*/
|
|
6852
7028
|
class YMap extends AbstractType {
|
|
6853
7029
|
/**
|
|
@@ -6895,6 +7071,10 @@ class YMap extends AbstractType {
|
|
|
6895
7071
|
}
|
|
6896
7072
|
|
|
6897
7073
|
/**
|
|
7074
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
7075
|
+
*
|
|
7076
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
7077
|
+
*
|
|
6898
7078
|
* @return {YMap<MapType>}
|
|
6899
7079
|
*/
|
|
6900
7080
|
clone () {
|
|
@@ -6924,6 +7104,7 @@ class YMap extends AbstractType {
|
|
|
6924
7104
|
* @return {Object<string,any>}
|
|
6925
7105
|
*/
|
|
6926
7106
|
toJSON () {
|
|
7107
|
+
this.doc ?? warnPrematureAccess();
|
|
6927
7108
|
/**
|
|
6928
7109
|
* @type {Object<string,MapType>}
|
|
6929
7110
|
*/
|
|
@@ -6943,7 +7124,7 @@ class YMap extends AbstractType {
|
|
|
6943
7124
|
* @return {number}
|
|
6944
7125
|
*/
|
|
6945
7126
|
get size () {
|
|
6946
|
-
return [...createMapIterator(this
|
|
7127
|
+
return [...createMapIterator(this)].length
|
|
6947
7128
|
}
|
|
6948
7129
|
|
|
6949
7130
|
/**
|
|
@@ -6952,25 +7133,25 @@ class YMap extends AbstractType {
|
|
|
6952
7133
|
* @return {IterableIterator<string>}
|
|
6953
7134
|
*/
|
|
6954
7135
|
keys () {
|
|
6955
|
-
return iteratorMap(createMapIterator(this
|
|
7136
|
+
return iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[0])
|
|
6956
7137
|
}
|
|
6957
7138
|
|
|
6958
7139
|
/**
|
|
6959
7140
|
* Returns the values for each element in the YMap Type.
|
|
6960
7141
|
*
|
|
6961
|
-
* @return {IterableIterator<
|
|
7142
|
+
* @return {IterableIterator<MapType>}
|
|
6962
7143
|
*/
|
|
6963
7144
|
values () {
|
|
6964
|
-
return iteratorMap(createMapIterator(this
|
|
7145
|
+
return iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
|
|
6965
7146
|
}
|
|
6966
7147
|
|
|
6967
7148
|
/**
|
|
6968
7149
|
* Returns an Iterator of [key, value] pairs
|
|
6969
7150
|
*
|
|
6970
|
-
* @return {IterableIterator<
|
|
7151
|
+
* @return {IterableIterator<[string, MapType]>}
|
|
6971
7152
|
*/
|
|
6972
7153
|
entries () {
|
|
6973
|
-
return iteratorMap(createMapIterator(this
|
|
7154
|
+
return iteratorMap(createMapIterator(this), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
|
|
6974
7155
|
}
|
|
6975
7156
|
|
|
6976
7157
|
/**
|
|
@@ -6979,6 +7160,7 @@ class YMap extends AbstractType {
|
|
|
6979
7160
|
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
|
|
6980
7161
|
*/
|
|
6981
7162
|
forEach (f) {
|
|
7163
|
+
this.doc ?? warnPrematureAccess();
|
|
6982
7164
|
this._map.forEach((item, key) => {
|
|
6983
7165
|
if (!item.deleted) {
|
|
6984
7166
|
f(item.content.getContent()[item.length - 1], key, this);
|
|
@@ -6989,7 +7171,7 @@ class YMap extends AbstractType {
|
|
|
6989
7171
|
/**
|
|
6990
7172
|
* Returns an Iterator of [key, value] pairs
|
|
6991
7173
|
*
|
|
6992
|
-
* @return {IterableIterator<
|
|
7174
|
+
* @return {IterableIterator<[string, MapType]>}
|
|
6993
7175
|
*/
|
|
6994
7176
|
[Symbol.iterator] () {
|
|
6995
7177
|
return this.entries()
|
|
@@ -7002,7 +7184,7 @@ class YMap extends AbstractType {
|
|
|
7002
7184
|
*/
|
|
7003
7185
|
delete (key) {
|
|
7004
7186
|
if (this.doc !== null) {
|
|
7005
|
-
transact(this.doc, transaction => {
|
|
7187
|
+
transact$1(this.doc, transaction => {
|
|
7006
7188
|
typeMapDelete(transaction, this, key);
|
|
7007
7189
|
});
|
|
7008
7190
|
} else {
|
|
@@ -7020,7 +7202,7 @@ class YMap extends AbstractType {
|
|
|
7020
7202
|
*/
|
|
7021
7203
|
set (key, value) {
|
|
7022
7204
|
if (this.doc !== null) {
|
|
7023
|
-
transact(this.doc, transaction => {
|
|
7205
|
+
transact$1(this.doc, transaction => {
|
|
7024
7206
|
typeMapSet(transaction, this, key, /** @type {any} */ (value));
|
|
7025
7207
|
});
|
|
7026
7208
|
} else {
|
|
@@ -7054,7 +7236,7 @@ class YMap extends AbstractType {
|
|
|
7054
7236
|
*/
|
|
7055
7237
|
clear () {
|
|
7056
7238
|
if (this.doc !== null) {
|
|
7057
|
-
transact(this.doc, transaction => {
|
|
7239
|
+
transact$1(this.doc, transaction => {
|
|
7058
7240
|
this.forEach(function (_value, key, map) {
|
|
7059
7241
|
typeMapDelete(transaction, map, key);
|
|
7060
7242
|
});
|
|
@@ -7080,6 +7262,11 @@ class YMap extends AbstractType {
|
|
|
7080
7262
|
*/
|
|
7081
7263
|
const readYMap = _decoder => new YMap();
|
|
7082
7264
|
|
|
7265
|
+
/**
|
|
7266
|
+
* @module YText
|
|
7267
|
+
*/
|
|
7268
|
+
|
|
7269
|
+
|
|
7083
7270
|
/**
|
|
7084
7271
|
* @param {any} a
|
|
7085
7272
|
* @param {any} b
|
|
@@ -7164,14 +7351,15 @@ const findNextPosition = (transaction, pos, count) => {
|
|
|
7164
7351
|
* @param {Transaction} transaction
|
|
7165
7352
|
* @param {AbstractType<any>} parent
|
|
7166
7353
|
* @param {number} index
|
|
7354
|
+
* @param {boolean} useSearchMarker
|
|
7167
7355
|
* @return {ItemTextListPosition}
|
|
7168
7356
|
*
|
|
7169
7357
|
* @private
|
|
7170
7358
|
* @function
|
|
7171
7359
|
*/
|
|
7172
|
-
const findPosition = (transaction, parent, index) => {
|
|
7360
|
+
const findPosition = (transaction, parent, index, useSearchMarker) => {
|
|
7173
7361
|
const currentAttributes = new Map();
|
|
7174
|
-
const marker = findMarker(parent, index);
|
|
7362
|
+
const marker = useSearchMarker ? findMarker(parent, index) : null;
|
|
7175
7363
|
if (marker) {
|
|
7176
7364
|
const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes);
|
|
7177
7365
|
return findNextPosition(transaction, pos, index - marker.index)
|
|
@@ -7247,7 +7435,7 @@ const minimizeAttributeChanges = (currPos, attributes) => {
|
|
|
7247
7435
|
while (true) {
|
|
7248
7436
|
if (currPos.right === null) {
|
|
7249
7437
|
break
|
|
7250
|
-
} else if (currPos.right.deleted || (currPos.right.content.constructor === ContentFormat && equalAttrs(attributes[(/** @type {ContentFormat} */ (currPos.right.content)).key]
|
|
7438
|
+
} else if (currPos.right.deleted || (currPos.right.content.constructor === ContentFormat && equalAttrs(attributes[(/** @type {ContentFormat} */ (currPos.right.content)).key] ?? null, /** @type {ContentFormat} */ (currPos.right.content).value))) ; else {
|
|
7251
7439
|
break
|
|
7252
7440
|
}
|
|
7253
7441
|
currPos.forward();
|
|
@@ -7271,7 +7459,7 @@ const insertAttributes = (transaction, parent, currPos, attributes) => {
|
|
|
7271
7459
|
// insert format-start items
|
|
7272
7460
|
for (const key in attributes) {
|
|
7273
7461
|
const val = attributes[key];
|
|
7274
|
-
const currentVal = currPos.currentAttributes.get(key)
|
|
7462
|
+
const currentVal = currPos.currentAttributes.get(key) ?? null;
|
|
7275
7463
|
if (!equalAttrs(currentVal, val)) {
|
|
7276
7464
|
// save negated attribute (set null if currentVal undefined)
|
|
7277
7465
|
negatedAttributes.set(key, currentVal);
|
|
@@ -7433,12 +7621,12 @@ const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAtt
|
|
|
7433
7621
|
switch (content.constructor) {
|
|
7434
7622
|
case ContentFormat: {
|
|
7435
7623
|
const { key, value } = /** @type {ContentFormat} */ (content);
|
|
7436
|
-
const startAttrValue = startAttributes.get(key)
|
|
7624
|
+
const startAttrValue = startAttributes.get(key) ?? null;
|
|
7437
7625
|
if (endFormats.get(key) !== content || startAttrValue === value) {
|
|
7438
7626
|
// Either this format is overwritten or it is not necessary because the attribute already existed.
|
|
7439
7627
|
start.delete(transaction);
|
|
7440
7628
|
cleanups++;
|
|
7441
|
-
if (!reachedCurr && (currAttributes.get(key)
|
|
7629
|
+
if (!reachedCurr && (currAttributes.get(key) ?? null) === value && startAttrValue !== value) {
|
|
7442
7630
|
if (startAttrValue === null) {
|
|
7443
7631
|
currAttributes.delete(key);
|
|
7444
7632
|
} else {
|
|
@@ -7496,7 +7684,7 @@ const cleanupContextlessFormattingGap = (transaction, item) => {
|
|
|
7496
7684
|
*/
|
|
7497
7685
|
const cleanupYTextFormatting = type => {
|
|
7498
7686
|
let res = 0;
|
|
7499
|
-
transact(/** @type {Doc} */ (type.doc), transaction => {
|
|
7687
|
+
transact$1(/** @type {Doc} */ (type.doc), transaction => {
|
|
7500
7688
|
let start = /** @type {Item} */ (type._start);
|
|
7501
7689
|
let end = type._start;
|
|
7502
7690
|
let startAttributes = create$5();
|
|
@@ -7521,7 +7709,7 @@ const cleanupYTextFormatting = type => {
|
|
|
7521
7709
|
};
|
|
7522
7710
|
|
|
7523
7711
|
/**
|
|
7524
|
-
* This will be called by the
|
|
7712
|
+
* This will be called by the transaction once the event handlers are called to potentially cleanup
|
|
7525
7713
|
* formatting attributes.
|
|
7526
7714
|
*
|
|
7527
7715
|
* @param {Transaction} transaction
|
|
@@ -7547,7 +7735,7 @@ const cleanupYTextAfterTransaction = transaction => {
|
|
|
7547
7735
|
});
|
|
7548
7736
|
}
|
|
7549
7737
|
// cleanup in a new transaction
|
|
7550
|
-
transact(doc, (t) => {
|
|
7738
|
+
transact$1(doc, (t) => {
|
|
7551
7739
|
iterateDeletedStructs(transaction, transaction.deleteSet, item => {
|
|
7552
7740
|
if (item instanceof GC || !(/** @type {YText} */ (item.parent)._hasFormatting) || needFullCleanup.has(/** @type {YText} */ (item.parent))) {
|
|
7553
7741
|
return
|
|
@@ -7611,7 +7799,7 @@ const deleteText = (transaction, currPos, length) => {
|
|
|
7611
7799
|
|
|
7612
7800
|
/**
|
|
7613
7801
|
* The Quill Delta format represents changes on a text document with
|
|
7614
|
-
* formatting information. For
|
|
7802
|
+
* formatting information. For more information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
|
|
7615
7803
|
*
|
|
7616
7804
|
* @example
|
|
7617
7805
|
* {
|
|
@@ -7702,7 +7890,7 @@ class YTextEvent extends YEvent {
|
|
|
7702
7890
|
* @type {Array<{insert?:string|object|AbstractType<any>, delete?:number, retain?:number, attributes?: Object<string,any>}>}
|
|
7703
7891
|
*/
|
|
7704
7892
|
const delta = [];
|
|
7705
|
-
transact(y, transaction => {
|
|
7893
|
+
transact$1(y, transaction => {
|
|
7706
7894
|
const currentAttributes = new Map(); // saves all current attributes for insert
|
|
7707
7895
|
const oldAttributes = new Map();
|
|
7708
7896
|
let item = this.target._start;
|
|
@@ -7813,12 +8001,12 @@ class YTextEvent extends YEvent {
|
|
|
7813
8001
|
const { key, value } = /** @type {ContentFormat} */ (item.content);
|
|
7814
8002
|
if (this.adds(item)) {
|
|
7815
8003
|
if (!this.deletes(item)) {
|
|
7816
|
-
const curVal = currentAttributes.get(key)
|
|
8004
|
+
const curVal = currentAttributes.get(key) ?? null;
|
|
7817
8005
|
if (!equalAttrs(curVal, value)) {
|
|
7818
8006
|
if (action === 'retain') {
|
|
7819
8007
|
addOp();
|
|
7820
8008
|
}
|
|
7821
|
-
if (equalAttrs(value, (oldAttributes.get(key)
|
|
8009
|
+
if (equalAttrs(value, (oldAttributes.get(key) ?? null))) {
|
|
7822
8010
|
delete attributes[key];
|
|
7823
8011
|
} else {
|
|
7824
8012
|
attributes[key] = value;
|
|
@@ -7829,7 +8017,7 @@ class YTextEvent extends YEvent {
|
|
|
7829
8017
|
}
|
|
7830
8018
|
} else if (this.deletes(item)) {
|
|
7831
8019
|
oldAttributes.set(key, value);
|
|
7832
|
-
const curVal = currentAttributes.get(key)
|
|
8020
|
+
const curVal = currentAttributes.get(key) ?? null;
|
|
7833
8021
|
if (!equalAttrs(curVal, value)) {
|
|
7834
8022
|
if (action === 'retain') {
|
|
7835
8023
|
addOp();
|
|
@@ -7919,6 +8107,7 @@ class YText extends AbstractType {
|
|
|
7919
8107
|
* @type {number}
|
|
7920
8108
|
*/
|
|
7921
8109
|
get length () {
|
|
8110
|
+
this.doc ?? warnPrematureAccess();
|
|
7922
8111
|
return this._length
|
|
7923
8112
|
}
|
|
7924
8113
|
|
|
@@ -7941,6 +8130,10 @@ class YText extends AbstractType {
|
|
|
7941
8130
|
}
|
|
7942
8131
|
|
|
7943
8132
|
/**
|
|
8133
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
8134
|
+
*
|
|
8135
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
8136
|
+
*
|
|
7944
8137
|
* @return {YText}
|
|
7945
8138
|
*/
|
|
7946
8139
|
clone () {
|
|
@@ -7971,6 +8164,7 @@ class YText extends AbstractType {
|
|
|
7971
8164
|
* @public
|
|
7972
8165
|
*/
|
|
7973
8166
|
toString () {
|
|
8167
|
+
this.doc ?? warnPrematureAccess();
|
|
7974
8168
|
let str = '';
|
|
7975
8169
|
/**
|
|
7976
8170
|
* @type {Item|null}
|
|
@@ -7998,7 +8192,7 @@ class YText extends AbstractType {
|
|
|
7998
8192
|
/**
|
|
7999
8193
|
* Apply a {@link Delta} on this shared YText type.
|
|
8000
8194
|
*
|
|
8001
|
-
* @param {any} delta The changes to apply on this element.
|
|
8195
|
+
* @param {Array<any>} delta The changes to apply on this element.
|
|
8002
8196
|
* @param {object} opts
|
|
8003
8197
|
* @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
|
|
8004
8198
|
*
|
|
@@ -8007,7 +8201,7 @@ class YText extends AbstractType {
|
|
|
8007
8201
|
*/
|
|
8008
8202
|
applyDelta (delta, { sanitize = true } = {}) {
|
|
8009
8203
|
if (this.doc !== null) {
|
|
8010
|
-
transact(this.doc, transaction => {
|
|
8204
|
+
transact$1(this.doc, transaction => {
|
|
8011
8205
|
const currPos = new ItemTextListPosition(null, this._start, 0, new Map());
|
|
8012
8206
|
for (let i = 0; i < delta.length; i++) {
|
|
8013
8207
|
const op = delta[i];
|
|
@@ -8044,6 +8238,7 @@ class YText extends AbstractType {
|
|
|
8044
8238
|
* @public
|
|
8045
8239
|
*/
|
|
8046
8240
|
toDelta (snapshot, prevSnapshot, computeYChange) {
|
|
8241
|
+
this.doc ?? warnPrematureAccess();
|
|
8047
8242
|
/**
|
|
8048
8243
|
* @type{Array<any>}
|
|
8049
8244
|
*/
|
|
@@ -8132,7 +8327,7 @@ class YText extends AbstractType {
|
|
|
8132
8327
|
if (snapshot || prevSnapshot) {
|
|
8133
8328
|
// snapshots are merged again after the transaction, so we need to keep the
|
|
8134
8329
|
// transaction alive until we are done
|
|
8135
|
-
transact(doc, transaction => {
|
|
8330
|
+
transact$1(doc, transaction => {
|
|
8136
8331
|
if (snapshot) {
|
|
8137
8332
|
splitSnapshotAffectedStructs(transaction, snapshot);
|
|
8138
8333
|
}
|
|
@@ -8163,8 +8358,8 @@ class YText extends AbstractType {
|
|
|
8163
8358
|
}
|
|
8164
8359
|
const y = this.doc;
|
|
8165
8360
|
if (y !== null) {
|
|
8166
|
-
transact(y, transaction => {
|
|
8167
|
-
const pos = findPosition(transaction, this, index);
|
|
8361
|
+
transact$1(y, transaction => {
|
|
8362
|
+
const pos = findPosition(transaction, this, index, !attributes);
|
|
8168
8363
|
if (!attributes) {
|
|
8169
8364
|
attributes = {};
|
|
8170
8365
|
// @ts-ignore
|
|
@@ -8182,20 +8377,20 @@ class YText extends AbstractType {
|
|
|
8182
8377
|
*
|
|
8183
8378
|
* @param {number} index The index to insert the embed at.
|
|
8184
8379
|
* @param {Object | AbstractType<any>} embed The Object that represents the embed.
|
|
8185
|
-
* @param {TextAttributes} attributes Attribute information to apply on the
|
|
8380
|
+
* @param {TextAttributes} [attributes] Attribute information to apply on the
|
|
8186
8381
|
* embed
|
|
8187
8382
|
*
|
|
8188
8383
|
* @public
|
|
8189
8384
|
*/
|
|
8190
|
-
insertEmbed (index, embed, attributes
|
|
8385
|
+
insertEmbed (index, embed, attributes) {
|
|
8191
8386
|
const y = this.doc;
|
|
8192
8387
|
if (y !== null) {
|
|
8193
|
-
transact(y, transaction => {
|
|
8194
|
-
const pos = findPosition(transaction, this, index);
|
|
8195
|
-
insertText(transaction, this, pos, embed, attributes);
|
|
8388
|
+
transact$1(y, transaction => {
|
|
8389
|
+
const pos = findPosition(transaction, this, index, !attributes);
|
|
8390
|
+
insertText(transaction, this, pos, embed, attributes || {});
|
|
8196
8391
|
});
|
|
8197
8392
|
} else {
|
|
8198
|
-
/** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes));
|
|
8393
|
+
/** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes || {}));
|
|
8199
8394
|
}
|
|
8200
8395
|
}
|
|
8201
8396
|
|
|
@@ -8213,8 +8408,8 @@ class YText extends AbstractType {
|
|
|
8213
8408
|
}
|
|
8214
8409
|
const y = this.doc;
|
|
8215
8410
|
if (y !== null) {
|
|
8216
|
-
transact(y, transaction => {
|
|
8217
|
-
deleteText(transaction, findPosition(transaction, this, index), length);
|
|
8411
|
+
transact$1(y, transaction => {
|
|
8412
|
+
deleteText(transaction, findPosition(transaction, this, index, true), length);
|
|
8218
8413
|
});
|
|
8219
8414
|
} else {
|
|
8220
8415
|
/** @type {Array<function>} */ (this._pending).push(() => this.delete(index, length));
|
|
@@ -8237,8 +8432,8 @@ class YText extends AbstractType {
|
|
|
8237
8432
|
}
|
|
8238
8433
|
const y = this.doc;
|
|
8239
8434
|
if (y !== null) {
|
|
8240
|
-
transact(y, transaction => {
|
|
8241
|
-
const pos = findPosition(transaction, this, index);
|
|
8435
|
+
transact$1(y, transaction => {
|
|
8436
|
+
const pos = findPosition(transaction, this, index, false);
|
|
8242
8437
|
if (pos.right === null) {
|
|
8243
8438
|
return
|
|
8244
8439
|
}
|
|
@@ -8260,7 +8455,7 @@ class YText extends AbstractType {
|
|
|
8260
8455
|
*/
|
|
8261
8456
|
removeAttribute (attributeName) {
|
|
8262
8457
|
if (this.doc !== null) {
|
|
8263
|
-
transact(this.doc, transaction => {
|
|
8458
|
+
transact$1(this.doc, transaction => {
|
|
8264
8459
|
typeMapDelete(transaction, this, attributeName);
|
|
8265
8460
|
});
|
|
8266
8461
|
} else {
|
|
@@ -8280,7 +8475,7 @@ class YText extends AbstractType {
|
|
|
8280
8475
|
*/
|
|
8281
8476
|
setAttribute (attributeName, attributeValue) {
|
|
8282
8477
|
if (this.doc !== null) {
|
|
8283
|
-
transact(this.doc, transaction => {
|
|
8478
|
+
transact$1(this.doc, transaction => {
|
|
8284
8479
|
typeMapSet(transaction, this, attributeName, attributeValue);
|
|
8285
8480
|
});
|
|
8286
8481
|
} else {
|
|
@@ -8337,6 +8532,7 @@ const readYText = _decoder => new YText();
|
|
|
8337
8532
|
* @module YXml
|
|
8338
8533
|
*/
|
|
8339
8534
|
|
|
8535
|
+
|
|
8340
8536
|
/**
|
|
8341
8537
|
* Define the elements to which a set of CSS queries apply.
|
|
8342
8538
|
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|CSS_Selectors}
|
|
@@ -8380,6 +8576,7 @@ class YXmlTreeWalker {
|
|
|
8380
8576
|
*/
|
|
8381
8577
|
this._currentNode = /** @type {Item} */ (root._start);
|
|
8382
8578
|
this._firstCall = true;
|
|
8579
|
+
root.doc ?? warnPrematureAccess();
|
|
8383
8580
|
}
|
|
8384
8581
|
|
|
8385
8582
|
[Symbol.iterator] () {
|
|
@@ -8408,8 +8605,12 @@ class YXmlTreeWalker {
|
|
|
8408
8605
|
} else {
|
|
8409
8606
|
// walk right or up in the tree
|
|
8410
8607
|
while (n !== null) {
|
|
8411
|
-
|
|
8412
|
-
|
|
8608
|
+
/**
|
|
8609
|
+
* @type {Item | null}
|
|
8610
|
+
*/
|
|
8611
|
+
const nxt = n.next;
|
|
8612
|
+
if (nxt !== null) {
|
|
8613
|
+
n = nxt;
|
|
8413
8614
|
break
|
|
8414
8615
|
} else if (n.parent === this._root) {
|
|
8415
8616
|
n = null;
|
|
@@ -8477,6 +8678,10 @@ class YXmlFragment extends AbstractType {
|
|
|
8477
8678
|
}
|
|
8478
8679
|
|
|
8479
8680
|
/**
|
|
8681
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
8682
|
+
*
|
|
8683
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
8684
|
+
*
|
|
8480
8685
|
* @return {YXmlFragment}
|
|
8481
8686
|
*/
|
|
8482
8687
|
clone () {
|
|
@@ -8487,6 +8692,7 @@ class YXmlFragment extends AbstractType {
|
|
|
8487
8692
|
}
|
|
8488
8693
|
|
|
8489
8694
|
get length () {
|
|
8695
|
+
this.doc ?? warnPrematureAccess();
|
|
8490
8696
|
return this._prelimContent === null ? this._length : this._prelimContent.length
|
|
8491
8697
|
}
|
|
8492
8698
|
|
|
@@ -8619,7 +8825,7 @@ class YXmlFragment extends AbstractType {
|
|
|
8619
8825
|
*/
|
|
8620
8826
|
insert (index, content) {
|
|
8621
8827
|
if (this.doc !== null) {
|
|
8622
|
-
transact(this.doc, transaction => {
|
|
8828
|
+
transact$1(this.doc, transaction => {
|
|
8623
8829
|
typeListInsertGenerics(transaction, this, index, content);
|
|
8624
8830
|
});
|
|
8625
8831
|
} else {
|
|
@@ -8640,7 +8846,7 @@ class YXmlFragment extends AbstractType {
|
|
|
8640
8846
|
*/
|
|
8641
8847
|
insertAfter (ref, content) {
|
|
8642
8848
|
if (this.doc !== null) {
|
|
8643
|
-
transact(this.doc, transaction => {
|
|
8849
|
+
transact$1(this.doc, transaction => {
|
|
8644
8850
|
const refItem = (ref && ref instanceof AbstractType) ? ref._item : ref;
|
|
8645
8851
|
typeListInsertGenericsAfter(transaction, this, refItem, content);
|
|
8646
8852
|
});
|
|
@@ -8662,7 +8868,7 @@ class YXmlFragment extends AbstractType {
|
|
|
8662
8868
|
*/
|
|
8663
8869
|
delete (index, length = 1) {
|
|
8664
8870
|
if (this.doc !== null) {
|
|
8665
|
-
transact(this.doc, transaction => {
|
|
8871
|
+
transact$1(this.doc, transaction => {
|
|
8666
8872
|
typeListDelete(transaction, this, index, length);
|
|
8667
8873
|
});
|
|
8668
8874
|
} else {
|
|
@@ -8690,9 +8896,9 @@ class YXmlFragment extends AbstractType {
|
|
|
8690
8896
|
}
|
|
8691
8897
|
|
|
8692
8898
|
/**
|
|
8693
|
-
*
|
|
8899
|
+
* Prepends content to this YArray.
|
|
8694
8900
|
*
|
|
8695
|
-
* @param {Array<YXmlElement|YXmlText>} content Array of content to
|
|
8901
|
+
* @param {Array<YXmlElement|YXmlText>} content Array of content to prepend.
|
|
8696
8902
|
*/
|
|
8697
8903
|
unshift (content) {
|
|
8698
8904
|
this.insert(0, content);
|
|
@@ -8709,7 +8915,8 @@ class YXmlFragment extends AbstractType {
|
|
|
8709
8915
|
}
|
|
8710
8916
|
|
|
8711
8917
|
/**
|
|
8712
|
-
*
|
|
8918
|
+
* Returns a portion of this YXmlFragment into a JavaScript Array selected
|
|
8919
|
+
* from start to end (end not included).
|
|
8713
8920
|
*
|
|
8714
8921
|
* @param {number} [start]
|
|
8715
8922
|
* @param {number} [end]
|
|
@@ -8720,7 +8927,7 @@ class YXmlFragment extends AbstractType {
|
|
|
8720
8927
|
}
|
|
8721
8928
|
|
|
8722
8929
|
/**
|
|
8723
|
-
* Executes a provided function on once on
|
|
8930
|
+
* Executes a provided function on once on every child element.
|
|
8724
8931
|
*
|
|
8725
8932
|
* @param {function(YXmlElement|YXmlText,number, typeof self):void} f A function to execute on every element of this YArray.
|
|
8726
8933
|
*/
|
|
@@ -8756,7 +8963,7 @@ const readYXmlFragment = _decoder => new YXmlFragment();
|
|
|
8756
8963
|
|
|
8757
8964
|
/**
|
|
8758
8965
|
* An YXmlElement imitates the behavior of a
|
|
8759
|
-
*
|
|
8966
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element
|
|
8760
8967
|
*
|
|
8761
8968
|
* * An YXmlElement has attributes (key value pairs)
|
|
8762
8969
|
* * An YXmlElement has childElements that must inherit from YXmlElement
|
|
@@ -8817,6 +9024,10 @@ class YXmlElement extends YXmlFragment {
|
|
|
8817
9024
|
}
|
|
8818
9025
|
|
|
8819
9026
|
/**
|
|
9027
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
9028
|
+
*
|
|
9029
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
9030
|
+
*
|
|
8820
9031
|
* @return {YXmlElement<KV>}
|
|
8821
9032
|
*/
|
|
8822
9033
|
clone () {
|
|
@@ -8871,7 +9082,7 @@ class YXmlElement extends YXmlFragment {
|
|
|
8871
9082
|
*/
|
|
8872
9083
|
removeAttribute (attributeName) {
|
|
8873
9084
|
if (this.doc !== null) {
|
|
8874
|
-
transact(this.doc, transaction => {
|
|
9085
|
+
transact$1(this.doc, transaction => {
|
|
8875
9086
|
typeMapDelete(transaction, this, attributeName);
|
|
8876
9087
|
});
|
|
8877
9088
|
} else {
|
|
@@ -8891,7 +9102,7 @@ class YXmlElement extends YXmlFragment {
|
|
|
8891
9102
|
*/
|
|
8892
9103
|
setAttribute (attributeName, attributeValue) {
|
|
8893
9104
|
if (this.doc !== null) {
|
|
8894
|
-
transact(this.doc, transaction => {
|
|
9105
|
+
transact$1(this.doc, transaction => {
|
|
8895
9106
|
typeMapSet(transaction, this, attributeName, attributeValue);
|
|
8896
9107
|
});
|
|
8897
9108
|
} else {
|
|
@@ -8929,12 +9140,13 @@ class YXmlElement extends YXmlFragment {
|
|
|
8929
9140
|
/**
|
|
8930
9141
|
* Returns all attribute name/value pairs in a JSON Object.
|
|
8931
9142
|
*
|
|
9143
|
+
* @param {Snapshot} [snapshot]
|
|
8932
9144
|
* @return {{ [Key in Extract<keyof KV,string>]?: KV[Key]}} A JSON Object that describes the attributes.
|
|
8933
9145
|
*
|
|
8934
9146
|
* @public
|
|
8935
9147
|
*/
|
|
8936
|
-
getAttributes () {
|
|
8937
|
-
return /** @type {any} */ (typeMapGetAll(this))
|
|
9148
|
+
getAttributes (snapshot) {
|
|
9149
|
+
return /** @type {any} */ (snapshot ? typeMapGetAllSnapshot(this, snapshot) : typeMapGetAll(this))
|
|
8938
9150
|
}
|
|
8939
9151
|
|
|
8940
9152
|
/**
|
|
@@ -9001,7 +9213,7 @@ class YXmlEvent extends YEvent {
|
|
|
9001
9213
|
* @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
|
|
9002
9214
|
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
|
|
9003
9215
|
* child list changed.
|
|
9004
|
-
* @param {Transaction} transaction The transaction instance with
|
|
9216
|
+
* @param {Transaction} transaction The transaction instance with which the
|
|
9005
9217
|
* change was created.
|
|
9006
9218
|
*/
|
|
9007
9219
|
constructor (target, subs, transaction) {
|
|
@@ -9052,6 +9264,10 @@ class YXmlHook extends YMap {
|
|
|
9052
9264
|
}
|
|
9053
9265
|
|
|
9054
9266
|
/**
|
|
9267
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
9268
|
+
*
|
|
9269
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
9270
|
+
*
|
|
9055
9271
|
* @return {YXmlHook}
|
|
9056
9272
|
*/
|
|
9057
9273
|
clone () {
|
|
@@ -9142,6 +9358,10 @@ class YXmlText extends YText {
|
|
|
9142
9358
|
}
|
|
9143
9359
|
|
|
9144
9360
|
/**
|
|
9361
|
+
* Makes a copy of this data type that can be included somewhere else.
|
|
9362
|
+
*
|
|
9363
|
+
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
|
9364
|
+
*
|
|
9145
9365
|
* @return {YXmlText}
|
|
9146
9366
|
*/
|
|
9147
9367
|
clone () {
|
|
@@ -9253,7 +9473,7 @@ class AbstractStruct {
|
|
|
9253
9473
|
* This method is already assuming that `this.id.clock + this.length === this.id.clock`.
|
|
9254
9474
|
* Also this method does *not* remove right from StructStore!
|
|
9255
9475
|
* @param {AbstractStruct} right
|
|
9256
|
-
* @return {boolean}
|
|
9476
|
+
* @return {boolean} whether this merged with right
|
|
9257
9477
|
*/
|
|
9258
9478
|
mergeWith (right) {
|
|
9259
9479
|
return false
|
|
@@ -9956,6 +10176,8 @@ const readContentJSON = decoder => {
|
|
|
9956
10176
|
return new ContentJSON(cs)
|
|
9957
10177
|
};
|
|
9958
10178
|
|
|
10179
|
+
const isDevMode = getVariable('node_env') === 'development';
|
|
10180
|
+
|
|
9959
10181
|
class ContentAny {
|
|
9960
10182
|
/**
|
|
9961
10183
|
* @param {Array<any>} arr
|
|
@@ -9965,6 +10187,7 @@ class ContentAny {
|
|
|
9965
10187
|
* @type {Array<any>}
|
|
9966
10188
|
*/
|
|
9967
10189
|
this.arr = arr;
|
|
10190
|
+
isDevMode && deepFreeze(arr);
|
|
9968
10191
|
}
|
|
9969
10192
|
|
|
9970
10193
|
/**
|
|
@@ -10525,14 +10748,12 @@ class Item extends AbstractStruct {
|
|
|
10525
10748
|
}
|
|
10526
10749
|
if ((this.left && this.left.constructor === GC) || (this.right && this.right.constructor === GC)) {
|
|
10527
10750
|
this.parent = null;
|
|
10528
|
-
}
|
|
10529
|
-
|
|
10530
|
-
if (!this.parent) {
|
|
10751
|
+
} else if (!this.parent) {
|
|
10752
|
+
// only set parent if this shouldn't be garbage collected
|
|
10531
10753
|
if (this.left && this.left.constructor === Item) {
|
|
10532
10754
|
this.parent = this.left.parent;
|
|
10533
10755
|
this.parentSub = this.left.parentSub;
|
|
10534
|
-
}
|
|
10535
|
-
if (this.right && this.right.constructor === Item) {
|
|
10756
|
+
} else if (this.right && this.right.constructor === Item) {
|
|
10536
10757
|
this.parent = this.right.parent;
|
|
10537
10758
|
this.parentSub = this.right.parentSub;
|
|
10538
10759
|
}
|
|
@@ -10913,6 +11134,7 @@ class Skip extends AbstractStruct {
|
|
|
10913
11134
|
|
|
10914
11135
|
/** eslint-env browser */
|
|
10915
11136
|
|
|
11137
|
+
|
|
10916
11138
|
const glo = /** @type {any} */ (typeof globalThis !== 'undefined'
|
|
10917
11139
|
? globalThis
|
|
10918
11140
|
: typeof window !== 'undefined'
|
|
@@ -10941,67 +11163,86 @@ if (glo[importIdentifier] === true) {
|
|
|
10941
11163
|
}
|
|
10942
11164
|
glo[importIdentifier] = true;
|
|
10943
11165
|
|
|
10944
|
-
|
|
11166
|
+
/* eslint @typescript-eslint/no-explicit-any: off */
|
|
11167
|
+
// symbols
|
|
11168
|
+
const GET_ORIGINAL_SYMBOL = Symbol();
|
|
11169
|
+
// get object prototype
|
|
11170
|
+
const getProto$2 = Object.getPrototypeOf;
|
|
11171
|
+
const objectsToTrack = new WeakMap();
|
|
11172
|
+
// check if obj is a plain object or an array
|
|
11173
|
+
const isObjectToTrack = (obj) => obj &&
|
|
11174
|
+
(objectsToTrack.has(obj)
|
|
11175
|
+
? objectsToTrack.get(obj)
|
|
11176
|
+
: getProto$2(obj) === Object.prototype || getProto$2(obj) === Array.prototype);
|
|
11177
|
+
/**
|
|
11178
|
+
* Unwrap proxy to get the original object.
|
|
11179
|
+
*
|
|
11180
|
+
* Used to retrieve the original object used to create the proxy instance with `createProxy`.
|
|
11181
|
+
*
|
|
11182
|
+
* @param {Proxy<object>} obj - The proxy wrapper of the originial object.
|
|
11183
|
+
* @returns {object | null} - Return either the unwrapped object if exists.
|
|
11184
|
+
*
|
|
11185
|
+
* @example
|
|
11186
|
+
* import { createProxy, getUntracked } from 'proxy-compare';
|
|
11187
|
+
*
|
|
11188
|
+
* const original = { a: "1", c: "2", d: { e: "3" } };
|
|
11189
|
+
* const affected = new WeakMap();
|
|
11190
|
+
*
|
|
11191
|
+
* const proxy = createProxy(original, affected);
|
|
11192
|
+
* const originalFromProxy = getUntracked(proxy)
|
|
11193
|
+
*
|
|
11194
|
+
* Object.is(original, originalFromProxy) // true
|
|
11195
|
+
* isChanged(original, originalFromProxy, affected) // false
|
|
11196
|
+
*/
|
|
11197
|
+
const getUntracked = (obj) => {
|
|
11198
|
+
if (isObjectToTrack(obj)) {
|
|
11199
|
+
return obj[GET_ORIGINAL_SYMBOL] || null;
|
|
11200
|
+
}
|
|
11201
|
+
return null;
|
|
11202
|
+
};
|
|
10945
11203
|
|
|
10946
11204
|
const isObject = (x) => typeof x === "object" && x !== null;
|
|
10947
|
-
const
|
|
10948
|
-
const
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
}
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
const snap = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target));
|
|
10964
|
-
h(snap, true);
|
|
10965
|
-
snapCache.set(target, [version, snap]);
|
|
10966
|
-
Reflect.ownKeys(target).forEach((key) => {
|
|
10967
|
-
if (Object.getOwnPropertyDescriptor(snap, key)) {
|
|
10968
|
-
return;
|
|
11205
|
+
const canProxyDefault = (x) => isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise);
|
|
11206
|
+
const createHandlerDefault = (isInitializing, addPropListener, removePropListener, notifyUpdate) => ({
|
|
11207
|
+
deleteProperty(target, prop) {
|
|
11208
|
+
const prevValue = Reflect.get(target, prop);
|
|
11209
|
+
removePropListener(prop);
|
|
11210
|
+
const deleted = Reflect.deleteProperty(target, prop);
|
|
11211
|
+
if (deleted) {
|
|
11212
|
+
notifyUpdate(["delete", [prop], prevValue]);
|
|
11213
|
+
}
|
|
11214
|
+
return deleted;
|
|
11215
|
+
},
|
|
11216
|
+
set(target, prop, value, receiver) {
|
|
11217
|
+
const hasPrevValue = !isInitializing() && Reflect.has(target, prop);
|
|
11218
|
+
const prevValue = Reflect.get(target, prop, receiver);
|
|
11219
|
+
if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) {
|
|
11220
|
+
return true;
|
|
10969
11221
|
}
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
key
|
|
10974
|
-
);
|
|
10975
|
-
const desc = {
|
|
10976
|
-
value,
|
|
10977
|
-
enumerable,
|
|
10978
|
-
// This is intentional to avoid copying with proxy-compare.
|
|
10979
|
-
// It's still non-writable, so it avoids assigning a value.
|
|
10980
|
-
configurable: true
|
|
10981
|
-
};
|
|
10982
|
-
if (refSet.has(value)) {
|
|
10983
|
-
h(value, false);
|
|
10984
|
-
} else if (value instanceof Promise) {
|
|
10985
|
-
delete desc.value;
|
|
10986
|
-
desc.get = () => handlePromise(value);
|
|
10987
|
-
} else if (proxyStateMap.has(value)) {
|
|
10988
|
-
const [target2, ensureVersion] = proxyStateMap.get(
|
|
10989
|
-
value
|
|
10990
|
-
);
|
|
10991
|
-
desc.value = createSnapshot(
|
|
10992
|
-
target2,
|
|
10993
|
-
ensureVersion(),
|
|
10994
|
-
handlePromise
|
|
10995
|
-
);
|
|
11222
|
+
removePropListener(prop);
|
|
11223
|
+
if (isObject(value)) {
|
|
11224
|
+
value = getUntracked(value) || value;
|
|
10996
11225
|
}
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11226
|
+
const nextValue = !proxyStateMap.has(value) && canProxy(value) ? proxy(value) : value;
|
|
11227
|
+
addPropListener(prop, nextValue);
|
|
11228
|
+
Reflect.set(target, prop, nextValue, receiver);
|
|
11229
|
+
notifyUpdate(["set", [prop], value, prevValue]);
|
|
11230
|
+
return true;
|
|
11231
|
+
}
|
|
11232
|
+
});
|
|
11233
|
+
const proxyStateMap = /* @__PURE__ */ new WeakMap();
|
|
11234
|
+
const refSet = /* @__PURE__ */ new WeakSet();
|
|
11235
|
+
const versionHolder = [1, 1];
|
|
11236
|
+
const proxyCache = /* @__PURE__ */ new WeakMap();
|
|
11237
|
+
let objectIs = Object.is;
|
|
11238
|
+
let newProxy = (target, handler) => new Proxy(target, handler);
|
|
11239
|
+
let canProxy = canProxyDefault;
|
|
11240
|
+
let createHandler = createHandlerDefault;
|
|
11241
|
+
function proxy(baseObject = {}) {
|
|
11242
|
+
if (!isObject(baseObject)) {
|
|
11002
11243
|
throw new Error("object required");
|
|
11003
11244
|
}
|
|
11004
|
-
const found = proxyCache.get(
|
|
11245
|
+
const found = proxyCache.get(baseObject);
|
|
11005
11246
|
if (found) {
|
|
11006
11247
|
return found;
|
|
11007
11248
|
}
|
|
@@ -11032,15 +11273,18 @@ const buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) =
|
|
|
11032
11273
|
notifyUpdate(newOp, nextVersion);
|
|
11033
11274
|
};
|
|
11034
11275
|
const propProxyStates = /* @__PURE__ */ new Map();
|
|
11035
|
-
const addPropListener = (prop,
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11276
|
+
const addPropListener = (prop, propValue) => {
|
|
11277
|
+
const propProxyState = !refSet.has(propValue) && proxyStateMap.get(propValue);
|
|
11278
|
+
if (propProxyState) {
|
|
11279
|
+
if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && propProxyStates.has(prop)) {
|
|
11280
|
+
throw new Error("prop listener already exists");
|
|
11281
|
+
}
|
|
11282
|
+
if (listeners.size) {
|
|
11283
|
+
const remove = propProxyState[2](createPropListener(prop));
|
|
11284
|
+
propProxyStates.set(prop, [propProxyState, remove]);
|
|
11285
|
+
} else {
|
|
11286
|
+
propProxyStates.set(prop, [propProxyState]);
|
|
11287
|
+
}
|
|
11044
11288
|
}
|
|
11045
11289
|
};
|
|
11046
11290
|
const removePropListener = (prop) => {
|
|
@@ -11058,7 +11302,7 @@ const buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) =
|
|
|
11058
11302
|
if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production" && prevRemove) {
|
|
11059
11303
|
throw new Error("remove already exists");
|
|
11060
11304
|
}
|
|
11061
|
-
const remove = propProxyState[
|
|
11305
|
+
const remove = propProxyState[2](createPropListener(prop));
|
|
11062
11306
|
propProxyStates.set(prop, [propProxyState, remove]);
|
|
11063
11307
|
});
|
|
11064
11308
|
}
|
|
@@ -11075,93 +11319,28 @@ const buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) =
|
|
|
11075
11319
|
};
|
|
11076
11320
|
return removeListener;
|
|
11077
11321
|
};
|
|
11078
|
-
|
|
11079
|
-
const handler =
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
notifyUpdate(["delete", [prop], prevValue]);
|
|
11086
|
-
}
|
|
11087
|
-
return deleted;
|
|
11088
|
-
},
|
|
11089
|
-
set(target, prop, value, receiver) {
|
|
11090
|
-
const hasPrevValue = Reflect.has(target, prop);
|
|
11091
|
-
const prevValue = Reflect.get(target, prop, receiver);
|
|
11092
|
-
if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) {
|
|
11093
|
-
return true;
|
|
11094
|
-
}
|
|
11095
|
-
removePropListener(prop);
|
|
11096
|
-
if (isObject(value)) {
|
|
11097
|
-
value = y(value) || value;
|
|
11098
|
-
}
|
|
11099
|
-
let nextValue = value;
|
|
11100
|
-
if (value instanceof Promise) {
|
|
11101
|
-
value.then((v) => {
|
|
11102
|
-
value.status = "fulfilled";
|
|
11103
|
-
value.value = v;
|
|
11104
|
-
notifyUpdate(["resolve", [prop], v]);
|
|
11105
|
-
}).catch((e) => {
|
|
11106
|
-
value.status = "rejected";
|
|
11107
|
-
value.reason = e;
|
|
11108
|
-
notifyUpdate(["reject", [prop], e]);
|
|
11109
|
-
});
|
|
11110
|
-
} else {
|
|
11111
|
-
if (!proxyStateMap.has(value) && canProxy(value)) {
|
|
11112
|
-
nextValue = proxyFunction(value);
|
|
11113
|
-
}
|
|
11114
|
-
const childProxyState = !refSet.has(nextValue) && proxyStateMap.get(nextValue);
|
|
11115
|
-
if (childProxyState) {
|
|
11116
|
-
addPropListener(prop, childProxyState);
|
|
11117
|
-
}
|
|
11118
|
-
}
|
|
11119
|
-
Reflect.set(target, prop, nextValue, receiver);
|
|
11120
|
-
notifyUpdate(["set", [prop], value, prevValue]);
|
|
11121
|
-
return true;
|
|
11122
|
-
}
|
|
11123
|
-
};
|
|
11322
|
+
let initializing = true;
|
|
11323
|
+
const handler = createHandler(
|
|
11324
|
+
() => initializing,
|
|
11325
|
+
addPropListener,
|
|
11326
|
+
removePropListener,
|
|
11327
|
+
notifyUpdate
|
|
11328
|
+
);
|
|
11124
11329
|
const proxyObject = newProxy(baseObject, handler);
|
|
11125
|
-
proxyCache.set(
|
|
11126
|
-
const proxyState = [
|
|
11127
|
-
baseObject,
|
|
11128
|
-
ensureVersion,
|
|
11129
|
-
createSnapshot,
|
|
11130
|
-
addListener
|
|
11131
|
-
];
|
|
11330
|
+
proxyCache.set(baseObject, proxyObject);
|
|
11331
|
+
const proxyState = [baseObject, ensureVersion, addListener];
|
|
11132
11332
|
proxyStateMap.set(proxyObject, proxyState);
|
|
11133
|
-
Reflect.ownKeys(
|
|
11333
|
+
Reflect.ownKeys(baseObject).forEach((key) => {
|
|
11134
11334
|
const desc = Object.getOwnPropertyDescriptor(
|
|
11135
|
-
|
|
11335
|
+
baseObject,
|
|
11136
11336
|
key
|
|
11137
11337
|
);
|
|
11138
|
-
if ("value" in desc) {
|
|
11139
|
-
proxyObject[key] =
|
|
11140
|
-
delete desc.value;
|
|
11141
|
-
delete desc.writable;
|
|
11338
|
+
if ("value" in desc && desc.writable) {
|
|
11339
|
+
proxyObject[key] = baseObject[key];
|
|
11142
11340
|
}
|
|
11143
|
-
Object.defineProperty(baseObject, key, desc);
|
|
11144
11341
|
});
|
|
11342
|
+
initializing = false;
|
|
11145
11343
|
return proxyObject;
|
|
11146
|
-
}) => [
|
|
11147
|
-
// public functions
|
|
11148
|
-
proxyFunction,
|
|
11149
|
-
// shared state
|
|
11150
|
-
proxyStateMap,
|
|
11151
|
-
refSet,
|
|
11152
|
-
// internal things
|
|
11153
|
-
objectIs,
|
|
11154
|
-
newProxy,
|
|
11155
|
-
canProxy,
|
|
11156
|
-
defaultHandlePromise,
|
|
11157
|
-
snapCache,
|
|
11158
|
-
createSnapshot,
|
|
11159
|
-
proxyCache,
|
|
11160
|
-
versionHolder
|
|
11161
|
-
];
|
|
11162
|
-
const [defaultProxyFunction] = buildProxyFunction();
|
|
11163
|
-
function proxy(initialObject = {}) {
|
|
11164
|
-
return defaultProxyFunction(initialObject);
|
|
11165
11344
|
}
|
|
11166
11345
|
function getVersion(proxyObject) {
|
|
11167
11346
|
const proxyState = proxyStateMap.get(proxyObject);
|
|
@@ -11174,7 +11353,7 @@ function subscribe(proxyObject, callback, notifyInSync) {
|
|
|
11174
11353
|
}
|
|
11175
11354
|
let promise;
|
|
11176
11355
|
const ops = [];
|
|
11177
|
-
const addListener = proxyState[
|
|
11356
|
+
const addListener = proxyState[2];
|
|
11178
11357
|
let isListenerActive = false;
|
|
11179
11358
|
const listener = (op) => {
|
|
11180
11359
|
ops.push(op);
|
|
@@ -11244,9 +11423,354 @@ var fastDeepEqual = function equal(a, b) {
|
|
|
11244
11423
|
return a!==a && b!==b;
|
|
11245
11424
|
};
|
|
11246
11425
|
|
|
11247
|
-
var
|
|
11426
|
+
var deepEqual = /*@__PURE__*/getDefaultExportFromCjs(fastDeepEqual);
|
|
11427
|
+
|
|
11428
|
+
const parseProxyOps = (ops) => {
|
|
11429
|
+
const arrayOps = ops.flatMap((op) => {
|
|
11430
|
+
if (op[0] === 'resolve' || op[0] === 'reject')
|
|
11431
|
+
return [];
|
|
11432
|
+
const index = Number(op[1][op[1].length - 1]);
|
|
11433
|
+
if (!Number.isFinite(index))
|
|
11434
|
+
return [];
|
|
11435
|
+
return [[op[0], index, op[2], op[3]]];
|
|
11436
|
+
});
|
|
11437
|
+
const findCorrespondingInsert = (startOpIndex, startArrayIndex) => {
|
|
11438
|
+
let s = 0;
|
|
11439
|
+
let noInsert = null;
|
|
11440
|
+
while (startOpIndex + s + 1 < arrayOps.length) {
|
|
11441
|
+
if ((arrayOps[startOpIndex + s + 1][0] === 'set' ||
|
|
11442
|
+
arrayOps[startOpIndex + s + 1][0] === 'insert') &&
|
|
11443
|
+
arrayOps[startOpIndex + s + 1][1] < startArrayIndex &&
|
|
11444
|
+
arrayOps[startOpIndex + s + 1][3] === arrayOps[startOpIndex][2]) {
|
|
11445
|
+
return s + 1;
|
|
11446
|
+
}
|
|
11447
|
+
if (noInsert === null &&
|
|
11448
|
+
(arrayOps[startOpIndex + s + 1][0] === 'set' ||
|
|
11449
|
+
arrayOps[startOpIndex + s + 1][0] === 'insert') &&
|
|
11450
|
+
arrayOps[startOpIndex + s + 1][1] === startArrayIndex - (s + 1) &&
|
|
11451
|
+
arrayOps[startOpIndex + s + 1][3] === undefined) {
|
|
11452
|
+
s += 1;
|
|
11453
|
+
}
|
|
11454
|
+
else if (noInsert === null &&
|
|
11455
|
+
startOpIndex + s + 1 < arrayOps.length &&
|
|
11456
|
+
arrayOps[startOpIndex + s + 1][0] === 'set' &&
|
|
11457
|
+
arrayOps[startOpIndex + s + 1][3] !== undefined) {
|
|
11458
|
+
noInsert = [startOpIndex + s + 1, arrayOps[startOpIndex + s + 1][1]];
|
|
11459
|
+
s += 1;
|
|
11460
|
+
}
|
|
11461
|
+
else if (noInsert !== null &&
|
|
11462
|
+
arrayOps[startOpIndex + s + 1][0] === 'set' &&
|
|
11463
|
+
arrayOps[startOpIndex + s + 1][1] ===
|
|
11464
|
+
noInsert[1] + (s + 1 - noInsert[0]) &&
|
|
11465
|
+
arrayOps[startOpIndex + s + 1][3] !== undefined) {
|
|
11466
|
+
s += 1;
|
|
11467
|
+
}
|
|
11468
|
+
else {
|
|
11469
|
+
return null;
|
|
11470
|
+
}
|
|
11471
|
+
}
|
|
11472
|
+
return null;
|
|
11473
|
+
};
|
|
11474
|
+
const findContinuousDelete = (startOpIndex, startArrayIndex) => {
|
|
11475
|
+
let d = 0;
|
|
11476
|
+
while (startOpIndex + d + 1 < arrayOps.length &&
|
|
11477
|
+
arrayOps[startOpIndex + d + 1][0] === 'delete' &&
|
|
11478
|
+
arrayOps[startOpIndex + d + 1][1] === startArrayIndex - (d + 1)) {
|
|
11479
|
+
d += 1;
|
|
11480
|
+
}
|
|
11481
|
+
return d;
|
|
11482
|
+
};
|
|
11483
|
+
let i = 0;
|
|
11484
|
+
while (i < arrayOps.length) {
|
|
11485
|
+
if ((arrayOps[i][0] === 'set' || arrayOps[i][0] === 'insert') &&
|
|
11486
|
+
arrayOps[i][3] === undefined) {
|
|
11487
|
+
const startArrayIndex = arrayOps[i][1];
|
|
11488
|
+
const s = findCorrespondingInsert(i, startArrayIndex);
|
|
11489
|
+
if (s !== null) {
|
|
11490
|
+
const newArrayOp = [
|
|
11491
|
+
'insert',
|
|
11492
|
+
arrayOps[i + s][1],
|
|
11493
|
+
arrayOps[i + s][2],
|
|
11494
|
+
undefined,
|
|
11495
|
+
];
|
|
11496
|
+
arrayOps.splice(i + s, 1, newArrayOp);
|
|
11497
|
+
arrayOps.splice(i, 1);
|
|
11498
|
+
}
|
|
11499
|
+
else {
|
|
11500
|
+
i += 1;
|
|
11501
|
+
}
|
|
11502
|
+
}
|
|
11503
|
+
else if (i > 0 && arrayOps[i][0] === 'delete') {
|
|
11504
|
+
const startArrayIndex = arrayOps[i][1];
|
|
11505
|
+
const d = findContinuousDelete(i, startArrayIndex);
|
|
11506
|
+
if (arrayOps[i - 1][0] === 'set' &&
|
|
11507
|
+
arrayOps[i - 1][1] === startArrayIndex - (d + 1) &&
|
|
11508
|
+
arrayOps[i - 1][2] === arrayOps[i][2]) {
|
|
11509
|
+
const newArrayOp = [
|
|
11510
|
+
'delete',
|
|
11511
|
+
startArrayIndex - (d + 1),
|
|
11512
|
+
arrayOps[i - 1][3],
|
|
11513
|
+
undefined,
|
|
11514
|
+
];
|
|
11515
|
+
arrayOps.splice(i - 1, 2);
|
|
11516
|
+
arrayOps.splice(i - 1 + d, 0, newArrayOp);
|
|
11517
|
+
i -= 1;
|
|
11518
|
+
}
|
|
11519
|
+
else {
|
|
11520
|
+
i += 1;
|
|
11521
|
+
}
|
|
11522
|
+
}
|
|
11523
|
+
else {
|
|
11524
|
+
i += 1;
|
|
11525
|
+
}
|
|
11526
|
+
}
|
|
11527
|
+
return arrayOps;
|
|
11528
|
+
};
|
|
11248
11529
|
|
|
11249
|
-
|
|
11530
|
+
/* eslint @typescript-eslint/no-explicit-any: "off" */
|
|
11531
|
+
const isProxyObject = (x) => typeof x === 'object' && x !== null && getVersion(x) !== undefined;
|
|
11532
|
+
const isProxyArray = (x) => Array.isArray(x) && getVersion(x) !== undefined;
|
|
11533
|
+
const isPrimitiveMapValue = (v) => v === null ||
|
|
11534
|
+
typeof v === 'string' ||
|
|
11535
|
+
typeof v === 'number' ||
|
|
11536
|
+
typeof v === 'boolean';
|
|
11537
|
+
const transact = (doc, opts, fn) => {
|
|
11538
|
+
if (doc) {
|
|
11539
|
+
doc.transact(fn, opts.transactionOrigin);
|
|
11540
|
+
}
|
|
11541
|
+
else {
|
|
11542
|
+
fn();
|
|
11543
|
+
}
|
|
11544
|
+
};
|
|
11545
|
+
const toYValue = (val) => {
|
|
11546
|
+
if (isProxyArray(val)) {
|
|
11547
|
+
const arr = new YArray();
|
|
11548
|
+
arr.insert(0, val.map(toYValue).filter((v) => v !== undefined && v !== null));
|
|
11549
|
+
return arr;
|
|
11550
|
+
}
|
|
11551
|
+
if (isProxyObject(val)) {
|
|
11552
|
+
const map = new YMap();
|
|
11553
|
+
Object.entries(val).forEach(([key, value]) => {
|
|
11554
|
+
const v = toYValue(value);
|
|
11555
|
+
if (v !== undefined) {
|
|
11556
|
+
map.set(key, v);
|
|
11557
|
+
}
|
|
11558
|
+
});
|
|
11559
|
+
return map;
|
|
11560
|
+
}
|
|
11561
|
+
if (isPrimitiveMapValue(val)) {
|
|
11562
|
+
return val;
|
|
11563
|
+
}
|
|
11564
|
+
return undefined;
|
|
11565
|
+
};
|
|
11566
|
+
const toJSON = (yv) => {
|
|
11567
|
+
if (yv instanceof AbstractType) {
|
|
11568
|
+
return yv.toJSON();
|
|
11569
|
+
}
|
|
11570
|
+
return yv;
|
|
11571
|
+
};
|
|
11572
|
+
const getNestedValues = (p, y, path) => {
|
|
11573
|
+
let pv = p;
|
|
11574
|
+
let yv = y;
|
|
11575
|
+
for (let i = 0; i < path.length; i += 1) {
|
|
11576
|
+
const k = path[i];
|
|
11577
|
+
if (yv instanceof YMap) {
|
|
11578
|
+
// child may already be deleted
|
|
11579
|
+
if (!pv)
|
|
11580
|
+
break;
|
|
11581
|
+
pv = pv[k];
|
|
11582
|
+
yv = yv.get(k);
|
|
11583
|
+
}
|
|
11584
|
+
else if (yv instanceof YArray) {
|
|
11585
|
+
// child may already be deleted
|
|
11586
|
+
if (!pv)
|
|
11587
|
+
break;
|
|
11588
|
+
const index = Number(k);
|
|
11589
|
+
pv = pv[k];
|
|
11590
|
+
yv = yv.get(index);
|
|
11591
|
+
}
|
|
11592
|
+
else {
|
|
11593
|
+
pv = null;
|
|
11594
|
+
yv = null;
|
|
11595
|
+
}
|
|
11596
|
+
}
|
|
11597
|
+
return { p: pv, y: yv };
|
|
11598
|
+
};
|
|
11599
|
+
function bind$1(p, y, opts = {}) {
|
|
11600
|
+
if (isProxyArray(p) && !(y instanceof YArray)) ;
|
|
11601
|
+
if (isProxyObject(p) && !isProxyArray(p) && !(y instanceof YMap)) ;
|
|
11602
|
+
// initialize from y
|
|
11603
|
+
initializeFromY(p, y);
|
|
11604
|
+
// initialize from p
|
|
11605
|
+
initializeFromP(p, y, opts);
|
|
11606
|
+
if (isProxyArray(p) && y instanceof YArray) {
|
|
11607
|
+
p.splice(y.length);
|
|
11608
|
+
}
|
|
11609
|
+
// subscribe p
|
|
11610
|
+
const unsubscribeP = subscribeP(p, y, opts);
|
|
11611
|
+
// subscribe y
|
|
11612
|
+
const unsubscribeY = subscribeY(y, p);
|
|
11613
|
+
return () => {
|
|
11614
|
+
unsubscribeP();
|
|
11615
|
+
unsubscribeY();
|
|
11616
|
+
};
|
|
11617
|
+
}
|
|
11618
|
+
function initializeFromP(p, y, opts) {
|
|
11619
|
+
transact(y.doc, opts, () => {
|
|
11620
|
+
if (isProxyObject(p) && y instanceof YMap) {
|
|
11621
|
+
Object.entries(p).forEach(([k, pv]) => {
|
|
11622
|
+
const yv = y.get(k);
|
|
11623
|
+
if (!deepEqual(pv, toJSON(yv))) {
|
|
11624
|
+
insertPValueToY(pv, y, k);
|
|
11625
|
+
}
|
|
11626
|
+
});
|
|
11627
|
+
}
|
|
11628
|
+
if (isProxyArray(p) && y instanceof YArray) {
|
|
11629
|
+
p.forEach((pv, i) => {
|
|
11630
|
+
const yv = y.get(i);
|
|
11631
|
+
if (!deepEqual(pv, toJSON(yv))) {
|
|
11632
|
+
insertPValueToY(pv, y, i);
|
|
11633
|
+
}
|
|
11634
|
+
});
|
|
11635
|
+
}
|
|
11636
|
+
});
|
|
11637
|
+
}
|
|
11638
|
+
function initializeFromY(p, y) {
|
|
11639
|
+
if (isProxyObject(p) && y instanceof YMap) {
|
|
11640
|
+
y.forEach((yv, k) => {
|
|
11641
|
+
if (!deepEqual(p[k], toJSON(yv))) {
|
|
11642
|
+
p[k] = toJSON(yv);
|
|
11643
|
+
}
|
|
11644
|
+
});
|
|
11645
|
+
}
|
|
11646
|
+
if (isProxyArray(p) && y instanceof YArray) {
|
|
11647
|
+
y.forEach((yv, i) => {
|
|
11648
|
+
if (!deepEqual(p[i], toJSON(yv))) {
|
|
11649
|
+
insertYValueToP(yv, p, i);
|
|
11650
|
+
}
|
|
11651
|
+
});
|
|
11652
|
+
}
|
|
11653
|
+
}
|
|
11654
|
+
function insertPValueToY(pv, y, k) {
|
|
11655
|
+
const yv = toYValue(pv);
|
|
11656
|
+
if (yv === undefined && "production" !== 'production') {
|
|
11657
|
+
console.warn('unsupported p type', pv);
|
|
11658
|
+
return;
|
|
11659
|
+
}
|
|
11660
|
+
if (y instanceof YMap && typeof k === 'string') {
|
|
11661
|
+
y.set(k, yv);
|
|
11662
|
+
}
|
|
11663
|
+
else if (y instanceof YArray && typeof k === 'number') {
|
|
11664
|
+
y.insert(k, [yv]);
|
|
11665
|
+
}
|
|
11666
|
+
}
|
|
11667
|
+
function insertYValueToP(yv, p, k) {
|
|
11668
|
+
if (isProxyObject(p) && typeof k === 'string') {
|
|
11669
|
+
p[k] = toJSON(yv);
|
|
11670
|
+
}
|
|
11671
|
+
else if (isProxyArray(p) && typeof k === 'number') {
|
|
11672
|
+
p.splice(k, 0, toJSON(yv));
|
|
11673
|
+
}
|
|
11674
|
+
}
|
|
11675
|
+
function subscribeP(p, y, opts) {
|
|
11676
|
+
return subscribe(p, (ops) => {
|
|
11677
|
+
transact(y.doc, opts, () => {
|
|
11678
|
+
ops.forEach((op) => {
|
|
11679
|
+
const path = op[1].slice(0, -1);
|
|
11680
|
+
const k = op[1][op[1].length - 1];
|
|
11681
|
+
const parent = getNestedValues(p, y, path);
|
|
11682
|
+
if (parent.y instanceof YMap) {
|
|
11683
|
+
if (op[0] === 'delete') {
|
|
11684
|
+
parent.y.delete(k);
|
|
11685
|
+
}
|
|
11686
|
+
else if (op[0] === 'set') {
|
|
11687
|
+
const pv = parent.p[k];
|
|
11688
|
+
const yv = parent.y.get(k);
|
|
11689
|
+
if (!deepEqual(toJSON(yv), pv)) {
|
|
11690
|
+
insertPValueToY(pv, parent.y, k);
|
|
11691
|
+
}
|
|
11692
|
+
}
|
|
11693
|
+
}
|
|
11694
|
+
else if (parent.y instanceof YArray) {
|
|
11695
|
+
if (deepEqual(toJSON(parent.y), parent.p)) {
|
|
11696
|
+
return;
|
|
11697
|
+
}
|
|
11698
|
+
const arrayOps = parseProxyOps(ops);
|
|
11699
|
+
arrayOps.forEach((aOp) => {
|
|
11700
|
+
const i = aOp[1];
|
|
11701
|
+
if (aOp[0] === 'delete') {
|
|
11702
|
+
if (parent.y.length > i) {
|
|
11703
|
+
parent.y.delete(i, 1);
|
|
11704
|
+
}
|
|
11705
|
+
return;
|
|
11706
|
+
}
|
|
11707
|
+
const pv = parent.p[i];
|
|
11708
|
+
if (pv === undefined) {
|
|
11709
|
+
return;
|
|
11710
|
+
}
|
|
11711
|
+
if (aOp[0] === 'set') {
|
|
11712
|
+
if (parent.y.length > i) {
|
|
11713
|
+
parent.y.delete(i, 1);
|
|
11714
|
+
}
|
|
11715
|
+
insertPValueToY(pv, parent.y, i);
|
|
11716
|
+
}
|
|
11717
|
+
else if (aOp[0] === 'insert') {
|
|
11718
|
+
insertPValueToY(pv, parent.y, i);
|
|
11719
|
+
}
|
|
11720
|
+
});
|
|
11721
|
+
}
|
|
11722
|
+
});
|
|
11723
|
+
});
|
|
11724
|
+
});
|
|
11725
|
+
}
|
|
11726
|
+
function subscribeY(y, p) {
|
|
11727
|
+
const observer = (events) => {
|
|
11728
|
+
events.forEach((event) => {
|
|
11729
|
+
const path = event.path;
|
|
11730
|
+
const parent = getNestedValues(p, y, path);
|
|
11731
|
+
if (parent.y instanceof YMap) {
|
|
11732
|
+
event.changes.keys.forEach((item, k) => {
|
|
11733
|
+
if (item.action === 'delete') {
|
|
11734
|
+
delete parent.p[k];
|
|
11735
|
+
}
|
|
11736
|
+
else {
|
|
11737
|
+
const yv = parent.y.get(k);
|
|
11738
|
+
insertYValueToP(yv, parent.p, k);
|
|
11739
|
+
}
|
|
11740
|
+
});
|
|
11741
|
+
}
|
|
11742
|
+
else if (parent.y instanceof YArray) {
|
|
11743
|
+
if (deepEqual(parent.p, toJSON(parent.y))) {
|
|
11744
|
+
return;
|
|
11745
|
+
}
|
|
11746
|
+
let retain = 0;
|
|
11747
|
+
event.changes.delta.forEach((item) => {
|
|
11748
|
+
if (item.retain) {
|
|
11749
|
+
retain += item.retain;
|
|
11750
|
+
}
|
|
11751
|
+
if (item.delete) {
|
|
11752
|
+
parent.p.splice(retain, item.delete);
|
|
11753
|
+
}
|
|
11754
|
+
if (item.insert) {
|
|
11755
|
+
if (Array.isArray(item.insert)) {
|
|
11756
|
+
item.insert.forEach((yv, i) => {
|
|
11757
|
+
insertYValueToP(yv, parent.p, retain + i);
|
|
11758
|
+
});
|
|
11759
|
+
}
|
|
11760
|
+
else {
|
|
11761
|
+
insertYValueToP(item.insert, parent.p, retain);
|
|
11762
|
+
}
|
|
11763
|
+
retain += item.insert.length;
|
|
11764
|
+
}
|
|
11765
|
+
});
|
|
11766
|
+
}
|
|
11767
|
+
});
|
|
11768
|
+
};
|
|
11769
|
+
y.observeDeep(observer);
|
|
11770
|
+
return () => {
|
|
11771
|
+
y.unobserveDeep(observer);
|
|
11772
|
+
};
|
|
11773
|
+
}
|
|
11250
11774
|
|
|
11251
11775
|
class KokimokiTransaction {
|
|
11252
11776
|
// private _clones = new Map<
|
|
@@ -11267,7 +11791,7 @@ class KokimokiTransaction {
|
|
|
11267
11791
|
applyUpdate(docClone, encodeStateAsUpdate(store.doc));
|
|
11268
11792
|
// Set up proxy
|
|
11269
11793
|
const proxyClone = proxy();
|
|
11270
|
-
const unbindProxy =
|
|
11794
|
+
const unbindProxy = bind$1(proxyClone, docRoot);
|
|
11271
11795
|
this._proxies.push(proxyClone);
|
|
11272
11796
|
this._unbindProxies.push(unbindProxy);
|
|
11273
11797
|
// Listen for updates
|
|
@@ -11413,7 +11937,7 @@ class KokimokiStore {
|
|
|
11413
11937
|
// Construct proxy object
|
|
11414
11938
|
this.proxy = proxy(); //T["defaultValue"];
|
|
11415
11939
|
// @ts-ignore
|
|
11416
|
-
|
|
11940
|
+
bind$1(this.proxy, this.docRoot);
|
|
11417
11941
|
// // Create root proxy
|
|
11418
11942
|
// const store = this;
|
|
11419
11943
|
// // @ts-ignore
|
|
@@ -14934,6 +15458,20 @@ class KokimokiClient extends EventEmitter$1 {
|
|
|
14934
15458
|
});
|
|
14935
15459
|
return await res.json();
|
|
14936
15460
|
}
|
|
15461
|
+
/**
|
|
15462
|
+
* Generic AI chat endpoint: send a system prompt (and optional user prompt) to get a response.
|
|
15463
|
+
*/
|
|
15464
|
+
async chat(systemPrompt, userPrompt, temperature, maxTokens) {
|
|
15465
|
+
const res = await fetch(`${this._apiUrl}/ai/chat`, {
|
|
15466
|
+
method: "POST",
|
|
15467
|
+
headers: this.apiHeaders,
|
|
15468
|
+
body: JSON.stringify({ systemPrompt, userPrompt, temperature, maxTokens }),
|
|
15469
|
+
});
|
|
15470
|
+
if (!res.ok) {
|
|
15471
|
+
throw await res.json();
|
|
15472
|
+
}
|
|
15473
|
+
return await res.json();
|
|
15474
|
+
}
|
|
14937
15475
|
/**
|
|
14938
15476
|
* Use AI to apply prompt to an image
|
|
14939
15477
|
*/
|