@fluidframework/merge-tree 2.41.0 → 2.43.0-343119

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.
Files changed (154) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/client.d.ts +9 -6
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +79 -36
  5. package/dist/client.js.map +1 -1
  6. package/dist/collections/list.d.ts +95 -5
  7. package/dist/collections/list.d.ts.map +1 -1
  8. package/dist/collections/list.js +67 -5
  9. package/dist/collections/list.js.map +1 -1
  10. package/dist/constants.d.ts +5 -0
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/constants.js +6 -1
  13. package/dist/constants.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/mergeTree.d.ts +9 -9
  19. package/dist/mergeTree.d.ts.map +1 -1
  20. package/dist/mergeTree.js +15 -7
  21. package/dist/mergeTree.js.map +1 -1
  22. package/dist/perspective.d.ts +15 -0
  23. package/dist/perspective.d.ts.map +1 -1
  24. package/dist/perspective.js +25 -1
  25. package/dist/perspective.js.map +1 -1
  26. package/dist/revertibles.js +1 -1
  27. package/dist/revertibles.js.map +1 -1
  28. package/dist/stamps.d.ts +1 -0
  29. package/dist/stamps.d.ts.map +1 -1
  30. package/dist/stamps.js +5 -1
  31. package/dist/stamps.js.map +1 -1
  32. package/dist/test/beastTest.spec.js +1 -1
  33. package/dist/test/beastTest.spec.js.map +1 -1
  34. package/dist/test/client.annotateMarker.spec.js +1 -1
  35. package/dist/test/client.annotateMarker.spec.js.map +1 -1
  36. package/dist/test/client.applyMsg.spec.js +25 -25
  37. package/dist/test/client.applyMsg.spec.js.map +1 -1
  38. package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
  39. package/dist/test/client.applyStashedOpFarm.spec.js +3 -3
  40. package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
  41. package/dist/test/client.attributionFarm.spec.js +1 -1
  42. package/dist/test/client.attributionFarm.spec.js.map +1 -1
  43. package/dist/test/client.getPosition.spec.js +1 -0
  44. package/dist/test/client.getPosition.spec.js.map +1 -1
  45. package/dist/test/client.localReference.spec.js +62 -48
  46. package/dist/test/client.localReference.spec.js.map +1 -1
  47. package/dist/test/client.localReferenceFarm.spec.js +1 -0
  48. package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
  49. package/dist/test/client.reconnectFarm.spec.js +1 -1
  50. package/dist/test/client.reconnectFarm.spec.js.map +1 -1
  51. package/dist/test/client.rollback.spec.js +8 -6
  52. package/dist/test/client.rollback.spec.js.map +1 -1
  53. package/dist/test/client.searchForMarker.spec.js +2 -2
  54. package/dist/test/client.searchForMarker.spec.js.map +1 -1
  55. package/dist/test/clientTestHelper.js +1 -1
  56. package/dist/test/clientTestHelper.js.map +1 -1
  57. package/dist/test/mergeTree.annotate.spec.js +25 -25
  58. package/dist/test/mergeTree.annotate.spec.js.map +1 -1
  59. package/dist/test/mergeTree.markRangeRemoved.spec.js +1 -1
  60. package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  61. package/dist/test/obliterate.spec.js +4 -4
  62. package/dist/test/obliterate.spec.js.map +1 -1
  63. package/dist/test/resetPendingSegmentsToOp.spec.js +14 -14
  64. package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  65. package/dist/test/snapshot.utils.js +1 -1
  66. package/dist/test/snapshot.utils.js.map +1 -1
  67. package/dist/test/sortedSegmentSet.spec.js +3 -3
  68. package/dist/test/sortedSegmentSet.spec.js.map +1 -1
  69. package/dist/test/testClient.js +3 -3
  70. package/dist/test/testClient.js.map +1 -1
  71. package/dist/test/tracking.spec.js +7 -7
  72. package/dist/test/tracking.spec.js.map +1 -1
  73. package/dist/test/wordUnitTests.spec.js.map +1 -1
  74. package/lib/client.d.ts +9 -6
  75. package/lib/client.d.ts.map +1 -1
  76. package/lib/client.js +81 -38
  77. package/lib/client.js.map +1 -1
  78. package/lib/collections/list.d.ts +95 -5
  79. package/lib/collections/list.d.ts.map +1 -1
  80. package/lib/collections/list.js +67 -5
  81. package/lib/collections/list.js.map +1 -1
  82. package/lib/constants.d.ts +5 -0
  83. package/lib/constants.d.ts.map +1 -1
  84. package/lib/constants.js +5 -0
  85. package/lib/constants.js.map +1 -1
  86. package/lib/index.d.ts +1 -1
  87. package/lib/index.d.ts.map +1 -1
  88. package/lib/index.js +1 -1
  89. package/lib/index.js.map +1 -1
  90. package/lib/mergeTree.d.ts +9 -9
  91. package/lib/mergeTree.d.ts.map +1 -1
  92. package/lib/mergeTree.js +15 -7
  93. package/lib/mergeTree.js.map +1 -1
  94. package/lib/perspective.d.ts +15 -0
  95. package/lib/perspective.d.ts.map +1 -1
  96. package/lib/perspective.js +23 -0
  97. package/lib/perspective.js.map +1 -1
  98. package/lib/revertibles.js +1 -1
  99. package/lib/revertibles.js.map +1 -1
  100. package/lib/stamps.d.ts +1 -0
  101. package/lib/stamps.d.ts.map +1 -1
  102. package/lib/stamps.js +4 -1
  103. package/lib/stamps.js.map +1 -1
  104. package/lib/test/beastTest.spec.js +1 -1
  105. package/lib/test/beastTest.spec.js.map +1 -1
  106. package/lib/test/client.annotateMarker.spec.js +1 -1
  107. package/lib/test/client.annotateMarker.spec.js.map +1 -1
  108. package/lib/test/client.applyMsg.spec.js +25 -25
  109. package/lib/test/client.applyMsg.spec.js.map +1 -1
  110. package/lib/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
  111. package/lib/test/client.applyStashedOpFarm.spec.js +3 -3
  112. package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
  113. package/lib/test/client.attributionFarm.spec.js +1 -1
  114. package/lib/test/client.attributionFarm.spec.js.map +1 -1
  115. package/lib/test/client.getPosition.spec.js +1 -0
  116. package/lib/test/client.getPosition.spec.js.map +1 -1
  117. package/lib/test/client.localReference.spec.js +62 -48
  118. package/lib/test/client.localReference.spec.js.map +1 -1
  119. package/lib/test/client.localReferenceFarm.spec.js +1 -0
  120. package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
  121. package/lib/test/client.reconnectFarm.spec.js +1 -1
  122. package/lib/test/client.reconnectFarm.spec.js.map +1 -1
  123. package/lib/test/client.rollback.spec.js +8 -6
  124. package/lib/test/client.rollback.spec.js.map +1 -1
  125. package/lib/test/client.searchForMarker.spec.js +2 -2
  126. package/lib/test/client.searchForMarker.spec.js.map +1 -1
  127. package/lib/test/clientTestHelper.js +1 -1
  128. package/lib/test/clientTestHelper.js.map +1 -1
  129. package/lib/test/mergeTree.annotate.spec.js +25 -25
  130. package/lib/test/mergeTree.annotate.spec.js.map +1 -1
  131. package/lib/test/mergeTree.markRangeRemoved.spec.js +1 -1
  132. package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
  133. package/lib/test/obliterate.spec.js +4 -4
  134. package/lib/test/obliterate.spec.js.map +1 -1
  135. package/lib/test/resetPendingSegmentsToOp.spec.js +14 -14
  136. package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
  137. package/lib/test/snapshot.utils.js +1 -1
  138. package/lib/test/snapshot.utils.js.map +1 -1
  139. package/lib/test/sortedSegmentSet.spec.js +3 -3
  140. package/lib/test/sortedSegmentSet.spec.js.map +1 -1
  141. package/lib/test/testClient.js +3 -3
  142. package/lib/test/testClient.js.map +1 -1
  143. package/lib/test/tracking.spec.js +7 -7
  144. package/lib/test/tracking.spec.js.map +1 -1
  145. package/lib/test/wordUnitTests.spec.js.map +1 -1
  146. package/package.json +16 -16
  147. package/src/client.ts +117 -50
  148. package/src/collections/list.ts +101 -5
  149. package/src/constants.ts +6 -0
  150. package/src/index.ts +3 -0
  151. package/src/mergeTree.ts +30 -24
  152. package/src/perspective.ts +26 -0
  153. package/src/revertibles.ts +1 -1
  154. package/src/stamps.ts +9 -1
