@fluidframework/map 2.117.0 → 3.0.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/CHANGELOG.md +46 -2
- package/README.md +53 -50
- package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
- package/api-report/map.legacy.beta.api.md +9 -9
- package/api-report/map.legacy.public.api.md +4 -2
- package/dist/directory.js +171 -165
- package/dist/directory.js.map +1 -1
- package/dist/directoryFactory.d.ts +1 -1
- package/dist/directoryFactory.d.ts.map +1 -1
- package/dist/directoryFactory.js +15 -15
- package/dist/directoryFactory.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +26 -15
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/legacy.d.ts +0 -1
- package/dist/localValues.d.ts.map +1 -1
- package/dist/map.js +9 -6
- package/dist/map.js.map +1 -1
- package/dist/mapFactory.d.ts +1 -1
- package/dist/mapFactory.d.ts.map +1 -1
- package/dist/mapFactory.js +15 -15
- package/dist/mapFactory.js.map +1 -1
- package/dist/mapKernel.js +109 -104
- package/dist/mapKernel.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/lib/directory.js +171 -165
- package/lib/directory.js.map +1 -1
- package/lib/directoryFactory.js +15 -15
- package/lib/directoryFactory.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interfaces.d.ts +26 -15
- package/lib/interfaces.d.ts.map +1 -1
- package/lib/interfaces.js.map +1 -1
- package/lib/legacy.d.ts +1 -2
- package/lib/localValues.d.ts.map +1 -1
- package/lib/map.js +9 -6
- package/lib/map.js.map +1 -1
- package/lib/mapFactory.js +15 -15
- package/lib/mapFactory.js.map +1 -1
- package/lib/mapKernel.js +109 -104
- package/lib/mapKernel.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/package.json +44 -60
- package/src/index.ts +0 -1
- package/src/interfaces.ts +31 -17
- package/src/packageVersion.ts +1 -1
- package/tsconfig.json +1 -1
- package/internal.d.ts +0 -11
- package/legacy.d.ts +0 -11
- /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
- /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
package/dist/directory.js
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
8
|
};
|
|
9
|
-
var _a, _b;
|
|
10
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
10
|
exports.SharedDirectory = void 0;
|
|
12
11
|
// TODO: Fix prefer-nullish-coalescing and prefer-optional-chain lint violations
|
|
@@ -82,12 +81,24 @@ function isAcknowledgedOrDetached(seqData) {
|
|
|
82
81
|
* @sealed
|
|
83
82
|
*/
|
|
84
83
|
class SharedDirectory extends internal_5.SharedObject {
|
|
84
|
+
/**
|
|
85
|
+
* String representation for the class.
|
|
86
|
+
*/
|
|
87
|
+
[Symbol.toStringTag] = "SharedDirectory";
|
|
85
88
|
/**
|
|
86
89
|
* {@inheritDoc IDirectory.absolutePath}
|
|
87
90
|
*/
|
|
88
91
|
get absolutePath() {
|
|
89
92
|
return this.root.absolutePath;
|
|
90
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Root of the SharedDirectory, most operations on the SharedDirectory itself act on the root.
|
|
96
|
+
*/
|
|
97
|
+
root = new SubDirectory({ seq: 0, clientSeq: 0 }, new Set(), this, this.runtime, this.serializer, posix.sep, (0, internal_6.extractTelemetryLoggerExt)(this.logger));
|
|
98
|
+
/**
|
|
99
|
+
* Mapping of op types to message handlers.
|
|
100
|
+
*/
|
|
101
|
+
messageHandlers = new Map();
|
|
91
102
|
/**
|
|
92
103
|
* Constructs a new shared directory. If the object is non-local an id and service interfaces will
|
|
93
104
|
* be provided.
|
|
@@ -97,18 +108,6 @@ class SharedDirectory extends internal_5.SharedObject {
|
|
|
97
108
|
*/
|
|
98
109
|
constructor(id, runtime, attributes) {
|
|
99
110
|
super(id, runtime, attributes, "fluid_directory_");
|
|
100
|
-
/**
|
|
101
|
-
* String representation for the class.
|
|
102
|
-
*/
|
|
103
|
-
this[_a] = "SharedDirectory";
|
|
104
|
-
/**
|
|
105
|
-
* Root of the SharedDirectory, most operations on the SharedDirectory itself act on the root.
|
|
106
|
-
*/
|
|
107
|
-
this.root = new SubDirectory({ seq: 0, clientSeq: 0 }, new Set(), this, this.runtime, this.serializer, posix.sep, (0, internal_6.extractTelemetryLoggerExt)(this.logger));
|
|
108
|
-
/**
|
|
109
|
-
* Mapping of op types to message handlers.
|
|
110
|
-
*/
|
|
111
|
-
this.messageHandlers = new Map();
|
|
112
111
|
this.setMessageHandlers();
|
|
113
112
|
// Mirror the containedValueChanged op on the SharedDirectory
|
|
114
113
|
this.root.on("containedValueChanged", (changed, local) => {
|
|
@@ -186,7 +185,7 @@ class SharedDirectory extends internal_5.SharedObject {
|
|
|
186
185
|
*/
|
|
187
186
|
// TODO: Use `unknown` instead (breaking change).
|
|
188
187
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
189
|
-
[
|
|
188
|
+
[Symbol.iterator]() {
|
|
190
189
|
return this.root[Symbol.iterator]();
|
|
191
190
|
}
|
|
192
191
|
/**
|
|
@@ -610,6 +609,31 @@ function assertNonNullClientId(clientId) {
|
|
|
610
609
|
* @sealed
|
|
611
610
|
*/
|
|
612
611
|
class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
612
|
+
seqData;
|
|
613
|
+
clientIds;
|
|
614
|
+
directory;
|
|
615
|
+
runtime;
|
|
616
|
+
serializer;
|
|
617
|
+
absolutePath;
|
|
618
|
+
/**
|
|
619
|
+
* Tells if the sub directory is deleted or not.
|
|
620
|
+
*/
|
|
621
|
+
_deleted = false;
|
|
622
|
+
/**
|
|
623
|
+
* String representation for the class.
|
|
624
|
+
*/
|
|
625
|
+
[Symbol.toStringTag] = "SubDirectory";
|
|
626
|
+
/**
|
|
627
|
+
* The sequenced subdirectories the directory is holding independent of any pending
|
|
628
|
+
* create/delete subdirectory operations.
|
|
629
|
+
*/
|
|
630
|
+
_sequencedSubdirectories = new Map();
|
|
631
|
+
/**
|
|
632
|
+
* Assigns a unique ID to each subdirectory created locally but pending for acknowledgement, facilitating the tracking
|
|
633
|
+
* of the creation order.
|
|
634
|
+
*/
|
|
635
|
+
localCreationSeq = 0;
|
|
636
|
+
mc;
|
|
613
637
|
/**
|
|
614
638
|
* Constructor.
|
|
615
639
|
* @param sequenceNumber - Message seq number at which this was created.
|
|
@@ -627,156 +651,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
627
651
|
this.runtime = runtime;
|
|
628
652
|
this.serializer = serializer;
|
|
629
653
|
this.absolutePath = absolutePath;
|
|
630
|
-
/**
|
|
631
|
-
* Tells if the sub directory is deleted or not.
|
|
632
|
-
*/
|
|
633
|
-
this._deleted = false;
|
|
634
|
-
/**
|
|
635
|
-
* String representation for the class.
|
|
636
|
-
*/
|
|
637
|
-
this[_b] = "SubDirectory";
|
|
638
|
-
/**
|
|
639
|
-
* The sequenced subdirectories the directory is holding independent of any pending
|
|
640
|
-
* create/delete subdirectory operations.
|
|
641
|
-
*/
|
|
642
|
-
this._sequencedSubdirectories = new Map();
|
|
643
|
-
/**
|
|
644
|
-
* Assigns a unique ID to each subdirectory created locally but pending for acknowledgement, facilitating the tracking
|
|
645
|
-
* of the creation order.
|
|
646
|
-
*/
|
|
647
|
-
this.localCreationSeq = 0;
|
|
648
|
-
/**
|
|
649
|
-
* The data this SubDirectory instance is storing, but only including sequenced values (no local pending
|
|
650
|
-
* modifications are included).
|
|
651
|
-
*/
|
|
652
|
-
this.sequencedStorageData = new Map();
|
|
653
|
-
/**
|
|
654
|
-
* A data structure containing all local pending storage modifications, which is used in combination
|
|
655
|
-
* with the sequencedStorageData to compute optimistic values.
|
|
656
|
-
*
|
|
657
|
-
* Pending sets are aggregated into "lifetimes", which permit correct relative iteration order
|
|
658
|
-
* even across remote operations and rollbacks.
|
|
659
|
-
*/
|
|
660
|
-
this.pendingStorageData = [];
|
|
661
|
-
/**
|
|
662
|
-
* A data structure containing all local pending subdirectory create/deletes, which is used in combination
|
|
663
|
-
* with the _sequencedSubdirectories to compute optimistic values.
|
|
664
|
-
*/
|
|
665
|
-
this.pendingSubDirectoryData = [];
|
|
666
|
-
/**
|
|
667
|
-
* An internal iterator that iterates over the entries in the directory.
|
|
668
|
-
*/
|
|
669
|
-
this.internalIterator = () => {
|
|
670
|
-
// We perform iteration in two steps - first by iterating over members of the sequenced storage data that are not
|
|
671
|
-
// optimistically deleted or cleared, and then over the pending data lifetimes that have not subsequently
|
|
672
|
-
// been deleted or cleared. In total, this give an ordering of members based on when they were initially
|
|
673
|
-
// added to the sub directory (even if they were later modified), similar to the native Map.
|
|
674
|
-
const sequencedStorageDataIterator = this.sequencedStorageData.keys();
|
|
675
|
-
const pendingStorageDataIterator = this.pendingStorageData.values();
|
|
676
|
-
const next = () => {
|
|
677
|
-
let nextSequencedKey = sequencedStorageDataIterator.next();
|
|
678
|
-
while (!nextSequencedKey.done) {
|
|
679
|
-
const key = nextSequencedKey.value;
|
|
680
|
-
// If we have any pending deletes or clears, then we won't iterate to this key yet (if at all).
|
|
681
|
-
// Either it is optimistically deleted and will not be part of the iteration, or it was
|
|
682
|
-
// re-added later and we'll iterate to it when we get to the pending data.
|
|
683
|
-
if (!this.pendingStorageData.some((entry) => entry.type === "clear" || (entry.type === "delete" && entry.key === key))) {
|
|
684
|
-
(0, internal_1.assert)(this.has(key), 0xc03 /* key should exist in sequenced or pending data */);
|
|
685
|
-
const optimisticValue = this.getOptimisticValue(key);
|
|
686
|
-
return { value: [key, optimisticValue], done: false };
|
|
687
|
-
}
|
|
688
|
-
nextSequencedKey = sequencedStorageDataIterator.next();
|
|
689
|
-
}
|
|
690
|
-
let nextPending = pendingStorageDataIterator.next();
|
|
691
|
-
while (!nextPending.done) {
|
|
692
|
-
const nextPendingEntry = nextPending.value;
|
|
693
|
-
// A lifetime entry may need to be iterated.
|
|
694
|
-
if (nextPendingEntry.type === "lifetime") {
|
|
695
|
-
const nextPendingEntryIndex = this.pendingStorageData.indexOf(nextPendingEntry);
|
|
696
|
-
const mostRecentDeleteOrClearIndex = (0, utils_js_1.findLastIndex)(this.pendingStorageData, (entry) => entry.type === "clear" ||
|
|
697
|
-
(entry.type === "delete" && entry.key === nextPendingEntry.key));
|
|
698
|
-
// Only iterate the pending entry now if it hasn't been deleted or cleared.
|
|
699
|
-
if (nextPendingEntryIndex > mostRecentDeleteOrClearIndex) {
|
|
700
|
-
const latestPendingValue =
|
|
701
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
702
|
-
nextPendingEntry.keySets[nextPendingEntry.keySets.length - 1];
|
|
703
|
-
// Skip iterating if we would have would have already iterated it as part of the sequenced data.
|
|
704
|
-
// This is not a perfect check in the case the map has changed since the iterator was created
|
|
705
|
-
// (e.g. if a remote client added the same key in the meantime).
|
|
706
|
-
if (!this.sequencedStorageData.has(nextPendingEntry.key) ||
|
|
707
|
-
mostRecentDeleteOrClearIndex !== -1) {
|
|
708
|
-
return { value: [nextPendingEntry.key, latestPendingValue.value], done: false };
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
nextPending = pendingStorageDataIterator.next();
|
|
713
|
-
}
|
|
714
|
-
return { value: undefined, done: true };
|
|
715
|
-
};
|
|
716
|
-
const iterator = {
|
|
717
|
-
next,
|
|
718
|
-
[Symbol.iterator]() {
|
|
719
|
-
return this;
|
|
720
|
-
},
|
|
721
|
-
};
|
|
722
|
-
return iterator;
|
|
723
|
-
};
|
|
724
|
-
/**
|
|
725
|
-
* Compute the optimistic local value for a given key. This combines the sequenced data with
|
|
726
|
-
* any pending changes that have not yet been sequenced.
|
|
727
|
-
*/
|
|
728
|
-
this.getOptimisticValue = (key) => {
|
|
729
|
-
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingStorageData, (entry) => entry.type === "clear" || entry.key === key);
|
|
730
|
-
if (latestPendingEntry === undefined) {
|
|
731
|
-
return this.sequencedStorageData.get(key);
|
|
732
|
-
}
|
|
733
|
-
else if (latestPendingEntry.type === "lifetime") {
|
|
734
|
-
const latestPendingSet =
|
|
735
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
736
|
-
latestPendingEntry.keySets[latestPendingEntry.keySets.length - 1];
|
|
737
|
-
return latestPendingSet.value;
|
|
738
|
-
}
|
|
739
|
-
else {
|
|
740
|
-
// Delete or clear
|
|
741
|
-
return undefined;
|
|
742
|
-
}
|
|
743
|
-
};
|
|
744
|
-
/**
|
|
745
|
-
* Determine if the directory optimistically has the key.
|
|
746
|
-
* This will return true even if the value is undefined.
|
|
747
|
-
*/
|
|
748
|
-
this.optimisticallyHas = (key) => {
|
|
749
|
-
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingStorageData, (entry) => entry.type === "clear" || entry.key === key);
|
|
750
|
-
return latestPendingEntry === undefined
|
|
751
|
-
? this.sequencedStorageData.has(key)
|
|
752
|
-
: latestPendingEntry.type === "lifetime";
|
|
753
|
-
};
|
|
754
|
-
/**
|
|
755
|
-
* Get the optimistic local subdirectory. This combines the sequenced data with
|
|
756
|
-
* any pending changes that have not yet been sequenced. By default, we do not
|
|
757
|
-
* consider disposed directories as optimistically existing, but if `getIfDisposed`
|
|
758
|
-
* is true, we will include them since some scenarios require this.
|
|
759
|
-
*/
|
|
760
|
-
this.getOptimisticSubDirectory = (subdirName, getIfDisposed = false) => {
|
|
761
|
-
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingSubDirectoryData, (entry) => entry.subdirName === subdirName);
|
|
762
|
-
let subdir;
|
|
763
|
-
if (latestPendingEntry === undefined) {
|
|
764
|
-
subdir = this._sequencedSubdirectories.get(subdirName);
|
|
765
|
-
}
|
|
766
|
-
else if (latestPendingEntry.type === "createSubDirectory") {
|
|
767
|
-
subdir = latestPendingEntry.subdir;
|
|
768
|
-
(0, internal_1.assert)(subdir !== undefined, 0xc2f /* Subdirectory should exist in pending data */);
|
|
769
|
-
}
|
|
770
|
-
else {
|
|
771
|
-
// Pending delete
|
|
772
|
-
return undefined;
|
|
773
|
-
}
|
|
774
|
-
// If the subdirectory is disposed, treat it as non-existent for optimistic reads (unless specified otherwise)
|
|
775
|
-
if (subdir?.disposed && !getIfDisposed) {
|
|
776
|
-
return undefined;
|
|
777
|
-
}
|
|
778
|
-
return subdir;
|
|
779
|
-
};
|
|
780
654
|
this.mc = (0, internal_6.createChildMonitoringContext)({ logger, namespace: "Directory" });
|
|
781
655
|
}
|
|
782
656
|
dispose(error) {
|
|
@@ -1242,10 +1116,142 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1242
1116
|
* Get an iterator over the entries under this IDirectory.
|
|
1243
1117
|
* @returns The iterator
|
|
1244
1118
|
*/
|
|
1245
|
-
[
|
|
1119
|
+
[Symbol.iterator]() {
|
|
1246
1120
|
this.throwIfDisposed();
|
|
1247
1121
|
return this.internalIterator();
|
|
1248
1122
|
}
|
|
1123
|
+
/**
|
|
1124
|
+
* The data this SubDirectory instance is storing, but only including sequenced values (no local pending
|
|
1125
|
+
* modifications are included).
|
|
1126
|
+
*/
|
|
1127
|
+
sequencedStorageData = new Map();
|
|
1128
|
+
/**
|
|
1129
|
+
* A data structure containing all local pending storage modifications, which is used in combination
|
|
1130
|
+
* with the sequencedStorageData to compute optimistic values.
|
|
1131
|
+
*
|
|
1132
|
+
* Pending sets are aggregated into "lifetimes", which permit correct relative iteration order
|
|
1133
|
+
* even across remote operations and rollbacks.
|
|
1134
|
+
*/
|
|
1135
|
+
pendingStorageData = [];
|
|
1136
|
+
/**
|
|
1137
|
+
* A data structure containing all local pending subdirectory create/deletes, which is used in combination
|
|
1138
|
+
* with the _sequencedSubdirectories to compute optimistic values.
|
|
1139
|
+
*/
|
|
1140
|
+
pendingSubDirectoryData = [];
|
|
1141
|
+
/**
|
|
1142
|
+
* An internal iterator that iterates over the entries in the directory.
|
|
1143
|
+
*/
|
|
1144
|
+
internalIterator = () => {
|
|
1145
|
+
// We perform iteration in two steps - first by iterating over members of the sequenced storage data that are not
|
|
1146
|
+
// optimistically deleted or cleared, and then over the pending data lifetimes that have not subsequently
|
|
1147
|
+
// been deleted or cleared. In total, this give an ordering of members based on when they were initially
|
|
1148
|
+
// added to the sub directory (even if they were later modified), similar to the native Map.
|
|
1149
|
+
const sequencedStorageDataIterator = this.sequencedStorageData.keys();
|
|
1150
|
+
const pendingStorageDataIterator = this.pendingStorageData.values();
|
|
1151
|
+
const next = () => {
|
|
1152
|
+
let nextSequencedKey = sequencedStorageDataIterator.next();
|
|
1153
|
+
while (!nextSequencedKey.done) {
|
|
1154
|
+
const key = nextSequencedKey.value;
|
|
1155
|
+
// If we have any pending deletes or clears, then we won't iterate to this key yet (if at all).
|
|
1156
|
+
// Either it is optimistically deleted and will not be part of the iteration, or it was
|
|
1157
|
+
// re-added later and we'll iterate to it when we get to the pending data.
|
|
1158
|
+
if (!this.pendingStorageData.some((entry) => entry.type === "clear" || (entry.type === "delete" && entry.key === key))) {
|
|
1159
|
+
(0, internal_1.assert)(this.has(key), 0xc03 /* key should exist in sequenced or pending data */);
|
|
1160
|
+
const optimisticValue = this.getOptimisticValue(key);
|
|
1161
|
+
return { value: [key, optimisticValue], done: false };
|
|
1162
|
+
}
|
|
1163
|
+
nextSequencedKey = sequencedStorageDataIterator.next();
|
|
1164
|
+
}
|
|
1165
|
+
let nextPending = pendingStorageDataIterator.next();
|
|
1166
|
+
while (!nextPending.done) {
|
|
1167
|
+
const nextPendingEntry = nextPending.value;
|
|
1168
|
+
// A lifetime entry may need to be iterated.
|
|
1169
|
+
if (nextPendingEntry.type === "lifetime") {
|
|
1170
|
+
const nextPendingEntryIndex = this.pendingStorageData.indexOf(nextPendingEntry);
|
|
1171
|
+
const mostRecentDeleteOrClearIndex = (0, utils_js_1.findLastIndex)(this.pendingStorageData, (entry) => entry.type === "clear" ||
|
|
1172
|
+
(entry.type === "delete" && entry.key === nextPendingEntry.key));
|
|
1173
|
+
// Only iterate the pending entry now if it hasn't been deleted or cleared.
|
|
1174
|
+
if (nextPendingEntryIndex > mostRecentDeleteOrClearIndex) {
|
|
1175
|
+
const latestPendingValue =
|
|
1176
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1177
|
+
nextPendingEntry.keySets[nextPendingEntry.keySets.length - 1];
|
|
1178
|
+
// Skip iterating if we would have would have already iterated it as part of the sequenced data.
|
|
1179
|
+
// This is not a perfect check in the case the map has changed since the iterator was created
|
|
1180
|
+
// (e.g. if a remote client added the same key in the meantime).
|
|
1181
|
+
if (!this.sequencedStorageData.has(nextPendingEntry.key) ||
|
|
1182
|
+
mostRecentDeleteOrClearIndex !== -1) {
|
|
1183
|
+
return { value: [nextPendingEntry.key, latestPendingValue.value], done: false };
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
nextPending = pendingStorageDataIterator.next();
|
|
1188
|
+
}
|
|
1189
|
+
return { value: undefined, done: true };
|
|
1190
|
+
};
|
|
1191
|
+
const iterator = {
|
|
1192
|
+
next,
|
|
1193
|
+
[Symbol.iterator]() {
|
|
1194
|
+
return this;
|
|
1195
|
+
},
|
|
1196
|
+
};
|
|
1197
|
+
return iterator;
|
|
1198
|
+
};
|
|
1199
|
+
/**
|
|
1200
|
+
* Compute the optimistic local value for a given key. This combines the sequenced data with
|
|
1201
|
+
* any pending changes that have not yet been sequenced.
|
|
1202
|
+
*/
|
|
1203
|
+
getOptimisticValue = (key) => {
|
|
1204
|
+
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingStorageData, (entry) => entry.type === "clear" || entry.key === key);
|
|
1205
|
+
if (latestPendingEntry === undefined) {
|
|
1206
|
+
return this.sequencedStorageData.get(key);
|
|
1207
|
+
}
|
|
1208
|
+
else if (latestPendingEntry.type === "lifetime") {
|
|
1209
|
+
const latestPendingSet =
|
|
1210
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1211
|
+
latestPendingEntry.keySets[latestPendingEntry.keySets.length - 1];
|
|
1212
|
+
return latestPendingSet.value;
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
// Delete or clear
|
|
1216
|
+
return undefined;
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
/**
|
|
1220
|
+
* Determine if the directory optimistically has the key.
|
|
1221
|
+
* This will return true even if the value is undefined.
|
|
1222
|
+
*/
|
|
1223
|
+
optimisticallyHas = (key) => {
|
|
1224
|
+
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingStorageData, (entry) => entry.type === "clear" || entry.key === key);
|
|
1225
|
+
return latestPendingEntry === undefined
|
|
1226
|
+
? this.sequencedStorageData.has(key)
|
|
1227
|
+
: latestPendingEntry.type === "lifetime";
|
|
1228
|
+
};
|
|
1229
|
+
/**
|
|
1230
|
+
* Get the optimistic local subdirectory. This combines the sequenced data with
|
|
1231
|
+
* any pending changes that have not yet been sequenced. By default, we do not
|
|
1232
|
+
* consider disposed directories as optimistically existing, but if `getIfDisposed`
|
|
1233
|
+
* is true, we will include them since some scenarios require this.
|
|
1234
|
+
*/
|
|
1235
|
+
getOptimisticSubDirectory = (subdirName, getIfDisposed = false) => {
|
|
1236
|
+
const latestPendingEntry = (0, utils_js_1.findLast)(this.pendingSubDirectoryData, (entry) => entry.subdirName === subdirName);
|
|
1237
|
+
let subdir;
|
|
1238
|
+
if (latestPendingEntry === undefined) {
|
|
1239
|
+
subdir = this._sequencedSubdirectories.get(subdirName);
|
|
1240
|
+
}
|
|
1241
|
+
else if (latestPendingEntry.type === "createSubDirectory") {
|
|
1242
|
+
subdir = latestPendingEntry.subdir;
|
|
1243
|
+
(0, internal_1.assert)(subdir !== undefined, 0xc2f /* Subdirectory should exist in pending data */);
|
|
1244
|
+
}
|
|
1245
|
+
else {
|
|
1246
|
+
// Pending delete
|
|
1247
|
+
return undefined;
|
|
1248
|
+
}
|
|
1249
|
+
// If the subdirectory is disposed, treat it as non-existent for optimistic reads (unless specified otherwise)
|
|
1250
|
+
if (subdir?.disposed && !getIfDisposed) {
|
|
1251
|
+
return undefined;
|
|
1252
|
+
}
|
|
1253
|
+
return subdir;
|
|
1254
|
+
};
|
|
1249
1255
|
/**
|
|
1250
1256
|
* Checks if this directory should be considered visible in the optimistic view.
|
|
1251
1257
|
* This requires both:
|