@fluidframework/merge-tree 0.59.2001 → 0.59.3000

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 (93) hide show
  1. package/.eslintrc.js +0 -1
  2. package/dist/client.d.ts +15 -4
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +60 -34
  5. package/dist/client.js.map +1 -1
  6. package/dist/collections.d.ts +7 -1
  7. package/dist/collections.d.ts.map +1 -1
  8. package/dist/collections.js +27 -1
  9. package/dist/collections.js.map +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/localReference.d.ts +104 -10
  15. package/dist/localReference.d.ts.map +1 -1
  16. package/dist/localReference.js +152 -96
  17. package/dist/localReference.js.map +1 -1
  18. package/dist/mergeTree.d.ts +28 -21
  19. package/dist/mergeTree.d.ts.map +1 -1
  20. package/dist/mergeTree.js +100 -88
  21. package/dist/mergeTree.js.map +1 -1
  22. package/dist/partialLengths.js +10 -10
  23. package/dist/partialLengths.js.map +1 -1
  24. package/dist/referencePositions.d.ts +55 -0
  25. package/dist/referencePositions.d.ts.map +1 -0
  26. package/dist/referencePositions.js +93 -0
  27. package/dist/referencePositions.js.map +1 -0
  28. package/dist/segmentGroupCollection.js +1 -1
  29. package/dist/segmentGroupCollection.js.map +1 -1
  30. package/dist/segmentPropertiesManager.js +5 -5
  31. package/dist/segmentPropertiesManager.js.map +1 -1
  32. package/dist/snapshotChunks.js.map +1 -1
  33. package/dist/snapshotLoader.d.ts.map +1 -1
  34. package/dist/snapshotLoader.js +9 -9
  35. package/dist/snapshotLoader.js.map +1 -1
  36. package/dist/snapshotV1.js +7 -7
  37. package/dist/snapshotV1.js.map +1 -1
  38. package/dist/snapshotlegacy.js +6 -6
  39. package/dist/snapshotlegacy.js.map +1 -1
  40. package/dist/sortedSegmentSet.d.ts.map +1 -1
  41. package/dist/sortedSegmentSet.js +1 -1
  42. package/dist/sortedSegmentSet.js.map +1 -1
  43. package/dist/textSegment.js +3 -2
  44. package/dist/textSegment.js.map +1 -1
  45. package/lib/client.d.ts +15 -4
  46. package/lib/client.d.ts.map +1 -1
  47. package/lib/client.js +31 -5
  48. package/lib/client.js.map +1 -1
  49. package/lib/collections.d.ts +7 -1
  50. package/lib/collections.d.ts.map +1 -1
  51. package/lib/collections.js +26 -1
  52. package/lib/collections.js.map +1 -1
  53. package/lib/index.d.ts +1 -0
  54. package/lib/index.d.ts.map +1 -1
  55. package/lib/index.js +1 -0
  56. package/lib/index.js.map +1 -1
  57. package/lib/localReference.d.ts +104 -10
  58. package/lib/localReference.d.ts.map +1 -1
  59. package/lib/localReference.js +146 -90
  60. package/lib/localReference.js.map +1 -1
  61. package/lib/mergeTree.d.ts +28 -21
  62. package/lib/mergeTree.d.ts.map +1 -1
  63. package/lib/mergeTree.js +67 -51
  64. package/lib/mergeTree.js.map +1 -1
  65. package/lib/referencePositions.d.ts +55 -0
  66. package/lib/referencePositions.d.ts.map +1 -0
  67. package/lib/referencePositions.js +80 -0
  68. package/lib/referencePositions.js.map +1 -0
  69. package/lib/segmentPropertiesManager.js.map +1 -1
  70. package/lib/snapshotChunks.js.map +1 -1
  71. package/lib/snapshotLoader.d.ts.map +1 -1
  72. package/lib/snapshotLoader.js.map +1 -1
  73. package/lib/snapshotV1.js.map +1 -1
  74. package/lib/snapshotlegacy.js +1 -1
  75. package/lib/snapshotlegacy.js.map +1 -1
  76. package/lib/sortedSegmentSet.d.ts.map +1 -1
  77. package/lib/sortedSegmentSet.js +1 -1
  78. package/lib/sortedSegmentSet.js.map +1 -1
  79. package/lib/textSegment.js +3 -2
  80. package/lib/textSegment.js.map +1 -1
  81. package/package.json +161 -14
  82. package/src/client.ts +45 -19
  83. package/src/collections.ts +55 -54
  84. package/src/index.ts +1 -0
  85. package/src/localReference.ts +190 -100
  86. package/src/mergeTree.ts +107 -99
  87. package/src/referencePositions.ts +126 -0
  88. package/src/snapshotChunks.ts +8 -8
  89. package/src/snapshotLoader.ts +4 -4
  90. package/src/snapshotV1.ts +1 -1
  91. package/src/snapshotlegacy.ts +2 -2
  92. package/src/sortedSegmentSet.ts +4 -4
  93. package/src/textSegment.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"textSegment.js","sourceRoot":"","sources":["../src/textSegment.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 { IIntegerRange } from \"./base\";\nimport { BaseSegment, ISegment, Marker, MergeTree } from \"./mergeTree\";\nimport { IJSONSegment } from \"./ops\";\nimport { PropertySet } from \"./properties\";\nimport { LocalReferenceCollection } from \"./localReference\";\n\n// Maximum length of text segment to be considered to be merged with other segment.\n// Maximum segment length is at least 2x of it (not taking into account initial segment creation).\n// The bigger it is, the more expensive it is to break segment into sub-segments (on edits)\n// The smaller it is, the more segments we have in snapshots (and in memory) - it's more expensive to load snapshots.\n// Small number also makes ReplayTool produce false positives (\"same\" snapshots have slightly different binary\n// representations). More measurements needs to be done, but it's very likely the right spot is somewhere between\n// 1K-2K mark. That said, we also break segments on newline and there are very few segments that are longer than 256\n// because of it. Must be an even number\nconst TextSegmentGranularity = 256;\n\nexport interface IJSONTextSegment extends IJSONSegment {\n text: string;\n}\n\nexport class TextSegment extends BaseSegment {\n public static readonly type = \"TextSegment\";\n\n public static is(segment: ISegment): segment is TextSegment {\n return segment.type === TextSegment.type;\n }\n\n public static make(text: string, props?: PropertySet) {\n const seg = new TextSegment(text);\n if (props) {\n seg.addProperties(props);\n }\n return seg;\n }\n\n public static fromJSONObject(spec: any) {\n if (typeof spec === \"string\") {\n return new TextSegment(spec);\n } else if (spec && typeof spec === \"object\" && \"text\" in spec) {\n const textSpec = spec as IJSONTextSegment;\n return TextSegment.make(textSpec.text, textSpec.props as PropertySet);\n }\n return undefined;\n }\n\n public readonly type = TextSegment.type;\n\n constructor(public text: string) {\n super();\n this.cachedLength = text.length;\n }\n\n public toJSONObject() {\n // To reduce snapshot/ops size, we serialize a TextSegment as a plain 'string' if it is\n // not annotated.\n return this.properties\n ? { text: this.text, props: this.properties }\n : this.text;\n }\n\n public clone(start = 0, end?: number) {\n const text = this.text.substring(start, end);\n const b = TextSegment.make(text, this.properties);\n this.cloneInto(b);\n return b;\n }\n\n public canAppend(segment: ISegment): boolean {\n return !this.text.endsWith(\"\\n\")\n && TextSegment.is(segment)\n && (this.cachedLength <= TextSegmentGranularity ||\n segment.cachedLength <= TextSegmentGranularity);\n }\n\n public toString() {\n return this.text;\n }\n\n public append(segment: ISegment) {\n if (TextSegment.is(segment)) {\n // Note: Must call 'appendLocalRefs' before modifying this segment's length as\n // 'this.cachedLength' is used to adjust the offsets of the local refs.\n LocalReferenceCollection.append(this, segment);\n\n this.text += segment.text;\n this.cachedLength = this.text.length;\n } else {\n throw new Error(\"can only append text segment\");\n }\n }\n\n // TODO: retain removed text for undo\n // returns true if entire string removed\n public removeRange(start: number, end: number) {\n let remnantString = \"\";\n const len = this.text.length;\n if (start > 0) {\n remnantString += this.text.substring(0, start);\n }\n if (end < len) {\n remnantString += this.text.substring(end);\n }\n this.text = remnantString;\n this.cachedLength = remnantString.length;\n return (remnantString.length === 0);\n }\n\n protected createSplitSegmentAt(pos: number) {\n if (pos > 0) {\n const remainingText = this.text.substring(pos);\n this.text = this.text.substring(0, pos);\n this.cachedLength = this.text.length;\n const leafSegment = new TextSegment(remainingText);\n return leafSegment;\n }\n }\n}\n\ninterface ITextAccumulator {\n textSegment: TextSegment;\n placeholder?: string;\n parallelArrays?: boolean;\n}\n\ninterface ITextAndMarkerAccumulator extends ITextAccumulator {\n parallelArrays: true;\n parallelText: string[];\n parallelMarkers: Marker[];\n parallelMarkerLabel: string;\n tagsInProgress: string[];\n}\n\nfunction isTextAndMarkerAccumulator(accum: ITextAccumulator): accum is ITextAndMarkerAccumulator {\n return accum.parallelArrays === true;\n}\n\ntype ITextAccumulatorType = ITextAccumulator | ITextAndMarkerAccumulator;\nexport class MergeTreeTextHelper {\n constructor(private readonly mergeTree: MergeTree) { }\n\n public getTextAndMarkers(refSeq: number, clientId: number, label: string, start?: number, end?: number) {\n const range = this.getValidRange(start, end, refSeq, clientId);\n const accum: ITextAndMarkerAccumulator = {\n parallelArrays: true,\n parallelMarkerLabel: label,\n parallelMarkers: [],\n parallelText: [],\n tagsInProgress: [],\n textSegment: new TextSegment(\"\"),\n };\n\n this.mergeTree.mapRange<ITextAndMarkerAccumulator>(\n { leaf: this.gatherText },\n refSeq,\n clientId,\n accum,\n range.start,\n range.end);\n\n return { parallelText: accum.parallelText, parallelMarkers: accum.parallelMarkers };\n }\n\n public getText(refSeq: number, clientId: number, placeholder = \"\", start?: number, end?: number) {\n const range = this.getValidRange(start, end, refSeq, clientId);\n\n const accum: ITextAccumulator = { textSegment: new TextSegment(\"\"), placeholder };\n\n this.mergeTree.mapRange<ITextAccumulator>(\n { leaf: this.gatherText },\n refSeq,\n clientId,\n accum,\n range.start,\n range.end);\n return accum.textSegment.text;\n }\n\n private getValidRange(\n start: number | undefined,\n end: number | undefined,\n refSeq: number,\n clientId: number,\n ): IIntegerRange {\n const range: IIntegerRange = {\n end: end ?? this.mergeTree.getLength(refSeq, clientId),\n start: start ?? 0,\n };\n return range;\n }\n\n private readonly gatherText = (segment: ISegment, pos: number, refSeq: number, clientId: number, start: number,\n end: number, accumText: ITextAccumulatorType) => {\n let _start = start;\n if (TextSegment.is(segment)) {\n let beginTags = \"\";\n let endTags = \"\";\n if (isTextAndMarkerAccumulator(accumText)) {\n // TODO: let clients pass in function to get tag\n const tags = [] as string[];\n const initTags = [] as string[];\n\n if (segment.properties && (segment.properties[\"font-weight\"])) {\n tags.push(\"b\");\n }\n if (segment.properties && (segment.properties[\"text-decoration\"])) {\n tags.push(\"u\");\n }\n const remTags = [] as string[];\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!accumText.tagsInProgress.includes(tag)) {\n beginTags += `<${tag}>`;\n initTags.push(tag);\n }\n }\n for (const accumTag of accumText.tagsInProgress) {\n if (!tags.includes(accumTag)) {\n endTags += `</${accumTag}>`;\n remTags.push(accumTag);\n }\n }\n for (const initTag of initTags.reverse()) {\n accumText.tagsInProgress.push(initTag);\n }\n } else {\n for (const accumTag of accumText.tagsInProgress) {\n endTags += `</${accumTag}>`;\n remTags.push(accumTag);\n }\n }\n for (const remTag of remTags) {\n const remdex = accumText.tagsInProgress.indexOf(remTag);\n if (remdex >= 0) {\n accumText.tagsInProgress.splice(remdex, 1);\n }\n }\n }\n accumText.textSegment.text += endTags;\n accumText.textSegment.text += beginTags;\n if ((_start <= 0) && (end >= segment.text.length)) {\n accumText.textSegment.text += segment.text;\n } else {\n if (_start < 0) {\n _start = 0;\n }\n if (end >= segment.text.length) {\n accumText.textSegment.text += segment.text.substring(_start);\n } else {\n accumText.textSegment.text += segment.text.substring(_start, end);\n }\n }\n } else {\n if (accumText.placeholder && (accumText.placeholder.length > 0)) {\n if (accumText.placeholder === \"*\") {\n const marker = segment as Marker;\n accumText.textSegment.text += `\\n${marker.toString()}`;\n } else {\n for (let i = 0; i < segment.cachedLength; i++) {\n accumText.textSegment.text += accumText.placeholder;\n }\n }\n } else if (isTextAndMarkerAccumulator(accumText)) {\n const marker = segment as Marker;\n if (marker.hasTileLabel(accumText.parallelMarkerLabel)) {\n accumText.parallelMarkers.push(marker);\n accumText.parallelText.push(accumText.textSegment.text);\n accumText.textSegment.text = \"\";\n }\n }\n }\n\n return true;\n };\n}\n"]}
