reptree 0.1.1 → 0.1.3

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/index.js CHANGED
@@ -459,6 +459,191 @@ var Vertex = class {
459
459
  }
460
460
  };
461
461
 
462
+ // src/StateVector.ts
463
+ function subtractRanges(rangesA, rangesB) {
464
+ if (rangesB.length === 0) return rangesA.map((r) => [...r]);
465
+ if (rangesA.length === 0) return [];
466
+ const result = [];
467
+ let indexB = 0;
468
+ for (const rangeA of rangesA) {
469
+ let currentStart = rangeA[0];
470
+ const endA = rangeA[1];
471
+ while (indexB < rangesB.length && rangesB[indexB][1] < currentStart) {
472
+ indexB++;
473
+ }
474
+ while (indexB < rangesB.length && rangesB[indexB][0] <= endA) {
475
+ const startB = rangesB[indexB][0];
476
+ const endB = rangesB[indexB][1];
477
+ if (currentStart < startB) {
478
+ result.push([currentStart, Math.min(endA, startB - 1)]);
479
+ }
480
+ currentStart = Math.max(currentStart, endB + 1);
481
+ if (currentStart > endA) break;
482
+ if (endB >= endA) break;
483
+ if (endB < currentStart) {
484
+ indexB++;
485
+ } else if (startB >= currentStart) {
486
+ indexB++;
487
+ }
488
+ }
489
+ if (currentStart <= endA) {
490
+ result.push([currentStart, endA]);
491
+ }
492
+ }
493
+ return result;
494
+ }
495
+ var StateVector = class _StateVector {
496
+ /**
497
+ * Creates a new StateVector.
498
+ * @param initialState Optional initial state to copy from
499
+ */
500
+ constructor(initialState = {}) {
501
+ this.ranges = {};
502
+ for (const [peerId, peerRanges] of Object.entries(initialState)) {
503
+ this.ranges[peerId] = peerRanges.map((range) => [...range]);
504
+ }
505
+ }
506
+ /**
507
+ * Updates the state vector with a newly applied operation.
508
+ * Assumes ranges are sorted and non-overlapping.
509
+ *
510
+ * @param peerId The peer ID of the operation
511
+ * @param counter The counter value of the operation
512
+ */
513
+ update(peerId, counter) {
514
+ if (!this.ranges[peerId]) {
515
+ this.ranges[peerId] = [];
516
+ }
517
+ const ranges = this.ranges[peerId];
518
+ if (ranges.length === 0) {
519
+ ranges.push([counter, counter]);
520
+ return;
521
+ }
522
+ let rangeExtendedOrMerged = false;
523
+ let insertIndex = -1;
524
+ for (let i = 0; i < ranges.length; i++) {
525
+ const range = ranges[i];
526
+ if (counter >= range[0] && counter <= range[1]) {
527
+ rangeExtendedOrMerged = true;
528
+ break;
529
+ }
530
+ if (counter === range[0] - 1) {
531
+ range[0] = counter;
532
+ rangeExtendedOrMerged = true;
533
+ if (i > 0 && range[0] === ranges[i - 1][1] + 1) {
534
+ ranges[i - 1][1] = range[1];
535
+ ranges.splice(i, 1);
536
+ }
537
+ break;
538
+ }
539
+ if (counter === range[1] + 1) {
540
+ range[1] = counter;
541
+ rangeExtendedOrMerged = true;
542
+ if (i < ranges.length - 1 && range[1] + 1 === ranges[i + 1][0]) {
543
+ range[1] = ranges[i + 1][1];
544
+ ranges.splice(i + 1, 1);
545
+ }
546
+ break;
547
+ }
548
+ if (counter < range[0] && insertIndex === -1) {
549
+ insertIndex = i;
550
+ }
551
+ }
552
+ if (!rangeExtendedOrMerged) {
553
+ if (insertIndex === -1) {
554
+ insertIndex = ranges.length;
555
+ }
556
+ ranges.splice(insertIndex, 0, [counter, counter]);
557
+ if (insertIndex > 0 && ranges[insertIndex][0] === ranges[insertIndex - 1][1] + 1) {
558
+ ranges[insertIndex - 1][1] = ranges[insertIndex][1];
559
+ ranges.splice(insertIndex, 1);
560
+ insertIndex--;
561
+ }
562
+ if (insertIndex < ranges.length - 1 && ranges[insertIndex][1] + 1 === ranges[insertIndex + 1][0]) {
563
+ ranges[insertIndex][1] = ranges[insertIndex + 1][1];
564
+ ranges.splice(insertIndex + 1, 1);
565
+ }
566
+ }
567
+ }
568
+ /**
569
+ * Updates the state vector with a newly applied operation.
570
+ *
571
+ * @param op The operation that was just applied
572
+ */
573
+ updateFromOp(op) {
574
+ this.update(op.id.peerId, op.id.counter);
575
+ }
576
+ /**
577
+ * Returns the current state vector.
578
+ * Returns a readonly reference to the internal state.
579
+ */
580
+ getState() {
581
+ return this.ranges;
582
+ }
583
+ /**
584
+ * Calculates which operation ranges we have that the other state vector is missing
585
+ * by comparing state vectors.
586
+ *
587
+ * @param other The other state vector to compare against
588
+ * @returns Array of operation ID ranges that we have but they don't
589
+ */
590
+ diff(other) {
591
+ const missingRanges = [];
592
+ const theirState = other.getState();
593
+ for (const [peerId, ourRanges] of Object.entries(this.ranges)) {
594
+ const theirRanges = theirState[peerId] || [];
595
+ const missing = subtractRanges(ourRanges, theirRanges);
596
+ for (const [start, end] of missing) {
597
+ if (start <= end) {
598
+ missingRanges.push({
599
+ peerId,
600
+ start,
601
+ end
602
+ });
603
+ }
604
+ }
605
+ }
606
+ return missingRanges;
607
+ }
608
+ /**
609
+ * Checks if the state vector contains the given operation ID
610
+ *
611
+ * @param opId The operation ID to check
612
+ * @returns true if the operation is in the state vector, false otherwise
613
+ */
614
+ contains(opId) {
615
+ const peerId = opId.peerId;
616
+ const counter = opId.counter;
617
+ if (!this.ranges[peerId]) {
618
+ return false;
619
+ }
620
+ for (const [start, end] of this.ranges[peerId]) {
621
+ if (counter >= start && counter <= end) {
622
+ return true;
623
+ }
624
+ }
625
+ return false;
626
+ }
627
+ /**
628
+ * Creates a copy of this state vector
629
+ */
630
+ clone() {
631
+ return new _StateVector(this.ranges);
632
+ }
633
+ /**
634
+ * Builds a state vector from an array of operations
635
+ * @param operations The operations to build the state vector from
636
+ * @returns A new StateVector instance
637
+ */
638
+ static fromOperations(operations) {
639
+ const stateVector = new _StateVector();
640
+ for (const op of operations) {
641
+ stateVector.updateFromOp(op);
642
+ }
643
+ return stateVector;
644
+ }
645
+ };
646
+
462
647
  // src/RepTree.ts
