@fluidframework/merge-tree 2.70.0-360753 → 2.70.0-361248

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.
@@ -81,7 +81,7 @@ export interface IMergeTreeSegmentDelta {
81
81
  /**
82
82
  * A property set containing changes to properties on this segment.
83
83
  *
84
- * @remarks - Deleting a property is represented using `null` as the value.
84
+ * @remarks Deleting a property is represented using `null` as the value.
85
85
  * @example
86
86
  *
87
87
  * An annotation change which deleted the property "foo" and set "bar" to 5 would be represented as:
@@ -101,7 +101,7 @@ export interface IMergeTreeDeltaOpArgs {
101
101
  /**
102
102
  * The {@link IMergeTreeOp} corresponding to the delta.
103
103
  *
104
- * @remarks - This is useful for determining the type of change (see {@link (MergeTreeDeltaType:type)}).
104
+ * @remarks This is useful for determining the type of change (see {@link (MergeTreeDeltaType:type)}).
105
105
  */
106
106
  readonly op: IMergeTreeOp;
107
107
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTreeDeltaCallback.js","sourceRoot":"","sources":["../src/mergeTreeDeltaCallback.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACvC;;;;;;OAMG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;OAGG;IACH,KAAK,EAAE,CAAC,CAAC;IACT;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;OAGG;IACH,YAAY,EAAE,CAAC,CAAC;CACP,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { ISegment } from \"./mergeTreeNodes.js\";\n// eslint-disable-next-line import/no-deprecated\nimport type { IMergeTreeGroupMsg, IMergeTreeOp, MergeTreeDeltaType } from \"./ops.js\";\nimport type { PropertySet } from \"./properties.js\";\n\n/**\n * @legacy @beta\n */\nexport type MergeTreeDeltaOperationType =\n\t| typeof MergeTreeDeltaType.ANNOTATE\n\t| typeof MergeTreeDeltaType.INSERT\n\t| typeof MergeTreeDeltaType.REMOVE\n\t| typeof MergeTreeDeltaType.OBLITERATE;\n\n/**\n * Enum-like constant defining the types of \"maintenance\" events on a merge tree.\n * Maintenance events correspond to structural segment changes or acks of pending segments.\n *\n * Note: these values are assigned negative integers to avoid clashing with `MergeTreeDeltaType`.\n * @legacy @beta\n */\nexport const MergeTreeMaintenanceType = {\n\t/**\n\t * Notification that a segment \"append\" has occurred, i.e. two adjacent segments have been merged.\n\t * BEWARE: `deltaSegments` on the corresponding event will contain both the merged segment and the latter\n\t * segment, pre-merge.\n\t * For example, if the merge tree originally had two adjacent segments [A][B] and called A.append(B) to get\n\t * segment [AB], `deltaSegments` would contain [AB] and [B].\n\t */\n\tAPPEND: -1,\n\t/**\n\t * Notification that a segment has been split in two.\n\t * `deltaSegments` on the corresponding event will contain the resulting two segments.\n\t */\n\tSPLIT: -2,\n\t/**\n\t * Notification that a segment has been unlinked (i.e. removed) from the MergeTree.\n\t * This occurs on leaf segments during Zamboni when the segment's tracking collection is empty\n\t * (e.g., not being tracked for undo/redo).\n\t * It also occurs on internal merge tree segments when re-packing children to maintain tree balancing invariants.\n\t */\n\tUNLINK: -3,\n\t/**\n\t * Notification that a local change has been acknowledged by the server.\n\t * This means that it has made the round trip to the server and has had a sequence number assigned.\n\t */\n\tACKNOWLEDGED: -4,\n} as const;\n/**\n * @legacy @beta\n */\nexport type MergeTreeMaintenanceType =\n\t(typeof MergeTreeMaintenanceType)[keyof typeof MergeTreeMaintenanceType];\n\n/**\n * @legacy @beta\n */\nexport type MergeTreeDeltaOperationTypes =\n\t| MergeTreeDeltaOperationType\n\t| MergeTreeMaintenanceType;\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeDeltaCallbackArgs<\n\tTOperationType extends MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationType,\n> {\n\t/**\n\t * The type of operation that affected segments in the merge-tree.\n\t * The affected segments can be accessed via {@link IMergeTreeDeltaCallbackArgs.deltaSegments|deltaSegments}.\n\t *\n\t * See {@link MergeTreeDeltaOperationType} and {@link (MergeTreeMaintenanceType:type)} for possible values.\n\t */\n\treadonly operation: TOperationType;\n\n\t/**\n\t * A list of deltas describing actions taken on segments.\n\t *\n\t * Deltas are not guaranteed to be in any particular order.\n\t */\n\treadonly deltaSegments: IMergeTreeSegmentDelta[];\n}\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeSegmentDelta {\n\t/**\n\t * The segment this delta affected.\n\t */\n\tsegment: ISegment;\n\n\t/**\n\t * A property set containing changes to properties on this segment.\n\t *\n\t * @remarks - Deleting a property is represented using `null` as the value.\n\t * @example\n\t *\n\t * An annotation change which deleted the property \"foo\" and set \"bar\" to 5 would be represented as:\n\t * `{ foo: null, bar: 5 }`.\n\t */\n\tpropertyDeltas?: PropertySet;\n}\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeDeltaOpArgs {\n\t/**\n\t * The group op which contains the operation\n\t * if there operation is part of a group op.\n\t */\n\t// eslint-disable-next-line import/no-deprecated\n\treadonly groupOp?: IMergeTreeGroupMsg;\n\n\t/**\n\t * The {@link IMergeTreeOp} corresponding to the delta.\n\t *\n\t * @remarks - This is useful for determining the type of change (see {@link (MergeTreeDeltaType:type)}).\n\t */\n\treadonly op: IMergeTreeOp;\n\n\t/**\n\t * The {@link @fluidframework/protocol-definitions#ISequencedDocumentMessage} corresponding to this acknowledged change.\n\t *\n\t * This field is omitted for deltas corresponding to unacknowledged changes.\n\t */\n\treadonly sequencedMessage?: ISequencedDocumentMessage;\n\n\t/**\n\t * Set to true if this delta is being performed as part of a rollback of unsent local changes.\n\t */\n\treadonly rollback?: true;\n}\n\n/**\n * @internal\n */\nexport type MergeTreeDeltaCallback = (\n\topArgs: IMergeTreeDeltaOpArgs,\n\tdeltaArgs: IMergeTreeDeltaCallbackArgs,\n) => void;\n\n/**\n * @legacy @beta\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface IMergeTreeMaintenanceCallbackArgs\n\textends IMergeTreeDeltaCallbackArgs<MergeTreeMaintenanceType> {}\n\n/**\n * @internal\n */\nexport type MergeTreeMaintenanceCallback = (\n\tMaintenanceArgs: IMergeTreeMaintenanceCallbackArgs,\n\topArgs: IMergeTreeDeltaOpArgs | undefined,\n) => void;\n"]}
1
+ {"version":3,"file":"mergeTreeDeltaCallback.js","sourceRoot":"","sources":["../src/mergeTreeDeltaCallback.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACvC;;;;;;OAMG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;OAGG;IACH,KAAK,EAAE,CAAC,CAAC;IACT;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;OAGG;IACH,YAAY,EAAE,CAAC,CAAC;CACP,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { ISegment } from \"./mergeTreeNodes.js\";\n// eslint-disable-next-line import/no-deprecated\nimport type { IMergeTreeGroupMsg, IMergeTreeOp, MergeTreeDeltaType } from \"./ops.js\";\nimport type { PropertySet } from \"./properties.js\";\n\n/**\n * @legacy @beta\n */\nexport type MergeTreeDeltaOperationType =\n\t| typeof MergeTreeDeltaType.ANNOTATE\n\t| typeof MergeTreeDeltaType.INSERT\n\t| typeof MergeTreeDeltaType.REMOVE\n\t| typeof MergeTreeDeltaType.OBLITERATE;\n\n/**\n * Enum-like constant defining the types of \"maintenance\" events on a merge tree.\n * Maintenance events correspond to structural segment changes or acks of pending segments.\n *\n * Note: these values are assigned negative integers to avoid clashing with `MergeTreeDeltaType`.\n * @legacy @beta\n */\nexport const MergeTreeMaintenanceType = {\n\t/**\n\t * Notification that a segment \"append\" has occurred, i.e. two adjacent segments have been merged.\n\t * BEWARE: `deltaSegments` on the corresponding event will contain both the merged segment and the latter\n\t * segment, pre-merge.\n\t * For example, if the merge tree originally had two adjacent segments [A][B] and called A.append(B) to get\n\t * segment [AB], `deltaSegments` would contain [AB] and [B].\n\t */\n\tAPPEND: -1,\n\t/**\n\t * Notification that a segment has been split in two.\n\t * `deltaSegments` on the corresponding event will contain the resulting two segments.\n\t */\n\tSPLIT: -2,\n\t/**\n\t * Notification that a segment has been unlinked (i.e. removed) from the MergeTree.\n\t * This occurs on leaf segments during Zamboni when the segment's tracking collection is empty\n\t * (e.g., not being tracked for undo/redo).\n\t * It also occurs on internal merge tree segments when re-packing children to maintain tree balancing invariants.\n\t */\n\tUNLINK: -3,\n\t/**\n\t * Notification that a local change has been acknowledged by the server.\n\t * This means that it has made the round trip to the server and has had a sequence number assigned.\n\t */\n\tACKNOWLEDGED: -4,\n} as const;\n/**\n * @legacy @beta\n */\nexport type MergeTreeMaintenanceType =\n\t(typeof MergeTreeMaintenanceType)[keyof typeof MergeTreeMaintenanceType];\n\n/**\n * @legacy @beta\n */\nexport type MergeTreeDeltaOperationTypes =\n\t| MergeTreeDeltaOperationType\n\t| MergeTreeMaintenanceType;\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeDeltaCallbackArgs<\n\tTOperationType extends MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationType,\n> {\n\t/**\n\t * The type of operation that affected segments in the merge-tree.\n\t * The affected segments can be accessed via {@link IMergeTreeDeltaCallbackArgs.deltaSegments|deltaSegments}.\n\t *\n\t * See {@link MergeTreeDeltaOperationType} and {@link (MergeTreeMaintenanceType:type)} for possible values.\n\t */\n\treadonly operation: TOperationType;\n\n\t/**\n\t * A list of deltas describing actions taken on segments.\n\t *\n\t * Deltas are not guaranteed to be in any particular order.\n\t */\n\treadonly deltaSegments: IMergeTreeSegmentDelta[];\n}\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeSegmentDelta {\n\t/**\n\t * The segment this delta affected.\n\t */\n\tsegment: ISegment;\n\n\t/**\n\t * A property set containing changes to properties on this segment.\n\t *\n\t * @remarks Deleting a property is represented using `null` as the value.\n\t * @example\n\t *\n\t * An annotation change which deleted the property \"foo\" and set \"bar\" to 5 would be represented as:\n\t * `{ foo: null, bar: 5 }`.\n\t */\n\tpropertyDeltas?: PropertySet;\n}\n\n/**\n * @legacy @beta\n */\nexport interface IMergeTreeDeltaOpArgs {\n\t/**\n\t * The group op which contains the operation\n\t * if there operation is part of a group op.\n\t */\n\t// eslint-disable-next-line import/no-deprecated\n\treadonly groupOp?: IMergeTreeGroupMsg;\n\n\t/**\n\t * The {@link IMergeTreeOp} corresponding to the delta.\n\t *\n\t * @remarks This is useful for determining the type of change (see {@link (MergeTreeDeltaType:type)}).\n\t */\n\treadonly op: IMergeTreeOp;\n\n\t/**\n\t * The {@link @fluidframework/protocol-definitions#ISequencedDocumentMessage} corresponding to this acknowledged change.\n\t *\n\t * This field is omitted for deltas corresponding to unacknowledged changes.\n\t */\n\treadonly sequencedMessage?: ISequencedDocumentMessage;\n\n\t/**\n\t * Set to true if this delta is being performed as part of a rollback of unsent local changes.\n\t */\n\treadonly rollback?: true;\n}\n\n/**\n * @internal\n */\nexport type MergeTreeDeltaCallback = (\n\topArgs: IMergeTreeDeltaOpArgs,\n\tdeltaArgs: IMergeTreeDeltaCallbackArgs,\n) => void;\n\n/**\n * @legacy @beta\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-empty-interface\nexport interface IMergeTreeMaintenanceCallbackArgs\n\textends IMergeTreeDeltaCallbackArgs<MergeTreeMaintenanceType> {}\n\n/**\n * @internal\n */\nexport type MergeTreeMaintenanceCallback = (\n\tMaintenanceArgs: IMergeTreeMaintenanceCallbackArgs,\n\topArgs: IMergeTreeDeltaOpArgs | undefined,\n) => void;\n"]}
@@ -340,7 +340,7 @@ export declare class CollaborationWindow {
340
340
  * Semantically, `localSeq`s provide an ordering on in-flight merge-tree operations:
341
341
  * for operations stamped with localSeqs `a` and `b`, `a < b` if and only if `a` was submitted before `b`.
342
342
  *
343
- * @remarks - This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree
343
+ * @remarks This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree
344
344
  * at op submission time rather than only at ack time. This enables more natural state tracking for in-flight ops.
345
345
  *
346
346
  * It's useful to stamp ops with such an incrementing counter because it enables reasoning about which segments existed from
@@ -304,7 +304,7 @@ export class CollaborationWindow {
304
304
  * Semantically, `localSeq`s provide an ordering on in-flight merge-tree operations:
305
305
  * for operations stamped with localSeqs `a` and `b`, `a < b` if and only if `a` was submitted before `b`.
306
306
  *
307
- * @remarks - This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree
307
+ * @remarks This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree
308
308
  * at op submission time rather than only at ack time. This enables more natural state tracking for in-flight ops.
309
309
  *
310
310
  * It's useful to stamp ops with such an incrementing counter because it enables reasoning about which segments existed from
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTreeNodes.js","sourceRoot":"","sources":["../src/mergeTreeNodes.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { AttributionKey } from \"@fluidframework/runtime-definitions/internal\";\n\nimport type { IAttributionCollection } from \"./attributionCollection.js\";\nimport {\n\tLocalClientId,\n\tNonCollabClient,\n\tUnassignedSequenceNumber,\n\tUniversalSequenceNumber,\n} from \"./constants.js\";\nimport { LocalReferenceCollection, type LocalReferencePosition } from \"./localReference.js\";\nimport { TrackingGroupCollection, type ITrackingGroup } from \"./mergeTreeTracking.js\";\nimport type { IJSONSegment, IMarkerDef, ReferenceType } from \"./ops.js\";\nimport { computeHierarchicalOrdinal } from \"./ordinal.js\";\nimport type { PartialSequenceLengths } from \"./partialLengths.js\";\nimport { LocalDefaultPerspective, PriorPerspective, type Perspective } from \"./perspective.js\";\nimport { type PropertySet, clone, createMap, type MapLike } from \"./properties.js\";\nimport type { ReferencePosition } from \"./referencePositions.js\";\nimport type { SegmentGroupCollection } from \"./segmentGroupCollection.js\";\nimport {\n\thasProp,\n\tisInserted,\n\tisMergeNodeInfo as isMergeNode,\n\tisRemoved,\n\toverwriteInfo,\n\ttype IHasInsertionInfo,\n\ttype IMergeNodeInfo,\n\ttype IHasRemovalInfo,\n\ttype SegmentWithInfo,\n\ttype ISegmentInsideObliterateInfo,\n\tisInsideObliterate,\n} from \"./segmentInfos.js\";\nimport type { PropertiesManager } from \"./segmentPropertiesManager.js\";\nimport type { Side } from \"./sequencePlace.js\";\nimport type { OperationStamp, SliceRemoveOperationStamp } from \"./stamps.js\";\n\n/**\n * This interface exposes internal things to dds that leverage merge tree,\n * like sequence and matrix.\n *\n * We use tiered interface to control visibility of segment properties.\n * This sits between ISegment and ISegmentPrivate. It should only expose\n * things tagged internal.\n *\n * Everything added here beyond ISegment should be optional to keep the ability\n * to implicitly convert between the tiered interfaces.\n *\n * @internal\n */\nexport interface ISegmentInternal extends ISegment {\n\tlocalRefs?: LocalReferenceCollection;\n\t/**\n\t * Whether or not this segment is a special segment denoting the start or\n\t * end of the tree\n\t *\n\t * Endpoint segments are imaginary segments positioned immediately before or\n\t * after the tree. These segments cannot be referenced by regular operations\n\t * and exist primarily as a bucket for local references to slide onto during\n\t * deletion of regular segments.\n\t */\n\treadonly endpointType?: \"start\" | \"end\";\n}\n\n/**\n * We use tiered interface to control visibility of segment properties.\n * This is the lowest interface and is not exported, it site below ISegment and ISegmentInternal.\n * It should only expose unexported things.\n *\n * Everything added here beyond ISegmentInternal should be optional to keep the ability\n * to implicitly convert between the tiered interfaces.\n *\n * someday we may split tree leaves from segments, but for now they are the same\n * this is just a convenience type that makes it clear that we need something that is both a segment and a leaf node\n */\nexport interface ISegmentPrivate extends ISegmentInternal {\n\tsegmentGroups?: SegmentGroupCollection;\n\tpropertyManager?: PropertiesManager;\n}\n/**\n * Segment leafs are segments that have both IMergeNodeInfo and IHasInsertionInfo. This means they\n * are inserted at a position, and bound via their parent MergeBlock to the merge tree. MergeBlocks'\n * children are either a segment leaf, or another merge block for interior nodes of the tree. When working\n * within the tree it is generally unnecessary to use type coercions methods common to the infos, and segment\n * leafs, as the children of MergeBlocks are already well typed. However, when segments come from outside the\n * merge tree, like via client's public methods, it becomes necessary to use the type coercions methods\n * to ensure the passed in segment objects are correctly bound to the merge tree.\n */\nexport type ISegmentLeaf = SegmentWithInfo<IMergeNodeInfo & IHasInsertionInfo>;\n/**\n * A type-guard which determines if the segment has segment leaf, and\n * returns true if it does, along with applying strong typing.\n * @param nodeLike - The segment-like object to check.\n * @returns True if the segment is a segment leaf, otherwise false.\n */\nexport const isSegmentLeaf = (segmentLike: unknown): segmentLike is ISegmentLeaf =>\n\tisInserted(segmentLike) && isMergeNode(segmentLike);\n\n/**\n * Converts a segment-like object to a segment leaf object if possible.\n *\n * @param segmentLike - The segment-like object to convert.\n * @returns The segment leaf if the conversion is possible, otherwise undefined.\n */\nexport const toSegmentLeaf = (segmentLike: unknown): ISegmentLeaf | undefined =>\n\tisSegmentLeaf(segmentLike) ? segmentLike : undefined;\n/**\n * Asserts that the segment is a segment leaf. Usage of this function should not produce a user facing error.\n *\n * @param segmentLike - The segment-like object to check.\n * @throws Will throw an error if the segment is not a segment leaf.\n */\nexport const assertSegmentLeaf: (segmentLike: unknown) => asserts segmentLike is ISegmentLeaf =\n\t(segmentLike) => assert(isSegmentLeaf(segmentLike), 0xaab /* must be segment leaf */);\n/**\n * This type is used for building MergeBlocks from segments and other MergeBlocks. We need this\n * type as segments may not yet be bound to the tree, so lack merge node info which is required for\n * segment leafs.\n */\nexport type IMergeNodeBuilder = MergeBlock | SegmentWithInfo<IHasInsertionInfo>;\n\n/**\n * This type is used by MergeBlocks to define their children, which are either segments or other\n * MergeBlocks.\n */\nexport type IMergeNode = MergeBlock | ISegmentLeaf;\n\n/**\n * A segment representing a portion of the merge tree.\n * Segments are leaf nodes of the merge tree and contain data.\n * @legacy @beta\n */\nexport interface ISegment {\n\treadonly type: string;\n\n\treadonly trackingCollection: TrackingGroupCollection;\n\n\t/**\n\t * The length of the contents of the node.\n\t */\n\tcachedLength: number;\n\t/**\n\t * Stores attribution keys associated with offsets of this segment.\n\t * This data is only persisted if MergeTree's `attributions.track` flag is set to true.\n\t * Pending segments (i.e. ones that only exist locally and haven't been acked by the server) also have\n\t * `attribution === undefined` until ack.\n\t *\n\t * Keys can be used opaquely with an IAttributor or a container runtime that provides attribution.\n\t * @remarks There are plans to make the shape of the data stored extensible in a couple ways:\n\t *\n\t * 1. Injection of custom attribution information associated with the segment (ex: copy-paste of\n\t * content but keeping the old attribution information).\n\t *\n\t * 2. Storage of multiple \"channels\" of information (ex: track property changes separately from insertion,\n\t * or only attribute certain property modifications, etc.)\n\t */\n\tattribution?: IAttributionCollection<AttributionKey>;\n\n\t/**\n\t * Properties that have been added to this segment via annotation.\n\t */\n\tproperties?: PropertySet;\n\n\tclone(): ISegment;\n\tcanAppend(segment: ISegment): boolean;\n\tappend(segment: ISegment): void;\n\tsplitAt(pos: number): ISegment | undefined;\n\t// Changing this to something other than any would break consumers.\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\ttoJSONObject(): any;\n\tisLeaf(): this is ISegment;\n}\n\n/**\n * Determine if a segment has been removed.\n * @legacy @beta\n */\nexport function segmentIsRemoved(segment: ISegment): boolean {\n\treturn isRemoved(segment);\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISegmentAction<TClientData> {\n\t// eslint-disable-next-line @typescript-eslint/prefer-function-type\n\t(\n\t\tsegment: ISegment,\n\t\tpos: number,\n\t\trefSeq: number,\n\t\tclientId: number,\n\t\tstart: number,\n\t\tend: number,\n\t\taccum: TClientData,\n\t): boolean;\n}\nexport interface ISegmentChanges {\n\tnext?: SegmentWithInfo<IHasInsertionInfo>;\n\treplaceCurrent?: SegmentWithInfo<IHasInsertionInfo>;\n}\n\nexport interface InsertContext {\n\tcandidateSegment?: SegmentWithInfo<IHasInsertionInfo>;\n\tleaf: (segment: ISegmentLeaf | undefined, pos: number, ic: InsertContext) => ISegmentChanges;\n\tcontinuePredicate?: (continueFromBlock: MergeBlock) => boolean;\n}\n\nexport interface ObliterateInfo {\n\tstart: LocalReferencePosition;\n\tstartSide: Side;\n\tend: LocalReferencePosition;\n\tendSide: Side;\n\trefSeq: number;\n\tstamp: SliceRemoveOperationStamp;\n\tsegmentGroup: SegmentGroup | undefined;\n\t/**\n\t * Defined only for unacked obliterates.\n\t *\n\t * Contains all segments inserted into the range this obliterate affects where at the time of insertion,\n\t * this obliterate was the newest concurrent obliterate that overlapped the insertion point (this information\n\t * is relevant for the tiebreak policy of allowing last-obliterater to insert).\n\t *\n\t * We need to keep this around for unacked ops because on reconnect, outstanding local obliterates may have set `obliteratePrecedingInsertion`\n\t * (tiebreak) on segments they no longer apply to, since the reissued obliterate may affect a smaller range than the original one when content\n\t * near the obliterate's endpoints was removed by another client between the time of the original obliterate and reissuing.\n\t */\n\ttiebreakTrackingGroup: ITrackingGroup | undefined;\n}\n\nexport interface SegmentGroup {\n\tsegments: ISegmentLeaf[];\n\tpreviousProps?: PropertySet[];\n\tlocalSeq?: number;\n\trefSeq: number;\n\tobliterateInfo?: ObliterateInfo;\n}\n\n/**\n * Note that the actual branching factor of the MergeTree is `MaxNodesInBlock - 1`. This is because\n * the MergeTree always inserts first, then checks for overflow and splits if the child count equals\n * `MaxNodesInBlock`. (i.e., `MaxNodesInBlock` contains 1 extra slot for temporary storage to\n * facilitate splits.)\n */\nexport const MaxNodesInBlock = 8;\nexport class MergeBlock implements Partial<IMergeNodeInfo> {\n\tpublic children: IMergeNode[];\n\tpublic needsScour?: boolean;\n\tpublic parent?: MergeBlock;\n\tpublic index: number = 0;\n\tpublic ordinal: string = \"\";\n\tpublic cachedLength: number | undefined = 0;\n\n\t/**\n\t * Maps each tile label in this block to the rightmost (i.e. furthest) marker associated with that tile label.\n\t * When combined with the tree structure of MergeBlocks, this allows accelerated queries for nearest tile\n\t * with a certain label before a given position\n\t */\n\tpublic rightmostTiles: Readonly<MapLike<Marker>>;\n\t/**\n\t * Maps each tile label in this block to the leftmost (i.e. nearest) marker associated with that tile label.\n\t * When combined with the tree structure of MergeBlocks, this allows accelerated queries for nearest tile\n\t * with a certain label before a given position\n\t */\n\tpublic leftmostTiles: Readonly<MapLike<Marker>>;\n\n\tisLeaf(): this is ISegmentInternal {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Supports querying the total length of all descendants of this IMergeBlock from the perspective of any\n\t * (clientId, seq) within the collab window.\n\t *\n\t * @remarks This is only optional for implementation reasons (internal nodes can be created/moved without\n\t * immediately initializing the partial lengths). Aside from mid-update on tree operations, these lengths\n\t * objects are always defined.\n\t */\n\tpartialLengths?: PartialSequenceLengths;\n\n\tpublic constructor(public childCount: number) {\n\t\t// Suppression needed due to the way the merge tree children are initialized - we\n\t\t// allocate 8 children blocks, but any unused blocks are not counted in the childCount.\n\t\t// Using Array.from leads to unused children being undefined, which are counted in childCount.\n\t\t// eslint-disable-next-line unicorn/no-new-array\n\t\tthis.children = new Array<IMergeNode>(MaxNodesInBlock);\n\t\tthis.rightmostTiles = createMap<Marker>();\n\t\tthis.leftmostTiles = createMap<Marker>();\n\t}\n\n\tpublic setOrdinal(child: IMergeNode, index: number): void {\n\t\tconst childCount = this.childCount;\n\t\tassert(\n\t\t\tchildCount >= 1 && childCount <= MaxNodesInBlock,\n\t\t\t0x040 /* \"Child count is not within [1,8] range!\" */,\n\t\t);\n\t\tchild.ordinal = computeHierarchicalOrdinal(\n\t\t\tMaxNodesInBlock,\n\t\t\tchildCount,\n\t\t\tthis.ordinal,\n\t\t\tindex === 0 ? undefined : this.children[index - 1]?.ordinal,\n\t\t);\n\t}\n}\nexport function assignChild<C extends IMergeNodeBuilder>(\n\tparent: MergeBlock,\n\tchild: C,\n\tindex: number,\n\tupdateOrdinal = true,\n): asserts child is C & IMergeNodeInfo {\n\tconst node = Object.assign<C, IMergeNodeInfo>(child, {\n\t\tparent,\n\t\tindex,\n\t\tordinal: hasProp(child, \"ordinal\", \"string\") ? child.ordinal : \"\",\n\t});\n\tif (updateOrdinal) {\n\t\tparent.setOrdinal(node, index);\n\t}\n\tparent.children[index] = node;\n}\n\nexport function seqLTE(seq: number, minOrRefSeq: number): boolean {\n\treturn seq !== UnassignedSequenceNumber && seq <= minOrRefSeq;\n}\n\n/**\n * @legacy @beta\n */\nexport abstract class BaseSegment implements ISegment {\n\tpublic cachedLength: number = 0;\n\n\tpublic readonly trackingCollection: TrackingGroupCollection = new TrackingGroupCollection(\n\t\tthis,\n\t);\n\t/***/\n\tpublic attribution?: IAttributionCollection<AttributionKey>;\n\n\tpublic properties?: PropertySet;\n\tpublic abstract readonly type: string;\n\tpublic constructor(properties?: PropertySet) {\n\t\tif (properties !== undefined) {\n\t\t\tthis.properties = clone(properties);\n\t\t}\n\t}\n\n\tpublic hasProperty(key: string): boolean {\n\t\treturn !!this.properties && this.properties[key] !== undefined;\n\t}\n\n\tpublic isLeaf(): this is ISegment {\n\t\treturn true;\n\t}\n\n\tprotected cloneInto(b: ISegment): void {\n\t\tconst seg: ISegmentPrivate = b;\n\t\tif (isInserted(this)) {\n\t\t\toverwriteInfo<IHasInsertionInfo>(seg, {\n\t\t\t\tinsert: this.insert,\n\t\t\t});\n\t\t}\n\t\t// TODO: deep clone properties\n\t\tseg.properties = clone(this.properties);\n\t\tif (isRemoved(this)) {\n\t\t\toverwriteInfo<IHasRemovalInfo>(seg, {\n\t\t\t\tremoves: [...this.removes],\n\t\t\t});\n\t\t}\n\n\t\tseg.attribution = this.attribution?.clone();\n\t}\n\n\tpublic canAppend(segment: ISegment): boolean {\n\t\treturn false;\n\t}\n\n\tprotected addSerializedProps(jseg: IJSONSegment): void {\n\t\tif (this.properties) {\n\t\t\tjseg.props = { ...this.properties };\n\t\t}\n\t}\n\t// This has to return any type because the return type is different for different segment types.\n\t// TODO: If possible, change the return type to match what should be returned for each segment type.\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic abstract toJSONObject(): any;\n\n\tpublic splitAt(pos: number): ISegment | undefined {\n\t\tif (pos <= 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst leafSegment: ISegmentPrivate | undefined = this.createSplitSegmentAt(pos);\n\n\t\tif (!leafSegment) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (isMergeNode(this)) {\n\t\t\toverwriteInfo<IMergeNodeInfo>(leafSegment, {\n\t\t\t\tindex: this.index + 1,\n\t\t\t\t// Give the leaf a temporary yet valid ordinal.\n\t\t\t\t// when this segment is put in the tree, it will get its real ordinal,\n\t\t\t\t// but this ordinal meets all the necessary invariants for now.\n\t\t\t\t// Ordinals exist purely for lexicographical sort order and use a small set of valid bytes for each string character.\n\t\t\t\t// The extra handling fromCodePoint has for things like surrogate pairs is therefore unnecessary.\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\t\t\tordinal: this.ordinal + String.fromCharCode(0),\n\t\t\t\tparent: this.parent,\n\t\t\t});\n\t\t}\n\n\t\tif (isInserted(this)) {\n\t\t\toverwriteInfo<IHasInsertionInfo>(leafSegment, { insert: this.insert });\n\t\t}\n\t\tif (isRemoved(this)) {\n\t\t\toverwriteInfo<IHasRemovalInfo>(leafSegment, {\n\t\t\t\tremoves: [...this.removes],\n\t\t\t});\n\t\t}\n\t\tif (isInsideObliterate(this)) {\n\t\t\toverwriteInfo<ISegmentInsideObliterateInfo>(leafSegment, {\n\t\t\t\tobliteratePrecedingInsertion: this.obliteratePrecedingInsertion,\n\t\t\t\tinsertionRefSeqStamp: this.insertionRefSeqStamp,\n\t\t\t});\n\t\t}\n\n\t\tthis.trackingCollection.copyTo(leafSegment);\n\t\tif (this.attribution) {\n\t\t\tleafSegment.attribution = this.attribution.splitAt(pos);\n\t\t}\n\n\t\treturn leafSegment;\n\t}\n\n\tpublic abstract clone(): ISegment;\n\n\tpublic append(other: ISegment): void {\n\t\t// Note: Must call 'appendLocalRefs' before modifying this segment's length as\n\t\t// 'this.cachedLength' is used to adjust the offsets of the local refs.\n\t\tLocalReferenceCollection.append(this, other);\n\t\tif (this.attribution) {\n\t\t\tassert(\n\t\t\t\tother.attribution !== undefined,\n\t\t\t\t0x4bd /* attribution should be set on appendee */,\n\t\t\t);\n\t\t\tthis.attribution.append(other.attribution);\n\t\t} else {\n\t\t\tassert(\n\t\t\t\tother.attribution === undefined,\n\t\t\t\t0x4be /* attribution should not be set on appendee */,\n\t\t\t);\n\t\t}\n\n\t\tthis.cachedLength ??= 0;\n\t\tthis.cachedLength += other.cachedLength;\n\t}\n\n\tprotected abstract createSplitSegmentAt(pos: number): BaseSegment | undefined;\n}\n\n/**\n * The special-cased property key that tracks the id of a {@link Marker}.\n *\n * @remarks In general, marker ids should be accessed using the inherent method\n * {@link Marker.getId}. Marker ids should not be updated after creation.\n * @legacy @beta\n */\nexport const reservedMarkerIdKey = \"markerId\";\n\n/**\n * @internal\n */\nexport const reservedMarkerSimpleTypeKey = \"markerSimpleType\";\n\n/**\n * @legacy @beta\n */\nexport interface IJSONMarkerSegment extends IJSONSegment {\n\tmarker: IMarkerDef;\n}\n\n/**\n * Markers are a special kind of segment that do not hold any content.\n *\n * Markers with a reference type of {@link ReferenceType.Tile} support spatially\n * accelerated queries for finding the next marker to the left or right of it in\n * sub-linear time. This is useful, for example, in the case of jumping from the\n * start of a paragraph to the end, assuming a paragraph is bound by markers at\n * the start and end.\n *\n * @legacy @beta\n */\nexport class Marker extends BaseSegment implements ReferencePosition, ISegment {\n\tpublic static readonly type = \"Marker\";\n\tpublic static is(segment: ISegment): segment is Marker {\n\t\treturn segment.type === Marker.type;\n\t}\n\tpublic readonly type = Marker.type;\n\n\tpublic static make(refType: ReferenceType, props?: PropertySet): Marker {\n\t\treturn new Marker(refType, props);\n\t}\n\n\tconstructor(\n\t\tpublic refType: ReferenceType,\n\t\tprops?: PropertySet,\n\t) {\n\t\tsuper(props);\n\t\tthis.cachedLength = 1;\n\t}\n\n\ttoJSONObject(): IJSONMarkerSegment {\n\t\tconst obj: IJSONMarkerSegment = { marker: { refType: this.refType } };\n\t\tsuper.addSerializedProps(obj);\n\t\treturn obj;\n\t}\n\n\tstatic fromJSONObject(spec: IJSONSegment): Marker | undefined {\n\t\tif (spec && typeof spec === \"object\" && \"marker\" in spec) {\n\t\t\treturn Marker.make((spec.marker as Marker).refType, spec.props as PropertySet);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tclone(): Marker {\n\t\tconst b = Marker.make(this.refType, this.properties);\n\t\tthis.cloneInto(b);\n\t\treturn b;\n\t}\n\n\tgetSegment(): Marker {\n\t\treturn this;\n\t}\n\n\tgetOffset(): number {\n\t\treturn 0;\n\t}\n\n\tgetProperties(): PropertySet | undefined {\n\t\treturn this.properties;\n\t}\n\n\tgetId(): string | undefined {\n\t\treturn this.properties?.[reservedMarkerIdKey] as string;\n\t}\n\n\ttoString(): string {\n\t\treturn `M${this.getId()}`;\n\t}\n\n\tprotected createSplitSegmentAt(pos: number): undefined {\n\t\treturn undefined;\n\t}\n\n\tcanAppend(segment: ISegment): boolean {\n\t\treturn false;\n\t}\n\n\tappend(): void {\n\t\tthrow new Error(\"Can not append to marker\");\n\t}\n}\n\n/**\n * Returns a stamp that occurs at the minimum sequence number.\n * @privateRemarks\n * This is a free function over something obtainable on CollaborationWindow to avoid exposing Perspective\n * and OperationStamp from the package (even internally), at least for now.\n * If/when `Client`'s API is refactored to be structured similarly to MergeTree (so that SharedString passes in\n * things closer to `Perspective`s when calling methods on `Client` rather than refSeq/localSeq/clientId etc),\n * it may be more reasonable to expose this more directly on `CollaborationWindow`.\n */\nexport function getMinSeqStamp(collabWindow: CollaborationWindow): OperationStamp {\n\treturn { seq: collabWindow.minSeq, clientId: NonCollabClient };\n}\n\n/**\n * Returns a perspective representing a readonly client's view of the tree at the minimum sequence number.\n * @privateRemarks\n * This is a free function over something obtainable on CollaborationWindow to avoid exposing Perspective\n * and OperationStamp from the package (even internally), at least for now.\n * If/when `Client`'s API is refactored to be structured similarly to MergeTree (so that SharedString passes in\n * things closer to `Perspective`s when calling methods on `Client` rather than refSeq/localSeq/clientId etc),\n * it may be more reasonable to expose this more directly on `CollaborationWindow`.\n */\nexport function getMinSeqPerspective(collabWindow: CollaborationWindow): Perspective {\n\treturn new PriorPerspective(collabWindow.minSeq, NonCollabClient);\n}\n\n/**\n * This class is used to track facts about the current window of collaboration. This window is defined by the server\n * specified minimum sequence number to the last sequence number seen. Additionally, it track state for outstanding\n * local operations.\n * @internal\n */\nexport class CollaborationWindow {\n\tclientId = LocalClientId;\n\tcollaborating = false;\n\n\t/**\n\t * Lowest-numbered segment in window; no client can reference a state before this one\n\t */\n\tminSeq = 0;\n\t/**\n\t * Highest-numbered segment in window and current reference sequence number for this client.\n\t */\n\tcurrentSeq = 0;\n\n\t/**\n\t * Highest-numbered localSeq used for a pending segment.\n\t * Semantically, `localSeq`s provide an ordering on in-flight merge-tree operations:\n\t * for operations stamped with localSeqs `a` and `b`, `a < b` if and only if `a` was submitted before `b`.\n\t *\n\t * @remarks - This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree\n\t * at op submission time rather than only at ack time. This enables more natural state tracking for in-flight ops.\n\t *\n\t * It's useful to stamp ops with such an incrementing counter because it enables reasoning about which segments existed from\n\t * the perspective of the local client at a given point in 'un-acked' time, which is necessary to support the reconnect flow.\n\t *\n\t * For example, imagine a client with initial state \"123456\" submits some ops to create the text \"123456ABC\".\n\t * If they insert the \"C\" first, then \"B\", then \"A\", their local segment state might look like this:\n\t * ```js\n\t * [\n\t * { seq: 0, text: \"1234\" },\n\t * { seq: 5, text: \"56\" },\n\t * { localSeq: 3, seq: UnassignedSequenceNumber, text: \"A\" },\n\t * { localSeq: 2, seq: UnassignedSequenceNumber, text: \"B\" },\n\t * { localSeq: 1, seq: UnassignedSequenceNumber, text: \"C\" },\n\t * ]\n\t * ```\n\t * (note that localSeq tracks the localSeq at which a segment was inserted)\n\t *\n\t * Suppose the client then disconnects and reconnects before any of its insertions are acked. The reconnect flow will necessitate\n\t * that the client regenerates and resubmits ops based on its current segment state as well as the original op that was sent.\n\t *\n\t * It will generate the ops\n\t * 1. \\{ pos: 6, text: \"C\" \\}\n\t * 2. \\{ pos: 6, text: \"B\" \\}\n\t * 3. \\{ pos: 6, text: \"A\" \\}\n\t *\n\t * since when submitting the first op, remote clients don't know that this client is about to submit the \"A\" and \"B\".\n\t *\n\t * On the other hand, imagine if the client had originally submitted the ops in the order \"A\", \"B\", \"C\"\n\t * such that the segments' local state was instead:\n\t *\n\t * ```js\n\t * [\n\t * { seq: 0, text: \"1234\" },\n\t * { seq: 5, text: \"56\" },\n\t * { localSeq: 1, seq: UnassignedSequenceNumber, text: \"A\" },\n\t * { localSeq: 2, seq: UnassignedSequenceNumber, text: \"B\" },\n\t * { localSeq: 3, seq: UnassignedSequenceNumber, text: \"C\" },\n\t * ]\n\t * ```\n\t *\n\t * The resubmitted ops should instead be:\n\t * 1. \\{ pos: 6, text: \"A\" \\}\n\t * 2. \\{ pos: 7, text: \"B\" \\}\n\t * 3. \\{ pos: 8, text: \"C\" \\}\n\t *\n\t * since remote clients will have seen the \"A\" when processing the \"B\" as well as both the \"A\" and \"B\" when processing the \"C\".\n\t * As can be seen, the list of resubmitted ops is different in the two cases despite the merge-tree's segment state only differing\n\t * in `localSeq`.\n\t *\n\t * This example is a bit simplified from the general scenario: since no remote clients modified the merge-tree while the client\n\t * was disconnected, the resubmitted ops end up matching the original ops exactly.\n\t * However, this is not generally true: the production reconnect code takes into account visibility of segments based on both acked\n\t * and local information as appropriate.\n\t * Nonetheless, this simple scenario is enough to understand why it's useful to be able to determine if a segment should be visible\n\t * from a given (seq, localSeq) perspective.\n\t */\n\tlocalSeq = 0;\n\n\tpublic localPerspective: Perspective = new LocalDefaultPerspective(this.clientId);\n\n\tpublic loadFrom(a: CollaborationWindow): void {\n\t\tthis.clientId = a.clientId;\n\t\tthis.collaborating = a.collaborating;\n\t\tthis.minSeq = a.minSeq;\n\t\tthis.currentSeq = a.currentSeq;\n\t}\n\n\tpublic mintNextLocalOperationStamp(): OperationStamp {\n\t\tif (this.collaborating) {\n\t\t\tthis.localSeq++;\n\t\t}\n\n\t\treturn {\n\t\t\tseq: this.collaborating ? UnassignedSequenceNumber : UniversalSequenceNumber,\n\t\t\tclientId: this.clientId,\n\t\t\tlocalSeq: this.localSeq,\n\t\t};\n\t}\n}\n\n/**\n * Compares two numbers.\n */\nexport const compareNumbers = (a: number, b: number): number => a - b;\n\n/**\n * Compares two strings.\n */\nexport const compareStrings = (a: string, b: string): number => a.localeCompare(b);\n"]}
1
+ {"version":3,"file":"mergeTreeNodes.js","sourceRoot":"","sources":["../src/mergeTreeNodes.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { AttributionKey } from \"@fluidframework/runtime-definitions/internal\";\n\nimport type { IAttributionCollection } from \"./attributionCollection.js\";\nimport {\n\tLocalClientId,\n\tNonCollabClient,\n\tUnassignedSequenceNumber,\n\tUniversalSequenceNumber,\n} from \"./constants.js\";\nimport { LocalReferenceCollection, type LocalReferencePosition } from \"./localReference.js\";\nimport { TrackingGroupCollection, type ITrackingGroup } from \"./mergeTreeTracking.js\";\nimport type { IJSONSegment, IMarkerDef, ReferenceType } from \"./ops.js\";\nimport { computeHierarchicalOrdinal } from \"./ordinal.js\";\nimport type { PartialSequenceLengths } from \"./partialLengths.js\";\nimport { LocalDefaultPerspective, PriorPerspective, type Perspective } from \"./perspective.js\";\nimport { type PropertySet, clone, createMap, type MapLike } from \"./properties.js\";\nimport type { ReferencePosition } from \"./referencePositions.js\";\nimport type { SegmentGroupCollection } from \"./segmentGroupCollection.js\";\nimport {\n\thasProp,\n\tisInserted,\n\tisMergeNodeInfo as isMergeNode,\n\tisRemoved,\n\toverwriteInfo,\n\ttype IHasInsertionInfo,\n\ttype IMergeNodeInfo,\n\ttype IHasRemovalInfo,\n\ttype SegmentWithInfo,\n\ttype ISegmentInsideObliterateInfo,\n\tisInsideObliterate,\n} from \"./segmentInfos.js\";\nimport type { PropertiesManager } from \"./segmentPropertiesManager.js\";\nimport type { Side } from \"./sequencePlace.js\";\nimport type { OperationStamp, SliceRemoveOperationStamp } from \"./stamps.js\";\n\n/**\n * This interface exposes internal things to dds that leverage merge tree,\n * like sequence and matrix.\n *\n * We use tiered interface to control visibility of segment properties.\n * This sits between ISegment and ISegmentPrivate. It should only expose\n * things tagged internal.\n *\n * Everything added here beyond ISegment should be optional to keep the ability\n * to implicitly convert between the tiered interfaces.\n *\n * @internal\n */\nexport interface ISegmentInternal extends ISegment {\n\tlocalRefs?: LocalReferenceCollection;\n\t/**\n\t * Whether or not this segment is a special segment denoting the start or\n\t * end of the tree\n\t *\n\t * Endpoint segments are imaginary segments positioned immediately before or\n\t * after the tree. These segments cannot be referenced by regular operations\n\t * and exist primarily as a bucket for local references to slide onto during\n\t * deletion of regular segments.\n\t */\n\treadonly endpointType?: \"start\" | \"end\";\n}\n\n/**\n * We use tiered interface to control visibility of segment properties.\n * This is the lowest interface and is not exported, it site below ISegment and ISegmentInternal.\n * It should only expose unexported things.\n *\n * Everything added here beyond ISegmentInternal should be optional to keep the ability\n * to implicitly convert between the tiered interfaces.\n *\n * someday we may split tree leaves from segments, but for now they are the same\n * this is just a convenience type that makes it clear that we need something that is both a segment and a leaf node\n */\nexport interface ISegmentPrivate extends ISegmentInternal {\n\tsegmentGroups?: SegmentGroupCollection;\n\tpropertyManager?: PropertiesManager;\n}\n/**\n * Segment leafs are segments that have both IMergeNodeInfo and IHasInsertionInfo. This means they\n * are inserted at a position, and bound via their parent MergeBlock to the merge tree. MergeBlocks'\n * children are either a segment leaf, or another merge block for interior nodes of the tree. When working\n * within the tree it is generally unnecessary to use type coercions methods common to the infos, and segment\n * leafs, as the children of MergeBlocks are already well typed. However, when segments come from outside the\n * merge tree, like via client's public methods, it becomes necessary to use the type coercions methods\n * to ensure the passed in segment objects are correctly bound to the merge tree.\n */\nexport type ISegmentLeaf = SegmentWithInfo<IMergeNodeInfo & IHasInsertionInfo>;\n/**\n * A type-guard which determines if the segment has segment leaf, and\n * returns true if it does, along with applying strong typing.\n * @param nodeLike - The segment-like object to check.\n * @returns True if the segment is a segment leaf, otherwise false.\n */\nexport const isSegmentLeaf = (segmentLike: unknown): segmentLike is ISegmentLeaf =>\n\tisInserted(segmentLike) && isMergeNode(segmentLike);\n\n/**\n * Converts a segment-like object to a segment leaf object if possible.\n *\n * @param segmentLike - The segment-like object to convert.\n * @returns The segment leaf if the conversion is possible, otherwise undefined.\n */\nexport const toSegmentLeaf = (segmentLike: unknown): ISegmentLeaf | undefined =>\n\tisSegmentLeaf(segmentLike) ? segmentLike : undefined;\n/**\n * Asserts that the segment is a segment leaf. Usage of this function should not produce a user facing error.\n *\n * @param segmentLike - The segment-like object to check.\n * @throws Will throw an error if the segment is not a segment leaf.\n */\nexport const assertSegmentLeaf: (segmentLike: unknown) => asserts segmentLike is ISegmentLeaf =\n\t(segmentLike) => assert(isSegmentLeaf(segmentLike), 0xaab /* must be segment leaf */);\n/**\n * This type is used for building MergeBlocks from segments and other MergeBlocks. We need this\n * type as segments may not yet be bound to the tree, so lack merge node info which is required for\n * segment leafs.\n */\nexport type IMergeNodeBuilder = MergeBlock | SegmentWithInfo<IHasInsertionInfo>;\n\n/**\n * This type is used by MergeBlocks to define their children, which are either segments or other\n * MergeBlocks.\n */\nexport type IMergeNode = MergeBlock | ISegmentLeaf;\n\n/**\n * A segment representing a portion of the merge tree.\n * Segments are leaf nodes of the merge tree and contain data.\n * @legacy @beta\n */\nexport interface ISegment {\n\treadonly type: string;\n\n\treadonly trackingCollection: TrackingGroupCollection;\n\n\t/**\n\t * The length of the contents of the node.\n\t */\n\tcachedLength: number;\n\t/**\n\t * Stores attribution keys associated with offsets of this segment.\n\t * This data is only persisted if MergeTree's `attributions.track` flag is set to true.\n\t * Pending segments (i.e. ones that only exist locally and haven't been acked by the server) also have\n\t * `attribution === undefined` until ack.\n\t *\n\t * Keys can be used opaquely with an IAttributor or a container runtime that provides attribution.\n\t * @remarks There are plans to make the shape of the data stored extensible in a couple ways:\n\t *\n\t * 1. Injection of custom attribution information associated with the segment (ex: copy-paste of\n\t * content but keeping the old attribution information).\n\t *\n\t * 2. Storage of multiple \"channels\" of information (ex: track property changes separately from insertion,\n\t * or only attribute certain property modifications, etc.)\n\t */\n\tattribution?: IAttributionCollection<AttributionKey>;\n\n\t/**\n\t * Properties that have been added to this segment via annotation.\n\t */\n\tproperties?: PropertySet;\n\n\tclone(): ISegment;\n\tcanAppend(segment: ISegment): boolean;\n\tappend(segment: ISegment): void;\n\tsplitAt(pos: number): ISegment | undefined;\n\t// Changing this to something other than any would break consumers.\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\ttoJSONObject(): any;\n\tisLeaf(): this is ISegment;\n}\n\n/**\n * Determine if a segment has been removed.\n * @legacy @beta\n */\nexport function segmentIsRemoved(segment: ISegment): boolean {\n\treturn isRemoved(segment);\n}\n\n/**\n * @legacy @beta\n */\nexport interface ISegmentAction<TClientData> {\n\t// eslint-disable-next-line @typescript-eslint/prefer-function-type\n\t(\n\t\tsegment: ISegment,\n\t\tpos: number,\n\t\trefSeq: number,\n\t\tclientId: number,\n\t\tstart: number,\n\t\tend: number,\n\t\taccum: TClientData,\n\t): boolean;\n}\nexport interface ISegmentChanges {\n\tnext?: SegmentWithInfo<IHasInsertionInfo>;\n\treplaceCurrent?: SegmentWithInfo<IHasInsertionInfo>;\n}\n\nexport interface InsertContext {\n\tcandidateSegment?: SegmentWithInfo<IHasInsertionInfo>;\n\tleaf: (segment: ISegmentLeaf | undefined, pos: number, ic: InsertContext) => ISegmentChanges;\n\tcontinuePredicate?: (continueFromBlock: MergeBlock) => boolean;\n}\n\nexport interface ObliterateInfo {\n\tstart: LocalReferencePosition;\n\tstartSide: Side;\n\tend: LocalReferencePosition;\n\tendSide: Side;\n\trefSeq: number;\n\tstamp: SliceRemoveOperationStamp;\n\tsegmentGroup: SegmentGroup | undefined;\n\t/**\n\t * Defined only for unacked obliterates.\n\t *\n\t * Contains all segments inserted into the range this obliterate affects where at the time of insertion,\n\t * this obliterate was the newest concurrent obliterate that overlapped the insertion point (this information\n\t * is relevant for the tiebreak policy of allowing last-obliterater to insert).\n\t *\n\t * We need to keep this around for unacked ops because on reconnect, outstanding local obliterates may have set `obliteratePrecedingInsertion`\n\t * (tiebreak) on segments they no longer apply to, since the reissued obliterate may affect a smaller range than the original one when content\n\t * near the obliterate's endpoints was removed by another client between the time of the original obliterate and reissuing.\n\t */\n\ttiebreakTrackingGroup: ITrackingGroup | undefined;\n}\n\nexport interface SegmentGroup {\n\tsegments: ISegmentLeaf[];\n\tpreviousProps?: PropertySet[];\n\tlocalSeq?: number;\n\trefSeq: number;\n\tobliterateInfo?: ObliterateInfo;\n}\n\n/**\n * Note that the actual branching factor of the MergeTree is `MaxNodesInBlock - 1`. This is because\n * the MergeTree always inserts first, then checks for overflow and splits if the child count equals\n * `MaxNodesInBlock`. (i.e., `MaxNodesInBlock` contains 1 extra slot for temporary storage to\n * facilitate splits.)\n */\nexport const MaxNodesInBlock = 8;\nexport class MergeBlock implements Partial<IMergeNodeInfo> {\n\tpublic children: IMergeNode[];\n\tpublic needsScour?: boolean;\n\tpublic parent?: MergeBlock;\n\tpublic index: number = 0;\n\tpublic ordinal: string = \"\";\n\tpublic cachedLength: number | undefined = 0;\n\n\t/**\n\t * Maps each tile label in this block to the rightmost (i.e. furthest) marker associated with that tile label.\n\t * When combined with the tree structure of MergeBlocks, this allows accelerated queries for nearest tile\n\t * with a certain label before a given position\n\t */\n\tpublic rightmostTiles: Readonly<MapLike<Marker>>;\n\t/**\n\t * Maps each tile label in this block to the leftmost (i.e. nearest) marker associated with that tile label.\n\t * When combined with the tree structure of MergeBlocks, this allows accelerated queries for nearest tile\n\t * with a certain label before a given position\n\t */\n\tpublic leftmostTiles: Readonly<MapLike<Marker>>;\n\n\tisLeaf(): this is ISegmentInternal {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Supports querying the total length of all descendants of this IMergeBlock from the perspective of any\n\t * (clientId, seq) within the collab window.\n\t *\n\t * @remarks This is only optional for implementation reasons (internal nodes can be created/moved without\n\t * immediately initializing the partial lengths). Aside from mid-update on tree operations, these lengths\n\t * objects are always defined.\n\t */\n\tpartialLengths?: PartialSequenceLengths;\n\n\tpublic constructor(public childCount: number) {\n\t\t// Suppression needed due to the way the merge tree children are initialized - we\n\t\t// allocate 8 children blocks, but any unused blocks are not counted in the childCount.\n\t\t// Using Array.from leads to unused children being undefined, which are counted in childCount.\n\t\t// eslint-disable-next-line unicorn/no-new-array\n\t\tthis.children = new Array<IMergeNode>(MaxNodesInBlock);\n\t\tthis.rightmostTiles = createMap<Marker>();\n\t\tthis.leftmostTiles = createMap<Marker>();\n\t}\n\n\tpublic setOrdinal(child: IMergeNode, index: number): void {\n\t\tconst childCount = this.childCount;\n\t\tassert(\n\t\t\tchildCount >= 1 && childCount <= MaxNodesInBlock,\n\t\t\t0x040 /* \"Child count is not within [1,8] range!\" */,\n\t\t);\n\t\tchild.ordinal = computeHierarchicalOrdinal(\n\t\t\tMaxNodesInBlock,\n\t\t\tchildCount,\n\t\t\tthis.ordinal,\n\t\t\tindex === 0 ? undefined : this.children[index - 1]?.ordinal,\n\t\t);\n\t}\n}\nexport function assignChild<C extends IMergeNodeBuilder>(\n\tparent: MergeBlock,\n\tchild: C,\n\tindex: number,\n\tupdateOrdinal = true,\n): asserts child is C & IMergeNodeInfo {\n\tconst node = Object.assign<C, IMergeNodeInfo>(child, {\n\t\tparent,\n\t\tindex,\n\t\tordinal: hasProp(child, \"ordinal\", \"string\") ? child.ordinal : \"\",\n\t});\n\tif (updateOrdinal) {\n\t\tparent.setOrdinal(node, index);\n\t}\n\tparent.children[index] = node;\n}\n\nexport function seqLTE(seq: number, minOrRefSeq: number): boolean {\n\treturn seq !== UnassignedSequenceNumber && seq <= minOrRefSeq;\n}\n\n/**\n * @legacy @beta\n */\nexport abstract class BaseSegment implements ISegment {\n\tpublic cachedLength: number = 0;\n\n\tpublic readonly trackingCollection: TrackingGroupCollection = new TrackingGroupCollection(\n\t\tthis,\n\t);\n\t/***/\n\tpublic attribution?: IAttributionCollection<AttributionKey>;\n\n\tpublic properties?: PropertySet;\n\tpublic abstract readonly type: string;\n\tpublic constructor(properties?: PropertySet) {\n\t\tif (properties !== undefined) {\n\t\t\tthis.properties = clone(properties);\n\t\t}\n\t}\n\n\tpublic hasProperty(key: string): boolean {\n\t\treturn !!this.properties && this.properties[key] !== undefined;\n\t}\n\n\tpublic isLeaf(): this is ISegment {\n\t\treturn true;\n\t}\n\n\tprotected cloneInto(b: ISegment): void {\n\t\tconst seg: ISegmentPrivate = b;\n\t\tif (isInserted(this)) {\n\t\t\toverwriteInfo<IHasInsertionInfo>(seg, {\n\t\t\t\tinsert: this.insert,\n\t\t\t});\n\t\t}\n\t\t// TODO: deep clone properties\n\t\tseg.properties = clone(this.properties);\n\t\tif (isRemoved(this)) {\n\t\t\toverwriteInfo<IHasRemovalInfo>(seg, {\n\t\t\t\tremoves: [...this.removes],\n\t\t\t});\n\t\t}\n\n\t\tseg.attribution = this.attribution?.clone();\n\t}\n\n\tpublic canAppend(segment: ISegment): boolean {\n\t\treturn false;\n\t}\n\n\tprotected addSerializedProps(jseg: IJSONSegment): void {\n\t\tif (this.properties) {\n\t\t\tjseg.props = { ...this.properties };\n\t\t}\n\t}\n\t// This has to return any type because the return type is different for different segment types.\n\t// TODO: If possible, change the return type to match what should be returned for each segment type.\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic abstract toJSONObject(): any;\n\n\tpublic splitAt(pos: number): ISegment | undefined {\n\t\tif (pos <= 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst leafSegment: ISegmentPrivate | undefined = this.createSplitSegmentAt(pos);\n\n\t\tif (!leafSegment) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (isMergeNode(this)) {\n\t\t\toverwriteInfo<IMergeNodeInfo>(leafSegment, {\n\t\t\t\tindex: this.index + 1,\n\t\t\t\t// Give the leaf a temporary yet valid ordinal.\n\t\t\t\t// when this segment is put in the tree, it will get its real ordinal,\n\t\t\t\t// but this ordinal meets all the necessary invariants for now.\n\t\t\t\t// Ordinals exist purely for lexicographical sort order and use a small set of valid bytes for each string character.\n\t\t\t\t// The extra handling fromCodePoint has for things like surrogate pairs is therefore unnecessary.\n\t\t\t\t// eslint-disable-next-line unicorn/prefer-code-point\n\t\t\t\tordinal: this.ordinal + String.fromCharCode(0),\n\t\t\t\tparent: this.parent,\n\t\t\t});\n\t\t}\n\n\t\tif (isInserted(this)) {\n\t\t\toverwriteInfo<IHasInsertionInfo>(leafSegment, { insert: this.insert });\n\t\t}\n\t\tif (isRemoved(this)) {\n\t\t\toverwriteInfo<IHasRemovalInfo>(leafSegment, {\n\t\t\t\tremoves: [...this.removes],\n\t\t\t});\n\t\t}\n\t\tif (isInsideObliterate(this)) {\n\t\t\toverwriteInfo<ISegmentInsideObliterateInfo>(leafSegment, {\n\t\t\t\tobliteratePrecedingInsertion: this.obliteratePrecedingInsertion,\n\t\t\t\tinsertionRefSeqStamp: this.insertionRefSeqStamp,\n\t\t\t});\n\t\t}\n\n\t\tthis.trackingCollection.copyTo(leafSegment);\n\t\tif (this.attribution) {\n\t\t\tleafSegment.attribution = this.attribution.splitAt(pos);\n\t\t}\n\n\t\treturn leafSegment;\n\t}\n\n\tpublic abstract clone(): ISegment;\n\n\tpublic append(other: ISegment): void {\n\t\t// Note: Must call 'appendLocalRefs' before modifying this segment's length as\n\t\t// 'this.cachedLength' is used to adjust the offsets of the local refs.\n\t\tLocalReferenceCollection.append(this, other);\n\t\tif (this.attribution) {\n\t\t\tassert(\n\t\t\t\tother.attribution !== undefined,\n\t\t\t\t0x4bd /* attribution should be set on appendee */,\n\t\t\t);\n\t\t\tthis.attribution.append(other.attribution);\n\t\t} else {\n\t\t\tassert(\n\t\t\t\tother.attribution === undefined,\n\t\t\t\t0x4be /* attribution should not be set on appendee */,\n\t\t\t);\n\t\t}\n\n\t\tthis.cachedLength ??= 0;\n\t\tthis.cachedLength += other.cachedLength;\n\t}\n\n\tprotected abstract createSplitSegmentAt(pos: number): BaseSegment | undefined;\n}\n\n/**\n * The special-cased property key that tracks the id of a {@link Marker}.\n *\n * @remarks In general, marker ids should be accessed using the inherent method\n * {@link Marker.getId}. Marker ids should not be updated after creation.\n * @legacy @beta\n */\nexport const reservedMarkerIdKey = \"markerId\";\n\n/**\n * @internal\n */\nexport const reservedMarkerSimpleTypeKey = \"markerSimpleType\";\n\n/**\n * @legacy @beta\n */\nexport interface IJSONMarkerSegment extends IJSONSegment {\n\tmarker: IMarkerDef;\n}\n\n/**\n * Markers are a special kind of segment that do not hold any content.\n *\n * Markers with a reference type of {@link ReferenceType.Tile} support spatially\n * accelerated queries for finding the next marker to the left or right of it in\n * sub-linear time. This is useful, for example, in the case of jumping from the\n * start of a paragraph to the end, assuming a paragraph is bound by markers at\n * the start and end.\n *\n * @legacy @beta\n */\nexport class Marker extends BaseSegment implements ReferencePosition, ISegment {\n\tpublic static readonly type = \"Marker\";\n\tpublic static is(segment: ISegment): segment is Marker {\n\t\treturn segment.type === Marker.type;\n\t}\n\tpublic readonly type = Marker.type;\n\n\tpublic static make(refType: ReferenceType, props?: PropertySet): Marker {\n\t\treturn new Marker(refType, props);\n\t}\n\n\tconstructor(\n\t\tpublic refType: ReferenceType,\n\t\tprops?: PropertySet,\n\t) {\n\t\tsuper(props);\n\t\tthis.cachedLength = 1;\n\t}\n\n\ttoJSONObject(): IJSONMarkerSegment {\n\t\tconst obj: IJSONMarkerSegment = { marker: { refType: this.refType } };\n\t\tsuper.addSerializedProps(obj);\n\t\treturn obj;\n\t}\n\n\tstatic fromJSONObject(spec: IJSONSegment): Marker | undefined {\n\t\tif (spec && typeof spec === \"object\" && \"marker\" in spec) {\n\t\t\treturn Marker.make((spec.marker as Marker).refType, spec.props as PropertySet);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tclone(): Marker {\n\t\tconst b = Marker.make(this.refType, this.properties);\n\t\tthis.cloneInto(b);\n\t\treturn b;\n\t}\n\n\tgetSegment(): Marker {\n\t\treturn this;\n\t}\n\n\tgetOffset(): number {\n\t\treturn 0;\n\t}\n\n\tgetProperties(): PropertySet | undefined {\n\t\treturn this.properties;\n\t}\n\n\tgetId(): string | undefined {\n\t\treturn this.properties?.[reservedMarkerIdKey] as string;\n\t}\n\n\ttoString(): string {\n\t\treturn `M${this.getId()}`;\n\t}\n\n\tprotected createSplitSegmentAt(pos: number): undefined {\n\t\treturn undefined;\n\t}\n\n\tcanAppend(segment: ISegment): boolean {\n\t\treturn false;\n\t}\n\n\tappend(): void {\n\t\tthrow new Error(\"Can not append to marker\");\n\t}\n}\n\n/**\n * Returns a stamp that occurs at the minimum sequence number.\n * @privateRemarks\n * This is a free function over something obtainable on CollaborationWindow to avoid exposing Perspective\n * and OperationStamp from the package (even internally), at least for now.\n * If/when `Client`'s API is refactored to be structured similarly to MergeTree (so that SharedString passes in\n * things closer to `Perspective`s when calling methods on `Client` rather than refSeq/localSeq/clientId etc),\n * it may be more reasonable to expose this more directly on `CollaborationWindow`.\n */\nexport function getMinSeqStamp(collabWindow: CollaborationWindow): OperationStamp {\n\treturn { seq: collabWindow.minSeq, clientId: NonCollabClient };\n}\n\n/**\n * Returns a perspective representing a readonly client's view of the tree at the minimum sequence number.\n * @privateRemarks\n * This is a free function over something obtainable on CollaborationWindow to avoid exposing Perspective\n * and OperationStamp from the package (even internally), at least for now.\n * If/when `Client`'s API is refactored to be structured similarly to MergeTree (so that SharedString passes in\n * things closer to `Perspective`s when calling methods on `Client` rather than refSeq/localSeq/clientId etc),\n * it may be more reasonable to expose this more directly on `CollaborationWindow`.\n */\nexport function getMinSeqPerspective(collabWindow: CollaborationWindow): Perspective {\n\treturn new PriorPerspective(collabWindow.minSeq, NonCollabClient);\n}\n\n/**\n * This class is used to track facts about the current window of collaboration. This window is defined by the server\n * specified minimum sequence number to the last sequence number seen. Additionally, it track state for outstanding\n * local operations.\n * @internal\n */\nexport class CollaborationWindow {\n\tclientId = LocalClientId;\n\tcollaborating = false;\n\n\t/**\n\t * Lowest-numbered segment in window; no client can reference a state before this one\n\t */\n\tminSeq = 0;\n\t/**\n\t * Highest-numbered segment in window and current reference sequence number for this client.\n\t */\n\tcurrentSeq = 0;\n\n\t/**\n\t * Highest-numbered localSeq used for a pending segment.\n\t * Semantically, `localSeq`s provide an ordering on in-flight merge-tree operations:\n\t * for operations stamped with localSeqs `a` and `b`, `a < b` if and only if `a` was submitted before `b`.\n\t *\n\t * @remarks This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree\n\t * at op submission time rather than only at ack time. This enables more natural state tracking for in-flight ops.\n\t *\n\t * It's useful to stamp ops with such an incrementing counter because it enables reasoning about which segments existed from\n\t * the perspective of the local client at a given point in 'un-acked' time, which is necessary to support the reconnect flow.\n\t *\n\t * For example, imagine a client with initial state \"123456\" submits some ops to create the text \"123456ABC\".\n\t * If they insert the \"C\" first, then \"B\", then \"A\", their local segment state might look like this:\n\t * ```js\n\t * [\n\t * { seq: 0, text: \"1234\" },\n\t * { seq: 5, text: \"56\" },\n\t * { localSeq: 3, seq: UnassignedSequenceNumber, text: \"A\" },\n\t * { localSeq: 2, seq: UnassignedSequenceNumber, text: \"B\" },\n\t * { localSeq: 1, seq: UnassignedSequenceNumber, text: \"C\" },\n\t * ]\n\t * ```\n\t * (note that localSeq tracks the localSeq at which a segment was inserted)\n\t *\n\t * Suppose the client then disconnects and reconnects before any of its insertions are acked. The reconnect flow will necessitate\n\t * that the client regenerates and resubmits ops based on its current segment state as well as the original op that was sent.\n\t *\n\t * It will generate the ops\n\t * 1. \\{ pos: 6, text: \"C\" \\}\n\t * 2. \\{ pos: 6, text: \"B\" \\}\n\t * 3. \\{ pos: 6, text: \"A\" \\}\n\t *\n\t * since when submitting the first op, remote clients don't know that this client is about to submit the \"A\" and \"B\".\n\t *\n\t * On the other hand, imagine if the client had originally submitted the ops in the order \"A\", \"B\", \"C\"\n\t * such that the segments' local state was instead:\n\t *\n\t * ```js\n\t * [\n\t * { seq: 0, text: \"1234\" },\n\t * { seq: 5, text: \"56\" },\n\t * { localSeq: 1, seq: UnassignedSequenceNumber, text: \"A\" },\n\t * { localSeq: 2, seq: UnassignedSequenceNumber, text: \"B\" },\n\t * { localSeq: 3, seq: UnassignedSequenceNumber, text: \"C\" },\n\t * ]\n\t * ```\n\t *\n\t * The resubmitted ops should instead be:\n\t * 1. \\{ pos: 6, text: \"A\" \\}\n\t * 2. \\{ pos: 7, text: \"B\" \\}\n\t * 3. \\{ pos: 8, text: \"C\" \\}\n\t *\n\t * since remote clients will have seen the \"A\" when processing the \"B\" as well as both the \"A\" and \"B\" when processing the \"C\".\n\t * As can be seen, the list of resubmitted ops is different in the two cases despite the merge-tree's segment state only differing\n\t * in `localSeq`.\n\t *\n\t * This example is a bit simplified from the general scenario: since no remote clients modified the merge-tree while the client\n\t * was disconnected, the resubmitted ops end up matching the original ops exactly.\n\t * However, this is not generally true: the production reconnect code takes into account visibility of segments based on both acked\n\t * and local information as appropriate.\n\t * Nonetheless, this simple scenario is enough to understand why it's useful to be able to determine if a segment should be visible\n\t * from a given (seq, localSeq) perspective.\n\t */\n\tlocalSeq = 0;\n\n\tpublic localPerspective: Perspective = new LocalDefaultPerspective(this.clientId);\n\n\tpublic loadFrom(a: CollaborationWindow): void {\n\t\tthis.clientId = a.clientId;\n\t\tthis.collaborating = a.collaborating;\n\t\tthis.minSeq = a.minSeq;\n\t\tthis.currentSeq = a.currentSeq;\n\t}\n\n\tpublic mintNextLocalOperationStamp(): OperationStamp {\n\t\tif (this.collaborating) {\n\t\t\tthis.localSeq++;\n\t\t}\n\n\t\treturn {\n\t\t\tseq: this.collaborating ? UnassignedSequenceNumber : UniversalSequenceNumber,\n\t\t\tclientId: this.clientId,\n\t\t\tlocalSeq: this.localSeq,\n\t\t};\n\t}\n}\n\n/**\n * Compares two numbers.\n */\nexport const compareNumbers = (a: number, b: number): number => a - b;\n\n/**\n * Compares two strings.\n */\nexport const compareStrings = (a: string, b: string): number => a.localeCompare(b);\n"]}
package/lib/stamps.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * from alternative perspectives: a remote client will have seen all of its own previous operations as well as
15
15
  * those at or below the op's reference sequence number.