1
+ {"version":3,"file":"textSegment.js","sourceRoot":"","sources":["../src/textSegment.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 { IIntegerRange } from \"./base\";\nimport { BaseSegment, ISegment, Marker, MergeTree } from \"./mergeTree\";\nimport { IJSONSegment } from \"./ops\";\nimport { PropertySet } from \"./properties\";\nimport { LocalReferenceCollection } from \"./localReference\";\n\n// Maximum length of text segment to be considered to be merged with other segment.\n// Maximum segment length is at least 2x of it (not taking into account initial segment creation).\n// The bigger it is, the more expensive it is to break segment into sub-segments (on edits)\n// The smaller it is, the more segments we have in snapshots (and in memory) - it's more expensive to load snapshots.\n// Small number also makes ReplayTool produce false positives (\"same\" snapshots have slightly different binary\n// representations). More measurements needs to be done, but it's very likely the right spot is somewhere between\n// 1K-2K mark. That said, we also break segments on newline and there are very few segments that are longer than 256\n// because of it. Must be an even number\nconst TextSegmentGranularity = 256;\n\nexport interface IJSONTextSegment extends IJSONSegment {\n text: string;\n}\n\nexport class TextSegment extends BaseSegment {\n public static readonly type = \"TextSegment\";\n\n public static is(segment: ISegment): segment is TextSegment {\n return segment.type === TextSegment.type;\n }\n\n public static make(text: string, props?: PropertySet) {\n const seg = new TextSegment(text);\n if (props) {\n seg.addProperties(props);\n }\n return seg;\n }\n\n public static fromJSONObject(spec: any) {\n if (typeof spec === \"string\") {\n return new TextSegment(spec);\n } else if (spec && typeof spec === \"object\" && \"text\" in spec) {\n const textSpec = spec as IJSONTextSegment;\n return TextSegment.make(textSpec.text, textSpec.props as PropertySet);\n }\n return undefined;\n }\n\n public readonly type = TextSegment.type;\n\n constructor(public text: string) {\n super();\n this.cachedLength = text.length;\n }\n\n public toJSONObject() {\n // To reduce snapshot/ops size, we serialize a TextSegment as a plain 'string' if it is\n // not annotated.\n return this.properties\n ? { text: this.text, props: this.properties }\n : this.text;\n }\n\n public clone(start = 0, end?: number) {\n const text = this.text.substring(start, end);\n const b = TextSegment.make(text, this.properties);\n this.cloneInto(b);\n return b;\n }\n\n public canAppend(segment: ISegment): boolean {\n return !this.text.endsWith(\"\\n\")\n && TextSegment.is(segment)\n && (this.cachedLength <= TextSegmentGranularity ||\n segment.cachedLength <= TextSegmentGranularity);\n }\n\n public toString() {\n return this.text;\n }\n\n public append(segment: ISegment) {\n if (TextSegment.is(segment)) {\n // Note: Must call 'appendLocalRefs' before modifying this segment's length as\n // 'this.cachedLength' is used to adjust the offsets of the local refs.\n LocalReferenceCollection.append(this, segment);\n\n this.text += segment.text;\n this.cachedLength = this.text.length;\n } else {\n throw new Error(\"can only append text segment\");\n }\n }\n\n // TODO: retain removed text for undo\n // returns true if entire string removed\n public removeRange(start: number, end: number) {\n let remnantString = \"\";\n const len = this.text.length;\n if (start > 0) {\n remnantString += this.text.substring(0, start);\n }\n if (end < len) {\n remnantString += this.text.substring(end);\n }\n this.text = remnantString;\n this.cachedLength = remnantString.length;\n return (remnantString.length === 0);\n }\n\n protected createSplitSegmentAt(pos: number) {\n if (pos > 0) {\n const remainingText = this.text.substring(pos);\n this.text = this.text.substring(0, pos);\n this.cachedLength = this.text.length;\n const leafSegment = new TextSegment(remainingText);\n return leafSegment;\n }\n }\n}\n\ninterface ITextAccumulator {\n textSegment: TextSegment;\n placeholder?: string;\n parallelArrays?: boolean;\n}\n\ninterface ITextAndMarkerAccumulator extends ITextAccumulator {\n parallelArrays: true;\n parallelText: string[];\n parallelMarkers: Marker[];\n parallelMarkerLabel: string;\n tagsInProgress: string[];\n}\n\nfunction isTextAndMarkerAccumulator(accum: ITextAccumulator): accum is ITextAndMarkerAccumulator {\n return accum.parallelArrays === true;\n}\n\ntype ITextAccumulatorType = ITextAccumulator | ITextAndMarkerAccumulator;\nexport class MergeTreeTextHelper {\n constructor(private readonly mergeTree: MergeTree) { }\n\n public getTextAndMarkers(refSeq: number, clientId: number, label: string, start?: number, end?: number) {\n const range = this.getValidRange(start, end, refSeq, clientId);\n const accum: ITextAndMarkerAccumulator = {\n parallelArrays: true,\n parallelMarkerLabel: label,\n parallelMarkers: [],\n parallelText: [],\n tagsInProgress: [],\n textSegment: new TextSegment(\"\"),\n };\n\n this.mergeTree.mapRange<ITextAndMarkerAccumulator>(\n { leaf: this.gatherText },\n refSeq,\n clientId,\n accum,\n range.start,\n range.end);\n\n return { parallelText: accum.parallelText, parallelMarkers: accum.parallelMarkers };\n }\n\n public getText(refSeq: number, clientId: number, placeholder = \"\", start?: number, end?: number) {\n const range = this.getValidRange(start, end, refSeq, clientId);\n\n const accum: ITextAccumulator = { textSegment: new TextSegment(\"\"), placeholder };\n\n this.mergeTree.mapRange<ITextAccumulator>(\n { leaf: this.gatherText },\n refSeq,\n clientId,\n accum,\n range.start,\n range.end);\n return accum.textSegment.text;\n }\n\n private getValidRange(\n start: number | undefined,\n end: number | undefined,\n refSeq: number,\n clientId: number,\n ): IIntegerRange {\n const range: IIntegerRange = {\n end: end ?? this.mergeTree.getLength(refSeq, clientId),\n start: start ?? 0,\n };\n return range;\n }\n\n private readonly gatherText = (segment: ISegment, pos: number, refSeq: number, clientId: number, start: number,\n end: number, accumText: ITextAccumulatorType) => {\n let _start = start;\n if (TextSegment.is(segment)) {\n let beginTags = \"\";\n let endTags = \"\";\n if (isTextAndMarkerAccumulator(accumText)) {\n // TODO: let clients pass in function to get tag\n const tags = [] as string[];\n const initTags = [] as string[];\n\n if (segment.properties?.[\"font-weight\"]) {\n tags.push(\"b\");\n }\n if (segment.properties?.[\"text-decoration\"]) {\n tags.push(\"u\");\n }\n const remTags = [] as string[];\n if (tags.length > 0) {\n for (const tag of tags) {\n if (!accumText.tagsInProgress.includes(tag)) {\n beginTags += `<${tag}>`;\n initTags.push(tag);\n }\n }\n for (const accumTag of accumText.tagsInProgress) {\n if (!tags.includes(accumTag)) {\n endTags += `</${accumTag}>`;\n remTags.push(accumTag);\n }\n }\n for (const initTag of initTags.reverse()) {\n accumText.tagsInProgress.push(initTag);\n }\n } else {\n for (const accumTag of accumText.tagsInProgress) {\n endTags += `</${accumTag}>`;\n remTags.push(accumTag);\n }\n }\n for (const remTag of remTags) {\n const remdex = accumText.tagsInProgress.indexOf(remTag);\n if (remdex >= 0) {\n accumText.tagsInProgress.splice(remdex, 1);\n }\n }\n }\n accumText.textSegment.text += endTags;\n accumText.textSegment.text += beginTags;\n if ((_start <= 0) && (end >= segment.text.length)) {\n accumText.textSegment.text += segment.text;\n } else {\n if (_start < 0) {\n _start = 0;\n }\n if (end >= segment.text.length) {\n accumText.textSegment.text += segment.text.substring(_start);\n } else {\n accumText.textSegment.text += segment.text.substring(_start, end);\n }\n }\n } else {\n if (accumText.placeholder && (accumText.placeholder.length > 0)) {\n if (accumText.placeholder === \"*\") {\n const marker = segment as Marker;\n accumText.textSegment.text += `\\n${marker.toString()}`;\n } else {\n for (let i = 0; i < segment.cachedLength; i++) {\n accumText.textSegment.text += accumText.placeholder;\n }\n }\n } else if (isTextAndMarkerAccumulator(accumText)) {\n const marker = segment as Marker;\n if (marker.hasTileLabel(accumText.parallelMarkerLabel)) {\n accumText.parallelMarkers.push(marker);\n accumText.parallelText.push(accumText.textSegment.text);\n accumText.textSegment.text = \"\";\n }\n }\n }\n\n return true;\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/merge-tree",
3
- "version": "0.59.2001",
3
+ "version": "0.59.3000",
4
4
  "description": "Merge tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -63,19 +63,20 @@
63
63
  "@fluidframework/common-utils": "^0.32.1",
64
64
  "@fluidframework/container-definitions": "^0.48.1000",
65
65
  "@fluidframework/core-interfaces": "^0.43.1000",
66
- "@fluidframework/datastore-definitions": "^0.59.2001",
66
+ "@fluidframework/datastore-definitions": "^0.59.3000",
67
67
  "@fluidframework/protocol-definitions": "^0.1028.1000",
68
- "@fluidframework/runtime-definitions": "^0.59.2001",
69
- "@fluidframework/runtime-utils": "^0.59.2001",
70
- "@fluidframework/shared-object-base": "^0.59.2001",
71
- "@fluidframework/telemetry-utils": "^0.59.2001"
68
+ "@fluidframework/runtime-definitions": "^0.59.3000",
69
+ "@fluidframework/runtime-utils": "^0.59.3000",
70
+ "@fluidframework/shared-object-base": "^0.59.3000",
71
+ "@fluidframework/telemetry-utils": "^0.59.3000"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@fluidframework/build-common": "^0.23.0",
75
- "@fluidframework/eslint-config-fluid": "^0.28.1000",
76
- "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@^0.58.0",
77
- "@fluidframework/mocha-test-setup": "^0.59.2001",
78
- "@fluidframework/test-runtime-utils": "^0.59.2001",
75
+ "@fluidframework/build-tools": "^0.2.66793",
76
+ "@fluidframework/eslint-config-fluid": "^0.28.2000",
77
+ "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@0.59.2000",
78
+ "@fluidframework/mocha-test-setup": "^0.59.3000",
79
+ "@fluidframework/test-runtime-utils": "^0.59.3000",
79
80
  "@microsoft/api-extractor": "^7.22.2",
80
81
  "@rushstack/eslint-config": "^2.5.1",
81
82
  "@types/diff": "^3.5.1",
@@ -103,12 +104,158 @@
103
104
  "random-js": "^1.0.8",
104
105
  "rimraf": "^2.6.2",
105
106
  "source-map-support": "^0.5.16",
106
- "typescript": "~4.1.3",
107
+ "typescript": "~4.5.5",
107
108
  "typescript-formatter": "7.1.0"
108
109
  },
109
110
  "typeValidation": {
110
- "version": "0.59.1000",
111
- "broken": {},
112
- "disabled": true
111
+ "version": "0.59.3000",
112
+ "broken": {
113
+ "InterfaceDeclaration_IMergeTreeAnnotateMsg": {
114
+ "forwardCompat": false,
115
+ "backCompat": false
116
+ },
117
+ "InterfaceDeclaration_IMergeTreeDelta": {
118
+ "forwardCompat": false,
119
+ "backCompat": false
120
+ },
121
+ "InterfaceDeclaration_IMergeTreeDeltaCallbackArgs": {
122
+ "forwardCompat": false,
123
+ "backCompat": false
124
+ },
125
+ "TypeAliasDeclaration_IMergeTreeDeltaOp": {
126
+ "forwardCompat": false,
127
+ "backCompat": false
128
+ },
129
+ "InterfaceDeclaration_IMergeTreeDeltaOpArgs": {
130
+ "forwardCompat": false,
131
+ "backCompat": false
132
+ },
133
+ "InterfaceDeclaration_IMergeTreeGroupMsg": {
134
+ "forwardCompat": false,
135
+ "backCompat": false
136
+ },
137
+ "InterfaceDeclaration_IMergeTreeInsertMsg": {
138
+ "forwardCompat": false,
139
+ "backCompat": false
140
+ },
141
+ "InterfaceDeclaration_IMergeTreeMaintenanceCallbackArgs": {
142
+ "forwardCompat": false,
143
+ "backCompat": false
144
+ },
145
+ "TypeAliasDeclaration_IMergeTreeOp": {
146
+ "forwardCompat": false,
147
+ "backCompat": false
148
+ },
149
+ "InterfaceDeclaration_IMergeTreeRemoveMsg": {
150
+ "forwardCompat": false,
151
+ "backCompat": false
152
+ },
153
+ "TypeAliasDeclaration_IntervalNode": {
154
+ "forwardCompat": false,
155
+ "backCompat": false
156
+ },
157
+ "TypeAliasDeclaration_MergeTreeDeltaOperationType": {
158
+ "forwardCompat": false,
159
+ "backCompat": false
160
+ },
161
+ "TypeAliasDeclaration_MergeTreeDeltaOperationTypes": {
162
+ "forwardCompat": false,
163
+ "backCompat": false
164
+ },
165
+ "EnumDeclaration_MergeTreeDeltaType": {
166
+ "forwardCompat": false,
167
+ "backCompat": false
168
+ },
169
+ "EnumDeclaration_MergeTreeMaintenanceType": {
170
+ "forwardCompat": false,
171
+ "backCompat": false
172
+ },
173
+ "EnumDeclaration_RBColor": {
174
+ "forwardCompat": false,
175
+ "backCompat": false
176
+ },
177
+ "InterfaceDeclaration_RBNode": {
178
+ "forwardCompat": false,
179
+ "backCompat": false
180
+ },
181
+ "ClassDeclaration_List": {
182
+ "forwardCompat": false
183
+ },
184
+ "ClassDeclaration_BaseSegment": {
185
+ "forwardCompat": false
186
+ },
187
+ "ClassDeclaration_Client": {
188
+ "forwardCompat": false
189
+ },
190
+ "InterfaceDeclaration_IConsensusInfo": {
191
+ "forwardCompat": false
192
+ },
193
+ "InterfaceDeclaration_IHierBlock": {
194
+ "forwardCompat": false
195
+ },
196
+ "InterfaceDeclaration_IMergeBlock": {
197
+ "forwardCompat": false
198
+ },
199
+ "TypeAliasDeclaration_IMergeNode": {
200
+ "forwardCompat": false
201
+ },
202
+ "InterfaceDeclaration_IMergeNodeCommon": {
203
+ "forwardCompat": false
204
+ },
205
+ "InterfaceDeclaration_IMergeTreeSegmentDelta": {
206
+ "forwardCompat": false
207
+ },
208
+ "ClassDeclaration_IncrementalMapState": {
209
+ "forwardCompat": false
210
+ },
211
+ "InterfaceDeclaration_InsertContext": {
212
+ "forwardCompat": false
213
+ },
214
+ "InterfaceDeclaration_ISegment": {
215
+ "forwardCompat": false
216
+ },
217
+ "ClassDeclaration_LocalReference": {
218
+ "forwardCompat": false
219
+ },
220
+ "ClassDeclaration_LocalReferenceCollection": {
221
+ "forwardCompat": false
222
+ },
223
+ "InterfaceDeclaration_LRUSegment": {
224
+ "forwardCompat": false
225
+ },
226
+ "ClassDeclaration_MergeBlock": {
227
+ "forwardCompat": false
228
+ },
229
+ "InterfaceDeclaration_ISegmentChanges": {
230
+ "forwardCompat": false
231
+ },
232
+ "ClassDeclaration_Marker": {
233
+ "forwardCompat": false
234
+ },
235
+ "ClassDeclaration_MergeNode": {
236
+ "forwardCompat": false
237
+ },
238
+ "ClassDeclaration_MergeTree": {
239
+ "forwardCompat": false
240
+ },
241
+ "InterfaceDeclaration_SegmentAccumulator": {
242
+ "forwardCompat": false
243
+ },
244
+ "InterfaceDeclaration_SegmentGroup": {
245
+ "forwardCompat": false
246
+ },
247
+ "ClassDeclaration_SnapshotLegacy": {
248
+ "forwardCompat": false
249
+ },
250
+ "ClassDeclaration_SortedSegmentSet": {
251
+ "forwardCompat": false
252
+ },
253
+ "ClassDeclaration_TextSegment": {
254
+ "forwardCompat": false
255
+ },
256
+ "ClassDeclaration_TrackingGroup": {
257
+ "forwardCompat": false
258
+ }
259
+ }
113
260
  }
114
261
  }