463
648
  var _RepTree = class _RepTree {
464
649
  /**
@@ -474,31 +659,40 @@ var _RepTree = class _RepTree {
474
659
  this.localOps = [];
475
660
  this.pendingMovesWithMissingParent = /* @__PURE__ */ new Map();
476
661
  this.pendingPropertiesWithMissingVertex = /* @__PURE__ */ new Map();
477
- this.appliedOps = /* @__PURE__ */ new Set();
662
+ this.knownOps = /* @__PURE__ */ new Set();
478
663
  this.parentIdBeforeMove = /* @__PURE__ */ new Map();
479
664
  this.opAppliedCallbacks = [];
480
665
  this.maxDepth = _RepTree.DEFAULT_MAX_DEPTH;
666
+ this._stateVectorEnabled = true;
481
667
  this.peerId = peerId;
482
668
  this.state = new TreeState();
669
+ this.stateVector = new StateVector();
483
670
  if (ops != null && ops.length > 0) {
484
- let rootMoveOp;
485
- for (let i = 0; i < ops.length; i++) {
486
- if (isMoveVertexOp(ops[i]) && ops[i].parentId === null) {
487
- rootMoveOp = ops[i];
488
- break;
489
- }
490
- }
491
- if (rootMoveOp) {
492
- this.rootVertexId = rootMoveOp.targetId;
493
- } else {
494
- throw new Error("The operations has to contain a move operation with a parentId as null to set the root vertex");
495
- }
496
671
  this.applyOps(ops);
497
- this.ensureTrashVertex();
672
+ const root = this.root;
673
+ if (!root) {
674
+ throw new Error("There has to be a root vertex in the operations");
675
+ }
498
676
  } else {
499
- this.rootVertexId = this.newVertexInternalWithUUID(null);
500
- this.ensureTrashVertex();
677
+ this.ensureNullVertex();
678
+ }
679
+ }
680
+ get root() {
681
+ if (!this.rootVertexId) {
682
+ const vertices = this.state.getAllVertices();
683
+ for (const vertex of vertices) {
684
+ if (vertex.parentId === null && vertex.id !== _RepTree.NULL_VERTEX_ID) {
685
+ this.rootVertexId = vertex.id;
686
+ return new Vertex(this, vertex);
687
+ }
688
+ }
689
+ return void 0;
690
+ }
691
+ const rootVertex = this.state.getVertex(this.rootVertexId);
692
+ if (!rootVertex) {
693
+ throw new Error("Root vertex not found");
501
694
  }
695
+ return new Vertex(this, rootVertex);
502
696
  }
