@fluidframework/map 0.58.1001 → 0.58.2000-58133

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/lib/directory.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
6
+ import { UsageError } from "@fluidframework/container-utils";
6
7
  import { readAndParse } from "@fluidframework/driver-utils";
7
8
  import { MessageType, } from "@fluidframework/protocol-definitions";
8
9
  import { SharedObject, ValueType } from "@fluidframework/shared-object-base";
@@ -196,6 +197,12 @@ export class SharedDirectory extends SharedObject {
196
197
  this.root.set(key, value);
197
198
  return this;
198
199
  }
200
+ dispose(error) {
201
+ this.root.dispose(error);
202
+ }
203
+ get disposed() {
204
+ return this.root.disposed;
205
+ }
199
206
  /**
200
207
  * Deletes the given key from within this IDirectory.
201
208
  * @param key - The key to delete
@@ -527,6 +534,10 @@ class SubDirectory extends TypedEventEmitter {
527
534
  this.runtime = runtime;
528
535
  this.serializer = serializer;
529
536
  this.absolutePath = absolutePath;
537
+ /**
538
+ * Tells if the sub directory is disposed or not.
539
+ */
540
+ this._disposed = false;
530
541
  /**
531
542
  * String representation for the class.
532
543
  */
@@ -557,12 +568,25 @@ class SubDirectory extends TypedEventEmitter {
557
568
  */
558
569
  this.pendingClearMessageId = -1;
559
570
  }
571
+ dispose(error) {
572
+ this._disposed = true;
573
+ this.emit("disposed", this);
574
+ }
575
+ get disposed() {
576
+ return this._disposed;
577
+ }
578
+ throwIfDisposed() {
579
+ if (this._disposed) {
580
+ throw new UsageError("Cannot access Disposed subDirectory");
581
+ }
582
+ }
560
583
  /**
561
584
  * Checks whether the given key exists in this IDirectory.
562
585
  * @param key - The key to check
563
586
  * @returns True if the key exists, false otherwise
564
587
  */
565
588
  has(key) {
589
+ this.throwIfDisposed();
566
590
  return this._storage.has(key);
567
591
  }
568
592
  /**
@@ -570,12 +594,14 @@ class SubDirectory extends TypedEventEmitter {
570
594
  */
571
595
  get(key) {
572
596
  var _a;
597
+ this.throwIfDisposed();
573
598
  return (_a = this._storage.get(key)) === null || _a === void 0 ? void 0 : _a.value;
574
599
  }
575
600
  /**
576
601
  * {@inheritDoc IDirectory.set}
577
602
  */