@@ -1 +1 @@
1
- {"version":3,"file":"clientTestHelper.js","sourceRoot":"","sources":["../../src/test/clientTestHelper.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 { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IMergeTreeOp, IMergeTreeOptions, InteriorSequencePlace } from \"../index.js\";\nimport type { SegmentGroup } from \"../mergeTreeNodes.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\nfunction isClientId(s: unknown): s is ClientName {\n\treturn ClientIds.includes(s as ClientName);\n}\n\nfunction clientNameOf(client: TestClient): ClientName {\n\tconst { longClientId } = client;\n\tassert(isClientId(longClientId), \"Client ID is not a valid client name\");\n\treturn longClientId;\n}\n\n/**\n * Helper for authoring tests which perform operations on a number of clients.\n * This class essentially serves the role of the server in that it maintains a sequencing order of ops as well as information\n * about the latest op that each client has applied.\n *\n * When using this class, *do not* perform operations which may submit ops on clients directly: it does not currently wire up client events\n * to the server. Instead, use methods on the helper and pass the client name they should apply to as the first argument.\n *\n * It is analogous to MockContainerRuntimeFactory in the test-runtime-utils package, though the APIs are not completely equivalent\n * (see for example differences noted on disconnect and reconnect).\n *\n * This helper is also designed to support advancing only some clients to a given sequence number\n * (not all clients must be synchronized at the same time).\n *\n * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq\n * in lockstep.\n *\n * @remarks\n * If we wired the server up to \"delta\" events on the client, it would be reasonable to rename this to `MockServer` and the API for tests\n * would be a bit cleaner.\n */\nexport class ClientTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tclientToLastAppliedSeq = new Map<ClientName, number>();\n\n\tperClientOps: ISequencedDocumentMessage[][];\n\tprivate readonly disconnectedClientOps = new Map<\n\t\tClientName,\n\t\t{ op: IMergeTreeOp; segmentGroup: SegmentGroup }[]\n\t>();\n\n\tprivate seq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableObliterateReconnect: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tprivate addMessage(client: TestClient, op: IMergeTreeOp): void {\n\t\tconst disconnectedQueue = this.disconnectedClientOps.get(clientNameOf(client));\n\t\tif (disconnectedQueue === undefined) {\n\t\t\tconst message = client.makeOpMessage(op, ++this.seq);\n\t\t\tthis.ops.push(message);\n\t\t\t// This implementation (specifically, that of applying ops / synchronizing clients) assumes messages\n\t\t\t// are pushed sequentially starting with seq 1.\n\t\t\tassert(\n\t\t\t\tmessage.sequenceNumber === this.ops.length,\n\t\t\t\t\"Partial sync test helper invariant violated\",\n\t\t\t);\n\t\t} else {\n\t\t\t// Client is not currently connected.\n\t\t\tconst segmentGroup = client.peekPendingSegmentGroups();\n\t\t\tassert(segmentGroup !== undefined, \"Client should have a pending segment group\");\n\t\t\tdisconnectedQueue.push({ op, segmentGroup });\n\t\t}\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst insertOp = client.insertTextLocal(pos, text);\n\t\tif (insertOp) {\n\t\t\tthis.addMessage(client, insertOp);\n\t\t}\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.obliterateRangeLocal(start, end));\n\t}\n\n\tpublic advanceClientToSeq(clientName: ClientName, seq: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst lastApplied = this.clientToLastAppliedSeq.get(clientName);\n\t\tassert(seq > 0, \"Can only advance clients to sequence numbers that exist\");\n\t\tassert(\n\t\t\tthis.ops.length >= seq,\n\t\t\t\"Cannot attempt to advance clients to sequence numbers that don't yet exist\",\n\t\t);\n\t\tlet startIndex: number;\n\t\tif (lastApplied === undefined) {\n\t\t\tstartIndex = 0;\n\t\t} else {\n\t\t\tif (lastApplied >= seq) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstartIndex = lastApplied;\n\t\t}\n\t\tfor (let i = startIndex; i < seq; i++) {\n\t\t\tconst nextMessage = this.ops[i];\n\t\t\tclient.applyMsg(nextMessage);\n\t\t\tthis.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);\n\t\t}\n\t}\n\n\t/**\n\t * Sends all known ops to the procieded client ids.\n\t */\n\tpublic advanceClients(...clientNames: ClientName[]): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of clientNames) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of ClientIds) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Causes the provided clients to \"disconnect\" by isolating their outbound queue from the op stream.\n\t * These clients will still receive ops from this helper just like all other clients.\n\t * When a client reconnects (see {@link reconnect}), the helper will rebase all of the client's pending ops (that they submitted since\n\t * `disconnect` was called) and re-add them to the op stream.\n\t *\n\t * BEWARE: This is slightly different from what the mocks in test-runtime-utils do in two ways:\n\t *\n\t * 1. Those mocks actually wipe outstanding ops submitted by the disconnected clients from the op stream and rebases those as well.\n\t * 2. Those mocks freeze the inbound queue of the disconnected clients as well as the outbound queue.\n\t *\n\t * E.g. (pseudocode; syntax is different for those mocks and these):\n\t *\n\t * ```typescript\n\t * B.submitLocalOp1()\n\t * B.submitLocalOp2()\n\t * disconnect(B)\n\t * A.submitLocalOp1()\n\t * B.submitLocalOp3()\n\t * processAllOps()\n\t * ```\n\t *\n\t * the test-runtime-mocks will...\n\t *\n\t * - have none of B's local ops be receieved by A in the processAllOps() line\n\t * - have B not receive A's local op 1\n\t *\n\t * whereas this helper will...\n\t *\n\t * - have B's local ops 1 and 2 be received by A, but not its third local op\n\t * - have B receive acks for its first two local ops as well as A's op in the processAllOps() line\n\t *\n\t * This operation is a no-op if called multiple times on the same client with no intervening reconnects.\n\t */\n\tpublic disconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst client = this.clients[clientName];\n\t\t\tif (this.isDisconnected(client)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.set(clientName, []);\n\t\t}\n\t}\n\n\t/**\n\t * Reconnects clients which have been disconnected. No-ops on any client which is already connected.\n\t * For disconnected clients, any pending ops they have will be resubmitted using the resubmit flow, see {@link disconnect} for details and an example.\n\t *\n\t * @remarks\n\t * If reconnecting multiple clients, the order that their ops will be resubmitted in will match the order in the array\n\t */\n\tpublic reconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst submittedOps = this.disconnectedClientOps.get(clientName);\n\t\t\tif (submittedOps === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.delete(clientName);\n\t\t\tconst client = this.clients[clientName];\n\t\t\tfor (const { op, segmentGroup } of submittedOps) {\n\t\t\t\tconst rebasedOp = client.regeneratePendingOp(op, segmentGroup);\n\t\t\t\tthis.addMessage(client, rebasedOp);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isDisconnected(client: TestClient): boolean {\n\t\treturn this.disconnectedClientOps.has(clientNameOf(client));\n\t}\n}\n"]}
1
+ {"version":3,"file":"clientTestHelper.js","sourceRoot":"","sources":["../../src/test/clientTestHelper.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 { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport type { IMergeTreeOp, IMergeTreeOptions, InteriorSequencePlace } from \"../index.js\";\nimport type { SegmentGroup } from \"../mergeTreeNodes.js\";\n\nimport type { TestClient } from \"./testClient.js\";\nimport { TestClientLogger, createClientsAtInitialState } from \"./testClientLogger.js\";\n\nconst ClientIds = [\"A\", \"B\", \"C\", \"D\"] as const;\ntype ClientName = (typeof ClientIds)[number];\n\nfunction isClientId(s: unknown): s is ClientName {\n\treturn ClientIds.includes(s as ClientName);\n}\n\nfunction clientNameOf(client: TestClient): ClientName {\n\tconst { longClientId } = client;\n\tassert(isClientId(longClientId), \"Client ID is not a valid client name\");\n\treturn longClientId;\n}\n\n/**\n * Helper for authoring tests which perform operations on a number of clients.\n * This class essentially serves the role of the server in that it maintains a sequencing order of ops as well as information\n * about the latest op that each client has applied.\n *\n * When using this class, *do not* perform operations which may submit ops on clients directly: it does not currently wire up client events\n * to the server. Instead, use methods on the helper and pass the client name they should apply to as the first argument.\n *\n * It is analogous to MockContainerRuntimeFactory in the test-runtime-utils package, though the APIs are not completely equivalent\n * (see for example differences noted on disconnect and reconnect).\n *\n * This helper is also designed to support advancing only some clients to a given sequence number\n * (not all clients must be synchronized at the same time).\n *\n * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq\n * in lockstep.\n *\n * @remarks\n * If we wired the server up to \"delta\" events on the client, it would be reasonable to rename this to `MockServer` and the API for tests\n * would be a bit cleaner.\n */\nexport class ClientTestHelper {\n\tclients: Record<ClientName, TestClient> & { all: TestClient[] };\n\n\tidxFromName(name: ClientName): number {\n\t\treturn (name.codePointAt(0) ?? 0) - (\"A\".codePointAt(0) ?? 0);\n\t}\n\n\tlogger: TestClientLogger;\n\n\tops: ISequencedDocumentMessage[] = [];\n\tclientToLastAppliedSeq = new Map<ClientName, number>();\n\n\tperClientOps: ISequencedDocumentMessage[][];\n\tprivate readonly disconnectedClientOps = new Map<\n\t\tClientName,\n\t\t{ op: IMergeTreeOp; segmentGroup: SegmentGroup }[]\n\t>();\n\n\tprivate seq: number = 0;\n\n\tpublic constructor(options: IMergeTreeOptions = {}) {\n\t\tthis.clients = createClientsAtInitialState(\n\t\t\t{\n\t\t\t\tinitialState: \"\",\n\t\t\t\toptions: {\n\t\t\t\t\tmergeTreeEnableObliterate: true,\n\t\t\t\t\tmergeTreeEnableObliterateReconnect: true,\n\t\t\t\t\t...options,\n\t\t\t\t},\n\t\t\t},\n\t\t\t...ClientIds,\n\t\t);\n\t\tthis.logger = new TestClientLogger(this.clients.all);\n\t\tthis.perClientOps = this.clients.all.map(() => []);\n\t}\n\n\tprivate addMessage(client: TestClient, op: IMergeTreeOp): void {\n\t\tconst disconnectedQueue = this.disconnectedClientOps.get(clientNameOf(client));\n\t\tif (disconnectedQueue === undefined) {\n\t\t\tconst message = client.makeOpMessage(op, ++this.seq);\n\t\t\tthis.ops.push(message);\n\t\t\t// This implementation (specifically, that of applying ops / synchronizing clients) assumes messages\n\t\t\t// are pushed sequentially starting with seq 1.\n\t\t\tassert(\n\t\t\t\tmessage.sequenceNumber === this.ops.length,\n\t\t\t\t\"Partial sync test helper invariant violated\",\n\t\t\t);\n\t\t} else {\n\t\t\t// Client is not currently connected.\n\t\t\tconst segmentGroup = client.peekPendingSegmentGroups();\n\t\t\tassert(segmentGroup !== undefined, \"Client should have a pending segment group\");\n\t\t\tdisconnectedQueue.push({ op, segmentGroup });\n\t\t}\n\t}\n\n\tpublic insertText(clientName: ClientName, pos: number, text: string): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst insertOp = client.insertTextLocal(pos, text);\n\t\tif (insertOp) {\n\t\t\tthis.addMessage(client, insertOp);\n\t\t}\n\t}\n\n\tpublic removeRange(clientName: ClientName, start: number, end: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.removeRangeLocal(start, end));\n\t}\n\n\tpublic obliterateRange(\n\t\tclientName: ClientName,\n\t\tstart: number | InteriorSequencePlace,\n\t\tend: number | InteriorSequencePlace,\n\t): void {\n\t\tconst client = this.clients[clientName];\n\t\tthis.addMessage(client, client.obliterateRangeLocal(start, end));\n\t}\n\n\tpublic advanceClientToSeq(clientName: ClientName, seq: number): void {\n\t\tconst client = this.clients[clientName];\n\t\tconst lastApplied = this.clientToLastAppliedSeq.get(clientName);\n\t\tassert(seq > 0, \"Can only advance clients to sequence numbers that exist\");\n\t\tassert(\n\t\t\tthis.ops.length >= seq,\n\t\t\t\"Cannot attempt to advance clients to sequence numbers that don't yet exist\",\n\t\t);\n\t\tlet startIndex: number;\n\t\tif (lastApplied === undefined) {\n\t\t\tstartIndex = 0;\n\t\t} else {\n\t\t\tif (lastApplied >= seq) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstartIndex = lastApplied;\n\t\t}\n\t\tfor (let i = startIndex; i < seq; i++) {\n\t\t\tconst nextMessage = this.ops[i];\n\t\t\tclient.applyMsg(nextMessage);\n\t\t\tthis.clientToLastAppliedSeq.set(clientName, nextMessage.sequenceNumber);\n\t\t}\n\t}\n\n\t/**\n\t * Sends all known ops to the procieded client ids.\n\t */\n\tpublic advanceClients(...clientNames: ClientName[]): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of clientNames) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\tpublic processAllOps(): void {\n\t\tconst latestSeq = this.ops[this.ops.length - 1].sequenceNumber;\n\t\tfor (const name of ClientIds) {\n\t\t\tthis.advanceClientToSeq(name, latestSeq);\n\t\t}\n\t}\n\n\t/**\n\t * Causes the provided clients to \"disconnect\" by isolating their outbound queue from the op stream.\n\t * These clients will still receive ops from this helper just like all other clients.\n\t * When a client reconnects (see {@link reconnect}), the helper will rebase all of the client's pending ops (that they submitted since\n\t * `disconnect` was called) and re-add them to the op stream.\n\t *\n\t * BEWARE: This is slightly different from what the mocks in test-runtime-utils do in two ways:\n\t *\n\t * 1. Those mocks actually wipe outstanding ops submitted by the disconnected clients from the op stream and rebases those as well.\n\t * 2. Those mocks freeze the inbound queue of the disconnected clients as well as the outbound queue.\n\t *\n\t * E.g. (pseudocode; syntax is different for those mocks and these):\n\t *\n\t * ```typescript\n\t * B.submitLocalOp1()\n\t * B.submitLocalOp2()\n\t * disconnect(B)\n\t * A.submitLocalOp1()\n\t * B.submitLocalOp3()\n\t * processAllOps()\n\t * ```\n\t *\n\t * the test-runtime-mocks will...\n\t *\n\t * - have none of B's local ops be receieved by A in the processAllOps() line\n\t * - have B not receive A's local op 1\n\t *\n\t * whereas this helper will...\n\t *\n\t * - have B's local ops 1 and 2 be received by A, but not its third local op\n\t * - have B receive acks for its first two local ops as well as A's op in the processAllOps() line\n\t *\n\t * This operation is a no-op if called multiple times on the same client with no intervening reconnects.\n\t */\n\tpublic disconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst client = this.clients[clientName];\n\t\t\tif (this.isDisconnected(client)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.set(clientName, []);\n\t\t}\n\t}\n\n\t/**\n\t * Reconnects clients which have been disconnected. No-ops on any client which is already connected.\n\t * For disconnected clients, any pending ops they have will be resubmitted using the resubmit flow, see {@link disconnect} for details and an example.\n\t *\n\t * @remarks\n\t * If reconnecting multiple clients, the order that their ops will be resubmitted in will match the order in the array\n\t */\n\tpublic reconnect(...clientNames: ClientName[]): void {\n\t\tfor (const clientName of clientNames) {\n\t\t\tconst submittedOps = this.disconnectedClientOps.get(clientName);\n\t\t\tif (submittedOps === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.disconnectedClientOps.delete(clientName);\n\t\t\tconst client = this.clients[clientName];\n\t\t\tfor (const { op, segmentGroup } of submittedOps) {\n\t\t\t\tconst rebasedOp = client.regeneratePendingOp(op, segmentGroup, false);\n\t\t\t\tthis.addMessage(client, rebasedOp);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate isDisconnected(client: TestClient): boolean {\n\t\treturn this.disconnectedClientOps.has(clientNameOf(client));\n\t}\n}\n"]}
@@ -40,7 +40,7 @@ describe("MergeTree", () => {
40
40
  props: { propertySource: "remote" },
41
41
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: currentSequenceNumber + 1 }), undefined);
42
42
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
43
- const segment = segmentInfo.segment;
43
+ const segment = segmentInfo?.segment;
44
44
  assert.equal(segment?.properties?.propertySource, "remote");