package/src/client.ts CHANGED
@@ -25,7 +25,6 @@ import {
25
25
  ISegmentAction,
26
26
  Marker,
27
27
  MergeTree,
28
- RangeStackMap,
29
28
  SegmentGroup,
30
29
  } from "./mergeTree";
31
30
  import { MergeTreeDeltaCallback } from "./mergeTreeDeltaCallback";
@@ -47,17 +46,18 @@ import {
47
46
  IMergeTreeOp,
48
47
  IRelativePosition,
49
48
  MergeTreeDeltaType,
49
+ ReferenceType,
50
50
  } from "./ops";
51
51
  import { PropertySet } from "./properties";
52
52
  import { SnapshotLegacy } from "./snapshotlegacy";
53
53
  import { SnapshotLoader } from "./snapshotLoader";
54
54
  import { MergeTreeTextHelper } from "./textSegment";
55
55
  import { SnapshotV1 } from "./snapshotV1";
56
+ import { ReferencePosition, RangeStackMap, DetachedReferencePosition } from "./referencePositions";
56
57
  import {
57
58
  IMergeTreeClientSequenceArgs,
58
59
  IMergeTreeDeltaOpArgs,
59
60
  MergeTreeMaintenanceCallback,
60
- ReferencePosition,
61
61
  } from "./index";