16
16
  *
17
- * @remarks - As the `readonly` identifies suggest, these stamps should be treated as immutable.
17
+ * @remarks As the `readonly` identifies suggest, these stamps should be treated as immutable.
18
18
  * New operations applied to a merge-tree should create new stamps rather than modify existing ones (e.g. when
19
19
  * a change's ack happens).
20
20
  * @internal
package/lib/stamps.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stamps.js","sourceRoot":"","sources":["../src/stamps.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tSquashClient,\n\tUnassignedSequenceNumber,\n\tUniversalSequenceNumber,\n} from \"./constants.js\";\n\n/**\n * A stamp that identifies provenance of an operation performed on the MergeTree.\n *\n * Stamps identify a point in time (`seq`/`localSeq`) as well as the source (`clientId`) for the operation.\n * This provides enough information to linearize all known applied operations: acked operations happen before\n * local+unacked ones, with acked operations ordered by their sequence numbers and local+unacked operations\n * ordered by their localSeq.\n *\n * By including `clientId`, it also provides enough information to resolve whether segments are visible\n * from alternative perspectives: a remote client will have seen all of its own previous operations as well as\n * those at or below the op's reference sequence number.\n *\n * @remarks - As the `readonly` identifies suggest, these stamps should be treated as immutable.\n * New operations applied to a merge-tree should create new stamps rather than modify existing ones (e.g. when\n * a change's ack happens).\n * @internal\n */\nexport interface OperationStamp {\n\t/**\n\t * The sequence number at which this operation was applied.\n\t */\n\treadonly seq: number;\n\n\t/**\n\t * Short clientId for the client that performed this operation.\n\t */\n\treadonly clientId: number;\n\n\t/**\n\t * Local seq at which this operation was applied.\n\t * This is defined if and only if the operation is pending an ack, i.e. `seq` is UnassignedSequenceNumber.\n\t *\n\t * @privateRemarks\n\t * See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.\n\t */\n\treadonly localSeq?: number;\n}\n\n/**\n * {@link OperationStamp} for an 'insert' operation.\n */\nexport interface InsertOperationStamp extends OperationStamp {\n\treadonly type: \"insert\";\n}\n\n/**\n * {@link OperationStamp} for a 'set remove' operation. This aligns with the `markRangeRemoved` API in MergeTree.\n *\n * @remarks The terminology here comes from the fact that the removal should affect only the *set* of nodes that were\n * specified at the time the local client issued the remove, and not any nodes that were inserted concurrently.\n *\n * Not using \"remove\" and \"obliterate\" here allows us to unambiguously use the term \"remove\" elsewhere in code to mean\n * \"removed from the tree, either by MergeTree.obliterateRange or MergeTree.removeRange\". This is convenient as the vast majority\n * of merge-tree code only cares about segment visibility and not the specific operation that caused a segment to be removed.\n */\nexport interface SetRemoveOperationStamp extends OperationStamp {\n\treadonly type: \"setRemove\";\n}\n\n/**\n * {@link OperationStamp} for a 'set remove' operation. This aligns with the `obliterateRange` API in MergeTree.\n *\n * @remarks The terminology here comes from the fact that the removal should affect the *slice* of nodes between the\n * start and end point specified by the local client, which includes any nodes that were inserted concurrently.\n *\n * Not using \"remove\" and \"obliterate\" here allows us to unambiguously use the term \"remove\" elsewhere in code to mean\n * \"removed from the tree, either by MergeTree.obliterateRange or MergeTree.removeRange\". This is convenient as the vast majority\n * of merge-tree code only cares about segment visibility and not the specific operation that caused a segment to be removed.\n */\nexport interface SliceRemoveOperationStamp extends OperationStamp {\n\treadonly type: \"sliceRemove\";\n}\n\nexport type RemoveOperationStamp = SetRemoveOperationStamp | SliceRemoveOperationStamp;\n\nexport function lessThan(a: OperationStamp, b: OperationStamp): boolean {\n\tif (a.seq === UnassignedSequenceNumber) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn b.seq === UnassignedSequenceNumber && a.localSeq! < b.localSeq!;\n\t}\n\n\tif (b.seq === UnassignedSequenceNumber) {\n\t\treturn true;\n\t}\n\n\treturn a.seq < b.seq;\n}\n\nexport function gte(a: OperationStamp, b: OperationStamp): boolean {\n\treturn !lessThan(a, b);\n}\n\nexport function greaterThan(a: OperationStamp, b: OperationStamp): boolean {\n\tif (a.seq === UnassignedSequenceNumber) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn b.seq !== UnassignedSequenceNumber || a.localSeq! > b.localSeq!;\n\t}\n\n\tif (b.seq === UnassignedSequenceNumber) {\n\t\treturn false;\n\t}\n\n\treturn a.seq > b.seq;\n}\n\nexport function lte(a: OperationStamp, b: OperationStamp): boolean {\n\treturn !greaterThan(a, b);\n}\n\nexport function equal(a: OperationStamp, b: OperationStamp): boolean {\n\treturn a.seq === b.seq && a.clientId === b.clientId && a.localSeq === b.localSeq;\n}\n\nexport function isLocal(a: OperationStamp): boolean {\n\treturn a.seq === UnassignedSequenceNumber;\n}\n\nexport function isSquashedOp(a: OperationStamp): boolean {\n\treturn a.clientId === SquashClient && a.seq === UniversalSequenceNumber;\n}\n\nexport function isAcked(a: OperationStamp): boolean {\n\treturn a.seq !== UnassignedSequenceNumber;\n}\n\n/**\n * Inserts a stamp into a sorted list of stamps in the correct (sorted) position.\n *\n * Beware that this uses Array.splice, thus requires asymptotics considerations.\n * If inserting a variable number of timestamps, consider just pushing them and sorting the list\n * after using {@link compare} instead.\n */\nexport function spliceIntoList(list: OperationStamp[], stamp: OperationStamp): void {\n\tif (isLocal(stamp) || list.length === 0) {\n\t\tlist.push(stamp);\n\t} else {\n\t\tfor (let i = list.length - 1; i >= 0; i--) {\n\t\t\tif (greaterThan(stamp, list[i])) {\n\t\t\t\tlist.splice(i + 1, 0, stamp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Less than all stamps in the list: put it at the beginning.\n\t\tlist.unshift(stamp);\n\t}\n}\n\nexport function hasAnyAckedOperation(list: OperationStamp[]): boolean {\n\treturn list.some((ts) => isAcked(ts));\n}\n\nexport function compare(a: OperationStamp, b: OperationStamp): number {\n\tif (greaterThan(a, b)) {\n\t\treturn 1;\n\t} else if (lessThan(a, b)) {\n\t\treturn -1;\n\t} else {\n\t\treturn 0;\n\t}\n}\n"]}
1
+ {"version":3,"file":"stamps.js","sourceRoot":"","sources":["../src/stamps.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tSquashClient,\n\tUnassignedSequenceNumber,\n\tUniversalSequenceNumber,\n} from \"./constants.js\";\n\n/**\n * A stamp that identifies provenance of an operation performed on the MergeTree.\n *\n * Stamps identify a point in time (`seq`/`localSeq`) as well as the source (`clientId`) for the operation.\n * This provides enough information to linearize all known applied operations: acked operations happen before\n * local+unacked ones, with acked operations ordered by their sequence numbers and local+unacked operations\n * ordered by their localSeq.\n *\n * By including `clientId`, it also provides enough information to resolve whether segments are visible\n * from alternative perspectives: a remote client will have seen all of its own previous operations as well as\n * those at or below the op's reference sequence number.\n *\n * @remarks As the `readonly` identifies suggest, these stamps should be treated as immutable.\n * New operations applied to a merge-tree should create new stamps rather than modify existing ones (e.g. when\n * a change's ack happens).\n * @internal\n */\nexport interface OperationStamp {\n\t/**\n\t * The sequence number at which this operation was applied.\n\t */\n\treadonly seq: number;\n\n\t/**\n\t * Short clientId for the client that performed this operation.\n\t */\n\treadonly clientId: number;\n\n\t/**\n\t * Local seq at which this operation was applied.\n\t * This is defined if and only if the operation is pending an ack, i.e. `seq` is UnassignedSequenceNumber.\n\t *\n\t * @privateRemarks\n\t * See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.\n\t */\n\treadonly localSeq?: number;\n}\n\n/**\n * {@link OperationStamp} for an 'insert' operation.\n */\nexport interface InsertOperationStamp extends OperationStamp {\n\treadonly type: \"insert\";\n}\n\n/**\n * {@link OperationStamp} for a 'set remove' operation. This aligns with the `markRangeRemoved` API in MergeTree.\n *\n * @remarks The terminology here comes from the fact that the removal should affect only the *set* of nodes that were\n * specified at the time the local client issued the remove, and not any nodes that were inserted concurrently.\n *\n * Not using \"remove\" and \"obliterate\" here allows us to unambiguously use the term \"remove\" elsewhere in code to mean\n * \"removed from the tree, either by MergeTree.obliterateRange or MergeTree.removeRange\". This is convenient as the vast majority\n * of merge-tree code only cares about segment visibility and not the specific operation that caused a segment to be removed.\n */\nexport interface SetRemoveOperationStamp extends OperationStamp {\n\treadonly type: \"setRemove\";\n}\n\n/**\n * {@link OperationStamp} for a 'set remove' operation. This aligns with the `obliterateRange` API in MergeTree.\n *\n * @remarks The terminology here comes from the fact that the removal should affect the *slice* of nodes between the\n * start and end point specified by the local client, which includes any nodes that were inserted concurrently.\n *\n * Not using \"remove\" and \"obliterate\" here allows us to unambiguously use the term \"remove\" elsewhere in code to mean\n * \"removed from the tree, either by MergeTree.obliterateRange or MergeTree.removeRange\". This is convenient as the vast majority\n * of merge-tree code only cares about segment visibility and not the specific operation that caused a segment to be removed.\n */\nexport interface SliceRemoveOperationStamp extends OperationStamp {\n\treadonly type: \"sliceRemove\";\n}\n\nexport type RemoveOperationStamp = SetRemoveOperationStamp | SliceRemoveOperationStamp;\n\nexport function lessThan(a: OperationStamp, b: OperationStamp): boolean {\n\tif (a.seq === UnassignedSequenceNumber) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn b.seq === UnassignedSequenceNumber && a.localSeq! < b.localSeq!;\n\t}\n\n\tif (b.seq === UnassignedSequenceNumber) {\n\t\treturn true;\n\t}\n\n\treturn a.seq < b.seq;\n}\n\nexport function gte(a: OperationStamp, b: OperationStamp): boolean {\n\treturn !lessThan(a, b);\n}\n\nexport function greaterThan(a: OperationStamp, b: OperationStamp): boolean {\n\tif (a.seq === UnassignedSequenceNumber) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\treturn b.seq !== UnassignedSequenceNumber || a.localSeq! > b.localSeq!;\n\t}\n\n\tif (b.seq === UnassignedSequenceNumber) {\n\t\treturn false;\n\t}\n\n\treturn a.seq > b.seq;\n}\n\nexport function lte(a: OperationStamp, b: OperationStamp): boolean {\n\treturn !greaterThan(a, b);\n}\n\nexport function equal(a: OperationStamp, b: OperationStamp): boolean {\n\treturn a.seq === b.seq && a.clientId === b.clientId && a.localSeq === b.localSeq;\n}\n\nexport function isLocal(a: OperationStamp): boolean {\n\treturn a.seq === UnassignedSequenceNumber;\n}\n\nexport function isSquashedOp(a: OperationStamp): boolean {\n\treturn a.clientId === SquashClient && a.seq === UniversalSequenceNumber;\n}\n\nexport function isAcked(a: OperationStamp): boolean {\n\treturn a.seq !== UnassignedSequenceNumber;\n}\n\n/**\n * Inserts a stamp into a sorted list of stamps in the correct (sorted) position.\n *\n * Beware that this uses Array.splice, thus requires asymptotics considerations.\n * If inserting a variable number of timestamps, consider just pushing them and sorting the list\n * after using {@link compare} instead.\n */\nexport function spliceIntoList(list: OperationStamp[], stamp: OperationStamp): void {\n\tif (isLocal(stamp) || list.length === 0) {\n\t\tlist.push(stamp);\n\t} else {\n\t\tfor (let i = list.length - 1; i >= 0; i--) {\n\t\t\tif (greaterThan(stamp, list[i])) {\n\t\t\t\tlist.splice(i + 1, 0, stamp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Less than all stamps in the list: put it at the beginning.\n\t\tlist.unshift(stamp);\n\t}\n}\n\nexport function hasAnyAckedOperation(list: OperationStamp[]): boolean {\n\treturn list.some((ts) => isAcked(ts));\n}\n\nexport function compare(a: OperationStamp, b: OperationStamp): number {\n\tif (greaterThan(a, b)) {\n\t\treturn 1;\n\t} else if (lessThan(a, b)) {\n\t\treturn -1;\n\t} else {\n\t\treturn 0;\n\t}\n}\n"]}
@@ -23,7 +23,7 @@ import { TestClientLogger, createClientsAtInitialState } from "./testClientLogge
23
23
  * be merged with the implementation that lives there
