@fluidframework/merge-tree 3.6.0 → 3.10.0

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 (72) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/localReference.d.ts +4 -0
  3. package/dist/localReference.d.ts.map +1 -1
  4. package/dist/localReference.js +6 -0
  5. package/dist/localReference.js.map +1 -1
  6. package/dist/mergeTreeTracking.d.ts.map +1 -1
  7. package/dist/mergeTreeTracking.js +3 -5
  8. package/dist/mergeTreeTracking.js.map +1 -1
  9. package/dist/partialLengths.d.ts +13 -0
  10. package/dist/partialLengths.d.ts.map +1 -1
  11. package/dist/partialLengths.js +28 -11
  12. package/dist/partialLengths.js.map +1 -1
  13. package/dist/segmentGroupCollection.d.ts +0 -1
  14. package/dist/segmentGroupCollection.d.ts.map +1 -1
  15. package/dist/segmentGroupCollection.js +9 -10
  16. package/dist/segmentGroupCollection.js.map +1 -1
  17. package/dist/snapshotV1.d.ts.map +1 -1
  18. package/dist/snapshotV1.js +2 -0
  19. package/dist/snapshotV1.js.map +1 -1
  20. package/dist/snapshotlegacy.d.ts.map +1 -1
  21. package/dist/snapshotlegacy.js +2 -0
  22. package/dist/snapshotlegacy.js.map +1 -1
  23. package/dist/test/localReference.spec.js +18 -0
  24. package/dist/test/localReference.spec.js.map +1 -1
  25. package/dist/test/partialLength.spec.js +62 -0
  26. package/dist/test/partialLength.spec.js.map +1 -1
  27. package/dist/test/segmentGroupCollection.spec.js +29 -0
  28. package/dist/test/segmentGroupCollection.spec.js.map +1 -1
  29. package/dist/test/testUtils.d.ts.map +1 -1
  30. package/dist/test/testUtils.js +1 -2
  31. package/dist/test/testUtils.js.map +1 -1
  32. package/dist/test/tracking.spec.js +16 -0
  33. package/dist/test/tracking.spec.js.map +1 -1
  34. package/lib/localReference.d.ts +4 -0
  35. package/lib/localReference.d.ts.map +1 -1
  36. package/lib/localReference.js +6 -0
  37. package/lib/localReference.js.map +1 -1
  38. package/lib/mergeTreeTracking.d.ts.map +1 -1
  39. package/lib/mergeTreeTracking.js +3 -5
  40. package/lib/mergeTreeTracking.js.map +1 -1
  41. package/lib/partialLengths.d.ts +13 -0
  42. package/lib/partialLengths.d.ts.map +1 -1
  43. package/lib/partialLengths.js +28 -11
  44. package/lib/partialLengths.js.map +1 -1
  45. package/lib/segmentGroupCollection.d.ts +0 -1
  46. package/lib/segmentGroupCollection.d.ts.map +1 -1
  47. package/lib/segmentGroupCollection.js +9 -10
  48. package/lib/segmentGroupCollection.js.map +1 -1
  49. package/lib/snapshotV1.d.ts.map +1 -1
  50. package/lib/snapshotV1.js +2 -0
  51. package/lib/snapshotV1.js.map +1 -1
  52. package/lib/snapshotlegacy.d.ts.map +1 -1
  53. package/lib/snapshotlegacy.js +2 -0
  54. package/lib/snapshotlegacy.js.map +1 -1
  55. package/lib/test/localReference.spec.js +18 -0
  56. package/lib/test/localReference.spec.js.map +1 -1
  57. package/lib/test/partialLength.spec.js +62 -0
  58. package/lib/test/partialLength.spec.js.map +1 -1
  59. package/lib/test/segmentGroupCollection.spec.js +30 -1
  60. package/lib/test/segmentGroupCollection.spec.js.map +1 -1
  61. package/lib/test/testUtils.d.ts.map +1 -1
  62. package/lib/test/testUtils.js +1 -2
  63. package/lib/test/testUtils.js.map +1 -1
  64. package/lib/test/tracking.spec.js +17 -1
  65. package/lib/test/tracking.spec.js.map +1 -1
  66. package/package.json +16 -16
  67. package/src/localReference.ts +7 -0
  68. package/src/mergeTreeTracking.ts +3 -6
  69. package/src/partialLengths.ts +31 -13
  70. package/src/segmentGroupCollection.ts +9 -11
  71. package/src/snapshotV1.ts +2 -0
  72. package/src/snapshotlegacy.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IChannelStorageService } from \"@fluidframework/datastore-definitions/internal\";\nimport type {\n\tISummaryTreeWithStats,\n\tAttributionKey,\n} from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tcreateChildLogger,\n\ttype TelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { IAttributionCollection } from \"./attributionCollection.js\";\nimport { NonCollabClient } from \"./constants.js\";\nimport type { MergeTree } from \"./mergeTree.js\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk.js\";\nimport type { ISegmentPrivate } from \"./mergeTreeNodes.js\";\nimport type { IJSONSegment } from \"./ops.js\";\nimport { type PropertySet, matchProperties } from \"./properties.js\";\nimport { assertInserted, isRemoved } from \"./segmentInfos.js\";\nimport {\n\ttype IJSONSegmentWithMergeInfo,\n\ttype JsonSegmentSpecs,\n\ttype MergeTreeChunkV1,\n\ttype MergeTreeHeaderMetadata,\n\tserializeAsMaxSupportedVersion,\n\ttoLatestVersion,\n\ttype VersionedMergeTreeChunk,\n} from \"./snapshotChunks.js\";\nimport { SnapshotLegacy } from \"./snapshotlegacy.js\";\nimport type { OperationStamp } from \"./stamps.js\";\nimport * as opstampUtils from \"./stamps.js\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: TelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: TelemetryLoggerExt,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tfor (const [index, chunk] of chunks.entries()) {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tfor (const value of blobs) {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): JsonSegmentSpecs[] {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\t\tconst minSeqStamp: OperationStamp = { seq: minSeq, clientId: NonCollabClient };\n\n\t\tlet originalSegments = 0;\n\t\tlet segmentsAfterCombine = 0;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t): void => {\n\t\t\tsegmentsAfterCombine += 1;\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegmentPrivate): void => {\n\t\t\tif (segment) {\n\t\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t}\n\t\t\t\tpushSegRaw(\n\t\t\t\t\tsegment.toJSONObject() as JsonSegmentSpecs,\n\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\tsegment.attribution,\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegmentPrivate | undefined;\n\t\tconst extractSegment = (segment: ISegmentPrivate): boolean => {\n\t\t\tassertInserted(segment);\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\tif (\n\t\t\t\topstampUtils.isLocal(segment.insert) ||\n\t\t\t\t(isRemoved(segment) && opstampUtils.lte(segment.removes[0], minSeqStamp))\n\t\t\t) {\n\t\t\t\tif (opstampUtils.isAcked(segment.insert)) {\n\t\t\t\t\toriginalSegments += 1;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\toriginalSegments += 1;\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\topstampUtils.lte(segment.insert, minSeqStamp) && // Segment is below the MSN, and...\n\t\t\t\t(!isRemoved(segment) || opstampUtils.isLocal(segment.removes[0]))\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t}\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo & { removedClient?: string } = {\n\t\t\t\t\tjson: segment.toJSONObject() as IJSONSegment,\n\t\t\t\t};\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\tif (opstampUtils.greaterThan(segment.insert, minSeqStamp)) {\n\t\t\t\t\traw.seq = segment.insert.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.insert.clientId);\n\t\t\t\t}\n\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (isRemoved(segment) && segment.removes.some((r) => r.type === \"setRemove\")) {\n\t\t\t\t\tconst removes = segment.removes.filter((r) => r.type === \"setRemove\");\n\t\t\t\t\tconst firstRemove = removes[0];\n\t\t\t\t\tassert(\n\t\t\t\t\t\topstampUtils.isAcked(firstRemove) &&\n\t\t\t\t\t\t\topstampUtils.greaterThan(firstRemove, minSeqStamp),\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\t// TODO:AB#32299 By not preserving sequence numbers other than the first move,\n\t\t\t\t\t// We drop data here which will be necessary to allow perspectives of remote clients that\n\t\t\t\t\t// don't include all of their ops. This should be remedied at some point.\n\t\t\t\t\traw.removedSeq = firstRemove.seq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\t// This can be removed when we can safely assume no clients running Fluid packages <= 0.58 will ever\n\t\t\t\t\t// load a document produced by a version beyond the removal. It is vestigial in the meantime.\n\t\t\t\t\traw.removedClient = this.getLongClientId(firstRemove.clientId);\n\n\t\t\t\t\traw.removedClientIds = removes.map(({ clientId }) => this.getLongClientId(clientId));\n\t\t\t\t}\n\n\t\t\t\tif (isRemoved(segment) && segment.removes.some((r) => r.type === \"sliceRemove\")) {\n\t\t\t\t\t// In this format, we used the term \"move\" to refer to a sliceRemove/obliterate.\n\t\t\t\t\tconst moves = segment.removes.filter((r) => r.type === \"sliceRemove\");\n\t\t\t\t\tconst firstMove = moves[0];\n\t\t\t\t\tassert(\n\t\t\t\t\t\topstampUtils.isAcked(firstMove) &&\n\t\t\t\t\t\t\topstampUtils.greaterThan(firstMove, minSeqStamp),\n\t\t\t\t\t\t0x873 /* On move info preservation, segment has invalid moved sequence number! */,\n\t\t\t\t\t);\n\t\t\t\t\traw.movedSeq = firstMove.seq;\n\t\t\t\t\traw.movedSeqs = moves.map(({ seq }) => seq);\n\t\t\t\t\traw.movedClientIds = moves.map(({ clientId }) => this.getLongClientId(clientId));\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq > minSeq or a (re)moved segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClientIds !== undefined) ||\n\t\t\t\t\t\t(raw.movedSeq !== undefined &&\n\t\t\t\t\t\t\traw.movedClientIds !== undefined &&\n\t\t\t\t\t\t\traw.movedClientIds.length > 0 &&\n\t\t\t\t\t\t\traw.movedSeqs !== undefined &&\n\t\t\t\t\t\t\traw.movedSeqs.length > 0),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with its required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segmentsAfterCombine) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeV1SummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: TelemetryLoggerExt,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: TelemetryLoggerExt,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj: VersionedMergeTreeChunk = serializer\n\t\t\t? (serializer.parse(chunk) as VersionedMergeTreeChunk)\n\t\t\t: (JSON.parse(chunk) as VersionedMergeTreeChunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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 { bufferToString } from \"@fluid-internal/client-utils\";\nimport type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IChannelStorageService } from \"@fluidframework/datastore-definitions/internal\";\nimport type {\n\tISummaryTreeWithStats,\n\tAttributionKey,\n} from \"@fluidframework/runtime-definitions/internal\";\n// eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tcreateChildLogger,\n\ttype TelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { IAttributionCollection } from \"./attributionCollection.js\";\nimport { NonCollabClient } from \"./constants.js\";\nimport type { MergeTree } from \"./mergeTree.js\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk.js\";\nimport type { ISegmentPrivate } from \"./mergeTreeNodes.js\";\nimport type { IJSONSegment } from \"./ops.js\";\nimport { type PropertySet, matchProperties } from \"./properties.js\";\nimport { assertInserted, isRemoved } from \"./segmentInfos.js\";\nimport {\n\ttype IJSONSegmentWithMergeInfo,\n\ttype JsonSegmentSpecs,\n\ttype MergeTreeChunkV1,\n\ttype MergeTreeHeaderMetadata,\n\tserializeAsMaxSupportedVersion,\n\ttoLatestVersion,\n\ttype VersionedMergeTreeChunk,\n} from \"./snapshotChunks.js\";\nimport { SnapshotLegacy } from \"./snapshotlegacy.js\";\nimport type { OperationStamp } from \"./stamps.js\";\nimport * as opstampUtils from \"./stamps.js\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: TelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: TelemetryLoggerExt,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tfor (const [index, chunk] of chunks.entries()) {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t}\n\n\t\t// eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tfor (const value of blobs) {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): JsonSegmentSpecs[] {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\t\tconst minSeqStamp: OperationStamp = { seq: minSeq, clientId: NonCollabClient };\n\n\t\tlet originalSegments = 0;\n\t\tlet segmentsAfterCombine = 0;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t): void => {\n\t\t\tsegmentsAfterCombine += 1;\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegmentPrivate): void => {\n\t\t\tif (segment) {\n\t\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t}\n\t\t\t\tpushSegRaw(\n\t\t\t\t\tsegment.toJSONObject() as JsonSegmentSpecs,\n\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\tsegment.attribution,\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegmentPrivate | undefined;\n\t\tconst extractSegment = (segment: ISegmentPrivate): boolean => {\n\t\t\tassertInserted(segment);\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\tif (\n\t\t\t\topstampUtils.isLocal(segment.insert) ||\n\t\t\t\t(isRemoved(segment) && opstampUtils.lte(segment.removes[0], minSeqStamp))\n\t\t\t) {\n\t\t\t\tif (opstampUtils.isAcked(segment.insert)) {\n\t\t\t\t\toriginalSegments += 1;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\toriginalSegments += 1;\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\topstampUtils.lte(segment.insert, minSeqStamp) && // Segment is below the MSN, and...\n\t\t\t\t(!isRemoved(segment) || opstampUtils.isLocal(segment.removes[0]))\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t}\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo & { removedClient?: string } = {\n\t\t\t\t\tjson: segment.toJSONObject() as IJSONSegment,\n\t\t\t\t};\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\tif (opstampUtils.greaterThan(segment.insert, minSeqStamp)) {\n\t\t\t\t\traw.seq = segment.insert.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.insert.clientId);\n\t\t\t\t}\n\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (isRemoved(segment) && segment.removes.some((r) => r.type === \"setRemove\")) {\n\t\t\t\t\tconst removes = segment.removes.filter((r) => r.type === \"setRemove\");\n\t\t\t\t\tconst firstRemove = removes[0];\n\t\t\t\t\tassert(\n\t\t\t\t\t\topstampUtils.isAcked(firstRemove) &&\n\t\t\t\t\t\t\topstampUtils.greaterThan(firstRemove, minSeqStamp),\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\t// TODO:AB#32299 By not preserving sequence numbers other than the first move,\n\t\t\t\t\t// We drop data here which will be necessary to allow perspectives of remote clients that\n\t\t\t\t\t// don't include all of their ops. This should be remedied at some point.\n\t\t\t\t\traw.removedSeq = firstRemove.seq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\t// This can be removed when we can safely assume no clients running Fluid packages <= 0.58 will ever\n\t\t\t\t\t// load a document produced by a version beyond the removal. It is vestigial in the meantime.\n\t\t\t\t\traw.removedClient = this.getLongClientId(firstRemove.clientId);\n\n\t\t\t\t\traw.removedClientIds = removes.map(({ clientId }) => this.getLongClientId(clientId));\n\t\t\t\t}\n\n\t\t\t\tif (isRemoved(segment) && segment.removes.some((r) => r.type === \"sliceRemove\")) {\n\t\t\t\t\t// In this format, we used the term \"move\" to refer to a sliceRemove/obliterate.\n\t\t\t\t\tconst moves = segment.removes.filter((r) => r.type === \"sliceRemove\");\n\t\t\t\t\tconst firstMove = moves[0];\n\t\t\t\t\tassert(\n\t\t\t\t\t\topstampUtils.isAcked(firstMove) &&\n\t\t\t\t\t\t\topstampUtils.greaterThan(firstMove, minSeqStamp),\n\t\t\t\t\t\t0x873 /* On move info preservation, segment has invalid moved sequence number! */,\n\t\t\t\t\t);\n\t\t\t\t\traw.movedSeq = firstMove.seq;\n\t\t\t\t\traw.movedSeqs = moves.map(({ seq }) => seq);\n\t\t\t\t\traw.movedClientIds = moves.map(({ clientId }) => this.getLongClientId(clientId));\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq > minSeq or a (re)moved segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClientIds !== undefined) ||\n\t\t\t\t\t\t(raw.movedSeq !== undefined &&\n\t\t\t\t\t\t\traw.movedClientIds !== undefined &&\n\t\t\t\t\t\t\traw.movedClientIds.length > 0 &&\n\t\t\t\t\t\t\traw.movedSeqs !== undefined &&\n\t\t\t\t\t\t\traw.movedSeqs.length > 0),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with its required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segmentsAfterCombine) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeV1SummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: TelemetryLoggerExt,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: TelemetryLoggerExt,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj: VersionedMergeTreeChunk = serializer\n\t\t\t? (serializer.parse(chunk) as VersionedMergeTreeChunk)\n\t\t\t: (JSON.parse(chunk) as VersionedMergeTreeChunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AAE1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAEN,KAAK,kBAAkB,EACvB,MAAM,0CAA0C,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAoB1E;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC,EAAE,MAAM;IACjB,YAAY,CAAC,GAAE,MAAM,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,kBAAkB,EACnB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,YAAY,CAAC,GAAE,MAAM,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IAiExB,WAAW,IAAI,eAAe,EAAE;CAoEhC"}