62
62
 
63
63
  function elapsedMicroseconds(trace: Trace) {
@@ -318,13 +318,36 @@ export class Client {
318
318
  }
319
319
  return this.mergeTree.getPosition(segment, this.getCurrentSeq(), this.getClientId());
320
320
  }
321
-
321
+ /**
322
+ * @deprecated - use createReferencePosition instead
323
+ */
322
324
  public addLocalReference(lref: LocalReference) {
323
325
  return this.mergeTree.addLocalReference(lref);
324
326
  }
325
327
 
328
+ /**
329
+ * @deprecated - use removeReferencePosition instead
330
+ */
326
331
  public removeLocalReference(lref: LocalReference) {
327
- return this.mergeTree.removeLocalReference(lref.segment!, lref);
332
+ return this.removeLocalReferencePosition(lref);
333
+ }
334
+
335
+ public createLocalReferencePosition(
336
+ segment: ISegment, offset: number, refType: ReferenceType, properties: PropertySet | undefined,
337
+ ): ReferencePosition {
338
+ return this.mergeTree.createLocalReferencePosition(segment, offset, refType, properties, this);
339
+ }
340
+
341
+ public removeLocalReferencePosition(lref: ReferencePosition) {
342
+ return this.mergeTree.removeLocalReferencePosition(lref);
343
+ }
344
+
345
+ public localReferencePositionToPosition(lref: ReferencePosition) {
346
+ const segment = lref.getSegment();
347
+ if (segment === undefined) {
348
+ return DetachedReferencePosition;
349
+ }
350
+ return this.getPosition(segment) + lref.getOffset();
328
351
  }