578
603
  set(key, value) {
604
+ this.throwIfDisposed();
579
605
  // Undefined/null keys can't be serialized to JSON in the manner we currently snapshot.
580
606
  if (key === undefined || key === null) {
581
607
  throw new Error("Undefined and null keys are not supported");
@@ -602,6 +628,7 @@ class SubDirectory extends TypedEventEmitter {
602
628
  * {@inheritDoc IDirectory.createSubDirectory}
603
629
  */
604
630
  createSubDirectory(subdirName) {
631
+ this.throwIfDisposed();
605
632
  // Undefined/null subdirectory names can't be serialized to JSON in the manner we currently snapshot.
606
633
  if (subdirName === undefined || subdirName === null) {
607
634
  throw new Error("SubDirectory name may not be undefined or null");
@@ -629,18 +656,21 @@ class SubDirectory extends TypedEventEmitter {
629
656
  * {@inheritDoc IDirectory.getSubDirectory}
630
657
  */
631
658
  getSubDirectory(subdirName) {
659
+ this.throwIfDisposed();
632
660
  return this._subdirectories.get(subdirName);
633
661
  }
634
662
  /**
635
663
  * {@inheritDoc IDirectory.hasSubDirectory}
636
664
  */
637
665
  hasSubDirectory(subdirName) {
666
+ this.throwIfDisposed();
638
667
  return this._subdirectories.has(subdirName);
639
668
  }
640
669
  /**
641
670
  * {@inheritDoc IDirectory.deleteSubDirectory}
642
671
  */
643
672
  deleteSubDirectory(subdirName) {
673
+ this.throwIfDisposed();
644
674
  // Delete the sub directory locally first.
645
675
  const successfullyRemoved = this.deleteSubDirectoryCore(subdirName, true);
646
676
  // If we are not attached, don't submit the op.
@@ -659,12 +689,14 @@ class SubDirectory extends TypedEventEmitter {
659
689
  * {@inheritDoc IDirectory.subdirectories}
660
690
  */
661
691
  subdirectories() {
692
+ this.throwIfDisposed();
662
693
  return this._subdirectories.entries();
663
694
  }
664
695
  /**
665
696
  * {@inheritDoc IDirectory.getWorkingDirectory}
666
697
  */
667
698
  getWorkingDirectory(relativePath) {
699
+ this.throwIfDisposed();
668
700
  return this.directory.getWorkingDirectory(this.makeAbsolute(relativePath));
669
701
  }
670
702
  /**
@@ -673,6 +705,7 @@ class SubDirectory extends TypedEventEmitter {
673
705
  * @returns True if the key existed and was deleted, false if it did not exist
674
706
  */
675
707
  delete(key) {
708
+ this.throwIfDisposed();
676
709
  // Delete the key locally first.
677
710
  const successfullyRemoved = this.deleteCore(key, true);
678
711
  // If we are not attached, don't submit the op.
@@ -691,6 +724,7 @@ class SubDirectory extends TypedEventEmitter {
691
724
  * Deletes all keys from within this IDirectory.
692
725
  */
693
726
  clear() {
727
+ this.throwIfDisposed();
694
728
  // Clear the data locally first.
695
729
  this.clearCore(true);
696
730
  // If we are not attached, don't submit the op.
@@ -708,6 +742,7 @@ class SubDirectory extends TypedEventEmitter {
708
742
  * @param callback - Callback to issue
709
743
  */
710
744
  forEach(callback) {
745
+ this.throwIfDisposed();
711
746
  this._storage.forEach((localValue, key, map) => {
712
747
  callback(localValue.value, key, map);
713
748
  });
@@ -716,6 +751,7 @@ class SubDirectory extends TypedEventEmitter {
716
751
  * The number of entries under this IDirectory.
717
752
  */
718
753
  get size() {
754
+ this.throwIfDisposed();
719
755
  return this._storage.size;
720
756
  }
721
757
  /**
@@ -723,6 +759,7 @@ class SubDirectory extends TypedEventEmitter {
723
759
  * @returns The iterator
724
760
  */
725
761
  entries() {
762
+ this.throwIfDisposed();
726
763
  const localEntriesIterator = this._storage.entries();
727
764
  const iterator = {
728
765
  next() {
@@ -746,6 +783,7 @@ class SubDirectory extends TypedEventEmitter {
746
783
  * @returns The iterator
747
784
  */
748
785
  keys() {
786
+ this.throwIfDisposed();
749
787
  return this._storage.keys();
750
788
  }
751
789
  /**
@@ -753,6 +791,7 @@ class SubDirectory extends TypedEventEmitter {
753
791
  * @returns The iterator
754
792
  */
755
793
  values() {
794
+ this.throwIfDisposed();
756
795
  const localValuesIterator = this._storage.values();
757
796
  const iterator = {
758
797
  next() {
@@ -776,6 +815,7 @@ class SubDirectory extends TypedEventEmitter {
776
815
  * @returns The iterator
777
816
  */
778
817
  [Symbol.iterator]() {
818
+ this.throwIfDisposed();
779
819
  return this.entries();
780
820
  }
781
821
  /**
@@ -788,6 +828,7 @@ class SubDirectory extends TypedEventEmitter {
788
828
  * @internal
789
829
  */
790
830
  processClearMessage(op, local, localOpMetadata) {
831
+ this.throwIfDisposed();
791
832
  if (local) {
792
833
  assert(localOpMetadata !== undefined, 0x00f /* `pendingMessageId is missing from the local client's ${op.type} operation` */);
793
834
  const pendingMessageId = localOpMetadata;
@@ -809,6 +850,7 @@ class SubDirectory extends TypedEventEmitter {
809
850
  * @internal
810
851
  */
811
852
  processDeleteMessage(op, local, localOpMetadata) {
853
+ this.throwIfDisposed();
812
854
  if (!this.needProcessStorageOperation(op, local, localOpMetadata)) {
813
855
  return;
814
856
  }
@@ -824,6 +866,7 @@ class SubDirectory extends TypedEventEmitter {
824
866
  * @internal
825
867
  */
826
868
  processSetMessage(op, context, local, localOpMetadata) {
869
+ this.throwIfDisposed();
827
870
  if (!this.needProcessStorageOperation(op, local, localOpMetadata)) {
828
871
  return;
829
872
  }
@@ -842,6 +885,7 @@ class SubDirectory extends TypedEventEmitter {
842
885
  * @internal
843
886
  */
844
887
  processCreateSubDirectoryMessage(op, local, localOpMetadata) {
888
+ this.throwIfDisposed();
845
889
  if (!this.needProcessSubDirectoryOperations(op, local, localOpMetadata)) {
846
890
  return;
847
891
  }
@@ -857,6 +901,7 @@ class SubDirectory extends TypedEventEmitter {
857
901
  * @internal
858
902
  */
859
903
  processDeleteSubDirectoryMessage(op, local, localOpMetadata) {
904
+ this.throwIfDisposed();
860
905
  if (!this.needProcessSubDirectoryOperations(op, local, localOpMetadata)) {
861
906
  return;
862
907
  }
@@ -868,6 +913,7 @@ class SubDirectory extends TypedEventEmitter {
868
913
  * @internal
869
914
  */
870
915
  submitClearMessage(op) {
916
+ this.throwIfDisposed();
871
917
  const pendingMessageId = ++this.pendingMessageId;
872
918
  this.directory.submitDirectoryMessage(op, pendingMessageId);
873
919
  this.pendingClearMessageId = pendingMessageId;
@@ -878,6 +924,7 @@ class SubDirectory extends TypedEventEmitter {
878
924
  * @internal
879
925
  */
880
926
  submitKeyMessage(op) {
927
+ this.throwIfDisposed();
881
928
  const pendingMessageId = ++this.pendingMessageId;
882
929
  this.directory.submitDirectoryMessage(op, pendingMessageId);
883
930
  this.pendingKeys.set(op.key, pendingMessageId);
@@ -888,6 +935,7 @@ class SubDirectory extends TypedEventEmitter {
888
935
  * @internal
889
936
  */
890
937
  submitSubDirectoryMessage(op) {
938
+ this.throwIfDisposed();
891
939
  const pendingMessageId = ++this.pendingMessageId;
892
940
  this.directory.submitDirectoryMessage(op, pendingMessageId);
893
941
  this.pendingSubDirectories.set(op.subdirName, pendingMessageId);
@@ -899,6 +947,7 @@ class SubDirectory extends TypedEventEmitter {
899
947
  * @internal
900
948
  */
901
949
  *getSerializedStorage(serializer) {
950
+ this.throwIfDisposed();
902
951
  for (const [key, localValue] of this._storage) {
903
952
  const value = localValue.makeSerialized(serializer, this.directory.handle);
904
953
  const res = [key, value];
@@ -912,6 +961,7 @@ class SubDirectory extends TypedEventEmitter {
912
961
  * @internal
913
962
  */
914
963
  populateStorage(key, localValue) {
964
+ this.throwIfDisposed();
915
965
  this._storage.set(key, localValue);
916
966
  }
917
967
  /**
@@ -921,6 +971,7 @@ class SubDirectory extends TypedEventEmitter {
921
971
  * @internal
922
972
  */
923
973
  populateSubDirectory(subdirName, newSubDir) {
974
+ this.throwIfDisposed();
924
975
  this._subdirectories.set(subdirName, newSubDir);
925
976
  }
926
977
  /**
@@ -931,6 +982,7 @@ class SubDirectory extends TypedEventEmitter {
931
982
  * @internal
932
983
  */
933
984
  getLocalValue(key) {
985
+ this.throwIfDisposed();
934
986
  return this._storage.get(key);
935
987
  }
936
988
  /**
@@ -1074,9 +1126,23 @@ class SubDirectory extends TypedEventEmitter {
1074
1126
  * @param op - The message if from a remote delete, or null if from a local delete
1075
1127
  */
1076
1128
  deleteSubDirectoryCore(subdirName, local) {
1129
+ const previousValue = this.getSubDirectory(subdirName);
1077
1130
  // This should make the subdirectory structure unreachable so it can be GC'd and won't appear in snapshots
1078
1131
  // Might want to consider cleaning out the structure more exhaustively though?
1079
- return this._subdirectories.delete(subdirName);
1132
+ const successfullyRemoved = this._subdirectories.delete(subdirName);
1133
+ this.disposeSubDirectoryTree(previousValue);
1134
+ return successfullyRemoved;
1135
+ }
1136
+ disposeSubDirectoryTree(directory) {
1137
+ if (!directory) {
1138
+ return;
1139
+ }
1140
+ // Dispose the subdirectory tree. This will dispose the subdirectories from bottom to top.
1141
+ const subDirectories = directory.subdirectories();
1142
+ for (const [_, subDirectory] of subDirectories) {
1143
+ this.disposeSubDirectoryTree(subDirectory);
1144
+ }
1145
+ directory.dispose();
1080
1146
  }
1081
1147
  }
1082
1148
  //# sourceMappingURL=directory.js.map