@fluidframework/map 2.0.0-rc.1.0.6 → 2.0.0-rc.2.0.1
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/{.eslintrc.js → .eslintrc.cjs} +10 -1
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +11 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/map.api.md +14 -57
- package/dist/directory.d.ts +10 -50
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +76 -164
- package/dist/directory.js.map +1 -1
- package/dist/index.d.ts +45 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -8
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/internalInterfaces.d.ts +2 -2
- package/dist/internalInterfaces.d.ts.map +1 -1
- package/dist/internalInterfaces.js.map +1 -1
- package/dist/localValues.d.ts +3 -5
- package/dist/localValues.d.ts.map +1 -1
- package/dist/localValues.js +9 -8
- package/dist/localValues.js.map +1 -1
- package/dist/map-alpha.d.ts +31 -116
- package/dist/map-beta.d.ts +24 -105
- package/dist/map-public.d.ts +24 -105
- package/dist/map-untrimmed.d.ts +31 -116
- package/dist/map.d.ts +4 -23
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +6 -29
- package/dist/map.js.map +1 -1
- package/dist/mapKernel.d.ts +3 -4
- package/dist/mapKernel.d.ts.map +1 -1
- package/dist/mapKernel.js +30 -35
- package/dist/mapKernel.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/{directory.d.mts → directory.d.ts} +11 -51
- package/lib/directory.d.ts.map +1 -0
- package/lib/{directory.mjs → directory.js} +77 -165
- package/lib/directory.js.map +1 -0
- package/lib/index.d.ts +61 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +55 -0
- package/lib/index.js.map +1 -0
- package/lib/{interfaces.d.mts → interfaces.d.ts} +1 -1
- package/lib/interfaces.d.ts.map +1 -0
- package/lib/{interfaces.mjs → interfaces.js} +1 -1
- package/lib/interfaces.js.map +1 -0
- package/lib/{internalInterfaces.d.mts → internalInterfaces.d.ts} +3 -3
- package/lib/internalInterfaces.d.ts.map +1 -0
- package/lib/{internalInterfaces.mjs → internalInterfaces.js} +1 -1
- package/lib/internalInterfaces.js.map +1 -0
- package/lib/{localValues.d.mts → localValues.d.ts} +4 -6
- package/lib/localValues.d.ts.map +1 -0
- package/lib/{localValues.mjs → localValues.js} +10 -9
- package/lib/localValues.js.map +1 -0
- package/lib/{map-alpha.d.mts → map-alpha.d.ts} +43 -116
- package/lib/{map-beta.d.mts → map-beta.d.ts} +36 -105
- package/lib/{map-public.d.mts → map-public.d.ts} +36 -105
- package/lib/{map-untrimmed.d.mts → map-untrimmed.d.ts} +43 -116
- package/lib/{map.d.mts → map.d.ts} +5 -24
- package/lib/map.d.ts.map +1 -0
- package/lib/{map.mjs → map.js} +5 -28
- package/lib/map.js.map +1 -0
- package/lib/{mapKernel.d.mts → mapKernel.d.ts} +4 -5
- package/lib/mapKernel.d.ts.map +1 -0
- package/lib/{mapKernel.mjs → mapKernel.js} +32 -37
- package/lib/mapKernel.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/test/memory/directory.spec.js +71 -0
- package/lib/test/memory/directory.spec.js.map +1 -0
- package/lib/test/memory/map.spec.js +71 -0
- package/lib/test/memory/map.spec.js.map +1 -0
- package/lib/test/mocha/directory.order.spec.js +422 -0
- package/lib/test/mocha/directory.order.spec.js.map +1 -0
- package/lib/test/mocha/directory.snapshot.spec.js +111 -0
- package/lib/test/mocha/directory.snapshot.spec.js.map +1 -0
- package/lib/test/mocha/directory.spec.js +1406 -0
- package/lib/test/mocha/directory.spec.js.map +1 -0
- package/lib/test/mocha/directoryEquivalenceUtils.js +36 -0
- package/lib/test/mocha/directoryEquivalenceUtils.js.map +1 -0
- package/lib/test/mocha/directoryFuzzTests.spec.js +337 -0
- package/lib/test/mocha/directoryFuzzTests.spec.js.map +1 -0
- package/lib/test/mocha/dirname.cjs +16 -0
- package/lib/test/mocha/dirname.cjs.map +1 -0
- package/lib/test/mocha/map.fuzz.spec.js +114 -0
- package/lib/test/mocha/map.fuzz.spec.js.map +1 -0
- package/lib/test/mocha/map.spec.js +685 -0
- package/lib/test/mocha/map.spec.js.map +1 -0
- package/lib/test/mocha/rebasing.spec.js +158 -0
- package/lib/test/mocha/rebasing.spec.js.map +1 -0
- package/lib/test/mocha/reconnection.spec.js +327 -0
- package/lib/test/mocha/reconnection.spec.js.map +1 -0
- package/lib/test/types/validateMapPrevious.generated.js +66 -0
- package/lib/test/types/validateMapPrevious.generated.js.map +1 -0
- package/package.json +55 -52
- package/src/directory.ts +122 -217
- package/src/index.ts +57 -4
- package/src/interfaces.ts +2 -2
- package/src/internalInterfaces.ts +2 -2
- package/src/localValues.ts +14 -9
- package/src/map.ts +7 -32
- package/src/mapKernel.ts +40 -42
- package/src/packageVersion.ts +1 -1
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/lib/directory.d.mts.map +0 -1
- package/lib/directory.mjs.map +0 -1
- package/lib/index.d.mts +0 -9
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -8
- package/lib/index.mjs.map +0 -1
- package/lib/interfaces.d.mts.map +0 -1
- package/lib/interfaces.mjs.map +0 -1
- package/lib/internalInterfaces.d.mts.map +0 -1
- package/lib/internalInterfaces.mjs.map +0 -1
- package/lib/localValues.d.mts.map +0 -1
- package/lib/localValues.mjs.map +0 -1
- package/lib/map.d.mts.map +0 -1
- package/lib/map.mjs.map +0 -1
- package/lib/mapKernel.d.mts.map +0 -1
- package/lib/mapKernel.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
package/dist/directory.js
CHANGED
|
@@ -18,8 +18,8 @@ const shared_object_base_1 = require("@fluidframework/shared-object-base");
|
|
|
18
18
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
19
19
|
const path_browserify_1 = __importDefault(require("path-browserify"));
|
|
20
20
|
const merge_tree_1 = require("@fluidframework/merge-tree");
|
|
21
|
-
const
|
|
22
|
-
const
|
|
21
|
+
const localValues_js_1 = require("./localValues.js");
|
|
22
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
23
23
|
// We use path-browserify since this code can run safely on the server or the browser.
|
|
24
24
|
// We standardize on using posix slashes everywhere.
|
|
25
25
|
const posix = path_browserify_1.default.posix;
|
|
@@ -71,7 +71,7 @@ DirectoryFactory.Type = "https://graph.microsoft.com/types/directory";
|
|
|
71
71
|
DirectoryFactory.Attributes = {
|
|
72
72
|
type: DirectoryFactory.Type,
|
|
73
73
|
snapshotFormatVersion: "0.1",
|
|
74
|
-
packageVersion:
|
|
74
|
+
packageVersion: packageVersion_js_1.pkgVersion,
|
|
75
75
|
};
|
|
76
76
|
/**
|
|
77
77
|
* The comparator essentially performs the following procedure to determine the order of subdirectory creation:
|
|
@@ -97,19 +97,19 @@ const seqDataComparator = (a, b) => {
|
|
|
97
97
|
if (isAcknowledgedOrDetached(a)) {
|
|
98
98
|
if (isAcknowledgedOrDetached(b)) {
|
|
99
99
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
100
|
-
return a.seq
|
|
100
|
+
return a.seq === b.seq ? a.clientSeq - b.clientSeq : a.seq - b.seq;
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
103
|
return -1;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
else {
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
return a.seq !== b.seq ? a.seq - b.seq : a.clientSeq - b.clientSeq;
|
|
107
|
+
if (isAcknowledgedOrDetached(b)) {
|
|
108
|
+
return 1;
|
|
110
109
|
}
|
|
111
110
|
else {
|
|
112
|
-
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
112
|
+
return a.seq === b.seq ? a.clientSeq - b.clientSeq : a.seq - b.seq;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
};
|
|
@@ -230,7 +230,7 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
230
230
|
* Mapping of op types to message handlers.
|
|
231
231
|
*/
|
|
232
232
|
this.messageHandlers = new Map();
|
|
233
|
-
this.localValueMaker = new
|
|
233
|
+
this.localValueMaker = new localValues_js_1.LocalValueMaker();
|
|
234
234
|
this.setMessageHandlers();
|
|
235
235
|
// Mirror the containedValueChanged op on the SharedDirectory
|
|
236
236
|
this.root.on("containedValueChanged", (changed, local) => {
|
|
@@ -480,9 +480,9 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
480
480
|
clientSeq: ++currentSubDir.localCreationSeq,
|
|
481
481
|
};
|
|
482
482
|
}
|
|
483
|
-
newSubDir = new SubDirectory(seqData, createInfo
|
|
484
|
-
? new Set(
|
|
485
|
-
: new Set(), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName), this.logger);
|
|
483
|
+
newSubDir = new SubDirectory(seqData, createInfo === undefined
|
|
484
|
+
? new Set()
|
|
485
|
+
: new Set(createInfo.ccIds), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName), this.logger);
|
|
486
486
|
currentSubDir.populateSubDirectory(subdirName, newSubDir);
|
|
487
487
|
// Record the newly inserted subdirectory to the creation tracker
|
|
488
488
|
currentSubDir.ackedCreationSeqTracker.set(subdirName, {
|
|
@@ -494,7 +494,9 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
494
494
|
}
|
|
495
495
|
if (currentSubDirObject.storage) {
|
|
496
496
|
for (const [key, serializable] of Object.entries(currentSubDirObject.storage)) {
|
|
497
|
-
const localValue = this.makeLocal(key, currentSubDir.absolutePath,
|
|
497
|
+
const localValue = this.makeLocal(key, currentSubDir.absolutePath,
|
|
498
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
499
|
+
(0, shared_object_base_1.parseHandles)(serializable, this.serializer));
|
|
498
500
|
currentSubDir.populateStorage(key, localValue);
|
|
499
501
|
}
|
|
500
502
|
}
|
|
@@ -543,7 +545,7 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
543
545
|
serializable) {
|
|
544
546
|
(0, core_utils_1.assert)(serializable.type === shared_object_base_1.ValueType[shared_object_base_1.ValueType.Plain] ||
|
|
545
547
|
serializable.type === shared_object_base_1.ValueType[shared_object_base_1.ValueType.Shared], 0x1e4 /* "Unexpected serializable type" */);
|
|
546
|
-
return this.localValueMaker.fromSerializable(serializable);
|
|
548
|
+
return this.localValueMaker.fromSerializable(serializable, this.serializer, this.handle);
|
|
547
549
|
}
|
|
548
550
|
/**
|
|
549
551
|
* This checks if there is pending delete op for local delete for a any subdir in the relative path.
|
|
@@ -590,12 +592,6 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
590
592
|
subdir.resubmitClearMessage(op, localOpMetadata);
|
|
591
593
|
}
|
|
592
594
|
},
|
|
593
|
-
applyStashedOp: (op) => {
|
|
594
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
595
|
-
if (subdir) {
|
|
596
|
-
return subdir.applyStashedClearMessage(op);
|
|
597
|
-
}
|
|
598
|
-
},
|
|
599
595
|
});
|
|
600
596
|
this.messageHandlers.set("delete", {
|
|
601
597
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -612,12 +608,6 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
612
608
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
613
609
|
}
|
|
614
610
|
},
|
|
615
|
-
applyStashedOp: (op) => {
|
|
616
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
617
|
-
if (subdir) {
|
|
618
|
-
return subdir.applyStashedDeleteMessage(op);
|
|
619
|
-
}
|
|
620
|
-
},
|
|
621
611
|
});
|
|
622
612
|
this.messageHandlers.set("set", {
|
|
623
613
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -635,13 +625,6 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
635
625
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
636
626
|
}
|
|
637
627
|
},
|
|
638
|
-
applyStashedOp: (op) => {
|
|
639
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
640
|
-
if (subdir) {
|
|
641
|
-
const context = this.makeLocal(op.key, op.path, op.value);
|
|
642
|
-
return subdir.applyStashedSetMessage(op, context);
|
|
643
|
-
}
|
|
644
|
-
},
|
|
645
628
|
});
|
|
646
629
|
this.messageHandlers.set("createSubDirectory", {
|
|
647
630
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -659,12 +642,6 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
659
642
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
660
643
|
}
|
|
661
644
|
},
|
|
662
|
-
applyStashedOp: (op) => {
|
|
663
|
-
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
664
|
-
if (parentSubdir) {
|
|
665
|
-
return parentSubdir.applyStashedCreateSubDirMessage(op);
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
645
|
});
|
|
669
646
|
this.messageHandlers.set("deleteSubDirectory", {
|
|
670
647
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -682,23 +659,39 @@ class SharedDirectory extends shared_object_base_1.SharedObject {
|
|
|
682
659
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
683
660
|
}
|
|
684
661
|
},
|
|
685
|
-
applyStashedOp: (op) => {
|
|
686
|
-
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
687
|
-
if (parentSubdir) {
|
|
688
|
-
return parentSubdir.applyStashedDeleteSubDirMessage(op);
|
|
689
|
-
}
|
|
690
|
-
},
|
|
691
662
|
});
|
|
692
663
|
}
|
|
693
664
|
/**
|
|
694
665
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
695
666
|
*/
|
|
696
667
|
applyStashedOp(op) {
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
668
|
+
const directoryOp = op;
|
|
669
|
+
const dir = this.getWorkingDirectory(directoryOp.path);
|
|
670
|
+
switch (directoryOp.type) {
|
|
671
|
+
case "clear": {
|
|
672
|
+
dir?.clear();
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
case "createSubDirectory": {
|
|
676
|
+
dir?.createSubDirectory(directoryOp.subdirName);
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
case "delete": {
|
|
680
|
+
dir?.delete(directoryOp.key);
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
case "deleteSubDirectory": {
|
|
684
|
+
dir?.deleteSubDirectory(directoryOp.subdirName);
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
case "set": {
|
|
688
|
+
dir?.set(directoryOp.key, this.localValueMaker.fromSerializable(directoryOp.value, this.serializer, this.handle).value);
|
|
689
|
+
break;
|
|
690
|
+
}
|
|
691
|
+
default: {
|
|
692
|
+
(0, core_utils_1.unreachableCase)(directoryOp);
|
|
693
|
+
}
|
|
700
694
|
}
|
|
701
|
-
return handler.applyStashedOp(op);
|
|
702
695
|
}
|
|
703
696
|
serializeDirectory(root, serializer, telemetryContext) {
|
|
704
697
|
const MinValueSizeSeparateSnapshotBlob = 8 * 1024;
|
|
@@ -781,6 +774,7 @@ function isDirectoryLocalOpMetadata(metadata) {
|
|
|
781
774
|
isSubDirLocalOpMetadata(metadata));
|
|
782
775
|
}
|
|
783
776
|
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
777
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
784
778
|
function assertNonNullClientId(clientId) {
|
|
785
779
|
(0, core_utils_1.assert)(clientId !== null, 0x6af /* client id should never be null */);
|
|
786
780
|
}
|
|
@@ -905,7 +899,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
905
899
|
}
|
|
906
900
|
// Create a local value and serialize it.
|
|
907
901
|
const localValue = this.directory.localValueMaker.fromInMemory(value);
|
|
908
|
-
const serializableValue = (0,
|
|
902
|
+
const serializableValue = (0, localValues_js_1.makeSerializable)(localValue, this.serializer, this.directory.handle);
|
|
909
903
|
// Set the value locally.
|
|
910
904
|
const previousValue = this.setCore(key, localValue, true);
|
|
911
905
|
// If we are not attached, don't submit the op.
|
|
@@ -959,13 +953,15 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
959
953
|
return subDir;
|
|
960
954
|
}
|
|
961
955
|
/**
|
|
962
|
-
*
|
|
956
|
+
* Gets the Sequence Data which should be used for local changes.
|
|
957
|
+
*
|
|
963
958
|
* @remarks While detached, 0 is used rather than -1 to represent a change which should be universally known (as opposed to known
|
|
964
959
|
* only by the local client). This ensures that if the directory is later attached, none of its data needs to be updated (the values
|
|
965
960
|
* last set while detached will now be known to any new client, until they are changed).
|
|
966
961
|
*
|
|
967
962
|
* The client sequence number is incremented by 1 for maintaining the internal order of locally created subdirectories
|
|
968
|
-
*
|
|
963
|
+
*
|
|
964
|
+
* @privateRemarks TODO: Convert these conventions to named constants. The semantics used here match those for merge-tree.
|
|
969
965
|
*/
|
|
970
966
|
getLocalSeq() {
|
|
971
967
|
return this.directory.isAttached()
|
|
@@ -1040,6 +1036,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1040
1036
|
if (this.index < subdirNames.length) {
|
|
1041
1037
|
const subdirName = subdirNames[this.index++];
|
|
1042
1038
|
const subdir = this.dirs.get(subdirName);
|
|
1039
|
+
(0, core_utils_1.assert)(subdir !== undefined, 0x8ac /* Could not find expected sub-directory. */);
|
|
1043
1040
|
return { value: [subdirName, subdir], done: false };
|
|
1044
1041
|
}
|
|
1045
1042
|
return { value: undefined, done: true };
|
|
@@ -1188,7 +1185,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1188
1185
|
* @param local - Whether the message originated from the local client
|
|
1189
1186
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1190
1187
|
* For messages from a remote client, this will be undefined.
|
|
1191
|
-
* @internal
|
|
1192
1188
|
*/
|
|
1193
1189
|
processClearMessage(msg, op, local, localOpMetadata) {
|
|
1194
1190
|
this.throwIfDisposed();
|
|
@@ -1203,24 +1199,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1203
1199
|
}
|
|
1204
1200
|
this.clearExceptPendingKeys(false);
|
|
1205
1201
|
}
|
|
1206
|
-
/**
|
|
1207
|
-
* Apply clear operation locally and generate metadata
|
|
1208
|
-
* @param op - Op to apply
|
|
1209
|
-
* @returns metadata generated for stahed op
|
|
1210
|
-
*/
|
|
1211
|
-
applyStashedClearMessage(op) {
|
|
1212
|
-
this.throwIfDisposed();
|
|
1213
|
-
const previousValue = new Map(this._storage);
|
|
1214
|
-
this.clearExceptPendingKeys(true);
|
|
1215
|
-
const pendingMsgId = ++this.pendingMessageId;
|
|
1216
|
-
this.pendingClearMessageIds.push(pendingMsgId);
|
|
1217
|
-
const metadata = {
|
|
1218
|
-
type: "clear",
|
|
1219
|
-
pendingMessageId: pendingMsgId,
|
|
1220
|
-
previousStorage: previousValue,
|
|
1221
|
-
};
|
|
1222
|
-
return metadata;
|
|
1223
|
-
}
|
|
1224
1202
|
/**
|
|
1225
1203
|
* Process a delete operation.
|
|
1226
1204
|
* @param msg - The message from the server to apply.
|
|
@@ -1228,7 +1206,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1228
1206
|
* @param local - Whether the message originated from the local client
|
|
1229
1207
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1230
1208
|
* For messages from a remote client, this will be undefined.
|
|
1231
|
-
* @internal
|
|
1232
1209
|
*/
|
|
1233
1210
|
processDeleteMessage(msg, op, local, localOpMetadata) {
|
|
1234
1211
|
this.throwIfDisposed();
|
|
@@ -1238,22 +1215,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1238
1215
|
}
|
|
1239
1216
|
this.deleteCore(op.key, local);
|
|
1240
1217
|
}
|
|
1241
|
-
/**
|
|
1242
|
-
* Apply delete operation locally and generate metadata
|
|
1243
|
-
* @param op - Op to apply
|
|
1244
|
-
* @returns metadata generated for stahed op
|
|
1245
|
-
*/
|
|
1246
|
-
applyStashedDeleteMessage(op) {
|
|
1247
|
-
this.throwIfDisposed();
|
|
1248
|
-
const previousValue = this.deleteCore(op.key, true);
|
|
1249
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1250
|
-
const localMetadata = {
|
|
1251
|
-
type: "edit",
|
|
1252
|
-
pendingMessageId,
|
|
1253
|
-
previousValue,
|
|
1254
|
-
};
|
|
1255
|
-
return localMetadata;
|
|
1256
|
-
}
|
|
1257
1218
|
/**
|
|
1258
1219
|
* Process a set operation.
|
|
1259
1220
|
* @param msg - The message from the server to apply.
|
|
@@ -1261,7 +1222,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1261
1222
|
* @param local - Whether the message originated from the local client
|
|
1262
1223
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1263
1224
|
* For messages from a remote client, this will be undefined.
|
|
1264
|
-
* @internal
|
|
1265
1225
|
*/
|
|
1266
1226
|
processSetMessage(msg, op, context, local, localOpMetadata) {
|
|
1267
1227
|
this.throwIfDisposed();
|
|
@@ -1274,24 +1234,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1274
1234
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1275
1235
|
this.setCore(op.key, context, local);
|
|
1276
1236
|
}
|
|
1277
|
-
/**
|
|
1278
|
-
* Apply set operation locally and generate metadata
|
|
1279
|
-
* @param op - Op to apply
|
|
1280
|
-
* @returns metadata generated for stahed op
|
|
1281
|
-
*/
|
|
1282
|
-
applyStashedSetMessage(op, context) {
|
|
1283
|
-
this.throwIfDisposed();
|
|
1284
|
-
// Set the value locally.
|
|
1285
|
-
const previousValue = this.setCore(op.key, context, true);
|
|
1286
|
-
// Create metadata
|
|
1287
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1288
|
-
const localMetadata = {
|
|
1289
|
-
type: "edit",
|
|
1290
|
-
pendingMessageId,
|
|
1291
|
-
previousValue,
|
|
1292
|
-
};
|
|
1293
|
-
return localMetadata;
|
|
1294
|
-
}
|
|
1295
1237
|
/**
|
|
1296
1238
|
* Process a create subdirectory operation.
|
|
1297
1239
|
* @param msg - The message from the server to apply.
|
|
@@ -1299,7 +1241,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1299
1241
|
* @param local - Whether the message originated from the local client
|
|
1300
1242
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1301
1243
|
* For messages from a remote client, this will be undefined.
|
|
1302
|
-
* @internal
|
|
1303
1244
|
*/
|
|
1304
1245
|
processCreateSubDirectoryMessage(msg, op, local, localOpMetadata) {
|
|
1305
1246
|
this.throwIfDisposed();
|
|
@@ -1310,21 +1251,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1310
1251
|
assertNonNullClientId(msg.clientId);
|
|
1311
1252
|
this.createSubDirectoryCore(op.subdirName, local, { seq: msg.sequenceNumber, clientSeq: msg.clientSequenceNumber }, msg.clientId);
|
|
1312
1253
|
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Apply createSubDirectory operation locally and generate metadata
|
|
1315
|
-
* @param op - Op to apply
|
|
1316
|
-
* @returns metadata generated for stahed op
|
|
1317
|
-
*/
|
|
1318
|
-
applyStashedCreateSubDirMessage(op) {
|
|
1319
|
-
this.throwIfDisposed();
|
|
1320
|
-
// Create the sub directory locally first.
|
|
1321
|
-
this.createSubDirectoryCore(op.subdirName, true, this.getLocalSeq(), this.runtime.clientId ?? "detached");
|
|
1322
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1323
|
-
const localOpMetadata = {
|
|
1324
|
-
type: "createSubDir",
|
|
1325
|
-
};
|
|
1326
|
-
return localOpMetadata;
|
|
1327
|
-
}
|
|
1328
1254
|
/**
|
|
1329
1255
|
* Process a delete subdirectory operation.
|
|
1330
1256
|
* @param msg - The message from the server to apply.
|
|
@@ -1332,7 +1258,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1332
1258
|
* @param local - Whether the message originated from the local client
|
|
1333
1259
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1334
1260
|
* For messages from a remote client, this will be undefined.
|
|
1335
|
-
* @internal
|
|
1336
1261
|
*/
|
|
1337
1262
|
processDeleteSubDirectoryMessage(msg, op, local, localOpMetadata) {
|
|
1338
1263
|
this.throwIfDisposed();
|
|
@@ -1342,21 +1267,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1342
1267
|
}
|
|
1343
1268
|
this.deleteSubDirectoryCore(op.subdirName, local);
|
|
1344
1269
|
}
|
|
1345
|
-
/**
|
|
1346
|
-
* Apply deleteSubDirectory operation locally and generate metadata
|
|
1347
|
-
* @param op - Op to apply
|
|
1348
|
-
* @returns metadata generated for stahed op
|
|
1349
|
-
*/
|
|
1350
|
-
applyStashedDeleteSubDirMessage(op) {
|
|
1351
|
-
this.throwIfDisposed();
|
|
1352
|
-
const subDir = this.deleteSubDirectoryCore(op.subdirName, true);
|
|
1353
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1354
|
-
const metadata = {
|
|
1355
|
-
type: "deleteSubDir",
|
|
1356
|
-
subDirectory: subDir,
|
|
1357
|
-
};
|
|
1358
|
-
return metadata;
|
|
1359
|
-
}
|
|
1360
1270
|
/**
|
|
1361
1271
|
* Submit a clear operation.
|
|
1362
1272
|
* @param op - The operation
|
|
@@ -1375,7 +1285,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1375
1285
|
/**
|
|
1376
1286
|
* Resubmit a clear operation.
|
|
1377
1287
|
* @param op - The operation
|
|
1378
|
-
* @internal
|
|
1379
1288
|
*/
|
|
1380
1289
|
resubmitClearMessage(op, localOpMetadata) {
|
|
1381
1290
|
(0, core_utils_1.assert)(isClearLocalOpMetadata(localOpMetadata), 0x32b /* Invalid localOpMetadata for clear */);
|
|
@@ -1394,11 +1303,11 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1394
1303
|
// We don't reuse the metadata pendingMessageId but send a new one on each submit.
|
|
1395
1304
|
const pendingMessageId = ++this.pendingMessageId;
|
|
1396
1305
|
const pendingMessageIds = this.pendingKeys.get(op.key);
|
|
1397
|
-
if (pendingMessageIds
|
|
1398
|
-
|
|
1306
|
+
if (pendingMessageIds === undefined) {
|
|
1307
|
+
this.pendingKeys.set(op.key, [pendingMessageId]);
|
|
1399
1308
|
}
|
|
1400
1309
|
else {
|
|
1401
|
-
|
|
1310
|
+
pendingMessageIds.push(pendingMessageId);
|
|
1402
1311
|
}
|
|
1403
1312
|
return pendingMessageId;
|
|
1404
1313
|
}
|
|
@@ -1417,7 +1326,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1417
1326
|
* Submit a key message to remote clients based on a previous submit.
|
|
1418
1327
|
* @param op - The map key message
|
|
1419
1328
|
* @param localOpMetadata - Metadata from the previous submit
|
|
1420
|
-
* @internal
|
|
1421
1329
|
*/
|
|
1422
1330
|
resubmitKeyMessage(op, localOpMetadata) {
|
|
1423
1331
|
(0, core_utils_1.assert)(isKeyEditLocalOpMetadata(localOpMetadata), 0x32d /* Invalid localOpMetadata in submit */);
|
|
@@ -1426,7 +1334,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1426
1334
|
// Only submit the op, if we have record for it, otherwise it is possible that the older instance
|
|
1427
1335
|
// is already deleted, in which case we don't need to submit the op.
|
|
1428
1336
|
if (pendingMessageIds !== undefined) {
|
|
1429
|
-
const index = pendingMessageIds.
|
|
1337
|
+
const index = pendingMessageIds.indexOf(localOpMetadata.pendingMessageId);
|
|
1430
1338
|
if (index === -1) {
|
|
1431
1339
|
return;
|
|
1432
1340
|
}
|
|
@@ -1490,7 +1398,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1490
1398
|
* Submit a subdirectory operation again
|
|
1491
1399
|
* @param op - The operation
|
|
1492
1400
|
* @param localOpMetadata - metadata submitted with the op originally
|
|
1493
|
-
* @internal
|
|
1494
1401
|
*/
|
|
1495
1402
|
resubmitSubDirectoryMessage(op, localOpMetadata) {
|
|
1496
1403
|
(0, core_utils_1.assert)(isSubDirLocalOpMetadata(localOpMetadata), 0x32f /* Invalid localOpMetadata for sub directory op */);
|
|
@@ -1517,7 +1424,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1517
1424
|
* Get the storage of this subdirectory in a serializable format, to be used in snapshotting.
|
|
1518
1425
|
* @param serializer - The serializer to use to serialize handles in its values.
|
|
1519
1426
|
* @returns The JSONable string representing the storage of this subdirectory
|
|
1520
|
-
* @internal
|
|
1521
1427
|
*/
|
|
1522
1428
|
*getSerializedStorage(serializer) {
|
|
1523
1429
|
this.throwIfDisposed();
|
|
@@ -1531,7 +1437,7 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1531
1437
|
this.throwIfDisposed();
|
|
1532
1438
|
const createInfo = {
|
|
1533
1439
|
csn: this.seqData.seq,
|
|
1534
|
-
ccIds:
|
|
1440
|
+
ccIds: [...this.clientIds],
|
|
1535
1441
|
};
|
|
1536
1442
|
return createInfo;
|
|
1537
1443
|
}
|
|
@@ -1539,7 +1445,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1539
1445
|
* Populate a key value in this subdirectory's storage, to be used when loading from snapshot.
|
|
1540
1446
|
* @param key - The key to populate
|
|
1541
1447
|
* @param localValue - The local value to populate into it
|
|
1542
|
-
* @internal
|
|
1543
1448
|
*/
|
|
1544
1449
|
populateStorage(key, localValue) {
|
|
1545
1450
|
this.throwIfDisposed();
|
|
@@ -1549,7 +1454,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1549
1454
|
* Populate a subdirectory into this subdirectory, to be used when loading from snapshot.
|
|
1550
1455
|
* @param subdirName - The name of the subdirectory to add
|
|
1551
1456
|
* @param newSubDir - The new subdirectory to add
|
|
1552
|
-
* @internal
|
|
1553
1457
|
*/
|
|
1554
1458
|
populateSubDirectory(subdirName, newSubDir) {
|
|
1555
1459
|
this.throwIfDisposed();
|
|
@@ -1560,7 +1464,6 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1560
1464
|
* value so op handlers can be retrieved
|
|
1561
1465
|
* @param key - The key to retrieve from
|
|
1562
1466
|
* @returns The local value
|
|
1563
|
-
* @internal
|
|
1564
1467
|
*/
|
|
1565
1468
|
getLocalValue(key) {
|
|
1566
1469
|
this.throwIfDisposed();
|
|
@@ -1603,37 +1506,46 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1603
1506
|
}
|
|
1604
1507
|
}
|
|
1605
1508
|
else if ((op.type === "delete" || op.type === "set") && localOpMetadata.type === "edit") {
|
|
1509
|
+
const key = op.key;
|
|
1510
|
+
(0, core_utils_1.assert)(key !== undefined, 0x8ad /* "key" property is missing from edit operation. */);
|
|
1511
|
+
(0, core_utils_1.assert)(typeof key === "string", 0x8ae /* "key" property in edit operation is misconfigured. Expected a string. */);
|
|
1606
1512
|
if (localOpMetadata.previousValue === undefined) {
|
|
1607
|
-
this.deleteCore(
|
|
1513
|
+
this.deleteCore(key, true);
|
|
1608
1514
|
}
|
|
1609
1515
|
else {
|
|
1610
|
-
this.setCore(
|
|
1516
|
+
this.setCore(key, localOpMetadata.previousValue, true);
|
|
1611
1517
|
}
|
|
1612
|
-
this.rollbackPendingMessageId(this.pendingKeys,
|
|
1518
|
+
this.rollbackPendingMessageId(this.pendingKeys, key, localOpMetadata.pendingMessageId);
|
|
1613
1519
|
}
|
|
1614
1520
|
else if (op.type === "createSubDirectory" && localOpMetadata.type === "createSubDir") {
|
|
1615
|
-
|
|
1616
|
-
|
|
1521
|
+
const subdirName = op.subdirName;
|
|
1522
|
+
(0, core_utils_1.assert)(subdirName !== undefined, 0x8af /* "subdirName" property is missing from "createSubDirectory" operation. */);
|
|
1523
|
+
(0, core_utils_1.assert)(typeof subdirName === "string", 0x8b0 /* "subdirName" property in "createSubDirectory" operation is misconfigured. Expected a string. */);
|
|
1524
|
+
this.deleteSubDirectoryCore(subdirName, true);
|
|
1525
|
+
this.decrementPendingSubDirCount(this.pendingCreateSubDirectoriesTracker, subdirName);
|
|
1617
1526
|
}
|
|
1618
1527
|
else if (op.type === "deleteSubDirectory" && localOpMetadata.type === "deleteSubDir") {
|
|
1528
|
+
const subdirName = op.subdirName;
|
|
1529
|
+
(0, core_utils_1.assert)(subdirName !== undefined, 0x8b1 /* "subdirName" property is missing from "deleteSubDirectory" operation. */);
|
|
1530
|
+
(0, core_utils_1.assert)(typeof subdirName === "string", 0x8b2 /* "subdirName" property in "deleteSubDirectory" operation is misconfigured. Expected a string. */);
|
|
1619
1531
|
if (localOpMetadata.subDirectory !== undefined) {
|
|
1620
1532
|
this.undeleteSubDirectoryTree(localOpMetadata.subDirectory);
|
|
1621
1533
|
// don't need to register events because deleting never unregistered
|
|
1622
|
-
this._subdirectories.set(
|
|
1534
|
+
this._subdirectories.set(subdirName, localOpMetadata.subDirectory);
|
|
1623
1535
|
// Restore the record in creation tracker
|
|
1624
1536
|
if (isAcknowledgedOrDetached(localOpMetadata.subDirectory.seqData)) {
|
|
1625
|
-
this.ackedCreationSeqTracker.set(
|
|
1537
|
+
this.ackedCreationSeqTracker.set(subdirName, {
|
|
1626
1538
|
...localOpMetadata.subDirectory.seqData,
|
|
1627
1539
|
});
|
|
1628
1540
|
}
|
|
1629
1541
|
else {
|
|
1630
|
-
this.localCreationSeqTracker.set(
|
|
1542
|
+
this.localCreationSeqTracker.set(subdirName, {
|
|
1631
1543
|
...localOpMetadata.subDirectory.seqData,
|
|
1632
1544
|
});
|
|
1633
1545
|
}
|
|
1634
|
-
this.emit("subDirectoryCreated",
|
|
1546
|
+
this.emit("subDirectoryCreated", subdirName, true, this);
|
|
1635
1547
|
}
|
|
1636
|
-
this.decrementPendingSubDirCount(this.pendingDeleteSubDirectoriesTracker,
|
|
1548
|
+
this.decrementPendingSubDirCount(this.pendingDeleteSubDirectoriesTracker, subdirName);
|
|
1637
1549
|
}
|
|
1638
1550
|
else {
|
|
1639
1551
|
throw new Error("Unsupported op for rollback");
|
|
@@ -1882,11 +1794,11 @@ class SubDirectory extends client_utils_1.TypedEventEmitter {
|
|
|
1882
1794
|
* Store the sequnce numbers of newly created subdirectory to the proper creation tracker, based
|
|
1883
1795
|
* on whether the creation behavior has been ack'd or not
|
|
1884
1796
|
*/
|
|
1885
|
-
if (
|
|
1886
|
-
this.
|
|
1797
|
+
if (isAcknowledgedOrDetached(seqData)) {
|
|
1798
|
+
this.ackedCreationSeqTracker.set(subdirName, { ...seqData });
|
|
1887
1799
|
}
|
|
1888
1800
|
else {
|
|
1889
|
-
this.
|
|
1801
|
+
this.localCreationSeqTracker.set(subdirName, { ...seqData });
|
|
1890
1802
|
}
|
|
1891
1803
|
this.registerEventsOnSubDirectory(subDir, subdirName);
|
|
1892
1804
|
this._subdirectories.set(subdirName, subDir);
|