329
352
 
330
353
  /**
@@ -629,8 +652,7 @@ export class Client {
629
652
  getLongClientId(shortClientId: number) {
630
653
  if (shortClientId >= 0) {
631
654
  return this.shortClientIdMap[shortClientId];
632
- }
633
- else {
655
+ } else {
634
656
  return "original";
635
657
  }
636
658
  }
@@ -780,22 +802,29 @@ export class Client {
780
802
 
781
803
  public applyStashedOp(op: IMergeTreeDeltaOp): SegmentGroup;
782
804
  public applyStashedOp(op: IMergeTreeGroupMsg): SegmentGroup[];
783
- public applyStashedOp(op: IMergeTreeOp) {
805
+ public applyStashedOp(op: IMergeTreeOp): SegmentGroup | SegmentGroup[];
806
+ public applyStashedOp(op: IMergeTreeOp): SegmentGroup | SegmentGroup[] {
807
+ let metadata: SegmentGroup | SegmentGroup[] | undefined;
784
808
  switch (op.type) {
785
809
  case MergeTreeDeltaType.INSERT:
786
810
  this.applyInsertOp({ op });
787
- return this.peekPendingSegmentGroups();
811
+ metadata = this.peekPendingSegmentGroups();
812
+ break;
788
813
  case MergeTreeDeltaType.REMOVE:
789
814
  this.applyRemoveRangeOp({ op });
790
- return this.peekPendingSegmentGroups();
815
+ metadata = this.peekPendingSegmentGroups();
816
+ break;
791
817
  case MergeTreeDeltaType.ANNOTATE:
792
818
  this.applyAnnotateRangeOp({ op });
793
- return this.peekPendingSegmentGroups();
819
+ metadata = this.peekPendingSegmentGroups();
820
+ break;
794
821
  case MergeTreeDeltaType.GROUP:
795
822
  return op.ops.map((o) => this.applyStashedOp(o));
796
823
  default:
797
824
  unreachableCase(op, "unrecognized op type");
798
825
  }
826
+ assert(!!metadata, 0x2db /* "Applying op must generate a pending segment" */);
827
+ return metadata;
799
828
  }