1
+ {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAC;AAG1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAEN,KAAK,kBAAkB,EACvB,MAAM,0CAA0C,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAoB1E;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC,EAAE,MAAM;IACjB,YAAY,CAAC,GAAE,MAAM,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,kBAAkB,EACnB,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,YAAY,CAAC,GAAE,MAAM,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IAkExB,WAAW,IAAI,eAAe,EAAE;CAoEhC"}
@@ -6,6 +6,7 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.SnapshotLegacy = void 0;
8
8
  const internal_1 = require("@fluidframework/core-utils/internal");
9
+ // eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).
9
10
  const internal_2 = require("@fluidframework/runtime-utils/internal");
10
11
  const internal_3 = require("@fluidframework/telemetry-utils/internal");
11
12
  const constants_js_1 = require("./constants.js");
@@ -83,6 +84,7 @@ class SnapshotLegacy {
83
84
  const chunk1 = this.getSeqLengthSegs(this.segments, this.chunkSize);
84
85
  let length = chunk1.chunkLengthChars;
85
86
  let segments = chunk1.chunkSegmentCount;
87
+ // eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).
86
88
  const builder = new internal_2.SummaryTreeBuilder();
87
89
  builder.addBlob(SnapshotLegacy.header, (0, snapshotChunks_js_1.serializeAsMinSupportedVersion)(SnapshotLegacy.header, chunk1, this.logger, this.mergeTree.options, serializer, bind));
88
90
  if (chunk1.chunkSegmentCount < chunk1.totalSegmentCount) {
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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 type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport type { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tcreateChildLogger,\n\ttype TelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { NonCollabClient } from \"./constants.js\";\nimport type { MergeTree } from \"./mergeTree.js\";\nimport { isSegmentLeaf, type ISegmentPrivate } from \"./mergeTreeNodes.js\";\nimport { PriorPerspective } from \"./perspective.js\";\nimport { matchProperties } from \"./properties.js\";\nimport {\n\ttype JsonSegmentSpecs,\n\ttype MergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks.js\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegmentPrivate[] | undefined;\n\tprivate readonly logger: TelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: TelemetryLoggerExt,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegmentPrivate[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegmentPrivate[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0 || this.mergeTree.attributionPolicy?.isAttached\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\t// Messages used to have a \"term\" property which has since been removed.\n\t\t\t// It is benign so it doesn't really need to be deleted here, but doing so permits snapshot tests\n\t\t\t// to pass with an exact match (and matching the updated definition of ISequencedDocumentMessage).\n\t\t\tfor (const message of catchUpMsgs) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tdelete (message as any).term;\n\t\t\t}\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): ISegmentPrivate[] {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tconst seq = (this.seq = collabWindow.minSeq);\n\t\tconst minSeqPerspective = new PriorPerspective(this.seq, NonCollabClient);\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(minSeqPerspective),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tlet originalSegments = 0;\n\n\t\tconst segs: ISegmentPrivate[] = [];\n\t\tlet prev: ISegmentPrivate | undefined;\n\t\tconst extractSegment = (segment: ISegmentPrivate): boolean => {\n\t\t\tif (isSegmentLeaf(segment) && minSeqPerspective.isSegmentPresent(segment)) {\n\t\t\t\toriginalSegments += 1;\n\t\t\t\tconst properties =\n\t\t\t\t\tsegment.propertyManager?.getAtSeq(segment.properties, seq) ?? segment.properties;\n\t\t\t\tif (prev?.canAppend(segment) && matchProperties(prev.properties, properties)) {\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tprev = segment.clone();\n\t\t\t\t\tprev.properties = properties;\n\t\t\t\t\tsegs.push(prev);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, minSeqPerspective, undefined);\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segs.length) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeLegacySummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine: segs.length,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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 type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport type { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\n// eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\nimport type { IFluidSerializer } from \"@fluidframework/shared-object-base/internal\";\nimport {\n\tcreateChildLogger,\n\ttype TelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { NonCollabClient } from \"./constants.js\";\nimport type { MergeTree } from \"./mergeTree.js\";\nimport { isSegmentLeaf, type ISegmentPrivate } from \"./mergeTreeNodes.js\";\nimport { PriorPerspective } from \"./perspective.js\";\nimport { matchProperties } from \"./properties.js\";\nimport {\n\ttype JsonSegmentSpecs,\n\ttype MergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks.js\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegmentPrivate[] | undefined;\n\tprivate readonly logger: TelemetryLoggerExt;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: TelemetryLoggerExt,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"Snapshot\" });\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegmentPrivate[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegmentPrivate[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0 || this.mergeTree.attributionPolicy?.isAttached\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\t// eslint-disable-next-line import-x/no-deprecated -- Internal implementation use is supported (AB#88250).\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\t// Messages used to have a \"term\" property which has since been removed.\n\t\t\t// It is benign so it doesn't really need to be deleted here, but doing so permits snapshot tests\n\t\t\t// to pass with an exact match (and matching the updated definition of ISequencedDocumentMessage).\n\t\t\tfor (const message of catchUpMsgs) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t\tdelete (message as any).term;\n\t\t\t}\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync(): ISegmentPrivate[] {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tconst seq = (this.seq = collabWindow.minSeq);\n\t\tconst minSeqPerspective = new PriorPerspective(this.seq, NonCollabClient);\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(minSeqPerspective),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tlet originalSegments = 0;\n\n\t\tconst segs: ISegmentPrivate[] = [];\n\t\tlet prev: ISegmentPrivate | undefined;\n\t\tconst extractSegment = (segment: ISegmentPrivate): boolean => {\n\t\t\tif (isSegmentLeaf(segment) && minSeqPerspective.isSegmentPresent(segment)) {\n\t\t\t\toriginalSegments += 1;\n\t\t\t\tconst properties =\n\t\t\t\t\tsegment.propertyManager?.getAtSeq(segment.properties, seq) ?? segment.properties;\n\t\t\t\tif (prev?.canAppend(segment) && matchProperties(prev.properties, properties)) {\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tprev = segment.clone();\n\t\t\t\t\tprev.properties = properties;\n\t\t\t\t\tsegs.push(prev);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, minSeqPerspective, undefined);\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// To reduce potential spam from this telemetry, we sample only a small\n\t\t// percentage of summaries\n\t\tif (Math.abs(originalSegments - segs.length) > 500 && Math.random() < 0.005) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"MergeTreeLegacySummarizeSegmentCount\",\n\t\t\t\toriginalSegments,\n\t\t\t\tsegmentsAfterCombine: segs.length,\n\t\t\t\tsegmentsLen: this.segments.length,\n\t\t\t});\n\t\t}\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
@@ -49,6 +49,24 @@ function addTombstones(collection, position, ids) {
49
49
  return refs;
50
50
  }
51
51
  describe("LocalReferenceCollection", () => {
52
+ describe("size", () => {
53
+ it("counts stored references as they are added and removed", () => {
54
+ const { collection } = setup("abc", 0);
55
+ node_assert_1.strict.equal(collection.size, 0);
56
+ const ref = collection.createLocalRef(1, ops_js_1.ReferenceType.Simple, undefined);
57
+ node_assert_1.strict.equal(collection.size, 1);
58
+ collection.createLocalRef(2, ops_js_1.ReferenceType.Transient, undefined);
59
+ node_assert_1.strict.equal(collection.size, 1); // Transient references are not stored.
60
+ collection.removeLocalRef(ref);
61
+ node_assert_1.strict.equal(collection.size, 0);
62
+ });
63
+ it("includes references in before, at, and after buckets", () => {
64
+ const { collection } = setup("abc", 1);
65
+ addTombstones(collection, "before", ["before-0", "before-1"]);
66
+ addTombstones(collection, "after", ["after-0"]);
67
+ node_assert_1.strict.equal(collection.size, 6); // Three at + two before + one after.
68
+ });
69
+ });
52
70
  describe("walkReferences", () => {
53
71
  it("walks all references when no start is provided", () => {
54
72
  const { collection } = setup("abc", 2);
@@ -1 +1 @@
1
- {"version":3,"file":"localReference.spec.js","sourceRoot":"","sources":["../../src/test/localReference.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 { LocalReferenceCollection, type LocalReferencePosition } from \"../localReference.js\";\nimport type { ISegmentInternal } from \"../mergeTreeNodes.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\ninterface TestSetup {\n\tcollection: LocalReferenceCollection;\n\t/**\n\t * All refs in collection order (offset ascending, and insertion order within an offset).\n\t */\n\trefs: LocalReferencePosition[];\n}\n\n/**\n * Creates a collection over a segment of length `text.length` with `refsPerOffset`\n * references at every offset. Each reference is labeled via its `id` property so\n * walk order can be asserted.\n */\nfunction setup(text: string, refsPerOffset: number): TestSetup {\n\tconst segment = TextSegment.make(text) as ISegmentInternal;\n\tconst collection = LocalReferenceCollection.setOrGet(segment);\n\tconst refs: LocalReferencePosition[] = [];\n\tfor (let offset = 0; offset < text.length; offset++) {\n\t\tfor (let i = 0; i < refsPerOffset; i++) {\n\t\t\trefs.push(\n\t\t\t\tcollection.createLocalRef(offset, ReferenceType.Simple, { id: `${offset}-${i}` }),\n\t\t\t);\n\t\t}\n\t}\n\treturn { collection, refs };\n}\n\nfunction walk(\n\tcollection: LocalReferenceCollection,\n\tstart?: LocalReferencePosition,\n\tforward: boolean = true,\n): string[] {\n\tconst visited: string[] = [];\n\tcollection.walkReferences(\n\t\t(lref) => {\n\t\t\tvisited.push(lref.properties?.id as string);\n\t\t},\n\t\tstart,\n\t\tforward,\n\t);\n\treturn visited;\n}\n\n/**\n * Slides references into the `before` bucket at offset 0, or the `after` bucket at the last\n * offset, of `collection`. Tombstoned references arrive from a segment that was removed, so\n * they are created on a donor segment and re-linked by the collection.\n */\nfunction addTombstones(\n\tcollection: LocalReferenceCollection,\n\tposition: \"before\" | \"after\",\n\tids: string[],\n): LocalReferencePosition[] {\n\tconst donor = TextSegment.make(\"x\") as ISegmentInternal;\n\tconst donorCollection = LocalReferenceCollection.setOrGet(donor);\n\tconst refs = ids.map((id) =>\n\t\tdonorCollection.createLocalRef(0, ReferenceType.SlideOnRemove, { id }),\n\t);\n\tif (position === \"before\") {\n\t\tcollection.addBeforeTombstones(refs);\n\t} else {\n\t\tcollection.addAfterTombstones(refs);\n\t}\n\treturn refs;\n}\n\ndescribe(\"LocalReferenceCollection\", () => {\n\tdescribe(\"walkReferences\", () => {\n\t\tit(\"walks all references when no start is provided\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection), [\"0-0\", \"0-1\", \"1-0\", \"1-1\", \"2-0\", \"2-1\"]);\n\t\t});\n\n\t\tit(\"walks all references backward when no start is provided\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection, undefined, false), [\n\t\t\t\t\"2-1\",\n\t\t\t\t\"2-0\",\n\t\t\t\t\"1-1\",\n\t\t\t\t\"1-0\",\n\t\t\t\t\"0-1\",\n\t\t\t\t\"0-0\",\n\t\t\t]);\n\t\t});\n\n\t\tit(\"includes the start reference when walking forward\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\t// refs[2] is the first reference at offset 1\n\t\t\tassert.deepEqual(walk(collection, refs[2]), [\"1-0\", \"1-1\", \"2-0\", \"2-1\"]);\n\t\t});\n\n\t\tit(\"includes the start reference when walking backward\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection, refs[2], false), [\"1-0\", \"0-1\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"resumes mid-list when start is not the first reference at its offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 3);\n\t\t\t// refs[4] is the second reference at offset 1\n\t\t\tassert.deepEqual(walk(collection, refs[4]), [\"1-1\", \"1-2\", \"2-0\", \"2-1\", \"2-2\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[4], false), [\"1-1\", \"1-0\", \"0-2\", \"0-1\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"includes the start reference at the first offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 1);\n\t\t\tassert.deepEqual(walk(collection, refs[0]), [\"0-0\", \"1-0\", \"2-0\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[0], false), [\"0-0\"]);\n\t\t});\n\n\t\tit(\"includes the start reference at the last offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 1);\n\t\t\tassert.deepEqual(walk(collection, refs[2]), [\"2-0\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[2], false), [\"2-0\", \"1-0\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"stops early when the visitor returns false\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\tconst visited: string[] = [];\n\t\t\tconst completed = collection.walkReferences((lref) => {\n\t\t\t\tvisited.push(lref.properties?.id as string);\n\t\t\t\treturn lref.properties?.id !== \"1-1\";\n\t\t\t}, refs[2]);\n\t\t\tassert.equal(completed, false);\n\t\t\tassert.deepEqual(visited, [\"1-0\", \"1-1\"]);\n\t\t});\n\n\t\tdescribe(\"when an offset holds multiple buckets\", () => {\n\t\t\t/**\n\t\t\t * Builds a collection over \"abc\" with an `at` reference at every offset, a `before`\n\t\t\t * bucket coexisting with `at` at offset 0, and an `after` bucket coexisting with `at`\n\t\t\t * at offset 2.\n\t\t\t */\n\t\t\tfunction setupMultiBucket(): {\n\t\t\t\tcollection: LocalReferenceCollection;\n\t\t\t\tat: LocalReferencePosition[];\n\t\t\t\tbefore: LocalReferencePosition[];\n\t\t\t\tafter: LocalReferencePosition[];\n\t\t\t} {\n\t\t\t\tconst { collection, refs: at } = setup(\"abc\", 1);\n\t\t\t\tconst before = addTombstones(collection, \"before\", [\"b-0\", \"b-1\"]);\n\t\t\t\tconst after = addTombstones(collection, \"after\", [\"a-0\", \"a-1\"]);\n\t\t\t\treturn { collection, at, before, after };\n\t\t\t}\n\n\t\t\tit(\"walks buckets in before/at/after order\", () => {\n\t\t\t\tconst { collection } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection), [\"b-0\", \"b-1\", \"0-0\", \"1-0\", \"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t\tassert.deepEqual(walk(collection, undefined, false), [\n\t\t\t\t\t\"a-1\",\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"b-0\",\n\t\t\t\t]);\n\t\t\t});\n\n\t\t\tit(\"skips sibling buckets preceding the bucket holding start\", () => {\n\t\t\t\tconst { collection, at } = setupMultiBucket();\n\t\t\t\t// Starting at the `at` bucket must discard the `before` bucket at the same offset,\n\t\t\t\t// without discarding the `at` bucket itself.\n\t\t\t\tassert.deepEqual(walk(collection, at[0]), [\"0-0\", \"1-0\", \"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t\t// Starting at the `at` bucket of the last offset must discard nothing it needs,\n\t\t\t\t// and still reach the trailing `after` bucket.\n\t\t\t\tassert.deepEqual(walk(collection, at[2]), [\"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t});\n\n\t\t\tit(\"skips sibling buckets following the bucket holding start when walking backward\", () => {\n\t\t\t\tconst { collection, at } = setupMultiBucket();\n\t\t\t\t// Walking backward from the `at` bucket must discard the trailing `after` bucket\n\t\t\t\t// at the same offset, then continue into the `before` bucket.\n\t\t\t\tassert.deepEqual(walk(collection, at[2], false), [\"2-0\", \"1-0\", \"0-0\", \"b-1\", \"b-0\"]);\n\t\t\t\tassert.deepEqual(walk(collection, at[0], false), [\"0-0\", \"b-1\", \"b-0\"]);\n\t\t\t});\n\n\t\t\tit(\"starts within the before bucket\", () => {\n\t\t\t\tconst { collection, before } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection, before[1]), [\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"a-1\",\n\t\t\t\t]);\n\t\t\t\tassert.deepEqual(walk(collection, before[1], false), [\"b-1\", \"b-0\"]);\n\t\t\t});\n\n\t\t\tit(\"starts within the after bucket\", () => {\n\t\t\t\tconst { collection, after } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection, after[0]), [\"a-0\", \"a-1\"]);\n\t\t\t\tassert.deepEqual(walk(collection, after[0], false), [\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"b-0\",\n\t\t\t\t]);\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"localReference.spec.js","sourceRoot":"","sources":["../../src/test/localReference.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 { LocalReferenceCollection, type LocalReferencePosition } from \"../localReference.js\";\nimport type { ISegmentInternal } from \"../mergeTreeNodes.js\";\nimport { ReferenceType } from \"../ops.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\ninterface TestSetup {\n\tcollection: LocalReferenceCollection;\n\t/**\n\t * All refs in collection order (offset ascending, and insertion order within an offset).\n\t */\n\trefs: LocalReferencePosition[];\n}\n\n/**\n * Creates a collection over a segment of length `text.length` with `refsPerOffset`\n * references at every offset. Each reference is labeled via its `id` property so\n * walk order can be asserted.\n */\nfunction setup(text: string, refsPerOffset: number): TestSetup {\n\tconst segment = TextSegment.make(text) as ISegmentInternal;\n\tconst collection = LocalReferenceCollection.setOrGet(segment);\n\tconst refs: LocalReferencePosition[] = [];\n\tfor (let offset = 0; offset < text.length; offset++) {\n\t\tfor (let i = 0; i < refsPerOffset; i++) {\n\t\t\trefs.push(\n\t\t\t\tcollection.createLocalRef(offset, ReferenceType.Simple, { id: `${offset}-${i}` }),\n\t\t\t);\n\t\t}\n\t}\n\treturn { collection, refs };\n}\n\nfunction walk(\n\tcollection: LocalReferenceCollection,\n\tstart?: LocalReferencePosition,\n\tforward: boolean = true,\n): string[] {\n\tconst visited: string[] = [];\n\tcollection.walkReferences(\n\t\t(lref) => {\n\t\t\tvisited.push(lref.properties?.id as string);\n\t\t},\n\t\tstart,\n\t\tforward,\n\t);\n\treturn visited;\n}\n\n/**\n * Slides references into the `before` bucket at offset 0, or the `after` bucket at the last\n * offset, of `collection`. Tombstoned references arrive from a segment that was removed, so\n * they are created on a donor segment and re-linked by the collection.\n */\nfunction addTombstones(\n\tcollection: LocalReferenceCollection,\n\tposition: \"before\" | \"after\",\n\tids: string[],\n): LocalReferencePosition[] {\n\tconst donor = TextSegment.make(\"x\") as ISegmentInternal;\n\tconst donorCollection = LocalReferenceCollection.setOrGet(donor);\n\tconst refs = ids.map((id) =>\n\t\tdonorCollection.createLocalRef(0, ReferenceType.SlideOnRemove, { id }),\n\t);\n\tif (position === \"before\") {\n\t\tcollection.addBeforeTombstones(refs);\n\t} else {\n\t\tcollection.addAfterTombstones(refs);\n\t}\n\treturn refs;\n}\n\ndescribe(\"LocalReferenceCollection\", () => {\n\tdescribe(\"size\", () => {\n\t\tit(\"counts stored references as they are added and removed\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 0);\n\t\t\tassert.equal(collection.size, 0);\n\n\t\t\tconst ref = collection.createLocalRef(1, ReferenceType.Simple, undefined);\n\t\t\tassert.equal(collection.size, 1);\n\t\t\tcollection.createLocalRef(2, ReferenceType.Transient, undefined);\n\t\t\tassert.equal(collection.size, 1); // Transient references are not stored.\n\n\t\t\tcollection.removeLocalRef(ref);\n\t\t\tassert.equal(collection.size, 0);\n\t\t});\n\n\t\tit(\"includes references in before, at, and after buckets\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 1);\n\t\t\taddTombstones(collection, \"before\", [\"before-0\", \"before-1\"]);\n\t\t\taddTombstones(collection, \"after\", [\"after-0\"]);\n\t\t\tassert.equal(collection.size, 6); // Three at + two before + one after.\n\t\t});\n\t});\n\n\tdescribe(\"walkReferences\", () => {\n\t\tit(\"walks all references when no start is provided\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection), [\"0-0\", \"0-1\", \"1-0\", \"1-1\", \"2-0\", \"2-1\"]);\n\t\t});\n\n\t\tit(\"walks all references backward when no start is provided\", () => {\n\t\t\tconst { collection } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection, undefined, false), [\n\t\t\t\t\"2-1\",\n\t\t\t\t\"2-0\",\n\t\t\t\t\"1-1\",\n\t\t\t\t\"1-0\",\n\t\t\t\t\"0-1\",\n\t\t\t\t\"0-0\",\n\t\t\t]);\n\t\t});\n\n\t\tit(\"includes the start reference when walking forward\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\t// refs[2] is the first reference at offset 1\n\t\t\tassert.deepEqual(walk(collection, refs[2]), [\"1-0\", \"1-1\", \"2-0\", \"2-1\"]);\n\t\t});\n\n\t\tit(\"includes the start reference when walking backward\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\tassert.deepEqual(walk(collection, refs[2], false), [\"1-0\", \"0-1\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"resumes mid-list when start is not the first reference at its offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 3);\n\t\t\t// refs[4] is the second reference at offset 1\n\t\t\tassert.deepEqual(walk(collection, refs[4]), [\"1-1\", \"1-2\", \"2-0\", \"2-1\", \"2-2\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[4], false), [\"1-1\", \"1-0\", \"0-2\", \"0-1\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"includes the start reference at the first offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 1);\n\t\t\tassert.deepEqual(walk(collection, refs[0]), [\"0-0\", \"1-0\", \"2-0\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[0], false), [\"0-0\"]);\n\t\t});\n\n\t\tit(\"includes the start reference at the last offset\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 1);\n\t\t\tassert.deepEqual(walk(collection, refs[2]), [\"2-0\"]);\n\t\t\tassert.deepEqual(walk(collection, refs[2], false), [\"2-0\", \"1-0\", \"0-0\"]);\n\t\t});\n\n\t\tit(\"stops early when the visitor returns false\", () => {\n\t\t\tconst { collection, refs } = setup(\"abc\", 2);\n\t\t\tconst visited: string[] = [];\n\t\t\tconst completed = collection.walkReferences((lref) => {\n\t\t\t\tvisited.push(lref.properties?.id as string);\n\t\t\t\treturn lref.properties?.id !== \"1-1\";\n\t\t\t}, refs[2]);\n\t\t\tassert.equal(completed, false);\n\t\t\tassert.deepEqual(visited, [\"1-0\", \"1-1\"]);\n\t\t});\n\n\t\tdescribe(\"when an offset holds multiple buckets\", () => {\n\t\t\t/**\n\t\t\t * Builds a collection over \"abc\" with an `at` reference at every offset, a `before`\n\t\t\t * bucket coexisting with `at` at offset 0, and an `after` bucket coexisting with `at`\n\t\t\t * at offset 2.\n\t\t\t */\n\t\t\tfunction setupMultiBucket(): {\n\t\t\t\tcollection: LocalReferenceCollection;\n\t\t\t\tat: LocalReferencePosition[];\n\t\t\t\tbefore: LocalReferencePosition[];\n\t\t\t\tafter: LocalReferencePosition[];\n\t\t\t} {\n\t\t\t\tconst { collection, refs: at } = setup(\"abc\", 1);\n\t\t\t\tconst before = addTombstones(collection, \"before\", [\"b-0\", \"b-1\"]);\n\t\t\t\tconst after = addTombstones(collection, \"after\", [\"a-0\", \"a-1\"]);\n\t\t\t\treturn { collection, at, before, after };\n\t\t\t}\n\n\t\t\tit(\"walks buckets in before/at/after order\", () => {\n\t\t\t\tconst { collection } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection), [\"b-0\", \"b-1\", \"0-0\", \"1-0\", \"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t\tassert.deepEqual(walk(collection, undefined, false), [\n\t\t\t\t\t\"a-1\",\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"b-0\",\n\t\t\t\t]);\n\t\t\t});\n\n\t\t\tit(\"skips sibling buckets preceding the bucket holding start\", () => {\n\t\t\t\tconst { collection, at } = setupMultiBucket();\n\t\t\t\t// Starting at the `at` bucket must discard the `before` bucket at the same offset,\n\t\t\t\t// without discarding the `at` bucket itself.\n\t\t\t\tassert.deepEqual(walk(collection, at[0]), [\"0-0\", \"1-0\", \"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t\t// Starting at the `at` bucket of the last offset must discard nothing it needs,\n\t\t\t\t// and still reach the trailing `after` bucket.\n\t\t\t\tassert.deepEqual(walk(collection, at[2]), [\"2-0\", \"a-0\", \"a-1\"]);\n\t\t\t});\n\n\t\t\tit(\"skips sibling buckets following the bucket holding start when walking backward\", () => {\n\t\t\t\tconst { collection, at } = setupMultiBucket();\n\t\t\t\t// Walking backward from the `at` bucket must discard the trailing `after` bucket\n\t\t\t\t// at the same offset, then continue into the `before` bucket.\n\t\t\t\tassert.deepEqual(walk(collection, at[2], false), [\"2-0\", \"1-0\", \"0-0\", \"b-1\", \"b-0\"]);\n\t\t\t\tassert.deepEqual(walk(collection, at[0], false), [\"0-0\", \"b-1\", \"b-0\"]);\n\t\t\t});\n\n\t\t\tit(\"starts within the before bucket\", () => {\n\t\t\t\tconst { collection, before } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection, before[1]), [\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"a-1\",\n\t\t\t\t]);\n\t\t\t\tassert.deepEqual(walk(collection, before[1], false), [\"b-1\", \"b-0\"]);\n\t\t\t});\n\n\t\t\tit(\"starts within the after bucket\", () => {\n\t\t\t\tconst { collection, after } = setupMultiBucket();\n\t\t\t\tassert.deepEqual(walk(collection, after[0]), [\"a-0\", \"a-1\"]);\n\t\t\t\tassert.deepEqual(walk(collection, after[0], false), [\n\t\t\t\t\t\"a-0\",\n\t\t\t\t\t\"2-0\",\n\t\t\t\t\t\"1-0\",\n\t\t\t\t\t\"0-0\",\n\t\t\t\t\t\"b-1\",\n\t\t\t\t\t\"b-0\",\n\t\t\t\t]);\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
@@ -4,8 +4,11 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ const node_assert_1 = require("node:assert");
7
8
  const mergeTree_js_1 = require("../mergeTree.js");
9
+ const mergeTreeNodes_js_1 = require("../mergeTreeNodes.js");
8
10
  const ops_js_1 = require("../ops.js");
11
+ const partialLengths_js_1 = require("../partialLengths.js");
9
12
  const textSegment_js_1 = require("../textSegment.js");
10
13
  const testUtils_js_1 = require("./testUtils.js");
11
14
  describe("partial lengths", () => {
@@ -22,11 +25,70 @@ describe("partial lengths", () => {
22
25
  beforeEach(() => {
23
26
  mergeTree = new mergeTree_js_1.MergeTree();
24
27
  mergeTree.insertSegments(0, [textSegment_js_1.TextSegment.make("hello world!")], mergeTree.localPerspective, mergeTree.collabWindow.mintNextLocalOperationStamp(), undefined);
28
+ // The initial "hello world!" supplies the 12-character baseline at sequence 0.
25
29
  mergeTree.startCollaboration(localClientId, /* minSeq: */ 0, /* currentSeq: */ 0);
26
30
  });
27
31
  it("passes with no additional ops", () => {
28
32
  (0, testUtils_js_1.validatePartialLengths)(localClientId, mergeTree, [{ seq: refSeq, len: 12 }]);
29
33
  });
34
+ describe("scalar queries", () => {
35
+ it("reports zero count and baseline for empty partial lengths", () => {
36
+ for (const computeLocalPartials of [false, true]) {
37
+ const partials = new partialLengths_js_1.PartialSequenceLengths(refSeq, computeLocalPartials);
38
+ node_assert_1.strict.equal(partials.getSegmentCount(), 0);
39
+ node_assert_1.strict.equal(partials.getBaselineLength(), 0);
40
+ }
41
+ });
42
+ it("preserves the count and baseline when aggregating child partials", () => {
43
+ mergeTree.insertSegments(5, [textSegment_js_1.TextSegment.make("more ")], remoteClient1.perspectiveAt({ refSeq }), remoteClient1.stampAt({ seq: 1 }), undefined);
44
+ mergeTree.root.partialLengths = partialLengths_js_1.PartialSequenceLengths.combine(mergeTree.root, mergeTree.collabWindow);
45
+ const parent = new mergeTreeNodes_js_1.MergeBlock(1);
46
+ parent.children[0] = mergeTree.root;
47
+ const combined = partialLengths_js_1.PartialSequenceLengths.combine(parent, mergeTree.collabWindow);
48
+ // Both levels cover "hello" (5), "more " (5), and " world!" (7).
49
+ for (const partials of [mergeTree.root.partialLengths, combined]) {
50
+ node_assert_1.strict.equal(partials.getSegmentCount(), 3);
51
+ node_assert_1.strict.equal(partials.getBaselineLength(), 12); // minSeq 0 excludes the insertion.
52
+ node_assert_1.strict.equal(partials.getPartialLength(1, remoteClientId), 17); // 12 + 5 characters.
53
+ }
54
+ });
55
+ it("reports the baseline at the current minimum sequence", () => {
56
+ mergeTree.insertSegments(5, [textSegment_js_1.TextSegment.make("more ")], remoteClient1.perspectiveAt({ refSeq }), remoteClient1.stampAt({ seq: 1 }), undefined);
57
+ mergeTree.collabWindow.currentSeq = 1;
58
+ mergeTree.collabWindow.minSeq = 1;
59
+ const partials = partialLengths_js_1.PartialSequenceLengths.combine(mergeTree.root, mergeTree.collabWindow);
60
+ node_assert_1.strict.equal(partials.getSegmentCount(), 3);
61
+ // minSeq 1 now includes the 12 original + 5 inserted characters in the baseline.
62
+ node_assert_1.strict.equal(partials.getBaselineLength(), 17);
63
+ node_assert_1.strict.equal(partials.getPartialLength(1, remoteClientId), 17);
64
+ });
65
+ });
66
+ it("propagates only the last invalidation without changing calculated lengths", () => {
67
+ const childPartials = mergeTree.root.partialLengths;
68
+ (0, node_assert_1.strict)(childPartials !== undefined);
69
+ const parent = new mergeTreeNodes_js_1.MergeBlock(1);
70
+ parent.children[0] = mergeTree.root;
71
+ const parentPartials = partialLengths_js_1.PartialSequenceLengths.combine(parent, mergeTree.collabWindow);
72
+ parent.partialLengths = parentPartials;
73
+ const ancestor = new mergeTreeNodes_js_1.MergeBlock(1);
74
+ ancestor.children[0] = parent;
75
+ const ancestorPartials = partialLengths_js_1.PartialSequenceLengths.combine(ancestor, mergeTree.collabWindow);
76
+ ancestor.partialLengths = ancestorPartials;
77
+ // No edits here: each level still represents one 12-character text segment.
78
+ childPartials.invalidateIncrementalPropagation(1);
79
+ childPartials.invalidateIncrementalPropagation(2); // Only sequence 2 remains invalidated.
80
+ node_assert_1.strict.equal(childPartials.getPartialLength(2, remoteClientId), 12);
81
+ parentPartials.update(parent, 1, remoteClientId, mergeTree.collabWindow);
82
+ node_assert_1.strict.equal(parent.partialLengths, parentPartials);
83
+ node_assert_1.strict.equal(parent.partialLengths.getSegmentCount(), 1);
84
+ node_assert_1.strict.equal(parent.partialLengths.getPartialLength(1, remoteClientId), 12);
85
+ parentPartials.update(parent, 2, remoteClientId, mergeTree.collabWindow);
86
+ node_assert_1.strict.notEqual(parent.partialLengths, parentPartials);
87
+ node_assert_1.strict.equal(parent.partialLengths.getPartialLength(2, remoteClientId), 12);
88
+ ancestorPartials.update(ancestor, 2, remoteClientId, mergeTree.collabWindow);
89
+ node_assert_1.strict.notEqual(ancestor.partialLengths, ancestorPartials);
90
+ node_assert_1.strict.equal(ancestor.partialLengths.getPartialLength(2, remoteClientId), 12);
91
+ });
30
92
  describe("a single inserted element", () => {
31
93
  it("includes length of local insert for local view", () => {
32
94
  mergeTree.insertSegments(0, [textSegment_js_1.TextSegment.make("more ")], mergeTree.localPerspective, ackedLocalClientStamp(refSeq + 1), { op: { type: ops_js_1.MergeTreeDeltaType.INSERT } });
@@ -1 +1 @@
1
- {"version":3,"file":"partialLength.spec.js","sourceRoot":"","sources":["../../src/test/partialLength.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 { MergeTree } from \"../mergeTree.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport type { OperationStamp } from \"../stamps.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport {\n\tmakeRemoteClient,\n\tuseStrictPartialLengthChecks,\n\tvalidatePartialLengths,\n} from \"./testUtils.js\";\n\ndescribe(\"partial lengths\", () => {\n\tlet mergeTree: MergeTree;\n\tconst localClientId = 17;\n\tconst remoteClientId = 18;\n\tconst refSeq = 0;\n\n\tconst ackedLocalClientStamp = (seq: number): OperationStamp => ({\n\t\tseq,\n\t\tclientId: localClientId,\n\t});\n\n\tconst remoteClient1 = makeRemoteClient({ clientId: 18 });\n\n\tuseStrictPartialLengthChecks();\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\tmergeTree.startCollaboration(localClientId, /* minSeq: */ 0, /* currentSeq: */ 0);\n\t});\n\n\tit(\"passes with no additional ops\", () => {\n\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: refSeq, len: 12 }]);\n\t});\n\n\tdescribe(\"a single inserted element\", () => {\n\t\tit(\"includes length of local insert for local view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of local insert for remote view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of remote insert for local view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of remote insert for remote view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t});\n\n\tdescribe(\"a single removed segment\", () => {\n\t\tit(\"includes result of local delete for local view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of local delete for remote view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of remote delete for local view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of remote delete for remote view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t});\n\n\tdescribe(\"aggregation\", () => {\n\t\tit(\"includes lengths from multiple permutations in single tree\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"1\")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"2\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq: refSeq + 1 }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"3\")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 3),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"4\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq: refSeq + 3 }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 4 }),\n\t\t\t\tundefined,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 4, len: 16 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 4, len: 16 }]);\n\t\t});\n\n\t\tit(\"is correct for different heights\", () => {\n\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\tmergeTree.insertSegments(\n\t\t\t\t\t0,\n\t\t\t\t\t[TextSegment.make(\"a\")],\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tackedLocalClientStamp(i + 1),\n\t\t\t\t\tundefined,\n\t\t\t\t);\n\n\t\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: i + 1, len: i + 13 }]);\n\t\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: i + 1, len: i + 13 }]);\n\t\t\t}\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 100, len: 112 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 100, len: 112 }]);\n\t\t});\n\t});\n\n\tdescribe(\"concurrent, overlapping deletes\", () => {\n\t\tit(\"concurrent remote changes are visible to local\", () => {\n\t\t\tconst remoteClient2 = makeRemoteClient({ clientId: 19 });\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId + 1, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t\tit(\"concurrent local and remote changes are visible\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t\tit(\"concurrent remote and unsequenced local changes are visible\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t});\n});\n"]}
1
+ {"version":3,"file":"partialLength.spec.js","sourceRoot":"","sources":["../../src/test/partialLength.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 { MergeTree } from \"../mergeTree.js\";\nimport { MergeBlock } from \"../mergeTreeNodes.js\";\nimport { MergeTreeDeltaType } from \"../ops.js\";\nimport { PartialSequenceLengths } from \"../partialLengths.js\";\nimport type { OperationStamp } from \"../stamps.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\nimport {\n\tmakeRemoteClient,\n\tuseStrictPartialLengthChecks,\n\tvalidatePartialLengths,\n} from \"./testUtils.js\";\n\ndescribe(\"partial lengths\", () => {\n\tlet mergeTree: MergeTree;\n\tconst localClientId = 17;\n\tconst remoteClientId = 18;\n\tconst refSeq = 0;\n\n\tconst ackedLocalClientStamp = (seq: number): OperationStamp => ({\n\t\tseq,\n\t\tclientId: localClientId,\n\t});\n\n\tconst remoteClient1 = makeRemoteClient({ clientId: 18 });\n\n\tuseStrictPartialLengthChecks();\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\t// The initial \"hello world!\" supplies the 12-character baseline at sequence 0.\n\t\tmergeTree.startCollaboration(localClientId, /* minSeq: */ 0, /* currentSeq: */ 0);\n\t});\n\n\tit(\"passes with no additional ops\", () => {\n\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: refSeq, len: 12 }]);\n\t});\n\n\tdescribe(\"scalar queries\", () => {\n\t\tit(\"reports zero count and baseline for empty partial lengths\", () => {\n\t\t\tfor (const computeLocalPartials of [false, true]) {\n\t\t\t\tconst partials = new PartialSequenceLengths(refSeq, computeLocalPartials);\n\t\t\t\tassert.equal(partials.getSegmentCount(), 0);\n\t\t\t\tassert.equal(partials.getBaselineLength(), 0);\n\t\t\t}\n\t\t});\n\n\t\tit(\"preserves the count and baseline when aggregating child partials\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: 1 }),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.root.partialLengths = PartialSequenceLengths.combine(\n\t\t\t\tmergeTree.root,\n\t\t\t\tmergeTree.collabWindow,\n\t\t\t);\n\t\t\tconst parent = new MergeBlock(1);\n\t\t\tparent.children[0] = mergeTree.root;\n\t\t\tconst combined = PartialSequenceLengths.combine(parent, mergeTree.collabWindow);\n\n\t\t\t// Both levels cover \"hello\" (5), \"more \" (5), and \" world!\" (7).\n\t\t\tfor (const partials of [mergeTree.root.partialLengths, combined]) {\n\t\t\t\tassert.equal(partials.getSegmentCount(), 3);\n\t\t\t\tassert.equal(partials.getBaselineLength(), 12); // minSeq 0 excludes the insertion.\n\t\t\t\tassert.equal(partials.getPartialLength(1, remoteClientId), 17); // 12 + 5 characters.\n\t\t\t}\n\t\t});\n\n\t\tit(\"reports the baseline at the current minimum sequence\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t5,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: 1 }),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.collabWindow.currentSeq = 1;\n\t\t\tmergeTree.collabWindow.minSeq = 1;\n\t\t\tconst partials = PartialSequenceLengths.combine(mergeTree.root, mergeTree.collabWindow);\n\n\t\t\tassert.equal(partials.getSegmentCount(), 3);\n\t\t\t// minSeq 1 now includes the 12 original + 5 inserted characters in the baseline.\n\t\t\tassert.equal(partials.getBaselineLength(), 17);\n\t\t\tassert.equal(partials.getPartialLength(1, remoteClientId), 17);\n\t\t});\n\t});\n\n\tit(\"propagates only the last invalidation without changing calculated lengths\", () => {\n\t\tconst childPartials = mergeTree.root.partialLengths;\n\t\tassert(childPartials !== undefined);\n\t\tconst parent = new MergeBlock(1);\n\t\tparent.children[0] = mergeTree.root;\n\t\tconst parentPartials = PartialSequenceLengths.combine(parent, mergeTree.collabWindow);\n\t\tparent.partialLengths = parentPartials;\n\t\tconst ancestor = new MergeBlock(1);\n\t\tancestor.children[0] = parent;\n\t\tconst ancestorPartials = PartialSequenceLengths.combine(ancestor, mergeTree.collabWindow);\n\t\tancestor.partialLengths = ancestorPartials;\n\n\t\t// No edits here: each level still represents one 12-character text segment.\n\t\tchildPartials.invalidateIncrementalPropagation(1);\n\t\tchildPartials.invalidateIncrementalPropagation(2); // Only sequence 2 remains invalidated.\n\t\tassert.equal(childPartials.getPartialLength(2, remoteClientId), 12);\n\n\t\tparentPartials.update(parent, 1, remoteClientId, mergeTree.collabWindow);\n\t\tassert.equal(parent.partialLengths, parentPartials);\n\t\tassert.equal(parent.partialLengths.getSegmentCount(), 1);\n\t\tassert.equal(parent.partialLengths.getPartialLength(1, remoteClientId), 12);\n\n\t\tparentPartials.update(parent, 2, remoteClientId, mergeTree.collabWindow);\n\t\tassert.notEqual(parent.partialLengths, parentPartials);\n\t\tassert.equal(parent.partialLengths.getPartialLength(2, remoteClientId), 12);\n\n\t\tancestorPartials.update(ancestor, 2, remoteClientId, mergeTree.collabWindow);\n\t\tassert.notEqual(ancestor.partialLengths, ancestorPartials);\n\t\tassert.equal(ancestor.partialLengths.getPartialLength(2, remoteClientId), 12);\n\t});\n\n\tdescribe(\"a single inserted element\", () => {\n\t\tit(\"includes length of local insert for local view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of local insert for remote view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of remote insert for local view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t\tit(\"includes length of remote insert for remote view\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"more \")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\t{ op: { type: MergeTreeDeltaType.INSERT } },\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 17 }]);\n\t\t});\n\t});\n\n\tdescribe(\"a single removed segment\", () => {\n\t\tit(\"includes result of local delete for local view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of local delete for remote view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of remote delete for local view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t\tit(\"includes result of remote delete for remote view\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t12,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 0 }]);\n\t\t});\n\t});\n\n\tdescribe(\"aggregation\", () => {\n\t\tit(\"includes lengths from multiple permutations in single tree\", () => {\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"1\")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"2\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq: refSeq + 1 }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"3\")],\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 3),\n\t\t\t\tundefined,\n\t\t\t);\n\t\t\tmergeTree.insertSegments(\n\t\t\t\t0,\n\t\t\t\t[TextSegment.make(\"4\")],\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq: refSeq + 3 }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 4 }),\n\t\t\t\tundefined,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 4, len: 16 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 4, len: 16 }]);\n\t\t});\n\n\t\tit(\"is correct for different heights\", () => {\n\t\t\tfor (let i = 0; i < 100; i++) {\n\t\t\t\tmergeTree.insertSegments(\n\t\t\t\t\t0,\n\t\t\t\t\t[TextSegment.make(\"a\")],\n\t\t\t\t\tmergeTree.localPerspective,\n\t\t\t\t\tackedLocalClientStamp(i + 1),\n\t\t\t\t\tundefined,\n\t\t\t\t);\n\n\t\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: i + 1, len: i + 13 }]);\n\t\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: i + 1, len: i + 13 }]);\n\t\t\t}\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 100, len: 112 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 100, len: 112 }]);\n\t\t});\n\t});\n\n\tdescribe(\"concurrent, overlapping deletes\", () => {\n\t\tit(\"concurrent remote changes are visible to local\", () => {\n\t\t\tconst remoteClient2 = makeRemoteClient({ clientId: 19 });\n\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient2.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient2.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId + 1, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t\tit(\"concurrent local and remote changes are visible\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tackedLocalClientStamp(refSeq + 1),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 2 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t\tit(\"concurrent remote and unsequenced local changes are visible\", () => {\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tmergeTree.localPerspective,\n\t\t\t\tmergeTree.collabWindow.mintNextLocalOperationStamp(),\n\t\t\t\tundefined as never,\n\t\t\t);\n\t\t\tmergeTree.markRangeRemoved(\n\t\t\t\t0,\n\t\t\t\t10,\n\t\t\t\tremoteClient1.perspectiveAt({ refSeq }),\n\t\t\t\tremoteClient1.stampAt({ seq: refSeq + 1 }),\n\t\t\t\tundefined as never,\n\t\t\t);\n\n\t\t\tvalidatePartialLengths(localClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t\tvalidatePartialLengths(remoteClientId, mergeTree, [{ seq: 1, len: 2 }]);\n\t\t});\n\t});\n});\n"]}
@@ -78,5 +78,34 @@ describe("segmentGroupCollection", () => {
78
78
  node_assert_1.strict.equal(segmentGroup.segments[1], segmentCopy);
79
79
  }
80
80
  });
81
+ it(".copyTo preserves the previous properties for the source segment", () => {
82
+ const [precedingSegment, segmentCopy] = ["before", "copy"].map((text) => {
83
+ const leaf = (0, segmentInfos_js_1.overwriteInfo)(textSegment_js_1.TextSegment.make(text), {
84
+ insert: {
85
+ type: "insert",
86
+ clientId: 0,
87
+ seq: 1,
88
+ },
89
+ });
90
+ (0, mergeTreeNodes_js_1.assignChild)(parent, leaf, parent.childCount++);
91
+ return leaf;
92
+ });
93
+ const previousProps = { key: "source" };
94
+ const segmentGroup = {
95
+ segments: [precedingSegment],
96
+ previousProps: [{ key: "before" }, previousProps],
97
+ localSeq: 1,
98
+ refSeq: 0,
99
+ };
100
+ segmentGroups.enqueue(segmentGroup);
101
+ const segmentGroupCopy = new segmentGroupCollection_js_1.SegmentGroupCollection(segmentCopy);
102
+ segmentGroups.copyTo(segmentGroupCopy);
103
+ node_assert_1.strict.equal(segmentGroupCopy.dequeue(), segmentGroup);
104
+ node_assert_1.strict.deepEqual(segmentGroup.segments, [precedingSegment, segment, segmentCopy]);
105
+ // The copy's slot (2) must reuse the source's previous properties from slot 1.
106
+ node_assert_1.strict.equal(segmentGroup.previousProps?.length, 3);
107
+ node_assert_1.strict.equal(segmentGroup.previousProps?.[2], previousProps);
108
+ node_assert_1.strict.equal(segmentGroups.dequeue(), segmentGroup);
109
+ });
81
110
  });
82
111
  //# sourceMappingURL=segmentGroupCollection.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"segmentGroupCollection.spec.js","sourceRoot":"","sources":["../../src/test/segmentGroupCollection.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 { assignChild, MergeBlock, type ISegmentPrivate } from \"../mergeTreeNodes.js\";\nimport { SegmentGroupCollection } from \"../segmentGroupCollection.js\";\nimport { type IHasInsertionInfo, overwriteInfo } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\ndescribe(\"segmentGroupCollection\", () => {\n\tlet parent: MergeBlock;\n\tlet segment: ISegmentPrivate;\n\tlet segmentGroups: SegmentGroupCollection;\n\tbeforeEach(() => {\n\t\tparent = new MergeBlock(1);\n\t\tconst newSeg = (segment = overwriteInfo<IHasInsertionInfo>(TextSegment.make(\"abc\"), {\n\t\t\tinsert: {\n\t\t\t\ttype: \"insert\",\n\t\t\t\tclientId: 0,\n\t\t\t\tseq: 1,\n\t\t\t},\n\t\t}));\n\t\tassignChild(parent, newSeg, 0);\n\n\t\tsegmentGroups = segment.segmentGroups = new SegmentGroupCollection(newSeg);\n\t});\n\tit(\".empty\", () => {\n\t\tassert(segmentGroups.empty);\n\t});\n\n\tit(\".size\", () => {\n\t\tassert.equal(segmentGroups.size, 0);\n\t});\n\n\tit(\".enqueue\", () => {\n\t\tconst segmentGroup = { segments: [], localSeq: 1, refSeq: 0 };\n\t\tsegmentGroups.enqueue(segmentGroup);\n\n\t\tassert(!segmentGroups.empty);\n\t\tassert.equal(segmentGroups.size, 1);\n\t\tassert.equal(segmentGroup.segments.length, 1);\n\t\tassert.equal(segmentGroup.segments[0], segment);\n\t});\n\n\tit(\".dequeue\", () => {\n\t\tconst segmentGroup = { segments: [], localSeq: 1, refSeq: 0 };\n\t\tsegmentGroups.enqueue(segmentGroup);\n\t\tconst segmentGroupCount = 6;\n\t\twhile (segmentGroups.size < segmentGroupCount) {\n\t\t\tsegmentGroups.enqueue({ segments: [], localSeq: 1, refSeq: 0 });\n\t\t}\n\n\t\tconst dequeuedSegmentGroup = segmentGroups.dequeue();\n\n\t\tassert.equal(segmentGroups.size, segmentGroupCount - 1);\n\t\tassert.equal(dequeuedSegmentGroup?.segments.length, 1);\n\t\tassert.equal(dequeuedSegmentGroup.segments[0], segment);\n\t\tassert.equal(dequeuedSegmentGroup, segmentGroup);\n\t});\n\n\tit(\".copyTo\", () => {\n\t\tconst segmentGroupCount = 6;\n\t\twhile (segmentGroups.size < segmentGroupCount) {\n\t\t\tsegmentGroups.enqueue({ segments: [], localSeq: 1, refSeq: 0 });\n\t\t}\n\n\t\tconst segmentCopy = overwriteInfo<IHasInsertionInfo>(TextSegment.make(\"\"), {\n\t\t\tinsert: {\n\t\t\t\ttype: \"insert\",\n\t\t\t\tclientId: 0,\n\t\t\t\tseq: 1,\n\t\t\t},\n\t\t});\n\t\tassignChild(parent, segmentCopy, parent.childCount++);\n\n\t\tconst segmentGroupCopy = new SegmentGroupCollection(segmentCopy);\n\t\tsegmentGroups.copyTo(segmentGroupCopy);\n\n\t\tassert.equal(segmentGroups.size, segmentGroupCount);\n\t\tassert.equal(segmentGroupCopy.size, segmentGroupCount);\n\n\t\twhile (!segmentGroups.empty || !segmentGroupCopy.empty) {\n\t\t\tconst segmentGroup = segmentGroups.dequeue();\n\t\t\tconst copySegmentGroup = segmentGroupCopy.dequeue();\n\n\t\t\tassert.equal(segmentGroup, copySegmentGroup);\n\t\t\tassert.equal(segmentGroup?.segments.length, 2);\n\t\t\tassert.equal(segmentGroup.segments[0], segment);\n\t\t\tassert.equal(segmentGroup.segments[1], segmentCopy);\n\t\t}\n\t});\n});\n"]}
1
+ {"version":3,"file":"segmentGroupCollection.spec.js","sourceRoot":"","sources":["../../src/test/segmentGroupCollection.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 {\n\tassignChild,\n\tMergeBlock,\n\ttype ISegmentPrivate,\n\ttype SegmentGroup,\n} from \"../mergeTreeNodes.js\";\nimport { SegmentGroupCollection } from \"../segmentGroupCollection.js\";\nimport { type IHasInsertionInfo, overwriteInfo } from \"../segmentInfos.js\";\nimport { TextSegment } from \"../textSegment.js\";\n\ndescribe(\"segmentGroupCollection\", () => {\n\tlet parent: MergeBlock;\n\tlet segment: ISegmentPrivate;\n\tlet segmentGroups: SegmentGroupCollection;\n\tbeforeEach(() => {\n\t\tparent = new MergeBlock(1);\n\t\tconst newSeg = (segment = overwriteInfo<IHasInsertionInfo>(TextSegment.make(\"abc\"), {\n\t\t\tinsert: {\n\t\t\t\ttype: \"insert\",\n\t\t\t\tclientId: 0,\n\t\t\t\tseq: 1,\n\t\t\t},\n\t\t}));\n\t\tassignChild(parent, newSeg, 0);\n\n\t\tsegmentGroups = segment.segmentGroups = new SegmentGroupCollection(newSeg);\n\t});\n\tit(\".empty\", () => {\n\t\tassert(segmentGroups.empty);\n\t});\n\n\tit(\".size\", () => {\n\t\tassert.equal(segmentGroups.size, 0);\n\t});\n\n\tit(\".enqueue\", () => {\n\t\tconst segmentGroup = { segments: [], localSeq: 1, refSeq: 0 };\n\t\tsegmentGroups.enqueue(segmentGroup);\n\n\t\tassert(!segmentGroups.empty);\n\t\tassert.equal(segmentGroups.size, 1);\n\t\tassert.equal(segmentGroup.segments.length, 1);\n\t\tassert.equal(segmentGroup.segments[0], segment);\n\t});\n\n\tit(\".dequeue\", () => {\n\t\tconst segmentGroup = { segments: [], localSeq: 1, refSeq: 0 };\n\t\tsegmentGroups.enqueue(segmentGroup);\n\t\tconst segmentGroupCount = 6;\n\t\twhile (segmentGroups.size < segmentGroupCount) {\n\t\t\tsegmentGroups.enqueue({ segments: [], localSeq: 1, refSeq: 0 });\n\t\t}\n\n\t\tconst dequeuedSegmentGroup = segmentGroups.dequeue();\n\n\t\tassert.equal(segmentGroups.size, segmentGroupCount - 1);\n\t\tassert.equal(dequeuedSegmentGroup?.segments.length, 1);\n\t\tassert.equal(dequeuedSegmentGroup.segments[0], segment);\n\t\tassert.equal(dequeuedSegmentGroup, segmentGroup);\n\t});\n\n\tit(\".copyTo\", () => {\n\t\tconst segmentGroupCount = 6;\n\t\twhile (segmentGroups.size < segmentGroupCount) {\n\t\t\tsegmentGroups.enqueue({ segments: [], localSeq: 1, refSeq: 0 });\n\t\t}\n\n\t\tconst segmentCopy = overwriteInfo<IHasInsertionInfo>(TextSegment.make(\"\"), {\n\t\t\tinsert: {\n\t\t\t\ttype: \"insert\",\n\t\t\t\tclientId: 0,\n\t\t\t\tseq: 1,\n\t\t\t},\n\t\t});\n\t\tassignChild(parent, segmentCopy, parent.childCount++);\n\n\t\tconst segmentGroupCopy = new SegmentGroupCollection(segmentCopy);\n\t\tsegmentGroups.copyTo(segmentGroupCopy);\n\n\t\tassert.equal(segmentGroups.size, segmentGroupCount);\n\t\tassert.equal(segmentGroupCopy.size, segmentGroupCount);\n\n\t\twhile (!segmentGroups.empty || !segmentGroupCopy.empty) {\n\t\t\tconst segmentGroup = segmentGroups.dequeue();\n\t\t\tconst copySegmentGroup = segmentGroupCopy.dequeue();\n\n\t\t\tassert.equal(segmentGroup, copySegmentGroup);\n\t\t\tassert.equal(segmentGroup?.segments.length, 2);\n\t\t\tassert.equal(segmentGroup.segments[0], segment);\n\t\t\tassert.equal(segmentGroup.segments[1], segmentCopy);\n\t\t}\n\t});\n\n\tit(\".copyTo preserves the previous properties for the source segment\", () => {\n\t\tconst [precedingSegment, segmentCopy] = [\"before\", \"copy\"].map((text) => {\n\t\t\tconst leaf = overwriteInfo<IHasInsertionInfo>(TextSegment.make(text), {\n\t\t\t\tinsert: {\n\t\t\t\t\ttype: \"insert\",\n\t\t\t\t\tclientId: 0,\n\t\t\t\t\tseq: 1,\n\t\t\t\t},\n\t\t\t});\n\t\t\tassignChild(parent, leaf, parent.childCount++);\n\t\t\treturn leaf;\n\t\t});\n\t\tconst previousProps = { key: \"source\" };\n\t\tconst segmentGroup: SegmentGroup = {\n\t\t\tsegments: [precedingSegment],\n\t\t\tpreviousProps: [{ key: \"before\" }, previousProps],\n\t\t\tlocalSeq: 1,\n\t\t\trefSeq: 0,\n\t\t};\n\t\tsegmentGroups.enqueue(segmentGroup);\n\t\tconst segmentGroupCopy = new SegmentGroupCollection(segmentCopy);\n\n\t\tsegmentGroups.copyTo(segmentGroupCopy);\n\n\t\tassert.equal(segmentGroupCopy.dequeue(), segmentGroup);\n\t\tassert.deepEqual(segmentGroup.segments, [precedingSegment, segment, segmentCopy]);\n\t\t// The copy's slot (2) must reuse the source's previous properties from slot 1.\n\t\tassert.equal(segmentGroup.previousProps?.length, 3);\n\t\tassert.equal(segmentGroup.previousProps?.[2], previousProps);\n\t\tassert.equal(segmentGroups.dequeue(), segmentGroup);\n\t});\n});\n"]}