@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
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
var _a, _b;
|
|
6
|
-
import { assert } from "@fluidframework/core-utils";
|
|
6
|
+
import { assert, unreachableCase } from "@fluidframework/core-utils";
|
|
7
7
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
8
8
|
import { UsageError } from "@fluidframework/telemetry-utils";
|
|
9
9
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
10
10
|
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
11
|
-
import { SharedObject, ValueType } from "@fluidframework/shared-object-base";
|
|
11
|
+
import { SharedObject, ValueType, parseHandles, } from "@fluidframework/shared-object-base";
|
|
12
12
|
import { SummaryTreeBuilder } from "@fluidframework/runtime-utils";
|
|
13
13
|
import path from "path-browserify";
|
|
14
14
|
import { RedBlackTree } from "@fluidframework/merge-tree";
|
|
15
|
-
import { LocalValueMaker, makeSerializable } from "./localValues.
|
|
16
|
-
import { pkgVersion } from "./packageVersion.
|
|
15
|
+
import { LocalValueMaker, makeSerializable } from "./localValues.js";
|
|
16
|
+
import { pkgVersion } from "./packageVersion.js";
|
|
17
17
|
// We use path-browserify since this code can run safely on the server or the browser.
|
|
18
18
|
// We standardize on using posix slashes everywhere.
|
|
19
19
|
const posix = path.posix;
|
|
@@ -90,19 +90,19 @@ const seqDataComparator = (a, b) => {
|
|
|
90
90
|
if (isAcknowledgedOrDetached(a)) {
|
|
91
91
|
if (isAcknowledgedOrDetached(b)) {
|
|
92
92
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
93
|
-
return a.seq
|
|
93
|
+
return a.seq === b.seq ? a.clientSeq - b.clientSeq : a.seq - b.seq;
|
|
94
94
|
}
|
|
95
95
|
else {
|
|
96
96
|
return -1;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
else {
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
return a.seq !== b.seq ? a.seq - b.seq : a.clientSeq - b.clientSeq;
|
|
100
|
+
if (isAcknowledgedOrDetached(b)) {
|
|
101
|
+
return 1;
|
|
103
102
|
}
|
|
104
103
|
else {
|
|
105
|
-
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
105
|
+
return a.seq === b.seq ? a.clientSeq - b.clientSeq : a.seq - b.seq;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
};
|
|
@@ -223,7 +223,7 @@ export class SharedDirectory extends SharedObject {
|
|
|
223
223
|
* Mapping of op types to message handlers.
|
|
224
224
|
*/
|
|
225
225
|
this.messageHandlers = new Map();
|
|
226
|
-
this.localValueMaker = new LocalValueMaker(
|
|
226
|
+
this.localValueMaker = new LocalValueMaker();
|
|
227
227
|
this.setMessageHandlers();
|
|
228
228
|
// Mirror the containedValueChanged op on the SharedDirectory
|
|
229
229
|
this.root.on("containedValueChanged", (changed, local) => {
|
|
@@ -473,9 +473,9 @@ export class SharedDirectory extends SharedObject {
|
|
|
473
473
|
clientSeq: ++currentSubDir.localCreationSeq,
|
|
474
474
|
};
|
|
475
475
|
}
|
|
476
|
-
newSubDir = new SubDirectory(seqData, createInfo
|
|
477
|
-
? new Set(
|
|
478
|
-
: new Set(), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName), this.logger);
|
|
476
|
+
newSubDir = new SubDirectory(seqData, createInfo === undefined
|
|
477
|
+
? new Set()
|
|
478
|
+
: new Set(createInfo.ccIds), this, this.runtime, this.serializer, posix.join(currentSubDir.absolutePath, subdirName), this.logger);
|
|
479
479
|
currentSubDir.populateSubDirectory(subdirName, newSubDir);
|
|
480
480
|
// Record the newly inserted subdirectory to the creation tracker
|
|
481
481
|
currentSubDir.ackedCreationSeqTracker.set(subdirName, {
|
|
@@ -487,7 +487,9 @@ export class SharedDirectory extends SharedObject {
|
|
|
487
487
|
}
|
|
488
488
|
if (currentSubDirObject.storage) {
|
|
489
489
|
for (const [key, serializable] of Object.entries(currentSubDirObject.storage)) {
|
|
490
|
-
const localValue = this.makeLocal(key, currentSubDir.absolutePath,
|
|
490
|
+
const localValue = this.makeLocal(key, currentSubDir.absolutePath,
|
|
491
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
492
|
+
parseHandles(serializable, this.serializer));
|
|
491
493
|
currentSubDir.populateStorage(key, localValue);
|
|
492
494
|
}
|
|
493
495
|
}
|
|
@@ -536,7 +538,7 @@ export class SharedDirectory extends SharedObject {
|
|
|
536
538
|
serializable) {
|
|
537
539
|
assert(serializable.type === ValueType[ValueType.Plain] ||
|
|
538
540
|
serializable.type === ValueType[ValueType.Shared], 0x1e4 /* "Unexpected serializable type" */);
|
|
539
|
-
return this.localValueMaker.fromSerializable(serializable);
|
|
541
|
+
return this.localValueMaker.fromSerializable(serializable, this.serializer, this.handle);
|
|
540
542
|
}
|
|
541
543
|
/**
|
|
542
544
|
* This checks if there is pending delete op for local delete for a any subdir in the relative path.
|
|
@@ -583,12 +585,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
583
585
|
subdir.resubmitClearMessage(op, localOpMetadata);
|
|
584
586
|
}
|
|
585
587
|
},
|
|
586
|
-
applyStashedOp: (op) => {
|
|
587
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
588
|
-
if (subdir) {
|
|
589
|
-
return subdir.applyStashedClearMessage(op);
|
|
590
|
-
}
|
|
591
|
-
},
|
|
592
588
|
});
|
|
593
589
|
this.messageHandlers.set("delete", {
|
|
594
590
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -605,12 +601,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
605
601
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
606
602
|
}
|
|
607
603
|
},
|
|
608
|
-
applyStashedOp: (op) => {
|
|
609
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
610
|
-
if (subdir) {
|
|
611
|
-
return subdir.applyStashedDeleteMessage(op);
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
604
|
});
|
|
615
605
|
this.messageHandlers.set("set", {
|
|
616
606
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -628,13 +618,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
628
618
|
subdir.resubmitKeyMessage(op, localOpMetadata);
|
|
629
619
|
}
|
|
630
620
|
},
|
|
631
|
-
applyStashedOp: (op) => {
|
|
632
|
-
const subdir = this.getWorkingDirectory(op.path);
|
|
633
|
-
if (subdir) {
|
|
634
|
-
const context = this.makeLocal(op.key, op.path, op.value);
|
|
635
|
-
return subdir.applyStashedSetMessage(op, context);
|
|
636
|
-
}
|
|
637
|
-
},
|
|
638
621
|
});
|
|
639
622
|
this.messageHandlers.set("createSubDirectory", {
|
|
640
623
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -652,12 +635,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
652
635
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
653
636
|
}
|
|
654
637
|
},
|
|
655
|
-
applyStashedOp: (op) => {
|
|
656
|
-
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
657
|
-
if (parentSubdir) {
|
|
658
|
-
return parentSubdir.applyStashedCreateSubDirMessage(op);
|
|
659
|
-
}
|
|
660
|
-
},
|
|
661
638
|
});
|
|
662
639
|
this.messageHandlers.set("deleteSubDirectory", {
|
|
663
640
|
process: (msg, op, local, localOpMetadata) => {
|
|
@@ -675,23 +652,39 @@ export class SharedDirectory extends SharedObject {
|
|
|
675
652
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
676
653
|
}
|
|
677
654
|
},
|
|
678
|
-
applyStashedOp: (op) => {
|
|
679
|
-
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
680
|
-
if (parentSubdir) {
|
|
681
|
-
return parentSubdir.applyStashedDeleteSubDirMessage(op);
|
|
682
|
-
}
|
|
683
|
-
},
|
|
684
655
|
});
|
|
685
656
|
}
|
|
686
657
|
/**
|
|
687
658
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
688
659
|
*/
|
|
689
660
|
applyStashedOp(op) {
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
|
|
661
|
+
const directoryOp = op;
|
|
662
|
+
const dir = this.getWorkingDirectory(directoryOp.path);
|
|
663
|
+
switch (directoryOp.type) {
|
|
664
|
+
case "clear": {
|
|
665
|
+
dir?.clear();
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
case "createSubDirectory": {
|
|
669
|
+
dir?.createSubDirectory(directoryOp.subdirName);
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
case "delete": {
|
|
673
|
+
dir?.delete(directoryOp.key);
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
case "deleteSubDirectory": {
|
|
677
|
+
dir?.deleteSubDirectory(directoryOp.subdirName);
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
case "set": {
|
|
681
|
+
dir?.set(directoryOp.key, this.localValueMaker.fromSerializable(directoryOp.value, this.serializer, this.handle).value);
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
default: {
|
|
685
|
+
unreachableCase(directoryOp);
|
|
686
|
+
}
|
|
693
687
|
}
|
|
694
|
-
return handler.applyStashedOp(op);
|
|
695
688
|
}
|
|
696
689
|
serializeDirectory(root, serializer, telemetryContext) {
|
|
697
690
|
const MinValueSizeSeparateSnapshotBlob = 8 * 1024;
|
|
@@ -773,6 +766,7 @@ function isDirectoryLocalOpMetadata(metadata) {
|
|
|
773
766
|
isSubDirLocalOpMetadata(metadata));
|
|
774
767
|
}
|
|
775
768
|
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
769
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
776
770
|
function assertNonNullClientId(clientId) {
|
|
777
771
|
assert(clientId !== null, 0x6af /* client id should never be null */);
|
|
778
772
|
}
|
|
@@ -951,13 +945,15 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
951
945
|
return subDir;
|
|
952
946
|
}
|
|
953
947
|
/**
|
|
954
|
-
*
|
|
948
|
+
* Gets the Sequence Data which should be used for local changes.
|
|
949
|
+
*
|
|
955
950
|
* @remarks While detached, 0 is used rather than -1 to represent a change which should be universally known (as opposed to known
|
|
956
951
|
* only by the local client). This ensures that if the directory is later attached, none of its data needs to be updated (the values
|
|
957
952
|
* last set while detached will now be known to any new client, until they are changed).
|
|
958
953
|
*
|
|
959
954
|
* The client sequence number is incremented by 1 for maintaining the internal order of locally created subdirectories
|
|
960
|
-
*
|
|
955
|
+
*
|
|
956
|
+
* @privateRemarks TODO: Convert these conventions to named constants. The semantics used here match those for merge-tree.
|
|
961
957
|
*/
|
|
962
958
|
getLocalSeq() {
|
|
963
959
|
return this.directory.isAttached()
|
|
@@ -1032,6 +1028,7 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1032
1028
|
if (this.index < subdirNames.length) {
|
|
1033
1029
|
const subdirName = subdirNames[this.index++];
|
|
1034
1030
|
const subdir = this.dirs.get(subdirName);
|
|
1031
|
+
assert(subdir !== undefined, 0x8ac /* Could not find expected sub-directory. */);
|
|
1035
1032
|
return { value: [subdirName, subdir], done: false };
|
|
1036
1033
|
}
|
|
1037
1034
|
return { value: undefined, done: true };
|
|
@@ -1180,7 +1177,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1180
1177
|
* @param local - Whether the message originated from the local client
|
|
1181
1178
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1182
1179
|
* For messages from a remote client, this will be undefined.
|
|
1183
|
-
* @internal
|
|
1184
1180
|
*/
|
|
1185
1181
|
processClearMessage(msg, op, local, localOpMetadata) {
|
|
1186
1182
|
this.throwIfDisposed();
|
|
@@ -1195,24 +1191,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1195
1191
|
}
|
|
1196
1192
|
this.clearExceptPendingKeys(false);
|
|
1197
1193
|
}
|
|
1198
|
-
/**
|
|
1199
|
-
* Apply clear operation locally and generate metadata
|
|
1200
|
-
* @param op - Op to apply
|
|
1201
|
-
* @returns metadata generated for stahed op
|
|
1202
|
-
*/
|
|
1203
|
-
applyStashedClearMessage(op) {
|
|
1204
|
-
this.throwIfDisposed();
|
|
1205
|
-
const previousValue = new Map(this._storage);
|
|
1206
|
-
this.clearExceptPendingKeys(true);
|
|
1207
|
-
const pendingMsgId = ++this.pendingMessageId;
|
|
1208
|
-
this.pendingClearMessageIds.push(pendingMsgId);
|
|
1209
|
-
const metadata = {
|
|
1210
|
-
type: "clear",
|
|
1211
|
-
pendingMessageId: pendingMsgId,
|
|
1212
|
-
previousStorage: previousValue,
|
|
1213
|
-
};
|
|
1214
|
-
return metadata;
|
|
1215
|
-
}
|
|
1216
1194
|
/**
|
|
1217
1195
|
* Process a delete operation.
|
|
1218
1196
|
* @param msg - The message from the server to apply.
|
|
@@ -1220,7 +1198,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1220
1198
|
* @param local - Whether the message originated from the local client
|
|
1221
1199
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1222
1200
|
* For messages from a remote client, this will be undefined.
|
|
1223
|
-
* @internal
|
|
1224
1201
|
*/
|
|
1225
1202
|
processDeleteMessage(msg, op, local, localOpMetadata) {
|
|
1226
1203
|
this.throwIfDisposed();
|
|
@@ -1230,22 +1207,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1230
1207
|
}
|
|
1231
1208
|
this.deleteCore(op.key, local);
|
|
1232
1209
|
}
|
|
1233
|
-
/**
|
|
1234
|
-
* Apply delete operation locally and generate metadata
|
|
1235
|
-
* @param op - Op to apply
|
|
1236
|
-
* @returns metadata generated for stahed op
|
|
1237
|
-
*/
|
|
1238
|
-
applyStashedDeleteMessage(op) {
|
|
1239
|
-
this.throwIfDisposed();
|
|
1240
|
-
const previousValue = this.deleteCore(op.key, true);
|
|
1241
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1242
|
-
const localMetadata = {
|
|
1243
|
-
type: "edit",
|
|
1244
|
-
pendingMessageId,
|
|
1245
|
-
previousValue,
|
|
1246
|
-
};
|
|
1247
|
-
return localMetadata;
|
|
1248
|
-
}
|
|
1249
1210
|
/**
|
|
1250
1211
|
* Process a set operation.
|
|
1251
1212
|
* @param msg - The message from the server to apply.
|
|
@@ -1253,7 +1214,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1253
1214
|
* @param local - Whether the message originated from the local client
|
|
1254
1215
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1255
1216
|
* For messages from a remote client, this will be undefined.
|
|
1256
|
-
* @internal
|
|
1257
1217
|
*/
|
|
1258
1218
|
processSetMessage(msg, op, context, local, localOpMetadata) {
|
|
1259
1219
|
this.throwIfDisposed();
|
|
@@ -1266,24 +1226,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1266
1226
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1267
1227
|
this.setCore(op.key, context, local);
|
|
1268
1228
|
}
|
|
1269
|
-
/**
|
|
1270
|
-
* Apply set operation locally and generate metadata
|
|
1271
|
-
* @param op - Op to apply
|
|
1272
|
-
* @returns metadata generated for stahed op
|
|
1273
|
-
*/
|
|
1274
|
-
applyStashedSetMessage(op, context) {
|
|
1275
|
-
this.throwIfDisposed();
|
|
1276
|
-
// Set the value locally.
|
|
1277
|
-
const previousValue = this.setCore(op.key, context, true);
|
|
1278
|
-
// Create metadata
|
|
1279
|
-
const pendingMessageId = this.getKeyMessageId(op);
|
|
1280
|
-
const localMetadata = {
|
|
1281
|
-
type: "edit",
|
|
1282
|
-
pendingMessageId,
|
|
1283
|
-
previousValue,
|
|
1284
|
-
};
|
|
1285
|
-
return localMetadata;
|
|
1286
|
-
}
|
|
1287
1229
|
/**
|
|
1288
1230
|
* Process a create subdirectory operation.
|
|
1289
1231
|
* @param msg - The message from the server to apply.
|
|
@@ -1291,7 +1233,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1291
1233
|
* @param local - Whether the message originated from the local client
|
|
1292
1234
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1293
1235
|
* For messages from a remote client, this will be undefined.
|
|
1294
|
-
* @internal
|
|
1295
1236
|
*/
|
|
1296
1237
|
processCreateSubDirectoryMessage(msg, op, local, localOpMetadata) {
|
|
1297
1238
|
this.throwIfDisposed();
|
|
@@ -1302,21 +1243,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1302
1243
|
assertNonNullClientId(msg.clientId);
|
|
1303
1244
|
this.createSubDirectoryCore(op.subdirName, local, { seq: msg.sequenceNumber, clientSeq: msg.clientSequenceNumber }, msg.clientId);
|
|
1304
1245
|
}
|
|
1305
|
-
/**
|
|
1306
|
-
* Apply createSubDirectory operation locally and generate metadata
|
|
1307
|
-
* @param op - Op to apply
|
|
1308
|
-
* @returns metadata generated for stahed op
|
|
1309
|
-
*/
|
|
1310
|
-
applyStashedCreateSubDirMessage(op) {
|
|
1311
|
-
this.throwIfDisposed();
|
|
1312
|
-
// Create the sub directory locally first.
|
|
1313
|
-
this.createSubDirectoryCore(op.subdirName, true, this.getLocalSeq(), this.runtime.clientId ?? "detached");
|
|
1314
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1315
|
-
const localOpMetadata = {
|
|
1316
|
-
type: "createSubDir",
|
|
1317
|
-
};
|
|
1318
|
-
return localOpMetadata;
|
|
1319
|
-
}
|
|
1320
1246
|
/**
|
|
1321
1247
|
* Process a delete subdirectory operation.
|
|
1322
1248
|
* @param msg - The message from the server to apply.
|
|
@@ -1324,7 +1250,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1324
1250
|
* @param local - Whether the message originated from the local client
|
|
1325
1251
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
1326
1252
|
* For messages from a remote client, this will be undefined.
|
|
1327
|
-
* @internal
|
|
1328
1253
|
*/
|
|
1329
1254
|
processDeleteSubDirectoryMessage(msg, op, local, localOpMetadata) {
|
|
1330
1255
|
this.throwIfDisposed();
|
|
@@ -1334,21 +1259,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1334
1259
|
}
|
|
1335
1260
|
this.deleteSubDirectoryCore(op.subdirName, local);
|
|
1336
1261
|
}
|
|
1337
|
-
/**
|
|
1338
|
-
* Apply deleteSubDirectory operation locally and generate metadata
|
|
1339
|
-
* @param op - Op to apply
|
|
1340
|
-
* @returns metadata generated for stahed op
|
|
1341
|
-
*/
|
|
1342
|
-
applyStashedDeleteSubDirMessage(op) {
|
|
1343
|
-
this.throwIfDisposed();
|
|
1344
|
-
const subDir = this.deleteSubDirectoryCore(op.subdirName, true);
|
|
1345
|
-
this.updatePendingSubDirMessageCount(op);
|
|
1346
|
-
const metadata = {
|
|
1347
|
-
type: "deleteSubDir",
|
|
1348
|
-
subDirectory: subDir,
|
|
1349
|
-
};
|
|
1350
|
-
return metadata;
|
|
1351
|
-
}
|
|
1352
1262
|
/**
|
|
1353
1263
|
* Submit a clear operation.
|
|
1354
1264
|
* @param op - The operation
|
|
@@ -1367,7 +1277,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1367
1277
|
/**
|
|
1368
1278
|
* Resubmit a clear operation.
|
|
1369
1279
|
* @param op - The operation
|
|
1370
|
-
* @internal
|
|
1371
1280
|
*/
|
|
1372
1281
|
resubmitClearMessage(op, localOpMetadata) {
|
|
1373
1282
|
assert(isClearLocalOpMetadata(localOpMetadata), 0x32b /* Invalid localOpMetadata for clear */);
|
|
@@ -1386,11 +1295,11 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1386
1295
|
// We don't reuse the metadata pendingMessageId but send a new one on each submit.
|
|
1387
1296
|
const pendingMessageId = ++this.pendingMessageId;
|
|
1388
1297
|
const pendingMessageIds = this.pendingKeys.get(op.key);
|
|
1389
|
-
if (pendingMessageIds
|
|
1390
|
-
|
|
1298
|
+
if (pendingMessageIds === undefined) {
|
|
1299
|
+
this.pendingKeys.set(op.key, [pendingMessageId]);
|
|
1391
1300
|
}
|
|
1392
1301
|
else {
|
|
1393
|
-
|
|
1302
|
+
pendingMessageIds.push(pendingMessageId);
|
|
1394
1303
|
}
|
|
1395
1304
|
return pendingMessageId;
|
|
1396
1305
|
}
|
|
@@ -1409,7 +1318,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1409
1318
|
* Submit a key message to remote clients based on a previous submit.
|
|
1410
1319
|
* @param op - The map key message
|
|
1411
1320
|
* @param localOpMetadata - Metadata from the previous submit
|
|
1412
|
-
* @internal
|
|
1413
1321
|
*/
|
|
1414
1322
|
resubmitKeyMessage(op, localOpMetadata) {
|
|
1415
1323
|
assert(isKeyEditLocalOpMetadata(localOpMetadata), 0x32d /* Invalid localOpMetadata in submit */);
|
|
@@ -1418,7 +1326,7 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1418
1326
|
// Only submit the op, if we have record for it, otherwise it is possible that the older instance
|
|
1419
1327
|
// is already deleted, in which case we don't need to submit the op.
|
|
1420
1328
|
if (pendingMessageIds !== undefined) {
|
|
1421
|
-
const index = pendingMessageIds.
|
|
1329
|
+
const index = pendingMessageIds.indexOf(localOpMetadata.pendingMessageId);
|
|
1422
1330
|
if (index === -1) {
|
|
1423
1331
|
return;
|
|
1424
1332
|
}
|
|
@@ -1482,7 +1390,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1482
1390
|
* Submit a subdirectory operation again
|
|
1483
1391
|
* @param op - The operation
|
|
1484
1392
|
* @param localOpMetadata - metadata submitted with the op originally
|
|
1485
|
-
* @internal
|
|
1486
1393
|
*/
|
|
1487
1394
|
resubmitSubDirectoryMessage(op, localOpMetadata) {
|
|
1488
1395
|
assert(isSubDirLocalOpMetadata(localOpMetadata), 0x32f /* Invalid localOpMetadata for sub directory op */);
|
|
@@ -1509,7 +1416,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1509
1416
|
* Get the storage of this subdirectory in a serializable format, to be used in snapshotting.
|
|
1510
1417
|
* @param serializer - The serializer to use to serialize handles in its values.
|
|
1511
1418
|
* @returns The JSONable string representing the storage of this subdirectory
|
|
1512
|
-
* @internal
|
|
1513
1419
|
*/
|
|
1514
1420
|
*getSerializedStorage(serializer) {
|
|
1515
1421
|
this.throwIfDisposed();
|
|
@@ -1523,7 +1429,7 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1523
1429
|
this.throwIfDisposed();
|
|
1524
1430
|
const createInfo = {
|
|
1525
1431
|
csn: this.seqData.seq,
|
|
1526
|
-
ccIds:
|
|
1432
|
+
ccIds: [...this.clientIds],
|
|
1527
1433
|
};
|
|
1528
1434
|
return createInfo;
|
|
1529
1435
|
}
|
|
@@ -1531,7 +1437,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1531
1437
|
* Populate a key value in this subdirectory's storage, to be used when loading from snapshot.
|
|
1532
1438
|
* @param key - The key to populate
|
|
1533
1439
|
* @param localValue - The local value to populate into it
|
|
1534
|
-
* @internal
|
|
1535
1440
|
*/
|
|
1536
1441
|
populateStorage(key, localValue) {
|
|
1537
1442
|
this.throwIfDisposed();
|
|
@@ -1541,7 +1446,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1541
1446
|
* Populate a subdirectory into this subdirectory, to be used when loading from snapshot.
|
|
1542
1447
|
* @param subdirName - The name of the subdirectory to add
|
|
1543
1448
|
* @param newSubDir - The new subdirectory to add
|
|
1544
|
-
* @internal
|
|
1545
1449
|
*/
|
|
1546
1450
|
populateSubDirectory(subdirName, newSubDir) {
|
|
1547
1451
|
this.throwIfDisposed();
|
|
@@ -1552,7 +1456,6 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1552
1456
|
* value so op handlers can be retrieved
|
|
1553
1457
|
* @param key - The key to retrieve from
|
|
1554
1458
|
* @returns The local value
|
|
1555
|
-
* @internal
|
|
1556
1459
|
*/
|
|
1557
1460
|
getLocalValue(key) {
|
|
1558
1461
|
this.throwIfDisposed();
|
|
@@ -1595,37 +1498,46 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1595
1498
|
}
|
|
1596
1499
|
}
|
|
1597
1500
|
else if ((op.type === "delete" || op.type === "set") && localOpMetadata.type === "edit") {
|
|
1501
|
+
const key = op.key;
|
|
1502
|
+
assert(key !== undefined, 0x8ad /* "key" property is missing from edit operation. */);
|
|
1503
|
+
assert(typeof key === "string", 0x8ae /* "key" property in edit operation is misconfigured. Expected a string. */);
|
|
1598
1504
|
if (localOpMetadata.previousValue === undefined) {
|
|
1599
|
-
this.deleteCore(
|
|
1505
|
+
this.deleteCore(key, true);
|
|
1600
1506
|
}
|
|
1601
1507
|
else {
|
|
1602
|
-
this.setCore(
|
|
1508
|
+
this.setCore(key, localOpMetadata.previousValue, true);
|
|
1603
1509
|
}
|
|
1604
|
-
this.rollbackPendingMessageId(this.pendingKeys,
|
|
1510
|
+
this.rollbackPendingMessageId(this.pendingKeys, key, localOpMetadata.pendingMessageId);
|
|
1605
1511
|
}
|
|
1606
1512
|
else if (op.type === "createSubDirectory" && localOpMetadata.type === "createSubDir") {
|
|
1607
|
-
|
|
1608
|
-
|
|
1513
|
+
const subdirName = op.subdirName;
|
|
1514
|
+
assert(subdirName !== undefined, 0x8af /* "subdirName" property is missing from "createSubDirectory" operation. */);
|
|
1515
|
+
assert(typeof subdirName === "string", 0x8b0 /* "subdirName" property in "createSubDirectory" operation is misconfigured. Expected a string. */);
|
|
1516
|
+
this.deleteSubDirectoryCore(subdirName, true);
|
|
1517
|
+
this.decrementPendingSubDirCount(this.pendingCreateSubDirectoriesTracker, subdirName);
|
|
1609
1518
|
}
|
|
1610
1519
|
else if (op.type === "deleteSubDirectory" && localOpMetadata.type === "deleteSubDir") {
|
|
1520
|
+
const subdirName = op.subdirName;
|
|
1521
|
+
assert(subdirName !== undefined, 0x8b1 /* "subdirName" property is missing from "deleteSubDirectory" operation. */);
|
|
1522
|
+
assert(typeof subdirName === "string", 0x8b2 /* "subdirName" property in "deleteSubDirectory" operation is misconfigured. Expected a string. */);
|
|
1611
1523
|
if (localOpMetadata.subDirectory !== undefined) {
|
|
1612
1524
|
this.undeleteSubDirectoryTree(localOpMetadata.subDirectory);
|
|
1613
1525
|
// don't need to register events because deleting never unregistered
|
|
1614
|
-
this._subdirectories.set(
|
|
1526
|
+
this._subdirectories.set(subdirName, localOpMetadata.subDirectory);
|
|
1615
1527
|
// Restore the record in creation tracker
|
|
1616
1528
|
if (isAcknowledgedOrDetached(localOpMetadata.subDirectory.seqData)) {
|
|
1617
|
-
this.ackedCreationSeqTracker.set(
|
|
1529
|
+
this.ackedCreationSeqTracker.set(subdirName, {
|
|
1618
1530
|
...localOpMetadata.subDirectory.seqData,
|
|
1619
1531
|
});
|
|
1620
1532
|
}
|
|
1621
1533
|
else {
|
|
1622
|
-
this.localCreationSeqTracker.set(
|
|
1534
|
+
this.localCreationSeqTracker.set(subdirName, {
|
|
1623
1535
|
...localOpMetadata.subDirectory.seqData,
|
|
1624
1536
|
});
|
|
1625
1537
|
}
|
|
1626
|
-
this.emit("subDirectoryCreated",
|
|
1538
|
+
this.emit("subDirectoryCreated", subdirName, true, this);
|
|
1627
1539
|
}
|
|
1628
|
-
this.decrementPendingSubDirCount(this.pendingDeleteSubDirectoriesTracker,
|
|
1540
|
+
this.decrementPendingSubDirCount(this.pendingDeleteSubDirectoriesTracker, subdirName);
|
|
1629
1541
|
}
|
|
1630
1542
|
else {
|
|
1631
1543
|
throw new Error("Unsupported op for rollback");
|
|
@@ -1874,11 +1786,11 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1874
1786
|
* Store the sequnce numbers of newly created subdirectory to the proper creation tracker, based
|
|
1875
1787
|
* on whether the creation behavior has been ack'd or not
|
|
1876
1788
|
*/
|
|
1877
|
-
if (
|
|
1878
|
-
this.
|
|
1789
|
+
if (isAcknowledgedOrDetached(seqData)) {
|
|
1790
|
+
this.ackedCreationSeqTracker.set(subdirName, { ...seqData });
|
|
1879
1791
|
}
|
|
1880
1792
|
else {
|
|
1881
|
-
this.
|
|
1793
|
+
this.localCreationSeqTracker.set(subdirName, { ...seqData });
|
|
1882
1794
|
}
|
|
1883
1795
|
this.registerEventsOnSubDirectory(subDir, subdirName);
|
|
1884
1796
|
this._subdirectories.set(subdirName, subDir);
|
|
@@ -1946,4 +1858,4 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1946
1858
|
}
|
|
1947
1859
|
}
|
|
1948
1860
|
}
|
|
1949
|
-
//# sourceMappingURL=directory.
|
|
1861
|
+
//# sourceMappingURL=directory.js.map
|