800
829
 
801
830
  public applyMsg(msg: ISequencedDocumentMessage, local: boolean = false) {
@@ -809,8 +838,7 @@ export class Client {
809
838
  };
810
839
  if (opArgs.sequencedMessage?.clientId === this.longClientId || local) {
811
840
  this.ackPendingSegment(opArgs);
812
- }
813
- else {
841
+ } else {
814
842
  this.applyRemoteOp(opArgs);
815
843
  }
816
844
  }
@@ -915,7 +943,7 @@ export class Client {
915
943
  assert(
916
944
  catchUpMsgs === undefined || catchUpMsgs.length === 0,
917
945
  0x03f /* "New format should not emit catchup ops" */);
918
- const snap = new SnapshotV1(this.mergeTree, this.logger, (id)=>this.getLongClientId(id));
946
+ const snap = new SnapshotV1(this.mergeTree, this.logger, (id) => this.getLongClientId(id));
919
947
  snap.extractSync();
920
948
  return snap.emit(serializer, handle);
921
949
  } else {
@@ -929,7 +957,7 @@ export class Client {
929
957
  runtime: IFluidDataStoreRuntime,
930
958
  storage: IChannelStorageService,
931
959
  serializer: IFluidSerializer,
932
- ): Promise<{ catchupOpsP: Promise<ISequencedDocumentMessage[]> }> {
960
+ ): Promise<{ catchupOpsP: Promise<ISequencedDocumentMessage[]>; }> {
933
961
  const loader = new SnapshotLoader(runtime, this, this.mergeTree, this.logger, serializer);
934
962
 
935
963
  return loader.initialize(storage);
@@ -943,8 +971,7 @@ export class Client {
943
971
  const segWindow = this.getCollabWindow();
944
972
  if (segWindow.collaborating) {
945
973
  return UnassignedSequenceNumber;
946
- }
947
- else {
974
+ } else {
948
975
  return UniversalSequenceNumber;
949
976
  }
950
977
  }
@@ -998,9 +1025,8 @@ export class Client {
998
1025
  let clientId: number;
999
1026
  if (op) {
1000
1027
  clientId = this.getOrAddShortClientId(op.clientId);
1001
- seq = op.sequenceNumber;
1002
- }
1003
- else {
1028
+ seq = op.referenceSequenceNumber;
1029
+ } else {
1004
1030
  const segWindow = this.mergeTree.getCollabWindow();
1005
1031
  seq = segWindow.currentSeq;
1006
1032
  clientId = segWindow.clientId;