24
24
  */
25
25
  export function spyOnMethod(
26
- // eslint-disable-next-line @typescript-eslint/ban-types
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/ban-types
27
27
  methodClass, methodName, spy) {
28
28
  const { prototype } = methodClass;
29
29
  const method = prototype[methodName];
@@ -1 +1 @@
1
- {"version":3,"file":"revertibles.spec.js","sourceRoot":"","sources":["../../src/test/revertibles.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\nimport { strict as assert } from \"node:assert\";\n\nimport { generatePairwiseOptions } from \"@fluid-private/test-pairwise-generator\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type {\n\tIMergeTreeDeltaCallbackArgs,\n\tIMergeTreeDeltaOpArgs,\n} from \"../mergeTreeDeltaCallback.js\";\nimport { TrackingGroup, UnorderedTrackingGroup } from \"../mergeTreeTracking.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport {\n\ttype MergeTreeDeltaRevertible,\n\tappendToMergeTreeDeltaRevertibles,\n\trevertMergeTreeDeltaRevertibles,\n} from \"../revertibles.js\";\n\nimport { createRevertDriver } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\n/**\n * Run a custom \"spy function\" every time the given method is invoked.\n * @param methodClass - the class that has the method\n * @param methodName - the name of the method\n * @param spy - the spy function to run alongside the method\n * @returns a function which will remove the spy function when invoked. Should be called exactly once\n * after the spy is no longer needed.\n *\n * This method is duplicated between shared-tree test code, and should eventually\n * be merged with the implementation that lives there\n */\nexport function spyOnMethod(\n\t// eslint-disable-next-line @typescript-eslint/ban-types\n\tmethodClass: Function,\n\tmethodName: string,\n\tspy: () => void,\n): () => void {\n\tconst { prototype } = methodClass;\n\tconst method = prototype[methodName];\n\tassert(typeof method === \"function\", `Method does not exist: ${methodName}`);\n\n\tconst methodSpy = function (this: unknown, ...args: unknown[]): unknown {\n\t\tspy();\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\treturn method.call(this, ...args);\n\t};\n\tprototype[methodName] = methodSpy;\n\n\treturn () => {\n\t\tprototype[methodName] = method;\n\t};\n}\n\ndescribe(\"MergeTree.Revertibles\", () => {\n\tit(\"revert insert\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tops.push(clients.B.makeOpMessage(clients.B.insertTextLocal(0, \"BB\"), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"BB123\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"has reasonable asymptotics in face of remove\", () => {\n\t\tconst length = 100;\n\n\t\t// track the amount of tracking group linking that occurs\n\t\tlet linkCount = 0;\n\t\tlet unlinkCount = 0;\n\n\t\tconst unspy1 = spyOnMethod(TrackingGroup, \"link\", () => (linkCount += 1));\n\t\tconst unspy2 = spyOnMethod(TrackingGroup, \"unlink\", () => (unlinkCount += 1));\n\t\tconst unspy3 = spyOnMethod(UnorderedTrackingGroup, \"link\", () => (linkCount += 1));\n\t\tconst unspy4 = spyOnMethod(UnorderedTrackingGroup, \"unlink\", () => (unlinkCount += 1));\n\n\t\ttry {\n\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t{\n\t\t\t\t\tinitialState: \"\",\n\t\t\t\t\toptions: {},\n\t\t\t\t},\n\t\t\t\t\"A\",\n\t\t\t);\n\n\t\t\tfor (let i = 1; i <= length; i++) {\n\t\t\t\tconst insertOp = clients.A.insertTextLocal(i - 1, \"a\");\n\t\t\t\tclients.A.applyMsg(\n\t\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\t\tinsertOp,\n\t\t\t\t\t\t/* seq */ i + 1,\n\t\t\t\t\t\t/* refSeq */ i,\n\t\t\t\t\t\tclients.A.longClientId,\n\t\t\t\t\t\t/* minSeq */ 1,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t\tclients.A.on(\"delta\", (_op, delta) => {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, revertibles);\n\t\t\t});\n\n\t\t\tconst op = clients.A.removeRangeLocal(0, length - 1);\n\n\t\t\tclients.A.applyMsg(\n\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\top,\n\t\t\t\t\t/* seq */ length + 1,\n\t\t\t\t\t/* refSeq */ length,\n\t\t\t\t\tclients.A.longClientId,\n\t\t\t\t\t/* minSeq */ length,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// the below checks act as a proxy for the asymptotics of undo-redo\n\t\t\t// linking. they are perhaps a bit more strict than necessary. if these\n\t\t\t// tests are failing and the number of calls is still within a sane limit,\n\t\t\t// it should be fine to update these checks to allow a larger number of\n\t\t\t// calls\n\t\t\tassert(\n\t\t\t\tlinkCount <= length * 3,\n\t\t\t\t`expected tracking group link to occur at most three times per segment. found ${linkCount} instead of ${\n\t\t\t\t\tlength * 3\n\t\t\t\t}`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tunlinkCount <= length * 2,\n\t\t\t\t`expected tracking group unlink to occur at most twice per segment. found ${unlinkCount} instead of ${\n\t\t\t\t\tlength * 2\n\t\t\t\t}`,\n\t\t\t);\n\t\t} finally {\n\t\t\tunspy1();\n\t\t\tunspy2();\n\t\t\tunspy3();\n\t\t\tunspy4();\n\t\t}\n\t});\n\n\tit(\"revert remove\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tops.push(clients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"23\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tfor (const { name, removeStart, removeEnd, expectedPostRemove } of [\n\t\t{\n\t\t\tname: \"revert overlapping remove\",\n\t\t\tremoveStart: 0,\n\t\t\tremoveEnd: 1,\n\t\t\texpectedPostRemove: \"23\",\n\t\t},\n\t\t{\n\t\t\tname: \"revert overlapping remove of multiple segments\",\n\t\t\tremoveStart: 0,\n\t\t\tremoveEnd: 2,\n\t\t\texpectedPreRemove: \"23\",\n\t\t},\n\t]) {\n\t\tit(name, () => {\n\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t{ initialState: \"1-23\", options: {} },\n\t\t\t\t\"A\",\n\t\t\t\t\"B\",\n\t\t\t\t\"C\",\n\t\t\t);\n\t\t\tconst logger = new TestClientLogger(clients.all);\n\t\t\tlet seq = 0;\n\t\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t\t});\n\n\t\t\tops.push(\n\t\t\t\tclients.C.makeOpMessage(clients.C.removeRangeLocal(removeStart, removeEnd), ++seq),\n\t\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(removeStart, removeEnd), ++seq),\n\t\t\t);\n\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\tlogger.validate({ baseText: expectedPostRemove });\n\n\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\tlogger.validate({ baseText: \"123\" });\n\t\t});\n\t}\n\n\tit(\"revert two overlapping removes\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tconst clientC_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientCDriver = createRevertDriver(clients.C);\n\t\tclientCDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.C.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tclients.C.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientC_Revertibles);\n\t\t});\n\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.C.makeOpMessage(clients.C.removeRangeLocal(0, 1), ++seq),\n\t\t);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"23\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\t\trevertMergeTreeDeltaRevertibles(clientCDriver, clientC_Revertibles.splice(0));\n\n\t\t// \"123\" would be the ideal final state, but due to current limitations,\n\t\t// the eventual consistent state is \"1123\"\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"1123\" });\n\t});\n\n\tit(\"revert annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\t\tops.push(clients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 1, { test: 1 }), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"Remove All Original Text and Insert then Revert\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1-2--\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t// the test logger uses these callbacks, so preserve it\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.insertTextLocal(0, \"BB\"), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(2, 3), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"12\" });\n\t});\n\n\tit(\"Re-Insert at position 0 in empty string\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"BBC-\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(2, 3), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.insertTextLocal(1, \"BB\"), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"BBC\" });\n\t});\n\n\tit(\"Revert remove to empty with annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1-23--\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 2), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 1, { test: 1 }), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"Revert Local annotate and remove with intersecting remote annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1234-----\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (\n\t\t\top: IMergeTreeDeltaOpArgs,\n\t\t\tdelta: IMergeTreeDeltaCallbackArgs,\n\t\t): void => {\n\t\t\tif (op.sequencedMessage === undefined) {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t\t}\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 4, { test: \"B\" }), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(1, 2), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tops.push(\n\t\t\tclients.C.makeOpMessage(clients.C.annotateRangeLocal(3, 4, { test: \"C\" }), ++seq),\n\t\t);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"134\" });\n\n\t\ttry {\n\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t} catch (error) {\n\t\t\tthrow logger.addLogsToError(error);\n\t\t}\n\n\t\tlogger.validate({ baseText: \"1234\" });\n\t});\n\n\tdescribe(\"Revertibles work as expected when a pair of markers and text is involved\", () => {\n\t\tfor (const options of generatePairwiseOptions({\n\t\t\trevertMarkerInsert: [true, undefined],\n\t\t\tackMarkerInsert: [true, undefined],\n\t\t\tsplitInsertTextRevertible: [true, undefined],\n\t\t\tackTextInsert: [true, undefined],\n\t\t\tsplitRemoveRevertible: [true, undefined],\n\t\t\tackTextRemove: [true, undefined],\n\t\t\tackUndo: [true, undefined],\n\t\t})) {\n\t\t\tit(JSON.stringify(options), () => {\n\t\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t\t{ initialState: \"\", options: {} },\n\t\t\t\t\t\"A\",\n\t\t\t\t\t\"B\",\n\t\t\t\t);\n\n\t\t\t\tconst logger = new TestClientLogger(clients.all);\n\t\t\t\tlet seq = 0;\n\t\t\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\t\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[][] = [];\n\t\t\t\tconst openNewUndoRedoTransaction = (): number => clientB_Revertibles.unshift([]);\n\t\t\t\t// the test logger uses these callbacks, so preserve it\n\t\t\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\t\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\t\t\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\t\t\tif (op.sequencedMessage === undefined && clientB_Revertibles.length > 0) {\n\t\t\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles[0]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet afterUndoBaseText: string | undefined;\n\t\t\t\tif (options.revertMarkerInsert) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\t\t\t\tops.push(\n\t\t\t\t\tclients.B.makeOpMessage(clients.B.insertMarkerLocal(0, ReferenceType.Simple), ++seq),\n\t\t\t\t\tclients.B.makeOpMessage(clients.B.insertMarkerLocal(1, ReferenceType.Simple), ++seq),\n\t\t\t\t);\n\n\t\t\t\tif (options.ackMarkerInsert) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: afterUndoBaseText });\n\t\t\t\t}\n\n\t\t\t\tif (options.splitInsertTextRevertible) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\t\t\t\tops.push(clients.B.makeOpMessage(clients.B.insertTextLocal(1, \"B\"), ++seq));\n\t\t\t\tif (options.ackTextInsert) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: \"B\" });\n\t\t\t\t}\n\n\t\t\t\tif (options.splitRemoveRevertible) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\n\t\t\t\tops.push(clients.B.makeOpMessage(clients.B.removeRangeLocal(1, 2), ++seq));\n\t\t\t\tif (options.ackTextRemove) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: \"\" });\n\t\t\t\t}\n\n\t\t\t\tconst afterRevertBaseTest = clients.B.getText();\n\t\t\t\ttry {\n\t\t\t\t\tconst reverts = clientB_Revertibles.splice(0);\n\t\t\t\t\tfor (const revert of reverts) {\n\t\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, revert);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow logger.addLogsToError(error);\n\t\t\t\t}\n\n\t\t\t\tif (options.ackUndo) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: afterUndoBaseText });\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst reverts = clientB_Revertibles.splice(0);\n\t\t\t\t\tfor (const revert of reverts) {\n\t\t\t\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, revert);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow logger.addLogsToError(error);\n\t\t\t\t}\n\n\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\tlogger.validate({ baseText: afterRevertBaseTest });\n\t\t\t});\n\t\t}\n\t});\n});\n"]}
1
+ {"version":3,"file":"revertibles.spec.js","sourceRoot":"","sources":["../../src/test/revertibles.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\nimport { strict as assert } from \"node:assert\";\n\nimport { generatePairwiseOptions } from \"@fluid-private/test-pairwise-generator\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type {\n\tIMergeTreeDeltaCallbackArgs,\n\tIMergeTreeDeltaOpArgs,\n} from \"../mergeTreeDeltaCallback.js\";\nimport { TrackingGroup, UnorderedTrackingGroup } from \"../mergeTreeTracking.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport {\n\ttype MergeTreeDeltaRevertible,\n\tappendToMergeTreeDeltaRevertibles,\n\trevertMergeTreeDeltaRevertibles,\n} from \"../revertibles.js\";\n\nimport { createRevertDriver } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\n/**\n * Run a custom \"spy function\" every time the given method is invoked.\n * @param methodClass - the class that has the method\n * @param methodName - the name of the method\n * @param spy - the spy function to run alongside the method\n * @returns a function which will remove the spy function when invoked. Should be called exactly once\n * after the spy is no longer needed.\n *\n * This method is duplicated between shared-tree test code, and should eventually\n * be merged with the implementation that lives there\n */\nexport function spyOnMethod(\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/ban-types\n\tmethodClass: Function,\n\tmethodName: string,\n\tspy: () => void,\n): () => void {\n\tconst { prototype } = methodClass;\n\tconst method = prototype[methodName];\n\tassert(typeof method === \"function\", `Method does not exist: ${methodName}`);\n\n\tconst methodSpy = function (this: unknown, ...args: unknown[]): unknown {\n\t\tspy();\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n\t\treturn method.call(this, ...args);\n\t};\n\tprototype[methodName] = methodSpy;\n\n\treturn () => {\n\t\tprototype[methodName] = method;\n\t};\n}\n\ndescribe(\"MergeTree.Revertibles\", () => {\n\tit(\"revert insert\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tops.push(clients.B.makeOpMessage(clients.B.insertTextLocal(0, \"BB\"), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"BB123\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"has reasonable asymptotics in face of remove\", () => {\n\t\tconst length = 100;\n\n\t\t// track the amount of tracking group linking that occurs\n\t\tlet linkCount = 0;\n\t\tlet unlinkCount = 0;\n\n\t\tconst unspy1 = spyOnMethod(TrackingGroup, \"link\", () => (linkCount += 1));\n\t\tconst unspy2 = spyOnMethod(TrackingGroup, \"unlink\", () => (unlinkCount += 1));\n\t\tconst unspy3 = spyOnMethod(UnorderedTrackingGroup, \"link\", () => (linkCount += 1));\n\t\tconst unspy4 = spyOnMethod(UnorderedTrackingGroup, \"unlink\", () => (unlinkCount += 1));\n\n\t\ttry {\n\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t{\n\t\t\t\t\tinitialState: \"\",\n\t\t\t\t\toptions: {},\n\t\t\t\t},\n\t\t\t\t\"A\",\n\t\t\t);\n\n\t\t\tfor (let i = 1; i <= length; i++) {\n\t\t\t\tconst insertOp = clients.A.insertTextLocal(i - 1, \"a\");\n\t\t\t\tclients.A.applyMsg(\n\t\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\t\tinsertOp,\n\t\t\t\t\t\t/* seq */ i + 1,\n\t\t\t\t\t\t/* refSeq */ i,\n\t\t\t\t\t\tclients.A.longClientId,\n\t\t\t\t\t\t/* minSeq */ 1,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t\tclients.A.on(\"delta\", (_op, delta) => {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, revertibles);\n\t\t\t});\n\n\t\t\tconst op = clients.A.removeRangeLocal(0, length - 1);\n\n\t\t\tclients.A.applyMsg(\n\t\t\t\tclients.A.makeOpMessage(\n\t\t\t\t\top,\n\t\t\t\t\t/* seq */ length + 1,\n\t\t\t\t\t/* refSeq */ length,\n\t\t\t\t\tclients.A.longClientId,\n\t\t\t\t\t/* minSeq */ length,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// the below checks act as a proxy for the asymptotics of undo-redo\n\t\t\t// linking. they are perhaps a bit more strict than necessary. if these\n\t\t\t// tests are failing and the number of calls is still within a sane limit,\n\t\t\t// it should be fine to update these checks to allow a larger number of\n\t\t\t// calls\n\t\t\tassert(\n\t\t\t\tlinkCount <= length * 3,\n\t\t\t\t`expected tracking group link to occur at most three times per segment. found ${linkCount} instead of ${\n\t\t\t\t\tlength * 3\n\t\t\t\t}`,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\tunlinkCount <= length * 2,\n\t\t\t\t`expected tracking group unlink to occur at most twice per segment. found ${unlinkCount} instead of ${\n\t\t\t\t\tlength * 2\n\t\t\t\t}`,\n\t\t\t);\n\t\t} finally {\n\t\t\tunspy1();\n\t\t\tunspy2();\n\t\t\tunspy3();\n\t\t\tunspy4();\n\t\t}\n\t});\n\n\tit(\"revert remove\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tops.push(clients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"23\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tfor (const { name, removeStart, removeEnd, expectedPostRemove } of [\n\t\t{\n\t\t\tname: \"revert overlapping remove\",\n\t\t\tremoveStart: 0,\n\t\t\tremoveEnd: 1,\n\t\t\texpectedPostRemove: \"23\",\n\t\t},\n\t\t{\n\t\t\tname: \"revert overlapping remove of multiple segments\",\n\t\t\tremoveStart: 0,\n\t\t\tremoveEnd: 2,\n\t\t\texpectedPreRemove: \"23\",\n\t\t},\n\t]) {\n\t\tit(name, () => {\n\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t{ initialState: \"1-23\", options: {} },\n\t\t\t\t\"A\",\n\t\t\t\t\"B\",\n\t\t\t\t\"C\",\n\t\t\t);\n\t\t\tconst logger = new TestClientLogger(clients.all);\n\t\t\tlet seq = 0;\n\t\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t\t});\n\n\t\t\tops.push(\n\t\t\t\tclients.C.makeOpMessage(clients.C.removeRangeLocal(removeStart, removeEnd), ++seq),\n\t\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(removeStart, removeEnd), ++seq),\n\t\t\t);\n\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\tlogger.validate({ baseText: expectedPostRemove });\n\n\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\tlogger.validate({ baseText: \"123\" });\n\t\t});\n\t}\n\n\tit(\"revert two overlapping removes\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tconst clientC_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientCDriver = createRevertDriver(clients.C);\n\t\tclientCDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.C.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\n\t\tclients.C.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientC_Revertibles);\n\t\t});\n\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.C.makeOpMessage(clients.C.removeRangeLocal(0, 1), ++seq),\n\t\t);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"23\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\t\trevertMergeTreeDeltaRevertibles(clientCDriver, clientC_Revertibles.splice(0));\n\n\t\t// \"123\" would be the ideal final state, but due to current limitations,\n\t\t// the eventual consistent state is \"1123\"\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"1123\" });\n\t});\n\n\tit(\"revert annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"123\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t);\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t});\n\t\tops.push(clients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 1, { test: 1 }), ++seq));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"Remove All Original Text and Insert then Revert\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1-2--\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\t// the test logger uses these callbacks, so preserve it\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.insertTextLocal(0, \"BB\"), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(2, 3), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"12\" });\n\t});\n\n\tit(\"Re-Insert at position 0 in empty string\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"BBC-\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(2, 3), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.insertTextLocal(1, \"BB\"), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"BBC\" });\n\t});\n\n\tit(\"Revert remove to empty with annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1-23--\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (op, delta: IMergeTreeDeltaCallbackArgs): void => {\n\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 2), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 1, { test: 1 }), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(0, 1), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\n\t\tlogger.validate({ baseText: \"123\" });\n\t});\n\n\tit(\"Revert Local annotate and remove with intersecting remote annotate\", () => {\n\t\tconst clients = createClientsAtInitialState(\n\t\t\t{ initialState: \"1234-----\", options: {} },\n\t\t\t\"A\",\n\t\t\t\"B\",\n\t\t\t\"C\",\n\t\t);\n\n\t\tconst logger = new TestClientLogger(clients.all);\n\t\tlet seq = 0;\n\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[] = [];\n\t\tconst deltaCallback = (\n\t\t\top: IMergeTreeDeltaOpArgs,\n\t\t\tdelta: IMergeTreeDeltaCallbackArgs,\n\t\t): void => {\n\t\t\tif (op.sequencedMessage === undefined) {\n\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles);\n\t\t\t}\n\t\t};\n\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\n\t\tclients.B.on(\"delta\", deltaCallback);\n\t\tops.push(\n\t\t\tclients.B.makeOpMessage(clients.B.annotateRangeLocal(0, 4, { test: \"B\" }), ++seq),\n\t\t\tclients.B.makeOpMessage(clients.B.removeRangeLocal(1, 2), ++seq),\n\t\t);\n\n\t\t// revert to the original callback\n\t\tclients.B.off(\"delta\", deltaCallback);\n\n\t\tops.push(\n\t\t\tclients.C.makeOpMessage(clients.C.annotateRangeLocal(3, 4, { test: \"C\" }), ++seq),\n\t\t);\n\n\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\tlogger.validate({ baseText: \"134\" });\n\n\t\ttry {\n\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, clientB_Revertibles.splice(0));\n\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t} catch (error) {\n\t\t\tthrow logger.addLogsToError(error);\n\t\t}\n\n\t\tlogger.validate({ baseText: \"1234\" });\n\t});\n\n\tdescribe(\"Revertibles work as expected when a pair of markers and text is involved\", () => {\n\t\tfor (const options of generatePairwiseOptions({\n\t\t\trevertMarkerInsert: [true, undefined],\n\t\t\tackMarkerInsert: [true, undefined],\n\t\t\tsplitInsertTextRevertible: [true, undefined],\n\t\t\tackTextInsert: [true, undefined],\n\t\t\tsplitRemoveRevertible: [true, undefined],\n\t\t\tackTextRemove: [true, undefined],\n\t\t\tackUndo: [true, undefined],\n\t\t})) {\n\t\t\tit(JSON.stringify(options), () => {\n\t\t\t\tconst clients = createClientsAtInitialState(\n\t\t\t\t\t{ initialState: \"\", options: {} },\n\t\t\t\t\t\"A\",\n\t\t\t\t\t\"B\",\n\t\t\t\t);\n\n\t\t\t\tconst logger = new TestClientLogger(clients.all);\n\t\t\t\tlet seq = 0;\n\t\t\t\tconst ops: ISequencedDocumentMessage[] = [];\n\n\t\t\t\tconst clientB_Revertibles: MergeTreeDeltaRevertible[][] = [];\n\t\t\t\tconst openNewUndoRedoTransaction = (): number => clientB_Revertibles.unshift([]);\n\t\t\t\t// the test logger uses these callbacks, so preserve it\n\t\t\t\tconst clientBDriver = createRevertDriver(clients.B);\n\t\t\t\tclientBDriver.submitOpCallback = (op): number =>\n\t\t\t\t\tops.push(clients.B.makeOpMessage(op, ++seq));\n\t\t\t\tclients.B.on(\"delta\", (op, delta) => {\n\t\t\t\t\tif (op.sequencedMessage === undefined && clientB_Revertibles.length > 0) {\n\t\t\t\t\t\tappendToMergeTreeDeltaRevertibles(delta, clientB_Revertibles[0]);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet afterUndoBaseText: string | undefined;\n\t\t\t\tif (options.revertMarkerInsert) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\t\t\t\tops.push(\n\t\t\t\t\tclients.B.makeOpMessage(clients.B.insertMarkerLocal(0, ReferenceType.Simple), ++seq),\n\t\t\t\t\tclients.B.makeOpMessage(clients.B.insertMarkerLocal(1, ReferenceType.Simple), ++seq),\n\t\t\t\t);\n\n\t\t\t\tif (options.ackMarkerInsert) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: afterUndoBaseText });\n\t\t\t\t}\n\n\t\t\t\tif (options.splitInsertTextRevertible) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\t\t\t\tops.push(clients.B.makeOpMessage(clients.B.insertTextLocal(1, \"B\"), ++seq));\n\t\t\t\tif (options.ackTextInsert) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: \"B\" });\n\t\t\t\t}\n\n\t\t\t\tif (options.splitRemoveRevertible) {\n\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\tafterUndoBaseText ??= clients.B.getText();\n\t\t\t\t}\n\n\t\t\t\tops.push(clients.B.makeOpMessage(clients.B.removeRangeLocal(1, 2), ++seq));\n\t\t\t\tif (options.ackTextRemove) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: \"\" });\n\t\t\t\t}\n\n\t\t\t\tconst afterRevertBaseTest = clients.B.getText();\n\t\t\t\ttry {\n\t\t\t\t\tconst reverts = clientB_Revertibles.splice(0);\n\t\t\t\t\tfor (const revert of reverts) {\n\t\t\t\t\t\topenNewUndoRedoTransaction();\n\t\t\t\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, revert);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow logger.addLogsToError(error);\n\t\t\t\t}\n\n\t\t\t\tif (options.ackUndo) {\n\t\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\t\tlogger.validate({ baseText: afterUndoBaseText });\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst reverts = clientB_Revertibles.splice(0);\n\t\t\t\t\tfor (const revert of reverts) {\n\t\t\t\t\t\trevertMergeTreeDeltaRevertibles(clientBDriver, revert);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow logger.addLogsToError(error);\n\t\t\t\t}\n\n\t\t\t\tfor (const op of ops.splice(0)) for (const c of clients.all) c.applyMsg(op);\n\t\t\t\tlogger.validate({ baseText: afterRevertBaseTest });\n\t\t\t});\n\t\t}\n\t});\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/merge-tree",
3
- "version": "2.70.0-360753",
3
+ "version": "2.70.0-361248",
4
4
  "description": "Merge tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -81,30 +81,30 @@
81
81
  "temp-directory": "nyc/.nyc_output"
82
82
  },
83
83
  "dependencies": {
84
- "@fluid-internal/client-utils": "2.70.0-360753",
85
- "@fluidframework/container-definitions": "2.70.0-360753",
86
- "@fluidframework/core-interfaces": "2.70.0-360753",
87
- "@fluidframework/core-utils": "2.70.0-360753",
88
- "@fluidframework/datastore-definitions": "2.70.0-360753",
89
- "@fluidframework/driver-definitions": "2.70.0-360753",
90
- "@fluidframework/runtime-definitions": "2.70.0-360753",
91
- "@fluidframework/runtime-utils": "2.70.0-360753",
92
- "@fluidframework/shared-object-base": "2.70.0-360753",
93
- "@fluidframework/telemetry-utils": "2.70.0-360753"
84
+ "@fluid-internal/client-utils": "2.70.0-361248",
85
+ "@fluidframework/container-definitions": "2.70.0-361248",
86
+ "@fluidframework/core-interfaces": "2.70.0-361248",
87
+ "@fluidframework/core-utils": "2.70.0-361248",
88
+ "@fluidframework/datastore-definitions": "2.70.0-361248",
89
+ "@fluidframework/driver-definitions": "2.70.0-361248",
90
+ "@fluidframework/runtime-definitions": "2.70.0-361248",
91
+ "@fluidframework/runtime-utils": "2.70.0-361248",
92
+ "@fluidframework/shared-object-base": "2.70.0-361248",
93
+ "@fluidframework/telemetry-utils": "2.70.0-361248"
94
94
  },
95
95
  "devDependencies": {
96
96
  "@arethetypeswrong/cli": "^0.17.1",
97
97
  "@biomejs/biome": "~1.9.3",
98
- "@fluid-internal/mocha-test-setup": "2.70.0-360753",
99
- "@fluid-private/stochastic-test-utils": "2.70.0-360753",
100
- "@fluid-private/test-pairwise-generator": "2.70.0-360753",
98
+ "@fluid-internal/mocha-test-setup": "2.70.0-361248",
99
+ "@fluid-private/stochastic-test-utils": "2.70.0-361248",
100
+ "@fluid-private/test-pairwise-generator": "2.70.0-361248",
101
101
  "@fluid-tools/benchmark": "^0.51.0",
102
102
  "@fluid-tools/build-cli": "^0.58.3",
103
103
  "@fluidframework/build-common": "^2.0.3",
104
104
  "@fluidframework/build-tools": "^0.58.3",
105
- "@fluidframework/eslint-config-fluid": "^6.0.0",
105
+ "@fluidframework/eslint-config-fluid": "^6.1.0",
106
106
  "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@2.63.0",
107
- "@fluidframework/test-runtime-utils": "2.70.0-360753",
107
+ "@fluidframework/test-runtime-utils": "2.70.0-361248",
108
108
  "@microsoft/api-extractor": "7.52.11",
109
109
  "@types/diff": "^3.5.1",
110
110
  "@types/mocha": "^10.0.10",
@@ -114,7 +114,7 @@
114
114
  "copyfiles": "^2.4.1",
115
115
  "cross-env": "^7.0.3",
116
116
  "diff": "^3.5.0",
117
- "eslint": "~8.55.0",
117
+ "eslint": "~8.57.1",
118
118
  "mocha": "^10.8.2",
119
119
  "mocha-multi-reporters": "^1.5.1",
120
120
  "rimraf": "^4.4.0",
@@ -95,7 +95,7 @@ export interface IAttributionCollection<T> {
95
95
  * Example: If the Attribution Offsets in the segment is [0, 10, 20, 30, 40] and request is for (startOffset: 5, endOffset: 25),
96
96
  * then result would be [(offset: 0, key: key1), (offset:10, key: key2), (offset:20, key: key3)].
97
97
  * @param channel - When specified, gets attribution keys associated with a particular channel.
98
- * @returns - undefined if the provided channel is not found or list of attribution keys along with
98
+ * @returns undefined if the provided channel is not found or list of attribution keys along with
99
99
  * the corresponding offset start boundary.
100
100
  */
101
101
  getKeysInOffsetRange(
package/src/mergeTree.ts CHANGED
@@ -714,7 +714,7 @@ export class MergeTree {
714
714
 
715
715
  /**
716
716
  * Compute the net length of this segment leaf from some perspective.
717
- * @returns - Undefined if the segment has been removed and its removal is common knowledge to all collaborators (and therefore
717
+ * @returns Undefined if the segment has been removed and its removal is common knowledge to all collaborators (and therefore
718
718
  * may not even be present on clients that have loaded from a summary beyond this point). Otherwise, the length of the segment.
719
719
  */
720
720
  public leafLength(