@fluidframework/tree 2.61.0-356312 → 2.62.0-356644
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 +4 -0
- package/api-report/tree.alpha.api.md +3 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/rebase/index.d.ts +1 -1
- package/dist/core/rebase/index.d.ts.map +1 -1
- package/dist/core/rebase/index.js +2 -1
- package/dist/core/rebase/index.js.map +1 -1
- package/dist/core/rebase/utils.d.ts +10 -0
- package/dist/core/rebase/utils.d.ts.map +1 -1
- package/dist/core/rebase/utils.js +20 -1
- package/dist/core/rebase/utils.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +2 -2
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +12 -2
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +71 -33
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeCheckout.d.ts +13 -7
- package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
- package/dist/shared-tree/treeCheckout.js +114 -84
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +3 -0
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/branchIdCodec.d.ts +11 -0
- package/dist/shared-tree-core/branchIdCodec.d.ts.map +1 -0
- package/dist/shared-tree-core/branchIdCodec.js +18 -0
- package/dist/shared-tree-core/branchIdCodec.js.map +1 -0
- package/dist/shared-tree-core/editManager.d.ts +33 -63
- package/dist/shared-tree-core/editManager.d.ts.map +1 -1
- package/dist/shared-tree-core/editManager.js +437 -290
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts +1 -1
- package/dist/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/editManagerCodecs.js +7 -96
- package/dist/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts +17 -0
- package/dist/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -0
- package/dist/shared-tree-core/editManagerCodecsCommons.js +139 -0
- package/dist/shared-tree-core/editManagerCodecsCommons.js.map +1 -0
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts +16 -0
- package/dist/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -0
- package/dist/shared-tree-core/editManagerCodecsV1toV4.js +39 -0
- package/dist/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -0
- package/dist/shared-tree-core/editManagerCodecsV5.d.ts +16 -0
- package/dist/shared-tree-core/editManagerCodecsV5.d.ts.map +1 -0
- package/dist/shared-tree-core/editManagerCodecsV5.js +58 -0
- package/dist/shared-tree-core/editManagerCodecsV5.js.map +1 -0
- package/dist/shared-tree-core/{editManagerFormat.d.ts → editManagerFormatCommons.d.ts} +31 -7
- package/dist/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -0
- package/dist/shared-tree-core/{editManagerFormat.js → editManagerFormatCommons.js} +13 -12
- package/dist/shared-tree-core/editManagerFormatCommons.js.map +1 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts +31 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.js +24 -0
- package/dist/shared-tree-core/editManagerFormatV1toV4.js.map +1 -0
- package/dist/shared-tree-core/editManagerFormatV5.d.ts +62 -0
- package/dist/shared-tree-core/editManagerFormatV5.d.ts.map +1 -0
- package/dist/shared-tree-core/editManagerFormatV5.js +20 -0
- package/dist/shared-tree-core/editManagerFormatV5.js.map +1 -0
- package/dist/shared-tree-core/index.d.ts +3 -3
- package/dist/shared-tree-core/index.d.ts.map +1 -1
- package/dist/shared-tree-core/index.js.map +1 -1
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts +11 -0
- package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -0
- package/dist/shared-tree-core/messageCodecV1ToV4.js +59 -0
- package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -0
- package/dist/shared-tree-core/messageCodecV5.d.ts +11 -0
- package/dist/shared-tree-core/messageCodecV5.d.ts.map +1 -0
- package/dist/shared-tree-core/messageCodecV5.js +78 -0
- package/dist/shared-tree-core/messageCodecV5.js.map +1 -0
- package/dist/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/dist/shared-tree-core/messageCodecs.js +16 -47
- package/dist/shared-tree-core/messageCodecs.js.map +1 -1
- package/dist/shared-tree-core/{messageFormat.d.ts → messageFormatV1ToV4.d.ts} +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -0
- package/dist/shared-tree-core/{messageFormat.js → messageFormatV1ToV4.js} +1 -1
- package/dist/shared-tree-core/messageFormatV1ToV4.js.map +1 -0
- package/dist/shared-tree-core/messageFormatV5.d.ts +42 -0
- package/dist/shared-tree-core/messageFormatV5.d.ts.map +1 -0
- package/dist/shared-tree-core/messageFormatV5.js +20 -0
- package/dist/shared-tree-core/messageFormatV5.js.map +1 -0
- package/dist/shared-tree-core/messageTypes.d.ts +12 -2
- package/dist/shared-tree-core/messageTypes.d.ts.map +1 -1
- package/dist/shared-tree-core/messageTypes.js.map +1 -1
- package/dist/shared-tree-core/sequenceIdUtils.d.ts +1 -1
- package/dist/shared-tree-core/sequenceIdUtils.d.ts.map +1 -1
- package/dist/shared-tree-core/sequenceIdUtils.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +18 -5
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +175 -56
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/dirtyIndex.js +7 -7
- package/dist/simple-tree/api/dirtyIndex.js.map +1 -1
- package/dist/simple-tree/api/tree.d.ts +10 -0
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +4 -4
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/core/index.d.ts +1 -1
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/rebase/index.d.ts +1 -1
- package/lib/core/rebase/index.d.ts.map +1 -1
- package/lib/core/rebase/index.js +1 -1
- package/lib/core/rebase/index.js.map +1 -1
- package/lib/core/rebase/utils.d.ts +10 -0
- package/lib/core/rebase/utils.d.ts.map +1 -1
- package/lib/core/rebase/utils.js +18 -0
- package/lib/core/rebase/utils.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +2 -2
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +12 -2
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +72 -34
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeCheckout.d.ts +13 -7
- package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
- package/lib/shared-tree/treeCheckout.js +115 -85
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +3 -0
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/branchIdCodec.d.ts +11 -0
- package/lib/shared-tree-core/branchIdCodec.d.ts.map +1 -0
- package/lib/shared-tree-core/branchIdCodec.js +13 -0
- package/lib/shared-tree-core/branchIdCodec.js.map +1 -0
- package/lib/shared-tree-core/editManager.d.ts +33 -63
- package/lib/shared-tree-core/editManager.d.ts.map +1 -1
- package/lib/shared-tree-core/editManager.js +437 -290
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts +1 -1
- package/lib/shared-tree-core/editManagerCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/editManagerCodecs.js +4 -93
- package/lib/shared-tree-core/editManagerCodecs.js.map +1 -1
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts +17 -0
- package/lib/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -0
- package/lib/shared-tree-core/editManagerCodecsCommons.js +134 -0
- package/lib/shared-tree-core/editManagerCodecsCommons.js.map +1 -0
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts +16 -0
- package/lib/shared-tree-core/editManagerCodecsV1toV4.d.ts.map +1 -0
- package/lib/shared-tree-core/editManagerCodecsV1toV4.js +35 -0
- package/lib/shared-tree-core/editManagerCodecsV1toV4.js.map +1 -0
- package/lib/shared-tree-core/editManagerCodecsV5.d.ts +16 -0
- package/lib/shared-tree-core/editManagerCodecsV5.d.ts.map +1 -0
- package/lib/shared-tree-core/editManagerCodecsV5.js +54 -0
- package/lib/shared-tree-core/editManagerCodecsV5.js.map +1 -0
- package/lib/shared-tree-core/{editManagerFormat.d.ts → editManagerFormatCommons.d.ts} +31 -7
- package/lib/shared-tree-core/editManagerFormatCommons.d.ts.map +1 -0
- package/lib/shared-tree-core/{editManagerFormat.js → editManagerFormatCommons.js} +10 -11
- package/lib/shared-tree-core/editManagerFormatCommons.js.map +1 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts +31 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.d.ts.map +1 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.js +20 -0
- package/lib/shared-tree-core/editManagerFormatV1toV4.js.map +1 -0
- package/lib/shared-tree-core/editManagerFormatV5.d.ts +62 -0
- package/lib/shared-tree-core/editManagerFormatV5.d.ts.map +1 -0
- package/lib/shared-tree-core/editManagerFormatV5.js +16 -0
- package/lib/shared-tree-core/editManagerFormatV5.js.map +1 -0
- package/lib/shared-tree-core/index.d.ts +3 -3
- package/lib/shared-tree-core/index.d.ts.map +1 -1
- package/lib/shared-tree-core/index.js.map +1 -1
- package/lib/shared-tree-core/messageCodecV1ToV4.d.ts +11 -0
- package/lib/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -0
- package/lib/shared-tree-core/messageCodecV1ToV4.js +55 -0
- package/lib/shared-tree-core/messageCodecV1ToV4.js.map +1 -0
- package/lib/shared-tree-core/messageCodecV5.d.ts +11 -0
- package/lib/shared-tree-core/messageCodecV5.d.ts.map +1 -0
- package/lib/shared-tree-core/messageCodecV5.js +74 -0
- package/lib/shared-tree-core/messageCodecV5.js.map +1 -0
- package/lib/shared-tree-core/messageCodecs.d.ts.map +1 -1
- package/lib/shared-tree-core/messageCodecs.js +17 -48
- package/lib/shared-tree-core/messageCodecs.js.map +1 -1
- package/lib/shared-tree-core/{messageFormat.d.ts → messageFormatV1ToV4.d.ts} +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.d.ts.map +1 -0
- package/lib/shared-tree-core/{messageFormat.js → messageFormatV1ToV4.js} +1 -1
- package/lib/shared-tree-core/messageFormatV1ToV4.js.map +1 -0
- package/lib/shared-tree-core/messageFormatV5.d.ts +42 -0
- package/lib/shared-tree-core/messageFormatV5.d.ts.map +1 -0
- package/lib/shared-tree-core/messageFormatV5.js +16 -0
- package/lib/shared-tree-core/messageFormatV5.js.map +1 -0
- package/lib/shared-tree-core/messageTypes.d.ts +12 -2
- package/lib/shared-tree-core/messageTypes.d.ts.map +1 -1
- package/lib/shared-tree-core/messageTypes.js.map +1 -1
- package/lib/shared-tree-core/sequenceIdUtils.d.ts +1 -1
- package/lib/shared-tree-core/sequenceIdUtils.d.ts.map +1 -1
- package/lib/shared-tree-core/sequenceIdUtils.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +18 -5
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +176 -57
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/dirtyIndex.js +7 -7
- package/lib/simple-tree/api/dirtyIndex.js.map +1 -1
- package/lib/simple-tree/api/tree.d.ts +10 -0
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +4 -4
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/package.json +20 -20
- package/src/core/index.ts +1 -0
- package/src/core/rebase/index.ts +1 -0
- package/src/core/rebase/utils.ts +27 -0
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +2 -2
- package/src/shared-tree/sharedTree.ts +103 -46
- package/src/shared-tree/treeCheckout.ts +147 -98
- package/src/shared-tree-core/branch.ts +7 -0
- package/src/shared-tree-core/branchIdCodec.ts +28 -0
- package/src/shared-tree-core/editManager.ts +709 -437
- package/src/shared-tree-core/editManagerCodecs.ts +4 -164
- package/src/shared-tree-core/editManagerCodecsCommons.ts +236 -0
- package/src/shared-tree-core/editManagerCodecsV1toV4.ts +108 -0
- package/src/shared-tree-core/editManagerCodecsV5.ts +150 -0
- package/src/shared-tree-core/{editManagerFormat.ts → editManagerFormatCommons.ts} +17 -13
- package/src/shared-tree-core/editManagerFormatV1toV4.ts +42 -0
- package/src/shared-tree-core/editManagerFormatV5.ts +35 -0
- package/src/shared-tree-core/index.ts +3 -1
- package/src/shared-tree-core/messageCodecV1ToV4.ts +101 -0
- package/src/shared-tree-core/messageCodecV5.ts +128 -0
- package/src/shared-tree-core/messageCodecs.ts +16 -85
- package/src/shared-tree-core/messageFormatV5.ts +50 -0
- package/src/shared-tree-core/messageTypes.ts +15 -2
- package/src/shared-tree-core/sequenceIdUtils.ts +1 -1
- package/src/shared-tree-core/sharedTreeCore.ts +270 -84
- package/src/simple-tree/api/dirtyIndex.ts +7 -7
- package/src/simple-tree/api/tree.ts +15 -0
- package/src/simple-tree/core/treeNodeKernel.ts +4 -4
- package/dist/shared-tree-core/editManagerFormat.d.ts.map +0 -1
- package/dist/shared-tree-core/editManagerFormat.js.map +0 -1
- package/dist/shared-tree-core/messageFormat.d.ts.map +0 -1
- package/dist/shared-tree-core/messageFormat.js.map +0 -1
- package/lib/shared-tree-core/editManagerFormat.d.ts.map +0 -1
- package/lib/shared-tree-core/editManagerFormat.js.map +0 -1
- package/lib/shared-tree-core/messageFormat.d.ts.map +0 -1
- package/lib/shared-tree-core/messageFormat.js.map +0 -1
- /package/src/shared-tree-core/{messageFormat.ts → messageFormatV1ToV4.ts} +0 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { ErasedType, IFluidLoadable } from "@fluidframework/core-interfaces/internal";
|
|
7
7
|
import { assert, fail } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal";
|
|
9
|
-
import type { IIdCompressor } from "@fluidframework/id-compressor";
|
|
9
|
+
import type { IIdCompressor, StableId } from "@fluidframework/id-compressor";
|
|
10
10
|
import type {
|
|
11
11
|
IChannelView,
|
|
12
12
|
IFluidSerializer,
|
|
@@ -33,7 +33,6 @@ import {
|
|
|
33
33
|
ObjectNodeStoredSchema,
|
|
34
34
|
RevisionTagCodec,
|
|
35
35
|
SchemaVersion,
|
|
36
|
-
type TaggedChange,
|
|
37
36
|
type TreeFieldStoredSchema,
|
|
38
37
|
type TreeNodeSchemaIdentifier,
|
|
39
38
|
type TreeNodeStoredSchema,
|
|
@@ -62,8 +61,8 @@ import {
|
|
|
62
61
|
// eslint-disable-next-line import/no-internal-modules
|
|
63
62
|
import type { FormatV1 } from "../feature-libraries/schema-index/index.js";
|
|
64
63
|
import {
|
|
64
|
+
type BranchId,
|
|
65
65
|
type ClonableSchemaAndPolicy,
|
|
66
|
-
DefaultResubmitMachine,
|
|
67
66
|
type ExplicitCoreCodecVersions,
|
|
68
67
|
SharedTreeCore,
|
|
69
68
|
} from "../shared-tree-core/index.js";
|
|
@@ -189,6 +188,10 @@ const formatVersionToTopLevelCodecVersions = new Map<number, ExplicitCodecVersio
|
|
|
189
188
|
5,
|
|
190
189
|
{ forest: 1, schema: 2, detachedFieldIndex: 1, editManager: 4, message: 4, fieldBatch: 1 },
|
|
191
190
|
],
|
|
191
|
+
[
|
|
192
|
+
100, // SharedTreeFormatVersion.vSharedBranches
|
|
193
|
+
{ forest: 1, schema: 2, detachedFieldIndex: 1, editManager: 5, message: 5, fieldBatch: 1 },
|
|
194
|
+
],
|
|
192
195
|
]);
|
|
193
196
|
|
|
194
197
|
function getCodecVersions(formatVersion: number): ExplicitCodecVersions {
|
|
@@ -217,6 +220,8 @@ export class SharedTreeKernel
|
|
|
217
220
|
return this.checkout.storedSchema;
|
|
218
221
|
}
|
|
219
222
|
|
|
223
|
+
private readonly checkouts: Map<BranchId, TreeCheckout> = new Map();
|
|
224
|
+
|
|
220
225
|
/**
|
|
221
226
|
* The app-facing API for SharedTree implemented by this Kernel.
|
|
222
227
|
* @remarks
|
|
@@ -232,7 +237,7 @@ export class SharedTreeKernel
|
|
|
232
237
|
serializer: IFluidSerializer,
|
|
233
238
|
submitLocalMessage: (content: unknown, localOpMetadata?: unknown) => void,
|
|
234
239
|
lastSequenceNumber: () => number | undefined,
|
|
235
|
-
logger: ITelemetryLoggerExt | undefined,
|
|
240
|
+
private readonly logger: ITelemetryLoggerExt | undefined,
|
|
236
241
|
idCompressor: IIdCompressor,
|
|
237
242
|
optionsParam: SharedTreeOptionsInternal,
|
|
238
243
|
) {
|
|
@@ -319,16 +324,12 @@ export class SharedTreeKernel
|
|
|
319
324
|
idCompressor,
|
|
320
325
|
schema,
|
|
321
326
|
defaultSchemaPolicy,
|
|
322
|
-
|
|
323
|
-
(change: TaggedChange<SharedTreeChange>) =>
|
|
324
|
-
changeFamily.rebaser.invert(change, true, this.mintRevisionTag()),
|
|
325
|
-
changeEnricher,
|
|
326
|
-
),
|
|
327
|
+
undefined,
|
|
327
328
|
changeEnricher,
|
|
328
329
|
);
|
|
329
|
-
|
|
330
|
+
|
|
330
331
|
this.checkout = createTreeCheckout(idCompressor, this.mintRevisionTag, revisionTagCodec, {
|
|
331
|
-
branch:
|
|
332
|
+
branch: this.getLocalBranch(),
|
|
332
333
|
changeFamily,
|
|
333
334
|
schema,
|
|
334
335
|
forest,
|
|
@@ -340,39 +341,48 @@ export class SharedTreeKernel
|
|
|
340
341
|
disposeForksAfterTransaction: options.disposeForksAfterTransaction,
|
|
341
342
|
});
|
|
342
343
|
|
|
343
|
-
this.
|
|
344
|
-
|
|
344
|
+
this.registerCheckout("main", this.checkout);
|
|
345
|
+
|
|
346
|
+
this.view = {
|
|
347
|
+
contentSnapshot: () => this.contentSnapshot(),
|
|
348
|
+
exportSimpleSchema: () => this.exportSimpleSchema(),
|
|
349
|
+
exportVerbose: () => this.exportVerbose(),
|
|
350
|
+
viewWith: this.viewWith.bind(this),
|
|
351
|
+
viewSharedBranchWith: this.viewBranchWith.bind(this),
|
|
352
|
+
createSharedBranch: this.createSharedBranch.bind(this),
|
|
353
|
+
kernel: this,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private registerCheckout(branchId: BranchId, checkout: TreeCheckout): void {
|
|
358
|
+
this.checkouts.set(branchId, checkout);
|
|
359
|
+
const enricher = this.getCommitEnricher(branchId);
|
|
360
|
+
checkout.transaction.events.on("started", () => {
|
|
361
|
+
if (this.sharedObject.isAttached()) {
|
|
345
362
|
// It is currently forbidden to attach during a transaction, so transaction state changes can be ignored until after attaching.
|
|
346
|
-
|
|
363
|
+
enricher.startTransaction();
|
|
347
364
|
}
|
|
348
365
|
});
|
|
349
|
-
|
|
350
|
-
|
|
366
|
+
|
|
367
|
+
checkout.transaction.events.on("aborting", () => {
|
|
368
|
+
if (this.sharedObject.isAttached()) {
|
|
351
369
|
// It is currently forbidden to attach during a transaction, so transaction state changes can be ignored until after attaching.
|
|
352
|
-
|
|
370
|
+
enricher.abortTransaction();
|
|
353
371
|
}
|
|
354
372
|
});
|
|
355
|
-
|
|
356
|
-
if (sharedObject.isAttached()) {
|
|
373
|
+
checkout.transaction.events.on("committing", () => {
|
|
374
|
+
if (this.sharedObject.isAttached()) {
|
|
357
375
|
// It is currently forbidden to attach during a transaction, so transaction state changes can be ignored until after attaching.
|
|
358
|
-
|
|
376
|
+
enricher.commitTransaction();
|
|
359
377
|
}
|
|
360
378
|
});
|
|
361
|
-
|
|
362
|
-
if (event.type === "append" && sharedObject.isAttached()) {
|
|
363
|
-
if (
|
|
364
|
-
|
|
379
|
+
checkout.events.on("beforeBatch", (event) => {
|
|
380
|
+
if (event.type === "append" && this.sharedObject.isAttached()) {
|
|
381
|
+
if (checkout.transaction.isInProgress()) {
|
|
382
|
+
enricher.addTransactionCommits(event.newCommits);
|
|
365
383
|
}
|
|
366
384
|
}
|
|
367
385
|
});
|
|
368
|
-
|
|
369
|
-
this.view = {
|
|
370
|
-
contentSnapshot: () => this.contentSnapshot(),
|
|
371
|
-
exportSimpleSchema: () => this.exportSimpleSchema(),
|
|
372
|
-
exportVerbose: () => this.exportVerbose(),
|
|
373
|
-
viewWith: this.viewWith.bind(this),
|
|
374
|
-
kernel: this,
|
|
375
|
-
};
|
|
376
386
|
}
|
|
377
387
|
|
|
378
388
|
public exportVerbose(): VerboseTree | undefined {
|
|
@@ -415,18 +425,56 @@ export class SharedTreeKernel
|
|
|
415
425
|
TreeView<ReadSchema<TRoot>>;
|
|
416
426
|
}
|
|
417
427
|
|
|
428
|
+
public viewBranchWith<TRoot extends ImplicitFieldSchema>(
|
|
429
|
+
branchId: string,
|
|
430
|
+
config: TreeViewConfiguration<TRoot>,
|
|
431
|
+
): TreeView<TRoot>;
|
|
432
|
+
|
|
433
|
+
public viewBranchWith<TRoot extends ImplicitFieldSchema | UnsafeUnknownSchema>(
|
|
434
|
+
branchId: string,
|
|
435
|
+
config: TreeViewConfiguration<ReadSchema<TRoot>>,
|
|
436
|
+
): SchematizingSimpleTreeView<TRoot> & TreeView<ReadSchema<TRoot>> {
|
|
437
|
+
const compressedId = this.idCompressor.tryRecompress(branchId as StableId);
|
|
438
|
+
if (compressedId === undefined) {
|
|
439
|
+
throw new UsageError(`No branch found with id: ${branchId}`);
|
|
440
|
+
}
|
|
441
|
+
return this.getCheckout(compressedId).viewWith(
|
|
442
|
+
config,
|
|
443
|
+
) as SchematizingSimpleTreeView<TRoot> & TreeView<ReadSchema<TRoot>>;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private getCheckout(branchId: BranchId): TreeCheckout {
|
|
447
|
+
return this.checkouts.get(branchId) ?? this.checkoutBranch(branchId);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
private checkoutBranch(branchId: BranchId): TreeCheckout {
|
|
451
|
+
const checkout = this.checkout.branch();
|
|
452
|
+
checkout.switchBranch(this.getSharedBranch(branchId));
|
|
453
|
+
const enricher = new SharedTreeReadonlyChangeEnricher(
|
|
454
|
+
checkout.forest,
|
|
455
|
+
checkout.storedSchema,
|
|
456
|
+
checkout.removedRoots,
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
this.registerSharedBranchForEditing(branchId, enricher);
|
|
460
|
+
this.registerCheckout(branchId, checkout);
|
|
461
|
+
return checkout;
|
|
462
|
+
}
|
|
463
|
+
|
|
418
464
|
public override async loadCore(services: IChannelStorageService): Promise<void> {
|
|
419
465
|
await super.loadCore(services);
|
|
420
466
|
this.checkout.load();
|
|
421
467
|
}
|
|
422
468
|
|
|
423
469
|
public override didAttach(): void {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
470
|
+
for (const checkout of this.checkouts.values()) {
|
|
471
|
+
if (checkout.transaction.isInProgress()) {
|
|
472
|
+
// Attaching during a transaction is not currently supported.
|
|
473
|
+
// At least part of of the system is known to not handle this case correctly - commit enrichment - and there may be others.
|
|
474
|
+
throw new UsageError(
|
|
475
|
+
"Cannot attach while a transaction is in progress. Commit or abort the transaction before attaching.",
|
|
476
|
+
);
|
|
477
|
+
}
|
|
430
478
|
}
|
|
431
479
|
super.didAttach();
|
|
432
480
|
}
|
|
@@ -436,31 +484,35 @@ export class SharedTreeKernel
|
|
|
436
484
|
SharedTreeCore<SharedTreeEditBuilder, SharedTreeChange>["applyStashedOp"]
|
|
437
485
|
>
|
|
438
486
|
): void {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
487
|
+
for (const checkout of this.checkouts.values()) {
|
|
488
|
+
assert(
|
|
489
|
+
!checkout.transaction.isInProgress(),
|
|
490
|
+
0x674 /* Unexpected transaction is open while applying stashed ops */,
|
|
491
|
+
);
|
|
492
|
+
}
|
|
443
493
|
super.applyStashedOp(...args);
|
|
444
494
|
}
|
|
445
495
|
|
|
446
496
|
protected override submitCommit(
|
|
497
|
+
branchId: BranchId,
|
|
447
498
|
commit: GraphCommit<SharedTreeChange>,
|
|
448
499
|
schemaAndPolicy: ClonableSchemaAndPolicy,
|
|
449
500
|
isResubmit: boolean,
|
|
450
501
|
): void {
|
|
502
|
+
const checkout = this.getCheckout(branchId);
|
|
451
503
|
assert(
|
|
452
|
-
!
|
|
504
|
+
!checkout.transaction.isInProgress(),
|
|
453
505
|
0xaa6 /* Cannot submit a commit while a transaction is in progress */,
|
|
454
506
|
);
|
|
455
507
|
if (isResubmit) {
|
|
456
|
-
return super.submitCommit(commit, schemaAndPolicy, isResubmit);
|
|
508
|
+
return super.submitCommit(branchId, commit, schemaAndPolicy, isResubmit);
|
|
457
509
|
}
|
|
458
510
|
|
|
459
511
|
// Refrain from submitting new commits until they are validated by the checkout.
|
|
460
512
|
// This is not a strict requirement for correctness in our system, but in the event that there is a bug when applying commits to the checkout
|
|
461
513
|
// that causes a crash (e.g. in the forest), this will at least prevent this client from sending the problematic commit to any other clients.
|
|
462
|
-
|
|
463
|
-
super.submitCommit(commit, schemaAndPolicy, isResubmit),
|
|
514
|
+
checkout.onCommitValid(commit, () =>
|
|
515
|
+
super.submitCommit(branchId, commit, schemaAndPolicy, isResubmit),
|
|
464
516
|
);
|
|
465
517
|
}
|
|
466
518
|
|
|
@@ -561,6 +613,11 @@ export const SharedTreeFormatVersion = {
|
|
|
561
613
|
* Requires \@fluidframework/tree \>= 2.0.0.
|
|
562
614
|
*/
|
|
563
615
|
v5: 5,
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* For testing purposes only.
|
|
619
|
+
*/
|
|
620
|
+
vSharedBranches: 100,
|
|
564
621
|
} as const;
|
|
565
622
|
|
|
566
623
|
/**
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
type TreeNodeSchemaIdentifier,
|
|
48
48
|
type TreeNodeStoredSchema,
|
|
49
49
|
LeafNodeStoredSchema,
|
|
50
|
+
diffHistories,
|
|
50
51
|
} from "../core/index.js";
|
|
51
52
|
import {
|
|
52
53
|
type FieldBatchCodec,
|
|
@@ -310,6 +311,9 @@ export function createTreeCheckout(
|
|
|
310
311
|
args?.chunkCompressionStrategy,
|
|
311
312
|
idCompressor,
|
|
312
313
|
);
|
|
314
|
+
|
|
315
|
+
// TODO: If a branch is passed in, is it supposed to be local main?
|
|
316
|
+
// Otherwise shouldn't we set `isSharedBranch` to false?
|
|
313
317
|
const branch =
|
|
314
318
|
args?.branch ??
|
|
315
319
|
new SharedTreeBranch(
|
|
@@ -323,7 +327,7 @@ export function createTreeCheckout(
|
|
|
323
327
|
|
|
324
328
|
return new TreeCheckout(
|
|
325
329
|
branch,
|
|
326
|
-
|
|
330
|
+
true,
|
|
327
331
|
changeFamily,
|
|
328
332
|
schema,
|
|
329
333
|
forest,
|
|
@@ -366,7 +370,7 @@ export interface RevertMetrics {
|
|
|
366
370
|
export class TreeCheckout implements ITreeCheckoutFork {
|
|
367
371
|
public disposed = false;
|
|
368
372
|
|
|
369
|
-
private
|
|
373
|
+
private editLock: EditLock;
|
|
370
374
|
|
|
371
375
|
private readonly views = new Set<TreeView<ImplicitFieldSchema>>();
|
|
372
376
|
|
|
@@ -396,15 +400,15 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
396
400
|
|
|
397
401
|
public constructor(
|
|
398
402
|
branch: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>,
|
|
399
|
-
/** True if and only if this checkout is for a
|
|
400
|
-
public readonly
|
|
403
|
+
/** True if and only if this checkout is for a branch which is persisted and shared with other clients. */
|
|
404
|
+
public readonly isSharedBranch: boolean,
|
|
401
405
|
private readonly changeFamily: ChangeFamily<SharedTreeEditBuilder, SharedTreeChange>,
|
|
402
406
|
public readonly storedSchema: TreeStoredSchemaRepository,
|
|
403
407
|
public readonly forest: IEditableForest,
|
|
404
408
|
private readonly mintRevisionTag: () => RevisionTag,
|
|
405
409
|
private readonly revisionTagCodec: RevisionTagCodec,
|
|
406
410
|
private readonly idCompressor: IIdCompressor,
|
|
407
|
-
|
|
411
|
+
public removedRoots: DetachedFieldIndex = makeDetachedFieldIndex(
|
|
408
412
|
"repair",
|
|
409
413
|
revisionTagCodec,
|
|
410
414
|
idCompressor,
|
|
@@ -412,9 +416,29 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
412
416
|
/** Optional logger for telemetry. */
|
|
413
417
|
private readonly logger?: ITelemetryLoggerExt,
|
|
414
418
|
public readonly breaker: Breakable = new Breakable("TreeCheckout"),
|
|
415
|
-
|
|
419
|
+
public readonly disposeForksAfterTransaction = true,
|
|
416
420
|
) {
|
|
417
|
-
this.#transaction =
|
|
421
|
+
this.#transaction = this.createTransactionStack(branch);
|
|
422
|
+
this.editLock = new EditLock(this.#transaction.activeBranchEditor);
|
|
423
|
+
this.registerForBranchEvents();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private registerForBranchEvents(): void {
|
|
427
|
+
this.#transaction.branch.events.on("afterChange", this.onAfterBranchChange);
|
|
428
|
+
this.#transaction.activeBranchEvents.on("afterChange", this.onAfterChange);
|
|
429
|
+
this.#transaction.activeBranchEvents.on("ancestryTrimmed", this.onAncestryTrimmed);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private unregisterFromBranchEvents(): void {
|
|
433
|
+
this.#transaction.branch.events.off("afterChange", this.onAfterBranchChange);
|
|
434
|
+
this.#transaction.activeBranchEvents.off("afterChange", this.onAfterChange);
|
|
435
|
+
this.#transaction.activeBranchEvents.off("ancestryTrimmed", this.onAncestryTrimmed);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
private createTransactionStack(
|
|
439
|
+
branch: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>,
|
|
440
|
+
): SquashingTransactionStack<SharedTreeEditBuilder, SharedTreeChange> {
|
|
441
|
+
return new SquashingTransactionStack(
|
|
418
442
|
branch,
|
|
419
443
|
(commits) => {
|
|
420
444
|
const revision = this.mintRevisionTag();
|
|
@@ -450,58 +474,6 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
450
474
|
};
|
|
451
475
|
},
|
|
452
476
|
);
|
|
453
|
-
|
|
454
|
-
this.editLock = new EditLock(this.#transaction.activeBranchEditor);
|
|
455
|
-
|
|
456
|
-
branch.events.on("afterChange", (event) => {
|
|
457
|
-
// The following logic allows revertibles to be generated for the change.
|
|
458
|
-
// Currently only appends (including merges and transaction commits) are supported.
|
|
459
|
-
if (event.type === "append") {
|
|
460
|
-
// TODO:#20949: When the SharedTree is detached, these commits will already have been garbage collected.
|
|
461
|
-
// Figure out a way to generate revertibles before the commits are garbage collected.
|
|
462
|
-
for (const commit of event.newCommits) {
|
|
463
|
-
const kind = event.type === "append" ? event.kind : CommitKind.Default;
|
|
464
|
-
const { change, revision } = commit;
|
|
465
|
-
|
|
466
|
-
const getRevertible = hasSchemaChange(change)
|
|
467
|
-
? undefined
|
|
468
|
-
: (onRevertibleDisposed?: (revertible: RevertibleAlpha) => void) => {
|
|
469
|
-
if (!withinEventContext) {
|
|
470
|
-
throw new UsageError(
|
|
471
|
-
"Cannot get a revertible outside of the context of a changed event.",
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
if (this.revertibleCommitBranches.get(revision) !== undefined) {
|
|
475
|
-
throw new UsageError(
|
|
476
|
-
"Cannot generate the same revertible more than once. Note that this can happen when multiple changed event listeners are registered.",
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
|
-
const revertible = this.createRevertible(
|
|
480
|
-
revision,
|
|
481
|
-
kind,
|
|
482
|
-
this,
|
|
483
|
-
onRevertibleDisposed,
|
|
484
|
-
);
|
|
485
|
-
this.revertibleCommitBranches.set(
|
|
486
|
-
revision,
|
|
487
|
-
this.#transaction.activeBranch.fork(commit),
|
|
488
|
-
);
|
|
489
|
-
this.revertibles.add(revertible);
|
|
490
|
-
return revertible;
|
|
491
|
-
};
|
|
492
|
-
|
|
493
|
-
let withinEventContext = true;
|
|
494
|
-
this.#events.emit("changed", { isLocal: true, kind }, getRevertible);
|
|
495
|
-
withinEventContext = false;
|
|
496
|
-
}
|
|
497
|
-
} else if (this.isRemoteChangeEvent(event)) {
|
|
498
|
-
// TODO: figure out how to plumb through commit kind info for remote changes
|
|
499
|
-
this.#events.emit("changed", { isLocal: false, kind: CommitKind.Default });
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
this.#transaction.activeBranchEvents.on("afterChange", this.onAfterChange);
|
|
504
|
-
this.#transaction.activeBranchEvents.on("ancestryTrimmed", this.onAncestryTrimmed);
|
|
505
477
|
}
|
|
506
478
|
|
|
507
479
|
public exportVerbose(): VerboseTree | undefined {
|
|
@@ -522,6 +494,55 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
522
494
|
}
|
|
523
495
|
}
|
|
524
496
|
|
|
497
|
+
private readonly onAfterBranchChange = (
|
|
498
|
+
event: SharedTreeBranchChange<SharedTreeChange>,
|
|
499
|
+
): void => {
|
|
500
|
+
// The following logic allows revertibles to be generated for the change.
|
|
501
|
+
// Currently only appends (including merges and transaction commits) are supported.
|
|
502
|
+
if (event.type === "append") {
|
|
503
|
+
// TODO:#20949: When the SharedTree is detached, these commits will already have been garbage collected.
|
|
504
|
+
// Figure out a way to generate revertibles before the commits are garbage collected.
|
|
505
|
+
for (const commit of event.newCommits) {
|
|
506
|
+
const kind = event.type === "append" ? event.kind : CommitKind.Default;
|
|
507
|
+
const { change, revision } = commit;
|
|
508
|
+
|
|
509
|
+
const getRevertible = hasSchemaChange(change)
|
|
510
|
+
? undefined
|
|
511
|
+
: (onRevertibleDisposed?: (revertible: RevertibleAlpha) => void) => {
|
|
512
|
+
if (!withinEventContext) {
|
|
513
|
+
throw new UsageError(
|
|
514
|
+
"Cannot get a revertible outside of the context of a changed event.",
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
if (this.revertibleCommitBranches.get(revision) !== undefined) {
|
|
518
|
+
throw new UsageError(
|
|
519
|
+
"Cannot generate the same revertible more than once. Note that this can happen when multiple changed event listeners are registered.",
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
const revertible = this.createRevertible(
|
|
523
|
+
revision,
|
|
524
|
+
kind,
|
|
525
|
+
this,
|
|
526
|
+
onRevertibleDisposed,
|
|
527
|
+
);
|
|
528
|
+
this.revertibleCommitBranches.set(
|
|
529
|
+
revision,
|
|
530
|
+
this.#transaction.activeBranch.fork(commit),
|
|
531
|
+
);
|
|
532
|
+
this.revertibles.add(revertible);
|
|
533
|
+
return revertible;
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
let withinEventContext = true;
|
|
537
|
+
this.#events.emit("changed", { isLocal: true, kind }, getRevertible);
|
|
538
|
+
withinEventContext = false;
|
|
539
|
+
}
|
|
540
|
+
} else if (this.isRemoteChangeEvent(event)) {
|
|
541
|
+
// TODO: figure out how to plumb through commit kind info for remote changes
|
|
542
|
+
this.#events.emit("changed", { isLocal: false, kind: CommitKind.Default });
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
|
|
525
546
|
private readonly onAfterChange = (event: SharedTreeBranchChange<SharedTreeChange>): void => {
|
|
526
547
|
this.editLock.lock();
|
|
527
548
|
this.#events.emit("beforeBatch", event);
|
|
@@ -531,34 +552,7 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
531
552
|
? this.#transaction.activeBranch.getHead().revision
|
|
532
553
|
: event.change.revision;
|
|
533
554
|
|
|
534
|
-
|
|
535
|
-
for (const change of event.change.change.changes) {
|
|
536
|
-
if (change.type === "data") {
|
|
537
|
-
const delta = intoDelta(tagChange(change.innerChange, revision));
|
|
538
|
-
this.withCombinedVisitor((visitor) => {
|
|
539
|
-
visitDelta(delta, visitor, this.removedRoots, revision);
|
|
540
|
-
});
|
|
541
|
-
} else if (change.type === "schema") {
|
|
542
|
-
// Schema changes from a current to a new schema are expected to be backwards compatible.
|
|
543
|
-
// This guarantees that all data in the forest (which is valid before the schema change)
|
|
544
|
-
// is also valid under the new schema.
|
|
545
|
-
// Note however, that such schema changes may in some cases be rolled back:
|
|
546
|
-
// Case 1: A transaction with a schema change may be aborted.
|
|
547
|
-
// The transaction may have made some data changes that would render some trees invalid
|
|
548
|
-
// under the old schema, but these changes will also be rolled back, thereby putting the forest
|
|
549
|
-
// back in the state before the transaction, which is valid under the original (reinstated) schema.
|
|
550
|
-
// Case 2: A branch with a schema change may be rebased such that the schema change (because
|
|
551
|
-
// of a constraint) is no longer applied.
|
|
552
|
-
// Such a branch may contain data changes that would render some trees invalid under the
|
|
553
|
-
// original schema. These data changes may not necessarily be rolled back.
|
|
554
|
-
// They will however be rebased over the rollback of the schema change. This rebasing will
|
|
555
|
-
// ensure that these data changes are muted if they would render some trees invalid under the
|
|
556
|
-
// original (reinstated) schema.
|
|
557
|
-
this.storedSchema.apply(change.innerChange.schema.new);
|
|
558
|
-
} else {
|
|
559
|
-
fail(0xad1 /* Unknown Shared Tree change type. */);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
555
|
+
this.applyChange(event.change.change, revision);
|
|
562
556
|
}
|
|
563
557
|
this.#events.emit("afterBatch");
|
|
564
558
|
this.editLock.unlock();
|
|
@@ -567,6 +561,38 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
567
561
|
}
|
|
568
562
|
};
|
|
569
563
|
|
|
564
|
+
// Revision is the revision of the commit, if any, which caused this change.
|
|
565
|
+
private applyChange(change: SharedTreeChange, revision?: RevisionTag): void {
|
|
566
|
+
// Conflicts due to schema will be empty and thus are not applied.
|
|
567
|
+
for (const innerChange of change.changes) {
|
|
568
|
+
if (innerChange.type === "data") {
|
|
569
|
+
const delta = intoDelta(tagChange(innerChange.innerChange, revision));
|
|
570
|
+
this.withCombinedVisitor((visitor) => {
|
|
571
|
+
visitDelta(delta, visitor, this.removedRoots, revision);
|
|
572
|
+
});
|
|
573
|
+
} else if (innerChange.type === "schema") {
|
|
574
|
+
// Schema changes from a current to a new schema are expected to be backwards compatible.
|
|
575
|
+
// This guarantees that all data in the forest (which is valid before the schema change)
|
|
576
|
+
// is also valid under the new schema.
|
|
577
|
+
// Note however, that such schema changes may in some cases be rolled back:
|
|
578
|
+
// Case 1: A transaction with a schema change may be aborted.
|
|
579
|
+
// The transaction may have made some data changes that would render some trees invalid
|
|
580
|
+
// under the old schema, but these changes will also be rolled back, thereby putting the forest
|
|
581
|
+
// back in the state before the transaction, which is valid under the original (reinstated) schema.
|
|
582
|
+
// Case 2: A branch with a schema change may be rebased such that the schema change (because
|
|
583
|
+
// of a constraint) is no longer applied.
|
|
584
|
+
// Such a branch may contain data changes that would render some trees invalid under the
|
|
585
|
+
// original schema. These data changes may not necessarily be rolled back.
|
|
586
|
+
// They will however be rebased over the rollback of the schema change. This rebasing will
|
|
587
|
+
// ensure that these data changes are muted if they would render some trees invalid under the
|
|
588
|
+
// original (reinstated) schema.
|
|
589
|
+
this.storedSchema.apply(innerChange.innerChange.schema.new);
|
|
590
|
+
} else {
|
|
591
|
+
fail(0xad1 /* Unknown Shared Tree change type. */);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
570
596
|
private readonly onAncestryTrimmed = (revisions: RevisionTag[]): void => {
|
|
571
597
|
// When the branch is trimmed, we can garbage collect any repair data whose latest relevant revision is one of the
|
|
572
598
|
// trimmed revisions.
|
|
@@ -730,7 +756,7 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
730
756
|
* To avoid updating observers of the view state with intermediate results during a transaction,
|
|
731
757
|
* use {@link ITreeCheckout#branch} and {@link ISharedTreeFork#merge}.
|
|
732
758
|
*/
|
|
733
|
-
|
|
759
|
+
#transaction: SquashingTransactionStack<SharedTreeEditBuilder, SharedTreeChange>;
|
|
734
760
|
|
|
735
761
|
public branch(): TreeCheckout {
|
|
736
762
|
this.checkNotDisposed(
|
|
@@ -743,7 +769,7 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
743
769
|
const forest = this.forest.clone(storedSchema, anchors);
|
|
744
770
|
const checkout = new TreeCheckout(
|
|
745
771
|
branch,
|
|
746
|
-
|
|
772
|
+
false,
|
|
747
773
|
this.changeFamily,
|
|
748
774
|
storedSchema,
|
|
749
775
|
forest,
|
|
@@ -759,6 +785,29 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
759
785
|
return checkout;
|
|
760
786
|
}
|
|
761
787
|
|
|
788
|
+
public switchBranch(
|
|
789
|
+
branch: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>,
|
|
790
|
+
): void {
|
|
791
|
+
// TODO: Dispose old branch, if necessary
|
|
792
|
+
assert(!this.#transaction.isInProgress(), "Cannot switch branches during a transaction");
|
|
793
|
+
const diff = diffHistories(
|
|
794
|
+
this.changeFamily.rebaser,
|
|
795
|
+
this.#transaction.branch.getHead(),
|
|
796
|
+
branch.getHead(),
|
|
797
|
+
this.mintRevisionTag,
|
|
798
|
+
);
|
|
799
|
+
|
|
800
|
+
this.unregisterFromBranchEvents();
|
|
801
|
+
|
|
802
|
+
this.#transaction = this.createTransactionStack(branch);
|
|
803
|
+
this.editLock = new EditLock(this.#transaction.activeBranchEditor);
|
|
804
|
+
this.registerForBranchEvents();
|
|
805
|
+
|
|
806
|
+
// TODO: Rework eventing
|
|
807
|
+
this.applyChange(diff);
|
|
808
|
+
this.#events.emit("afterBatch");
|
|
809
|
+
}
|
|
810
|
+
|
|
762
811
|
public rebase(checkout: TreeCheckout): void {
|
|
763
812
|
this.checkNotDisposed(
|
|
764
813
|
"The target of the branch rebase has been disposed and cannot be rebased.",
|
|
@@ -772,8 +821,8 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
772
821
|
0x9af /* A view cannot be rebased while it has a pending transaction */,
|
|
773
822
|
);
|
|
774
823
|
assert(
|
|
775
|
-
checkout.
|
|
776
|
-
0xa5d /*
|
|
824
|
+
!checkout.isSharedBranch,
|
|
825
|
+
0xa5d /* Shared branches cannot be rebased onto another branch. */,
|
|
777
826
|
);
|
|
778
827
|
|
|
779
828
|
checkout.#transaction.activeBranch.rebaseOnto(this.#transaction.activeBranch);
|
|
@@ -804,8 +853,8 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
804
853
|
checkout.transaction.commit();
|
|
805
854
|
}
|
|
806
855
|
this.#transaction.activeBranch.merge(checkout.#transaction.activeBranch);
|
|
807
|
-
if (disposeMerged && checkout.
|
|
808
|
-
// Dispose the merged checkout unless it is
|
|
856
|
+
if (disposeMerged && !checkout.isSharedBranch) {
|
|
857
|
+
// Dispose the merged checkout unless it is a shared branch.
|
|
809
858
|
checkout[disposeSymbol]();
|
|
810
859
|
}
|
|
811
860
|
}
|
|
@@ -961,10 +1010,10 @@ export class TreeCheckout implements ITreeCheckoutFork {
|
|
|
961
1010
|
*/
|
|
962
1011
|
private isRemoteChangeEvent(event: SharedTreeBranchChange<SharedTreeChange>): boolean {
|
|
963
1012
|
return (
|
|
964
|
-
// Remote changes are only ever applied to
|
|
965
|
-
|
|
966
|
-
// Remote changes are applied to the
|
|
967
|
-
// No other rebases are allowed on
|
|
1013
|
+
// Remote changes are only ever applied to shared branches
|
|
1014
|
+
this.isSharedBranch &&
|
|
1015
|
+
// Remote changes are applied to the branch by rebasing it onto the trunk.
|
|
1016
|
+
// No other rebases are allowed on shared branches, so we can use this to detect remote changes.
|
|
968
1017
|
event.type === "rebase"
|
|
969
1018
|
);
|
|
970
1019
|
}
|
|
@@ -1020,7 +1069,7 @@ class EditLock {
|
|
|
1020
1069
|
* Edits the tree by calling the methods of the editor passed into the {@link EditLock} constructor.
|
|
1021
1070
|
* @remarks Edits will throw an error if the lock is currently locked.
|
|
1022
1071
|
*/
|
|
1023
|
-
public editor: ISharedTreeEditor;
|
|
1072
|
+
public readonly editor: ISharedTreeEditor;
|
|
1024
1073
|
private locked = false;
|
|
1025
1074
|
|
|
1026
1075
|
/**
|
|
@@ -24,6 +24,13 @@ import {
|
|
|
24
24
|
type RebaseStatsWithDuration,
|
|
25
25
|
} from "../core/index.js";
|
|
26
26
|
import { hasSome, defineLazyCachedProperty } from "../util/index.js";
|
|
27
|
+
import type {
|
|
28
|
+
OpSpaceCompressedId,
|
|
29
|
+
SessionSpaceCompressedId,
|
|
30
|
+
} from "@fluidframework/id-compressor";
|
|
31
|
+
|
|
32
|
+
export type BranchId = SessionSpaceCompressedId | "main";
|
|
33
|
+
export type EncodedBranchId = OpSpaceCompressedId;
|
|
27
34
|
|
|
28
35
|
/**
|
|
29
36
|
* Describes a change to a `SharedTreeBranch`. Each of the following event types provides a `change` which contains the net change to the branch (or is undefined if there was no net change):
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
IIdCompressor,
|
|
8
|
+
OpSpaceCompressedId,
|
|
9
|
+
SessionId,
|
|
10
|
+
} from "@fluidframework/id-compressor";
|
|
11
|
+
import type { BranchId } from "./branch.js";
|
|
12
|
+
|
|
13
|
+
export function encodeBranchId(
|
|
14
|
+
idCompressor: IIdCompressor,
|
|
15
|
+
branchId: BranchId,
|
|
16
|
+
): OpSpaceCompressedId | undefined {
|
|
17
|
+
return branchId === "main" ? undefined : idCompressor.normalizeToOpSpace(branchId);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function decodeBranchId(
|
|
21
|
+
idCompressor: IIdCompressor,
|
|
22
|
+
encoded: OpSpaceCompressedId | undefined,
|
|
23
|
+
context: { readonly originatorId: SessionId },
|
|
24
|
+
): BranchId {
|
|
25
|
+
return encoded === undefined
|
|
26
|
+
? "main"
|
|
27
|
+
: idCompressor.normalizeToSessionSpace(encoded, context.originatorId);
|
|
28
|
+
}
|