45
45
  });
46
46
  it("local", () => {
@@ -48,7 +48,7 @@ describe("MergeTree", () => {
48
48
  props: { propertySource: "local" },
49
49
  }, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
50
50
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
51
- const segment = segmentInfo.segment;
51
+ const segment = segmentInfo?.segment;
52
52
  assert.equal(segment.properties?.propertySource, "local");
53
53
  });
54
54
  });
@@ -67,7 +67,7 @@ describe("MergeTree", () => {
67
67
  });
68
68
  it("unsequenced local", () => {
69
69
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
70
- const segment = segmentInfo.segment;
70
+ const segment = segmentInfo?.segment;
71
71
  assert.equal(segment.properties?.propertySource, "local");
72
72
  });
73
73
  it("unsequenced local after unsequenced local", () => {
@@ -75,7 +75,7 @@ describe("MergeTree", () => {
75
75
  props: { secondProperty: "local" },
76
76
  }, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
77
77
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
78
- const segment = segmentInfo.segment;
78
+ const segment = segmentInfo?.segment;
79
79
  assert.equal(segment.properties?.secondProperty, "local");
80
80
  });
81
81
  it("unsequenced local split", () => {
@@ -83,7 +83,7 @@ describe("MergeTree", () => {
83
83
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84
84
  const splitSegment = splitAt(mergeTree, splitPos);
85
85
  assertMergeNode(splitSegment);
86
- assert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);
86
+ assert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);
87
87
  assert.equal(splitSegment.properties?.propertySource, "local");
88
88
  });
89
89
  it("unsequenced local after unsequenced local split", () => {
@@ -100,9 +100,9 @@ describe("MergeTree", () => {
100
100
  };
101
101
  mergeTree.annotateRange(splitPos, annotateEnd, splitOnlyProps, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
102
102
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
103
- const segment = segmentInfo.segment;
103
+ const segment = segmentInfo?.segment;
104
104
  const splitSegmentInfo = mergeTree.getContainingSegment(splitPos, mergeTree.localPerspective);
105
- const splitSegment = splitSegmentInfo.segment;
105
+ const splitSegment = splitSegmentInfo?.segment;
106
106
  assert.equal(segment.segmentGroups?.size, 2);
107
107
  assert.equal(segment.properties?.propertySource, "local");
108
108
  assert.equal(segment.properties?.secondChange, 1);
@@ -174,7 +174,7 @@ describe("MergeTree", () => {
174
174
  props: { propertySource: "remote", remoteProperty: 1 },
175
175
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
176
176
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
177
- const segment = segmentInfo.segment;
177
+ const segment = segmentInfo?.segment;
178
178
  assert.equal(segment.segmentGroups?.size, 1);
179
179
  assert.equal(segment.properties?.propertySource, "local");
180
180
  assert.equal(segment.properties?.remoteProperty, 1);
@@ -192,7 +192,7 @@ describe("MergeTree", () => {
192
192
  },
193
193
  });
194
194
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
195
- const segment = segmentInfo.segment;
195
+ const segment = segmentInfo?.segment;
196
196
  assert.equal(segment.segmentGroups?.size, 0);
197
197
  assert.equal(segment.properties?.propertySource, "local");
198
198
  });
@@ -212,14 +212,14 @@ describe("MergeTree", () => {
212
212
  props: { propertySource: "remote", remoteProperty: 1 },
213
213
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
214
214
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
215
- const segment = segmentInfo.segment;
215
+ const segment = segmentInfo?.segment;
216
216
  assert.equal(segment.segmentGroups?.size, 0);
217
217
  assert.equal(segment.properties?.propertySource, "remote");
218
218
  assert.equal(segment.properties?.remoteProperty, 1);
219
219
  });
220
220
  it("three local changes", () => {
221
221
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
222
- const segment = segmentInfo.segment;
222
+ const segment = segmentInfo?.segment;
223
223
  assert.equal(segment.properties?.propertySource, "local");
224
224
  const props2 = {
225
225
  props: { propertySource: "local2", secondSource: 1 },
@@ -298,7 +298,7 @@ describe("MergeTree", () => {
298
298
  props: { propertySource: "remote", remoteOnly: 1, secondSource: "remote" },
299
299
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
300
300
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
301
- const segment = segmentInfo.segment;
301
+ const segment = segmentInfo?.segment;
302
302
  assert.equal(segment.properties?.remoteOnly, 1);
303
303
  assert.equal(segment.properties?.propertySource, "remote");
304
304
  assert.equal(segment.properties?.secondSource, "local2");
@@ -310,11 +310,11 @@ describe("MergeTree", () => {
310
310
  props: { propertySource: "remote", remoteProperty: 1 },
311
311
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
312
312
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
313
- assert(segmentInfo.segment?.segmentGroups?.size !== 0);
313
+ assert(segmentInfo?.segment?.segmentGroups?.size !== 0);
314
314
  });
315
315
  it("remote only", () => {
316
316
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
317
- const segment = segmentInfo.segment;
317
+ const segment = segmentInfo?.segment;
318
318
  assert.equal(segment.properties?.propertySource, "remote");
319
319
  assert.equal(segment.properties?.remoteProperty, 1);
320
320
  });
@@ -323,7 +323,7 @@ describe("MergeTree", () => {
323
323
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
324
324
  const splitSegment = splitAt(mergeTree, annotateStart + 1);
325
325
  assertMergeNode(splitSegment);
326
- assert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);
326
+ assert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);
327
327
  assert.equal(splitSegment.properties?.propertySource, "remote");
328
328
  assert.equal(splitSegment.properties?.remoteProperty, 1);
329
329
  });
@@ -332,7 +332,7 @@ describe("MergeTree", () => {
332
332
  props: { propertySource: "local" },
333
333
  }, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
334
334
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
335
- const segment = segmentInfo.segment;
335
+ const segment = segmentInfo?.segment;
336
336
  assert.equal(segment.properties?.propertySource, "local");
337
337
  assert.equal(segment.properties?.remoteProperty, 1);
338
338
  });
@@ -341,9 +341,9 @@ describe("MergeTree", () => {
341
341
  props: { propertySource: "local" },
342
342
  };
343
343
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
344
- assert(segmentInfo.segment?.segmentGroups?.empty !== false);
344
+ assert(segmentInfo?.segment?.segmentGroups?.empty !== false);
345
345
  mergeTree.annotateRange(annotateStart, annotateEnd, props, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
346
- assert.equal(segmentInfo.segment?.segmentGroups?.size, 1);
346
+ assert.equal(segmentInfo?.segment?.segmentGroups?.size, 1);
347
347
  mergeTree.ackOp({
348
348
  op: {
349
349
  pos1: annotateStart,
@@ -355,9 +355,9 @@ describe("MergeTree", () => {
355
355
  sequenceNumber: ++currentSequenceNumber,
356
356
  },
357
357
  });
358
- assert(segmentInfo.segment?.segmentGroups?.empty);
359
- assert.equal(segmentInfo.segment?.properties?.propertySource, "local");
360
- assert.equal(segmentInfo.segment?.properties?.remoteProperty, 1);
358
+ assert(segmentInfo?.segment?.segmentGroups?.empty);
359
+ assert.equal(segmentInfo?.segment?.properties?.propertySource, "local");
360
+ assert.equal(segmentInfo?.segment?.properties?.remoteProperty, 1);
361
361
  });
362
362
  });
363
363
  describe("local with rewrite first", () => {
@@ -372,7 +372,7 @@ describe("MergeTree", () => {
372
372
  props: { propertySource: "local2", secondProperty: "local" },
373
373
  }, mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
374
374
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
375
- const segment = segmentInfo.segment;
375
+ const segment = segmentInfo?.segment;
376
376
  assert.equal(segment.properties?.propertySource, "local2");
377
377
  assert.equal(segment.properties?.secondProperty, "local");
378
378
  });
@@ -381,7 +381,7 @@ describe("MergeTree", () => {
381
381
  props: { propertySource: "remote", remoteProperty: 1 },
382
382
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
383
383
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
384
- const segment = segmentInfo.segment;
384
+ const segment = segmentInfo?.segment;
385
385
  assert.equal(segment.segmentGroups?.size, 1);
386
386
  assert.equal(segment.properties?.propertySource, "local");
387
387
  assert.equal(segment.properties?.remoteProperty, 1);
@@ -402,7 +402,7 @@ describe("MergeTree", () => {
402
402
  props: { propertySource: "remote", remoteProperty: 1 },
403
403
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
404
404
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
405
- const segment = segmentInfo.segment;
405
+ const segment = segmentInfo?.segment;
406
406
  assert.equal(segment.segmentGroups?.size, 0);
407
407
  assert.equal(segment.properties?.propertySource, "remote");
408
408
  assert.equal(segment.properties?.remoteProperty, 1);
@@ -426,7 +426,7 @@ describe("MergeTree", () => {
426
426
  props: { propertySource: "remote", remoteOnly: 1, secondSource: "remote" },
427
427
  }, remoteClient.perspectiveAt({ refSeq: currentSequenceNumber }), remoteClient.stampAt({ seq: ++currentSequenceNumber }), undefined);
428
428
  const segmentInfo = mergeTree.getContainingSegment(annotateStart, mergeTree.localPerspective);
429
- const segment = segmentInfo.segment;
429
+ const segment = segmentInfo?.segment;
430
430
  assert.equal(segment.properties?.remoteOnly, 1);
431
431
  assert.equal(segment.properties?.propertySource, "remote");
432
432
  assert.equal(segment.properties?.secondSource, "local2");
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTree.annotate.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.annotate.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\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { MergeTree } from \"../mergeTree.js\";\nimport { Marker, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { LocalDefaultPerspective } from \"../perspective.js\";\nimport { assertMergeNode } from \"../segmentInfos.js\";\nimport type { PropsOrAdjust } from \"../segmentPropertiesManager.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { makeRemoteClient } from \"./testUtils.js\";\n\nfunction splitAt(mergeTree: MergeTree, pos: number): ISegmentPrivate | undefined {\n\tlet segment: ISegmentPrivate | undefined;\n\tmergeTree.mapRange(\n\t\t(seg) => {\n\t\t\tsegment = seg;\n\t\t\treturn false;\n\t\t},\n\t\tnew LocalDefaultPerspective(mergeTree.collabWindow.clientId),\n\t\tundefined,\n\t\tpos,\n\t\tpos + 1,\n\t\ttrue,\n\t);\n\treturn segment;\n}\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\n\tconst annotateStart = 1;\n\tconst markerPosition = annotateStart + 2;\n\tconst annotateEnd = markerPosition + 2;\n\tconst splitPos = Math.floor((annotateEnd - annotateStart) / 2) + annotateStart;\n\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(\"hello world!\")],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.insertSegments(\n\t\t\tmarkerPosition,\n\t\t\t[Marker.make(ReferenceType.Tile)],\n\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\tundefined,\n\t\t);\n\t});\n\n\tdescribe(\"annotateRange\", () => {\n\t\tdescribe(\"not collaborating\", () => {\n\t\t\tit(\"remote\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"remote\" },\n\t\t\t\t\t},\n\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\tremoteClient.stampAt({ seq: currentSequenceNumber + 1 }),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment?.properties?.propertySource, \"remote\");\n\t\t\t});\n\n\t\t\tit(\"local\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t},\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t});\n\t\t});\n\t\tdescribe(\"collaborating\", () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tmergeTree.startCollaboration(\n\t\t\t\t\tlocalClientId,\n\t\t\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t\t\t);\n\t\t\t});\n\t\t\tdescribe(\"local first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local split\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, splitPos)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local split\", () => {\n\t\t\t\t\tconst secondChangeProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsecondChange: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsecondChangeProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst splitOnlyProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsplitOnly: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsplitOnlyProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tconst splitSegmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst splitSegment = splitSegmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 3);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment?.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...secondChangeProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: splitPos,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...splitOnlyProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"three local changes\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\n\t\t\t\t\tconst props2: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local2\", secondSource: 1 },\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops2,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\n\t\t\t\t\tconst props3: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tthirdSource: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops3,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props2,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props3,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"remote first\", () => {\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.size !== 0);\n\t\t\t\t});\n\t\t\t\tit(\"remote only\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"split remote\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, annotateStart + 1)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before sequenced local\", () => {\n\t\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t};\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.empty !== false);\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segmentInfo.segment?.segmentGroups?.size, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert(segmentInfo.segment?.segmentGroups?.empty);\n\t\t\t\t\tassert.equal(segmentInfo.segment?.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segmentInfo.segment?.properties?.remoteProperty, 1);\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"local with rewrite first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local2\", secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"mergeTree.annotate.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.annotate.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\nimport { strict as assert } from \"node:assert\";\n\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\n\nimport { MergeTree } from \"../mergeTree.js\";\nimport { Marker, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType, ReferenceType } from \"../ops.js\";\nimport { LocalDefaultPerspective } from \"../perspective.js\";\nimport { assertMergeNode } from \"../segmentInfos.js\";\nimport type { PropsOrAdjust } from \"../segmentPropertiesManager.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { makeRemoteClient } from \"./testUtils.js\";\n\nfunction splitAt(mergeTree: MergeTree, pos: number): ISegmentPrivate | undefined {\n\tlet segment: ISegmentPrivate | undefined;\n\tmergeTree.mapRange(\n\t\t(seg) => {\n\t\t\tsegment = seg;\n\t\t\treturn false;\n\t\t},\n\t\tnew LocalDefaultPerspective(mergeTree.collabWindow.clientId),\n\t\tundefined,\n\t\tpos,\n\t\tpos + 1,\n\t\ttrue,\n\t);\n\treturn segment;\n}\n\ndescribe(\"MergeTree\", () => {\n\tlet mergeTree: MergeTree;\n\tconst remoteClient = makeRemoteClient({ clientId: 35 });\n\tconst localClientId = 17;\n\tlet currentSequenceNumber: number;\n\n\tconst annotateStart = 1;\n\tconst markerPosition = annotateStart + 2;\n\tconst annotateEnd = markerPosition + 2;\n\tconst splitPos = Math.floor((annotateEnd - annotateStart) / 2) + annotateStart;\n\n\tbeforeEach(() => {\n\t\tmergeTree = new MergeTree();\n\t\tmergeTree.insertSegments(\n\t\t\t0,\n\t\t\t[TextSegment.make(\"hello world!\")],\n\t\t\tmergeTree.localPerspective,\n\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\tundefined,\n\t\t);\n\n\t\tcurrentSequenceNumber = 0;\n\t\tmergeTree.insertSegments(\n\t\t\tmarkerPosition,\n\t\t\t[Marker.make(ReferenceType.Tile)],\n\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\tundefined,\n\t\t);\n\t});\n\n\tdescribe(\"annotateRange\", () => {\n\t\tdescribe(\"not collaborating\", () => {\n\t\t\tit(\"remote\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"remote\" },\n\t\t\t\t\t},\n\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\tremoteClient.stampAt({ seq: currentSequenceNumber + 1 }),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment?.properties?.propertySource, \"remote\");\n\t\t\t});\n\n\t\t\tit(\"local\", () => {\n\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tannotateEnd,\n\t\t\t\t\t{\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t},\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\tundefined as never,\n\t\t\t\t);\n\n\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\tannotateStart,\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t);\n\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t});\n\t\t});\n\t\tdescribe(\"collaborating\", () => {\n\t\t\tbeforeEach(() => {\n\t\t\t\tmergeTree.startCollaboration(\n\t\t\t\t\tlocalClientId,\n\t\t\t\t\t/* minSeq: */ currentSequenceNumber,\n\t\t\t\t\t/* currentSeq: */ currentSequenceNumber,\n\t\t\t\t);\n\t\t\t});\n\t\t\tdescribe(\"local first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local split\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, splitPos)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local split\", () => {\n\t\t\t\t\tconst secondChangeProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsecondChange: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsecondChangeProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst splitOnlyProps: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsplitOnly: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tsplitOnlyProps,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tconst splitSegmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tsplitPos,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst splitSegment = splitSegmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 3);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment?.segmentGroups?.size, 2);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...secondChangeProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: splitPos,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...splitOnlyProps,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.secondChange, 1);\n\t\t\t\t\tassert(!segment.properties?.splitOnly);\n\n\t\t\t\t\tassert.equal(splitSegment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.secondChange, 1);\n\t\t\t\t\tassert.equal(splitSegment.properties?.splitOnly, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"three local changes\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\n\t\t\t\t\tconst props2: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local2\", secondSource: 1 },\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops2,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\n\t\t\t\t\tconst props3: PropsOrAdjust = {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tthirdSource: 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops3,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props2,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props3,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, 1);\n\t\t\t\t\tassert.equal(segment.properties?.thirdSource, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"remote first\", () => {\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.size !== 0);\n\t\t\t\t});\n\t\t\t\tit(\"remote only\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"split remote\", () => {\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tconst splitSegment = splitAt(mergeTree, annotateStart + 1)!;\n\t\t\t\t\tassertMergeNode(splitSegment);\n\t\t\t\t\tassert.notEqual(segmentInfo?.segment?.ordinal, splitSegment.ordinal);\n\t\t\t\t\tassert.equal(splitSegment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(splitSegment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"remote before sequenced local\", () => {\n\t\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t\t};\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.empty !== false);\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.segmentGroups?.size, 1);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tassert(segmentInfo?.segment?.segmentGroups?.empty);\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segmentInfo?.segment?.properties?.remoteProperty, 1);\n\t\t\t\t});\n\t\t\t});\n\t\t\tdescribe(\"local with rewrite first\", () => {\n\t\t\t\tconst props: PropsOrAdjust = {\n\t\t\t\t\tprops: { propertySource: \"local\" },\n\t\t\t\t};\n\t\t\t\tbeforeEach(() => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local after unsequenced local\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"local2\", secondProperty: \"local\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local2\");\n\t\t\t\t\tassert.equal(segment.properties?.secondProperty, \"local\");\n\t\t\t\t});\n\n\t\t\t\tit(\"unsequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"local\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"sequenced local before remote\", () => {\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteProperty: 1 },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.segmentGroups?.size, 0);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.remoteProperty, 1);\n\t\t\t\t});\n\n\t\t\t\tit(\"two local changes with interleaved remote\", () => {\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { secondSource: \"local2\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tmergeTree.ackOp({\n\t\t\t\t\t\top: {\n\t\t\t\t\t\t\tpos1: annotateStart,\n\t\t\t\t\t\t\tpos2: annotateEnd,\n\t\t\t\t\t\t\t...props,\n\t\t\t\t\t\t\ttype: MergeTreeDeltaType.ANNOTATE,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsequencedMessage: {\n\t\t\t\t\t\t\tsequenceNumber: ++currentSequenceNumber,\n\t\t\t\t\t\t} as unknown as ISequencedDocumentMessage,\n\t\t\t\t\t});\n\n\t\t\t\t\tmergeTree.annotateRange(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tannotateEnd,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprops: { propertySource: \"remote\", remoteOnly: 1, secondSource: \"remote\" },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tremoteClient.perspectiveAt({ refSeq: currentSequenceNumber }),\n\t\t\t\t\t\tremoteClient.stampAt({ seq: ++currentSequenceNumber }),\n\t\t\t\t\t\tundefined as never,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst segmentInfo = mergeTree.getContainingSegment(\n\t\t\t\t\t\tannotateStart,\n\t\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\t);\n\t\t\t\t\tconst segment = segmentInfo?.segment as ISegmentPrivate;\n\n\t\t\t\t\tassert.equal(segment.properties?.remoteOnly, 1);\n\t\t\t\t\tassert.equal(segment.properties?.propertySource, \"remote\");\n\t\t\t\t\tassert.equal(segment.properties?.secondSource, \"local2\");\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
@@ -48,7 +48,7 @@ describe("MergeTree.markRangeRemoved", () => {
48
48
  let seq = originalSeq;
49
49
  const remoteDeleteMessage = client.makeOpMessage(createRemoveRangeOp(0, client.getLength()), ++seq, undefined, "remote");
50
50
  const segmentExpectedRemovedSeq = seq;
51
- const { segment } = client.getContainingSegment(0);
51
+ const { segment } = client.getContainingSegment(0) ?? {};
52
52
  assert(segment !== undefined, "expected to find segment");
53
53
  const localDeleteMessage = client.makeOpMessage(client.removeRangeLocal(0, client.getLength()), ++seq, originalSeq /* refSeq */);
54
54
  assert.equal(client.getText(), "");
@@ -1 +1 @@
1
- {"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0);\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tconst localRemoveInfo = segment.removes[0];\n\t\tassert.equal(localRemoveInfo.seq, UnassignedSequenceNumber);\n\t\tassert(localRemoveInfo.localSeq !== undefined);\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tconst remoteRemoveInfo = segment.removes[0];\n\t\tassert.deepEqual(segment.removes[1], localRemoveInfo);\n\t\tassert.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tconst finalRemoveInfo = segment.removes[0];\n\t\tassert.equal(segment.removes.length, 2);\n\t\tassert.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(finalRemoveInfo.localSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
1
+ {"version":3,"file":"mergeTree.markRangeRemoved.spec.js","sourceRoot":"","sources":["../../src/test/mergeTree.markRangeRemoved.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-non-null-assertion */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { UnassignedSequenceNumber } from \"../constants.js\";\nimport type { ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { createInsertSegmentOp, createRemoveRangeOp } from \"../opBuilder.js\";\nimport { assertRemoved } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport { TestClient } from \"./testClient.js\";\n\ndescribe(\"MergeTree.markRangeRemoved\", () => {\n\tlet client: TestClient;\n\tbeforeEach(() => {\n\t\tclient = new TestClient();\n\t\tclient.startOrUpdateCollaboration(\"local\");\n\t\tfor (const char of \"hello world\") {\n\t\t\tclient.applyMsg(\n\t\t\t\tclient.makeOpMessage(\n\t\t\t\t\tclient.insertTextLocal(client.getLength(), char),\n\t\t\t\t\tclient.getCurrentSeq() + 1,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tassert.equal(client.getText(), \"hello world\");\n\t});\n\n\tit(\"local remove followed by local insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local insert followed by local remove\", () => {\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"texthello world\");\n\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by local insert\", () => {\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.insertTextLocal(0, \"text\");\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote insert\", () => {\n\t\tclient.removeRangeLocal(0, client.getLength());\n\t\tassert.equal(client.getText(), \"\");\n\n\t\tclient.applyMsg(\n\t\t\tclient.makeOpMessage(\n\t\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\t\"remote\",\n\t\t\t),\n\t\t);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local remove followed by remote overlapping remove\", () => {\n\t\tconst originalSeq = client.getCurrentSeq();\n\t\tlet seq = originalSeq;\n\t\tconst remoteDeleteMessage = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\t++seq,\n\t\t\tundefined,\n\t\t\t\"remote\",\n\t\t);\n\t\tconst segmentExpectedRemovedSeq = seq;\n\t\tconst { segment } = client.getContainingSegment<ISegmentPrivate>(0) ?? {};\n\t\tassert(segment !== undefined, \"expected to find segment\");\n\t\tconst localDeleteMessage = client.makeOpMessage(\n\t\t\tclient.removeRangeLocal(0, client.getLength()),\n\t\t\t++seq,\n\t\t\toriginalSeq /* refSeq */,\n\t\t);\n\n\t\tassert.equal(client.getText(), \"\");\n\t\tassertRemoved(segment);\n\t\tconst localRemoveInfo = segment.removes[0];\n\t\tassert.equal(localRemoveInfo.seq, UnassignedSequenceNumber);\n\t\tassert(localRemoveInfo.localSeq !== undefined);\n\n\t\tclient.applyMsg(remoteDeleteMessage);\n\t\tconst remoteRemoveInfo = segment.removes[0];\n\t\tassert.deepEqual(segment.removes[1], localRemoveInfo);\n\t\tassert.equal(remoteRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(client.getText(), \"\");\n\n\t\t// localRemovedSeq should remain on the segment until the local removal has been acked.\n\t\t// This ensures there's enough information to determine segment length in the case of\n\t\t// reconnect.\n\t\tclient.applyMsg(localDeleteMessage);\n\t\tconst finalRemoveInfo = segment.removes[0];\n\t\tassert.equal(segment.removes.length, 2);\n\t\tassert.equal(finalRemoveInfo.seq, segmentExpectedRemovedSeq);\n\t\tassert.equal(finalRemoveInfo.localSeq, undefined);\n\t\tassert.equal(client.getText(), \"\");\n\t});\n\n\tit(\"remote remove followed by remote insert\", () => {\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tclient.applyMsg(removeMsg);\n\t\tclient.applyMsg(insertMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"remote insert followed by remote remove\", () => {\n\t\tconst insertMsg = client.makeOpMessage(\n\t\t\tcreateInsertSegmentOp(0, TextSegment.make(\"text\")),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 1,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote\",\n\t\t);\n\n\t\tconst removeMsg = client.makeOpMessage(\n\t\t\tcreateRemoveRangeOp(0, client.getLength()),\n\t\t\tclient.mergeTree.collabWindow.currentSeq + 2,\n\t\t\tclient.mergeTree.collabWindow.currentSeq,\n\t\t\t\"remote2\",\n\t\t);\n\n\t\tclient.applyMsg(insertMsg);\n\t\tclient.applyMsg(removeMsg);\n\n\t\tassert.equal(client.getText(), \"text\");\n\t});\n\n\tit(\"local and remote clients race to insert at position of removed segment\", () => {\n\t\t// Note: This test constructs its own TestClients to avoid being initialized with \"hello world\".\n\n\t\t// First we run through the ops from the perspective of a passive observer (i.e., all operations are remote).\n\t\tconst expected = new TestClient();\n\t\texpected.startOrUpdateCollaboration(\"3\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"a\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"1\",\n\t\t\t);\n\t\t\texpected.removeRangeRemote(0, 1, ++seq, /* refSeq: */ 0, /* longClientId: */ \"1\");\n\t\t\tconst refSeqAt2 = expected.getCurrentSeq();\n\n\t\t\t// In parallel, Client 2 inserted \"x\" without knowledge of Client 1's insertion/removal.\n\t\t\texpected.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Client 1 inserts \"c\" having received acks for its own edits, but has not yet having\n\t\t\t// observed the insertion of \"X\" from client 2.\n\t\t\texpected.insertTextRemote(0, \"c\", undefined, ++seq, refSeqAt2, /* longClientId: */ \"1\");\n\t\t}\n\n\t\t// Next, we run through the same sequence from the perspective of client 1:\n\t\tconst actual = new TestClient();\n\t\tactual.startOrUpdateCollaboration(\"1\");\n\n\t\t{\n\t\t\tlet seq = 0;\n\n\t\t\t// Client 1 locally inserts and removes the letter \"a\".\n\t\t\tconst op1 = actual.insertTextLocal(0, \"a\")!;\n\t\t\tconst op2 = actual.removeRangeLocal(0, 1);\n\n\t\t\t// Client 1 receives ACKs for op1 and op2.\n\t\t\tactual.applyMsg(actual.makeOpMessage(op1, ++seq, /* refSeq: */ 0));\n\t\t\tactual.applyMsg(actual.makeOpMessage(op2, ++seq, /* refSeq: */ 0));\n\t\t\tconst refSeqAt2 = actual.getCurrentSeq();\n\n\t\t\t// Client 1 locally inserts \"c\".\n\t\t\tconst op4 = actual.insertTextLocal(0, \"c\");\n\n\t\t\t// Client 1 then processes the parallel insertion of \"X\" from Client 2 at refSeq=0\n\t\t\tactual.insertTextRemote(\n\t\t\t\t0,\n\t\t\t\t\"X\",\n\t\t\t\tundefined,\n\t\t\t\t++seq,\n\t\t\t\t/* refSeq: */ 0,\n\t\t\t\t/* longClientId: */ \"2\",\n\t\t\t);\n\n\t\t\t// Finally, client 1 receives the ack for its insertion of \"c\".\n\t\t\tactual.applyMsg(actual.makeOpMessage(op4, ++seq, refSeqAt2));\n\t\t}\n\n\t\tassert.equal(actual.getText(), expected.getText());\n\t});\n});\n"]}
@@ -75,11 +75,11 @@ describe("obliterate", () => {
75
75
  client.mergeTree.obliterateRange(obliterateStart, obliterateEnd, remoteClient1.perspectiveAt({ refSeq }), remoteClient1.stampAt({ seq: ++seq }), undefined);
76
76
  client.mergeTree.insertSegments(1, [TextSegment.make("more ")], remoteClient2.perspectiveAt({ refSeq }), remoteClient2.stampAt({ seq: ++seq }), { op: { type: MergeTreeDeltaType.INSERT } });
77
77
  assert.equal(client.getText(), "");
78
- startSeg.segment?.localRefs?.walkReferences((ref) => {
78
+ startSeg?.segment.localRefs?.walkReferences((ref) => {
79
79
  const oblProps = ref.properties?.obliterate;
80
80
  assert(oblProps?.start !== undefined, "start ref should NOT be removed");
81
81
  });
82
- endSeg.segment?.localRefs?.walkReferences((ref) => {
82
+ endSeg?.segment.localRefs?.walkReferences((ref) => {
83
83
  const oblProps = ref.properties?.obliterate;
84
84
  assert(oblProps?.end !== undefined, "end ref should NOT be removed");
85
85
  });
@@ -91,11 +91,11 @@ describe("obliterate", () => {
91
91
  client2.applyMsg(insert);
92
92
  }
93
93
  // want to check that the start and end segment don't have the obliterate refs on them
94
- startSeg.segment?.localRefs?.walkReferences((ref) => {
94
+ startSeg?.segment.localRefs?.walkReferences((ref) => {
95
95
  const oblProps = ref.properties?.obliterate;
96
96
  assert(oblProps.start === undefined, "start ref should be removed");
97
97
  });
98
- endSeg.segment?.localRefs?.walkReferences((ref) => {
98
+ endSeg?.segment.localRefs?.walkReferences((ref) => {
99
99
  const oblProps = ref.properties?.obliterate;
100
100
  assert(oblProps.end === undefined, "end ref should be removed");
101
101
  });