503
697
  getMoveOps() {
504
698
  return this.moveOps;
@@ -510,13 +704,6 @@ var _RepTree = class _RepTree {
510
704
  const vertex = this.state.getVertex(vertexId);
511
705
  return vertex ? new Vertex(this, vertex) : void 0;
512
706
  }
513
- get rootVertex() {
514
- const rootVertex = this.state.getVertex(this.rootVertexId);
515
- if (!rootVertex) {
516
- throw new Error("Root vertex not found");
517
- }
518
- return new Vertex(this, rootVertex);
519
- }
520
707
  getAllVertices() {
521
708
  return this.state.getAllVertices().map((v) => new Vertex(this, v));
522
709
  }
@@ -567,6 +754,17 @@ var _RepTree = class _RepTree {
567
754
  setMaxDepth(maxDepth) {
568
755
  this.maxDepth = maxDepth;
569
756
  }
757
+ createRoot() {
758
+ if (this.rootVertexId) {
759
+ throw new Error("Root vertex already exists");
760
+ }
761
+ this.rootVertexId = this.newVertexInternalWithUUID(null);
762
+ const rootVertex = this.state.getVertex(this.rootVertexId);
763
+ if (!rootVertex) {
764
+ throw new Error("Root vertex not found");
765
+ }
766
+ return new Vertex(this, rootVertex);
767
+ }
570
768
  newVertex(parentId, props = null) {
571
769
  const typedProps = props;
572
770
  const vertexId = this.newVertexInternalWithUUID(parentId);
@@ -599,7 +797,7 @@ var _RepTree = class _RepTree {
599
797
  this.applyMove(op);
600
798
  }
601
799
  deleteVertex(vertexId) {
602
- this.moveVertex(vertexId, _RepTree.TRASH_VERTEX_ID);
800
+ this.moveVertex(vertexId, _RepTree.NULL_VERTEX_ID);
603
801
  }
604
802
  setTransientVertexProperty(vertexId, key, value) {
605
803
  this.lamportClock++;
@@ -623,6 +821,9 @@ var _RepTree = class _RepTree {
623
821
  path = path.replace(/^\/+/, "");
624
822
  path = path.replace(/\/+$/, "");
625
823
  const pathParts = path.split("/");
824
+ if (!this.rootVertexId) {
825
+ return void 0;
826
+ }
626
827
  const root = this.state.getVertex(this.rootVertexId);
627
828
  if (!root) {
628
829
  throw new Error("The root vertex is not found");
@@ -644,12 +845,38 @@ var _RepTree = class _RepTree {
644
845
  return void 0;
645
846
  }
646
847
  printTree() {
848
+ if (!this.rootVertexId) {
849
+ return "";
850
+ }
647
851
  return this.state.printTree(this.rootVertexId);
648
852
  }
649
853
  merge(ops) {
650
854
  this.applyOps(ops);
651
855
  }
856
+ /** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */
857
+ applyOpsOptimizedForLotsOfMoves(ops) {
858
+ const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.knownOps.has(op.id.toString()));
859
+ if (newMoveOps.length > 0) {
860
+ const allMoveOps = [...this.moveOps, ...newMoveOps];
861
+ allMoveOps.sort((a, b) => OpId.compare(a.id, b.id));
862
+ for (let i = 0, len = allMoveOps.length; i < len; i++) {
863
+ const op = allMoveOps[i];
864
+ this.applyMove(op);
865
+ }
866
+ }
867
+ const propertyOps = ops.filter((op) => isSetPropertyOp(op) && !this.knownOps.has(op.id.toString()));
868
+ for (let i = 0, len = propertyOps.length; i < len; i++) {
869
+ const op = propertyOps[i];
870
+ this.applyProperty(op);
871
+ }
872
+ }
652
873
  compareStructure(other) {
874
+ if (this.root?.id !== other.root?.id) {
875
+ return false;
876
+ }
877
+ if (!this.rootVertexId) {
878
+ return true;
879
+ }
653
880
  return _RepTree.compareVertices(this.rootVertexId, this, other);
654
881
  }
655
882
  compareMoveOps(other) {
@@ -759,8 +986,8 @@ var _RepTree = class _RepTree {
759
986
  const vertexId = uuid();
760
987
  return this.newVertexInternal(vertexId, parentId);
761
988
  }
762
- ensureTrashVertex() {
763
- const vertexId = _RepTree.TRASH_VERTEX_ID;
989
+ ensureNullVertex() {
990
+ const vertexId = _RepTree.NULL_VERTEX_ID;
764
991
  if (this.state.getVertex(vertexId)) {
765
992
  return;
766
993
  }
@@ -772,6 +999,19 @@ var _RepTree = class _RepTree {
772
999
  this.lamportClock = operation.id.counter;
773
1000
  }
774
1001
  }
1002
+ applyPendingMovesForParent(parentId) {
1003
+ if (!this.state.getVertex(parentId)) {
1004
+ return;
1005
+ }
1006
+ const pendingMoves = this.pendingMovesWithMissingParent.get(parentId);
1007
+ if (!pendingMoves) {
1008
+ return;
1009
+ }
1010
+ this.pendingMovesWithMissingParent.delete(parentId);
1011
+ for (const pendingOp of pendingMoves) {
1012
+ this.applyMove(pendingOp);
1013
+ }
1014
+ }
775
1015
  applyMove(op) {
776
1016
  if (op.parentId !== null && !this.state.getVertex(op.parentId)) {
777
1017
  if (!this.pendingMovesWithMissingParent.has(op.parentId)) {
@@ -806,15 +1046,52 @@ var _RepTree = class _RepTree {
806
1046
  }
807
1047
  this.applyPendingMovesForParent(op.targetId);
808
1048
  }
809
- reportOpAsApplied(op) {
810
- this.appliedOps.add(op.id.toString());
811
- for (const callback of this.opAppliedCallbacks) {
812
- callback(op);
1049
+ setPropertyAndItsOpId(op) {
1050
+ this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
1051
+ this.state.setProperty(op.targetId, op.key, op.value);
1052
+ this.reportOpAsApplied(op);
1053
+ }
1054
+ setTransientPropertyAndItsOpId(op) {
1055
+ this.transientPropertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
1056
+ this.state.setTransientProperty(op.targetId, op.key, op.value);
1057
+ this.reportOpAsApplied(op);
1058
+ }
1059
+ applyProperty(op) {
1060
+ const targetVertex = this.state.getVertex(op.targetId);
1061
+ if (!targetVertex) {
1062
+ if (op.transient) {
1063
+ return;
1064
+ }
1065
+ if (!this.pendingPropertiesWithMissingVertex.has(op.targetId)) {
1066
+ this.pendingPropertiesWithMissingVertex.set(op.targetId, []);
1067
+ }
1068
+ this.pendingPropertiesWithMissingVertex.get(op.targetId).push(op);
1069
+ return;
1070
+ }
1071
+ this.updateLamportClock(op);
1072
+ const prevTransientOpId = this.transientPropertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
1073
+ const prevProp = targetVertex.getProperty(op.key);
1074
+ const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
1075
+ if (!op.transient) {
1076
+ this.setPropertyOps.push(op);
1077
+ if (!prevProp || !prevOpId || op.id.isGreaterThan(prevOpId)) {
1078
+ this.setPropertyAndItsOpId(op);
1079
+ } else {
1080
+ this.knownOps.add(op.id.toString());
1081
+ }
1082
+ if (prevTransientOpId && op.id.isGreaterThan(prevTransientOpId)) {
1083
+ this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);
1084
+ targetVertex.removeTransientProperty(op.key);
1085
+ }
1086
+ } else {
1087
+ if (!prevTransientOpId || op.id.isGreaterThan(prevTransientOpId)) {
1088
+ this.setTransientPropertyAndItsOpId(op);
1089
+ }
813
1090
  }
814
1091
  }
815
1092
  applyOps(ops) {
816
1093
  for (const op of ops) {
817
- if (this.appliedOps.has(op.id.toString())) {
1094
+ if (this.knownOps.has(op.id.toString())) {
818
1095
  continue;
819
1096
  }
820
1097
  if (isMoveVertexOp(op)) {
@@ -824,34 +1101,13 @@ var _RepTree = class _RepTree {
824
1101
  }
825
1102
  }
826
1103
  }
827
- /** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */
828
- applyOpsOptimizedForLotsOfMoves(ops) {
829
- const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.appliedOps.has(op.id.toString()));
830
- if (newMoveOps.length > 0) {
831
- const allMoveOps = [...this.moveOps, ...newMoveOps];
832
- allMoveOps.sort((a, b) => OpId.compare(a.id, b.id));
833
- for (let i = 0, len = allMoveOps.length; i < len; i++) {
834
- const op = allMoveOps[i];
835
- this.applyMove(op);
836
- }
837
- }
838
- const propertyOps = ops.filter((op) => isSetPropertyOp(op) && !this.appliedOps.has(op.id.toString()));
839
- for (let i = 0, len = propertyOps.length; i < len; i++) {
840
- const op = propertyOps[i];
841
- this.applyProperty(op);
842
- }
843
- }
844
- applyPendingMovesForParent(parentId) {
845
- if (!this.state.getVertex(parentId)) {
846
- return;
847
- }
848
- const pendingMoves = this.pendingMovesWithMissingParent.get(parentId);
849
- if (!pendingMoves) {
850
- return;
1104
+ reportOpAsApplied(op) {
1105
+ this.knownOps.add(op.id.toString());
1106
+ if (this._stateVectorEnabled) {
1107
+ this.stateVector.updateFromOp(op);
851
1108
  }
852
- this.pendingMovesWithMissingParent.delete(parentId);
853
- for (const pendingOp of pendingMoves) {
854
- this.applyMove(pendingOp);
1109
+ for (const callback of this.opAppliedCallbacks) {
1110
+ callback(op);
855
1111
  }
856
1112
  }
857
1113
  tryToMove(op) {
@@ -864,6 +1120,7 @@ var _RepTree = class _RepTree {
864
1120
  this.state.moveVertex(op.targetId, op.parentId);
865
1121
  if (!targetVertex) {
866
1122
  const pendingProperties = this.pendingPropertiesWithMissingVertex.get(op.targetId) || [];
1123
+ this.pendingPropertiesWithMissingVertex.delete(op.targetId);
867
1124
  for (const prop of pendingProperties) {
868
1125
  this.setPropertyAndItsOpId(prop);
869
1126
  }
@@ -881,54 +1138,71 @@ var _RepTree = class _RepTree {
881
1138
  }
882
1139
  this.state.moveVertex(op.targetId, prevParentId);
883
1140
  }
884
- setPropertyAndItsOpId(op) {
885
- this.propertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
886
- this.state.setProperty(op.targetId, op.key, op.value);
887
- this.reportOpAsApplied(op);
888
- }
889
- setTransientPropertyAndItsOpId(op) {
890
- this.transientPropertiesAndTheirOpIds.set(`${op.key}@${op.targetId}`, op.id);
891
- this.state.setTransientProperty(op.targetId, op.key, op.value);
892
- this.reportOpAsApplied(op);
1141
+ // --- Range-Based State Vector Methods ---
1142
+ /**
1143
+ * Returns the current state vector.
1144
+ * Returns a readonly reference to the internal state vector.
1145
+ */
1146
+ getStateVector() {
1147
+ if (!this._stateVectorEnabled) {
1148
+ return null;
1149
+ }
1150
+ return this.stateVector.getState();
893
1151
  }
894
- applyProperty(op) {
895
- const targetVertex = this.state.getVertex(op.targetId);
896
- if (!targetVertex) {
897
- if (op.transient) {
898
- return;
899
- }
900
- if (!this.pendingPropertiesWithMissingVertex.has(op.targetId)) {
901
- this.pendingPropertiesWithMissingVertex.set(op.targetId, []);
1152
+ /**
1153
+ * Determines which operations are needed to synchronize
1154
+ * with the provided state vector.
1155
+ *
1156
+ * @param theirStateVector The state vector from another peer
1157
+ * @returns Operations that should be sent to the other peer, sorted by OpId.
1158
+ */
1159
+ getMissingOps(theirStateVector) {
1160
+ if (!this._stateVectorEnabled) {
1161
+ return [...this.moveOps, ...this.setPropertyOps];
1162
+ }
1163
+ const otherStateVector = new StateVector(theirStateVector);
1164
+ const missingRanges = this.stateVector.diff(otherStateVector);
1165
+ const missingOps = [];
1166
+ const allOps = [...this.moveOps, ...this.setPropertyOps];
1167
+ for (const op of allOps) {
1168
+ for (const range of missingRanges) {
1169
+ if (op.id.peerId === range.peerId && op.id.counter >= range.start && op.id.counter <= range.end) {
1170
+ missingOps.push(op);
1171
+ break;
1172
+ }
902
1173
  }
903
- this.pendingPropertiesWithMissingVertex.get(op.targetId).push(op);
904
- return;
905
1174
  }
906
- this.updateLamportClock(op);
907
- const prevTransientOpId = this.transientPropertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
908
- const prevProp = targetVertex.getProperty(op.key);
909
- const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
910
- if (!op.transient) {
911
- this.setPropertyOps.push(op);
912
- if (!prevProp || !prevOpId || op.id.isGreaterThan(prevOpId)) {
913
- this.setPropertyAndItsOpId(op);
914
- }
915
- if (prevTransientOpId && op.id.isGreaterThan(prevTransientOpId)) {
916
- this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);
917
- targetVertex.removeTransientProperty(op.key);
918
- }
1175
+ missingOps.sort((a, b) => OpId.compare(a.id, b.id));
1176
+ return missingOps;
1177
+ }
1178
+ /**
1179
+ * Gets or sets whether state vector tracking is enabled
1180
+ */
1181
+ get stateVectorEnabled() {
1182
+ return this._stateVectorEnabled;
1183
+ }
1184
+ /**
1185
+ * Sets the state vector enabled status
1186
+ * When enabled, rebuilds the state vector from existing operations if needed
1187
+ */
1188
+ set stateVectorEnabled(value) {
1189
+ if (value === this._stateVectorEnabled) return;
1190
+ if (value) {
1191
+ this._stateVectorEnabled = true;
1192
+ this.stateVector = StateVector.fromOperations([...this.moveOps, ...this.setPropertyOps]);
919
1193
  } else {
920
- if (!prevTransientOpId || op.id.isGreaterThan(prevTransientOpId)) {
921
- this.setTransientPropertyAndItsOpId(op);
922
- }
1194
+ this._stateVectorEnabled = false;
1195
+ this.stateVector = new StateVector();
923
1196
  }
924
1197
  }
925
1198
  };
926
- _RepTree.TRASH_VERTEX_ID = "t";
1199
+ _RepTree.NULL_VERTEX_ID = "0";
927
1200
  _RepTree.DEFAULT_MAX_DEPTH = 1e5;
928
1201
  var RepTree = _RepTree;
929
1202
  export {
930
1203
  OpId,
931
1204
  RepTree,
1205
+ StateVector,
932
1206
  TreeState,
933
1207
  Vertex,
934
1208
  VertexState,