@fluid-experimental/tree 1.2.6 → 2.0.0-dev.1.3.0.96595

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 (175) hide show
  1. package/.mocharc.js +12 -0
  2. package/.prettierignore +6 -0
  3. package/README.md +1 -1
  4. package/dist/Checkout.d.ts +9 -4
  5. package/dist/Checkout.d.ts.map +1 -1
  6. package/dist/Checkout.js +34 -25
  7. package/dist/Checkout.js.map +1 -1
  8. package/dist/Common.d.ts +31 -18
  9. package/dist/Common.d.ts.map +1 -1
  10. package/dist/Common.js +33 -22
  11. package/dist/Common.js.map +1 -1
  12. package/dist/EditLog.js +2 -2
  13. package/dist/EditLog.js.map +1 -1
  14. package/dist/EditUtilities.d.ts +5 -0
  15. package/dist/EditUtilities.d.ts.map +1 -1
  16. package/dist/EditUtilities.js +4 -3
  17. package/dist/EditUtilities.js.map +1 -1
  18. package/dist/EventTypes.d.ts +11 -6
  19. package/dist/EventTypes.d.ts.map +1 -1
  20. package/dist/EventTypes.js +11 -6
  21. package/dist/EventTypes.js.map +1 -1
  22. package/dist/HistoryEditFactory.d.ts +5 -3
  23. package/dist/HistoryEditFactory.d.ts.map +1 -1
  24. package/dist/HistoryEditFactory.js +25 -6
  25. package/dist/HistoryEditFactory.js.map +1 -1
  26. package/dist/LogViewer.d.ts +12 -6
  27. package/dist/LogViewer.d.ts.map +1 -1
  28. package/dist/LogViewer.js.map +1 -1
  29. package/dist/RevisionValueCache.d.ts +8 -4
  30. package/dist/RevisionValueCache.d.ts.map +1 -1
  31. package/dist/RevisionValueCache.js +4 -2
  32. package/dist/RevisionValueCache.js.map +1 -1
  33. package/dist/SharedTree.d.ts +22 -11
  34. package/dist/SharedTree.d.ts.map +1 -1
  35. package/dist/SharedTree.js +25 -19
  36. package/dist/SharedTree.js.map +1 -1
  37. package/dist/StringInterner.d.ts +4 -3
  38. package/dist/StringInterner.d.ts.map +1 -1
  39. package/dist/StringInterner.js +4 -3
  40. package/dist/StringInterner.js.map +1 -1
  41. package/dist/Transaction.d.ts +2 -2
  42. package/dist/Transaction.d.ts.map +1 -1
  43. package/dist/Transaction.js +3 -2
  44. package/dist/Transaction.js.map +1 -1
  45. package/dist/TransactionInternal.d.ts.map +1 -1
  46. package/dist/TransactionInternal.js +1 -0
  47. package/dist/TransactionInternal.js.map +1 -1
  48. package/dist/id-compressor/IdCompressor.d.ts +14 -8
  49. package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
  50. package/dist/id-compressor/IdCompressor.js +36 -15
  51. package/dist/id-compressor/IdCompressor.js.map +1 -1
  52. package/dist/id-compressor/NumericUuid.d.ts +4 -0
  53. package/dist/id-compressor/NumericUuid.d.ts.map +1 -1
  54. package/dist/id-compressor/NumericUuid.js +13 -3
  55. package/dist/id-compressor/NumericUuid.js.map +1 -1
  56. package/dist/id-compressor/SessionIdNormalizer.d.ts +10 -5
  57. package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  58. package/dist/id-compressor/SessionIdNormalizer.js +10 -5
  59. package/dist/id-compressor/SessionIdNormalizer.js.map +1 -1
  60. package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  61. package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
  62. package/dist/index.d.ts +1 -1
  63. package/dist/index.js +1 -1
  64. package/dist/index.js.map +1 -1
  65. package/lib/Checkout.d.ts +9 -4
  66. package/lib/Checkout.d.ts.map +1 -1
  67. package/lib/Checkout.js +36 -27
  68. package/lib/Checkout.js.map +1 -1
  69. package/lib/Common.d.ts +31 -18
  70. package/lib/Common.d.ts.map +1 -1
  71. package/lib/Common.js +31 -21
  72. package/lib/Common.js.map +1 -1
  73. package/lib/EditLog.js +2 -2
  74. package/lib/EditLog.js.map +1 -1
  75. package/lib/EditUtilities.d.ts +5 -0
  76. package/lib/EditUtilities.d.ts.map +1 -1
  77. package/lib/EditUtilities.js +4 -3
  78. package/lib/EditUtilities.js.map +1 -1
  79. package/lib/EventTypes.d.ts +11 -6
  80. package/lib/EventTypes.d.ts.map +1 -1
  81. package/lib/EventTypes.js +11 -6
  82. package/lib/EventTypes.js.map +1 -1
  83. package/lib/HistoryEditFactory.d.ts +5 -3
  84. package/lib/HistoryEditFactory.d.ts.map +1 -1
  85. package/lib/HistoryEditFactory.js +25 -6
  86. package/lib/HistoryEditFactory.js.map +1 -1
  87. package/lib/LogViewer.d.ts +12 -6
  88. package/lib/LogViewer.d.ts.map +1 -1
  89. package/lib/LogViewer.js.map +1 -1
  90. package/lib/RevisionValueCache.d.ts +8 -4
  91. package/lib/RevisionValueCache.d.ts.map +1 -1
  92. package/lib/RevisionValueCache.js +4 -2
  93. package/lib/RevisionValueCache.js.map +1 -1
  94. package/lib/SharedTree.d.ts +22 -11
  95. package/lib/SharedTree.d.ts.map +1 -1
  96. package/lib/SharedTree.js +26 -20
  97. package/lib/SharedTree.js.map +1 -1
  98. package/lib/StringInterner.d.ts +4 -3
  99. package/lib/StringInterner.d.ts.map +1 -1
  100. package/lib/StringInterner.js +4 -3
  101. package/lib/StringInterner.js.map +1 -1
  102. package/lib/Transaction.d.ts +2 -2
  103. package/lib/Transaction.d.ts.map +1 -1
  104. package/lib/Transaction.js +3 -2
  105. package/lib/Transaction.js.map +1 -1
  106. package/lib/TransactionInternal.d.ts.map +1 -1
  107. package/lib/TransactionInternal.js +1 -0
  108. package/lib/TransactionInternal.js.map +1 -1
  109. package/lib/id-compressor/IdCompressor.d.ts +14 -8
  110. package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
  111. package/lib/id-compressor/IdCompressor.js +36 -15
  112. package/lib/id-compressor/IdCompressor.js.map +1 -1
  113. package/lib/id-compressor/NumericUuid.d.ts +4 -0
  114. package/lib/id-compressor/NumericUuid.d.ts.map +1 -1
  115. package/lib/id-compressor/NumericUuid.js +13 -3
  116. package/lib/id-compressor/NumericUuid.js.map +1 -1
  117. package/lib/id-compressor/SessionIdNormalizer.d.ts +10 -5
  118. package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  119. package/lib/id-compressor/SessionIdNormalizer.js +10 -5
  120. package/lib/id-compressor/SessionIdNormalizer.js.map +1 -1
  121. package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  122. package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
  123. package/lib/index.d.ts +1 -1
  124. package/lib/index.js +1 -1
  125. package/lib/index.js.map +1 -1
  126. package/lib/test/AppendOnlySortedMap.perf.tests.js.map +1 -1
  127. package/lib/test/Checkout.tests.d.ts.map +1 -1
  128. package/lib/test/Checkout.tests.js +39 -10
  129. package/lib/test/Checkout.tests.js.map +1 -1
  130. package/lib/test/Common.tests.js +20 -1
  131. package/lib/test/Common.tests.js.map +1 -1
  132. package/lib/test/HistoryEditFactory.tests.js +48 -9
  133. package/lib/test/HistoryEditFactory.tests.js.map +1 -1
  134. package/lib/test/IdCompressor.tests.js +23 -0
  135. package/lib/test/IdCompressor.tests.js.map +1 -1
  136. package/lib/test/SessionIdNormalizer.tests.js +3 -2
  137. package/lib/test/SessionIdNormalizer.tests.js.map +1 -1
  138. package/lib/test/fuzz/Generators.d.ts.map +1 -1
  139. package/lib/test/fuzz/Generators.js.map +1 -1
  140. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
  141. package/lib/test/fuzz/SharedTreeFuzzTests.js +2 -3
  142. package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
  143. package/lib/test/utilities/MockTransaction.d.ts.map +1 -1
  144. package/lib/test/utilities/MockTransaction.js +1 -0
  145. package/lib/test/utilities/MockTransaction.js.map +1 -1
  146. package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
  147. package/lib/test/utilities/SharedTreeTests.js +35 -26
  148. package/lib/test/utilities/SharedTreeTests.js.map +1 -1
  149. package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
  150. package/lib/test/utilities/SharedTreeVersioningTests.js +7 -0
  151. package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
  152. package/lib/test/utilities/TestUtilities.d.ts +5 -0
  153. package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
  154. package/lib/test/utilities/TestUtilities.js +4 -3
  155. package/lib/test/utilities/TestUtilities.js.map +1 -1
  156. package/lib/test/utilities/UndoRedoTests.js +3 -2
  157. package/lib/test/utilities/UndoRedoTests.js.map +1 -1
  158. package/package.json +28 -23
  159. package/src/Checkout.ts +56 -14
  160. package/src/Common.ts +39 -21
  161. package/src/EditLog.ts +2 -2
  162. package/src/EditUtilities.ts +3 -3
  163. package/src/EventTypes.ts +12 -6
  164. package/src/HistoryEditFactory.ts +31 -6
  165. package/src/LogViewer.ts +12 -6
  166. package/src/RevisionValueCache.ts +8 -4
  167. package/src/SharedTree.ts +39 -26
  168. package/src/StringInterner.ts +4 -3
  169. package/src/Transaction.ts +5 -4
  170. package/src/TransactionInternal.ts +1 -0
  171. package/src/id-compressor/IdCompressor.ts +55 -24
  172. package/src/id-compressor/NumericUuid.ts +17 -3
  173. package/src/id-compressor/SessionIdNormalizer.ts +10 -5
  174. package/src/id-compressor/persisted-types/0.0.1.ts +1 -0
  175. package/src/index.ts +1 -1
@@ -14,14 +14,15 @@ import { getChangeNodeFromViewNode } from './SerializationUtilities';
14
14
  * @param changes - the changes for which to produce an inverse.
15
15
  * @param before - a view of the tree state before `changes` are/were applied - used as a basis for generating the inverse.
16
16
  * @returns if the changes could be reverted, a sequence of changes _r_ that will produce `before` if applied to a view _A_, where _A_ is the result of
17
- * applying `changes` to `before`. Applying _r_ to views other than _A_ is legal but may cause the changes to fail to apply or may
18
- * not be a true semantic inverse. If the changes could not be reverted given the state of `before`, returns undefined.
17
+ * applying `changes` to `before`. Note that the size of the array of reverted changes may not be the same as the input array, and may even be empty in cases where
18
+ * the view did not change. Applying _r_ to views other than _A_ is legal but may cause the changes to fail to apply or may not be a true semantic inverse.
19
+ * If the changes could not be reverted given the state of `before`, returns undefined.
19
20
  *
20
21
  * TODO: what should this do if `changes` fails to apply to `before`?
21
22
  * TODO:#68574: Pass a view that corresponds to the appropriate Fluid reference sequence number rather than the view just before
22
23
  * @internal
23
24
  */
24
- export function revert(changes, before) {
25
+ export function revert(changes, before, logger) {
25
26
  const result = [];
26
27
  const builtNodes = new Map();
27
28
  const detachedNodes = new Map();
@@ -54,10 +55,20 @@ export function revert(changes, before) {
54
55
  const nodesBuilt = builtNodes.get(source);
55
56
  const nodesDetached = detachedNodes.get(source);
56
57
  if (nodesBuilt !== undefined) {
58
+ if (nodesBuilt.length === 0) {
59
+ builtNodes.delete(source);
60
+ logger === null || logger === void 0 ? void 0 : logger.sendTelemetryEvent({ eventName: 'reverting insertion of empty traits' });
61
+ continue;
62
+ }
57
63
  result.unshift(createInvertedInsert(change, nodesBuilt));
58
64
  builtNodes.delete(source);
59
65
  }
60
66
  else if (nodesDetached !== undefined) {
67
+ if (nodesDetached.length === 0) {
68
+ detachedNodes.delete(source);
69
+ logger === null || logger === void 0 ? void 0 : logger.sendTelemetryEvent({ eventName: 'reverting insertion of empty traits' });
70
+ continue;
71
+ }
61
72
  result.unshift(createInvertedInsert(change, nodesDetached, true));
62
73
  detachedNodes.delete(source);
63
74
  }
@@ -76,6 +87,10 @@ export function revert(changes, before) {
76
87
  return undefined;
77
88
  }
78
89
  const { invertedDetach, detachedNodeIds } = invert;
90
+ if (detachedNodeIds.length === 0) {
91
+ logger === null || logger === void 0 ? void 0 : logger.sendTelemetryEvent({ eventName: 'reverting detachment of empty traits' });
92
+ continue;
93
+ }
79
94
  if (destination !== undefined) {
80
95
  if (builtNodes.has(destination) || detachedNodes.has(destination)) {
81
96
  // Malformed: destination was already used by a prior build or detach
@@ -131,13 +146,16 @@ function createInvertedInsert(insert, nodesInserted, saveDetached = false) {
131
146
  * Information on the nodes that were detached is obtained by going to the revision before the detach.
132
147
  *
133
148
  * The anchor for the resulting Insert is chosen in the following order:
149
+ *
150
+ * ```markdown
134
151
  * 1. If detach.source.start.side is After: detach.source.start
135
152
  *
136
153
  * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,
137
154
  * if detach.source.start is "After B", the anchor for the resulting Insert will also be "After B".
138
155
  *
139
156
  * For nodes [A..F] G H where [A..F] represents the detached nodes,
140
- * if detach.source.start is "After start of trait", the anchor for the resulting Insert will also be "After start of trait".
157
+ * if detach.source.start is "After start of trait", the anchor for the resulting Insert will also be
158
+ * "After start of trait".
141
159
  *
142
160
  * 2. Else if detach.source.end.side is Before: detach.source.end
143
161
  *
@@ -150,9 +168,10 @@ function createInvertedInsert(insert, nodesInserted, saveDetached = false) {
150
168
  * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,
151
169
  * if detach.source.start is "Before C" and detach.source.end is "After F",
152
170
  * the anchor for the resulting Insert will be "After B".
171
+ * ```
153
172
  *
154
- * When choosing the anchor, the existing anchors on detach.source are preferred when they have a valid sibling. Otherwise, the valid
155
- * anchor to the left of the originally detached nodes is chosen.
173
+ * When choosing the anchor, the existing anchors on detach.source are preferred when they have a valid sibling.
174
+ * Otherwise, the valid anchor to the left of the originally detached nodes is chosen.
156
175
  */
157
176
  function createInvertedDetach(detach, viewBeforeChange) {
158
177
  const validatedSource = validateStableRange(viewBeforeChange, detach.source);
@@ -1 +1 @@
1
- {"version":3,"file":"HistoryEditFactory.js","sourceRoot":"","sources":["../src/HistoryEditFactory.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 { DetachedSequenceId, isDetachedSequenceId, NodeId } from './Identifiers';\nimport { assert, fail } from './Common';\nimport { rangeFromStableRange } from './TreeViewUtilities';\nimport {\n\tChangeInternal,\n\tChangeTypeInternal,\n\tDetachInternal,\n\tSetValueInternal,\n\tInsertInternal,\n\tBuildNodeInternal,\n\tSide,\n\tStableRangeInternal,\n} from './persisted-types';\nimport { TransactionInternal } from './TransactionInternal';\nimport { RangeValidationResultKind, validateStableRange } from './EditUtilities';\nimport { StablePlace } from './ChangeTypes';\nimport { RevisionView } from './RevisionView';\nimport { TreeView } from './TreeView';\nimport { getChangeNodeFromViewNode } from './SerializationUtilities';\n\n/**\n * Given a sequence of changes, produces an inverse sequence of changes, i.e. the minimal changes required to revert the given changes\n * @param changes - the changes for which to produce an inverse.\n * @param before - a view of the tree state before `changes` are/were applied - used as a basis for generating the inverse.\n * @returns if the changes could be reverted, a sequence of changes _r_ that will produce `before` if applied to a view _A_, where _A_ is the result of\n * applying `changes` to `before`. Applying _r_ to views other than _A_ is legal but may cause the changes to fail to apply or may\n * not be a true semantic inverse. If the changes could not be reverted given the state of `before`, returns undefined.\n *\n * TODO: what should this do if `changes` fails to apply to `before`?\n * TODO:#68574: Pass a view that corresponds to the appropriate Fluid reference sequence number rather than the view just before\n * @internal\n */\nexport function revert(changes: readonly ChangeInternal[], before: RevisionView): ChangeInternal[] | undefined {\n\tconst result: ChangeInternal[] = [];\n\n\tconst builtNodes = new Map<DetachedSequenceId, NodeId[]>();\n\tconst detachedNodes = new Map<DetachedSequenceId, NodeId[]>();\n\n\t// Open edit on revision to update it as changes are walked through\n\tconst editor = TransactionInternal.factory(before);\n\t// Apply `edit`, generating an inverse as we go.\n\tfor (const change of changes) {\n\t\t// Generate an inverse of each change\n\t\tswitch (change.type) {\n\t\t\tcase ChangeTypeInternal.Build: {\n\t\t\t\t// Save nodes added to the detached state for use in future changes\n\t\t\t\tconst { destination, source } = change;\n\t\t\t\tassert(!builtNodes.has(destination), `Cannot revert Build: destination is already used by a Build`);\n\t\t\t\tassert(!detachedNodes.has(destination), `Cannot revert Build: destination is already used by a Detach`);\n\t\t\t\tbuiltNodes.set(\n\t\t\t\t\tdestination,\n\t\t\t\t\tsource.reduce((ids: NodeId[], curr: BuildNodeInternal) => {\n\t\t\t\t\t\tif (isDetachedSequenceId(curr)) {\n\t\t\t\t\t\t\tconst nodesForDetachedSequence =\n\t\t\t\t\t\t\t\tbuiltNodes.get(curr) ?? fail('detached sequence must have associated built nodes');\n\n\t\t\t\t\t\t\tids.push(...nodesForDetachedSequence);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tids.push(curr.identifier);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ids;\n\t\t\t\t\t}, [])\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Insert: {\n\t\t\t\tconst { source } = change;\n\t\t\t\tconst nodesBuilt = builtNodes.get(source);\n\t\t\t\tconst nodesDetached = detachedNodes.get(source);\n\n\t\t\t\tif (nodesBuilt !== undefined) {\n\t\t\t\t\tresult.unshift(createInvertedInsert(change, nodesBuilt));\n\t\t\t\t\tbuiltNodes.delete(source);\n\t\t\t\t} else if (nodesDetached !== undefined) {\n\t\t\t\t\tresult.unshift(createInvertedInsert(change, nodesDetached, true));\n\t\t\t\t\tdetachedNodes.delete(source);\n\t\t\t\t} else {\n\t\t\t\t\t// Cannot revert an insert whose source is no longer available for inserting (i.e. not just built, and not detached)\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Detach: {\n\t\t\t\tconst { destination } = change;\n\t\t\t\tconst invert = createInvertedDetach(change, editor.view);\n\t\t\t\tif (invert === undefined) {\n\t\t\t\t\t// Cannot revert a detach whose source does not exist in the tree\n\t\t\t\t\t// TODO:68574: May not be possible once associated todo in `createInvertedDetach` is addressed\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tconst { invertedDetach, detachedNodeIds } = invert;\n\n\t\t\t\tif (destination !== undefined) {\n\t\t\t\t\tif (builtNodes.has(destination) || detachedNodes.has(destination)) {\n\t\t\t\t\t\t// Malformed: destination was already used by a prior build or detach\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tdetachedNodes.set(destination, detachedNodeIds);\n\t\t\t\t}\n\n\t\t\t\tresult.unshift(...invertedDetach);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.SetValue: {\n\t\t\t\tconst invert = createInvertedSetValue(change, editor.view);\n\t\t\t\tif (invert === undefined) {\n\t\t\t\t\t// Cannot revert a set for a node that does not exist in the tree\n\t\t\t\t\t// TODO:68574: May not be possible once associated todo in `createInvertedSetValue` is addressed\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tresult.unshift(...invert);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Constraint:\n\t\t\t\t// TODO:#46759: Support Constraint in reverts\n\t\t\t\tfail('Revert currently does not support Constraints');\n\t\t\tdefault:\n\t\t\t\tfail('Revert does not support the change type.');\n\t\t}\n\n\t\t// Update the revision\n\t\teditor.applyChange(change);\n\t}\n\n\teditor.close();\n\treturn result;\n}\n\n/**\n * The inverse of an Insert is a Detach that starts before the leftmost node inserted and ends after the rightmost.\n */\nfunction createInvertedInsert(\n\tinsert: InsertInternal,\n\tnodesInserted: readonly NodeId[],\n\tsaveDetached = false\n): ChangeInternal {\n\tconst leftmostNode = nodesInserted[0];\n\tconst rightmostNode = nodesInserted[nodesInserted.length - 1];\n\n\tconst source: StableRangeInternal = {\n\t\tstart: {\n\t\t\treferenceSibling: leftmostNode,\n\t\t\tside: Side.Before,\n\t\t},\n\t\tend: {\n\t\t\treferenceSibling: rightmostNode,\n\t\t\tside: Side.After,\n\t\t},\n\t};\n\n\treturn ChangeInternal.detach(source, saveDetached ? insert.source : undefined);\n}\n\n/**\n * If a detach does not include a destination, its inverse is a build and insert. Otherwise, it is just an insert.\n * Information on the nodes that were detached is obtained by going to the revision before the detach.\n *\n * The anchor for the resulting Insert is chosen in the following order:\n * 1. If detach.source.start.side is After: detach.source.start\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"After B\", the anchor for the resulting Insert will also be \"After B\".\n *\n * For nodes [A..F] G H where [A..F] represents the detached nodes,\n * if detach.source.start is \"After start of trait\", the anchor for the resulting Insert will also be \"After start of trait\".\n *\n * 2. Else if detach.source.end.side is Before: detach.source.end\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"Before C\" and detach.source.end is \"Before G\",\n * the anchor for the resulting Insert will be \"Before G\".\n *\n * 3. Else: After the node directly to the left of the originally detached nodes\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"Before C\" and detach.source.end is \"After F\",\n * the anchor for the resulting Insert will be \"After B\".\n *\n * When choosing the anchor, the existing anchors on detach.source are preferred when they have a valid sibling. Otherwise, the valid\n * anchor to the left of the originally detached nodes is chosen.\n */\nfunction createInvertedDetach(\n\tdetach: DetachInternal,\n\tviewBeforeChange: TreeView\n): { invertedDetach: ChangeInternal[]; detachedNodeIds: NodeId[] } | undefined {\n\tconst validatedSource = validateStableRange(viewBeforeChange, detach.source);\n\tif (validatedSource.result !== RangeValidationResultKind.Valid) {\n\t\t// TODO:#68574: having the reference view would potentially allow us to revert some detaches that currently conflict\n\t\treturn undefined;\n\t}\n\n\tconst { start, end } = rangeFromStableRange(viewBeforeChange, validatedSource);\n\tconst { trait: referenceTrait } = start;\n\tconst nodes = viewBeforeChange.getTrait(referenceTrait);\n\n\tconst startIndex = viewBeforeChange.findIndexWithinTrait(start);\n\tconst endIndex = viewBeforeChange.findIndexWithinTrait(end);\n\tconst detachedNodeIds: NodeId[] = nodes.slice(startIndex, endIndex);\n\n\tconst leftOfDetached = nodes.slice(0, startIndex);\n\n\tlet insertDestination: StablePlace;\n\n\tif (start.side === Side.After) {\n\t\tinsertDestination =\n\t\t\tstart.sibling === undefined\n\t\t\t\t? { side: Side.After, referenceTrait }\n\t\t\t\t: { side: Side.After, referenceSibling: start.sibling };\n\t} else if (end.side === Side.Before) {\n\t\tinsertDestination =\n\t\t\tend.sibling === undefined\n\t\t\t\t? { side: Side.Before, referenceTrait }\n\t\t\t\t: { side: Side.Before, referenceSibling: end.sibling };\n\t} else {\n\t\tconst referenceSibling = leftOfDetached.pop();\n\t\tinsertDestination = {\n\t\t\tside: Side.After,\n\t\t\treferenceSibling,\n\t\t\treferenceTrait: referenceSibling === undefined ? referenceTrait : undefined,\n\t\t};\n\t}\n\n\tif (detach.destination !== undefined) {\n\t\treturn {\n\t\t\tinvertedDetach: [ChangeInternal.insert(detach.destination, insertDestination)],\n\t\t\tdetachedNodeIds,\n\t\t};\n\t}\n\n\tconst detachedSequenceId = 0 as DetachedSequenceId;\n\treturn {\n\t\tinvertedDetach: [\n\t\t\tChangeInternal.build(\n\t\t\t\tdetachedNodeIds.map((id) => getChangeNodeFromViewNode(viewBeforeChange, id)),\n\t\t\t\tdetachedSequenceId\n\t\t\t),\n\t\t\tChangeInternal.insert(detachedSequenceId, insertDestination),\n\t\t],\n\t\tdetachedNodeIds,\n\t};\n}\n\n/**\n * The inverse of a SetValue is a SetValue that sets the value to what it was prior to the change.\n */\nfunction createInvertedSetValue(setValue: SetValueInternal, viewBeforeChange: TreeView): ChangeInternal[] | undefined {\n\tconst { nodeToModify } = setValue;\n\tconst node = viewBeforeChange.tryGetViewNode(nodeToModify);\n\tif (node === undefined) {\n\t\t// TODO:68574: With a reference view, may be able to better resolve conflicting sets\n\t\treturn undefined;\n\t}\n\n\t// Rationale: 'undefined' is reserved for future use (see 'SetValue' interface)\n\tif (node.payload !== null) {\n\t\treturn [ChangeInternal.setPayload(nodeToModify, node.payload)];\n\t}\n\treturn [ChangeInternal.clearPayload(nodeToModify)];\n}\n"]}
1
+ {"version":3,"file":"HistoryEditFactory.js","sourceRoot":"","sources":["../src/HistoryEditFactory.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 { ITelemetryLogger } from '@fluidframework/common-definitions';\nimport { DetachedSequenceId, isDetachedSequenceId, NodeId } from './Identifiers';\nimport { assert, fail } from './Common';\nimport { rangeFromStableRange } from './TreeViewUtilities';\nimport {\n\tChangeInternal,\n\tChangeTypeInternal,\n\tDetachInternal,\n\tSetValueInternal,\n\tInsertInternal,\n\tBuildNodeInternal,\n\tSide,\n\tStableRangeInternal,\n} from './persisted-types';\nimport { TransactionInternal } from './TransactionInternal';\nimport { RangeValidationResultKind, validateStableRange } from './EditUtilities';\nimport { StablePlace } from './ChangeTypes';\nimport { RevisionView } from './RevisionView';\nimport { TreeView } from './TreeView';\nimport { getChangeNodeFromViewNode } from './SerializationUtilities';\n\n/**\n * Given a sequence of changes, produces an inverse sequence of changes, i.e. the minimal changes required to revert the given changes\n * @param changes - the changes for which to produce an inverse.\n * @param before - a view of the tree state before `changes` are/were applied - used as a basis for generating the inverse.\n * @returns if the changes could be reverted, a sequence of changes _r_ that will produce `before` if applied to a view _A_, where _A_ is the result of\n * applying `changes` to `before`. Note that the size of the array of reverted changes may not be the same as the input array, and may even be empty in cases where\n * the view did not change. Applying _r_ to views other than _A_ is legal but may cause the changes to fail to apply or may not be a true semantic inverse.\n * If the changes could not be reverted given the state of `before`, returns undefined.\n *\n * TODO: what should this do if `changes` fails to apply to `before`?\n * TODO:#68574: Pass a view that corresponds to the appropriate Fluid reference sequence number rather than the view just before\n * @internal\n */\nexport function revert(\n\tchanges: readonly ChangeInternal[],\n\tbefore: RevisionView,\n\tlogger?: ITelemetryLogger\n): ChangeInternal[] | undefined {\n\tconst result: ChangeInternal[] = [];\n\n\tconst builtNodes = new Map<DetachedSequenceId, NodeId[]>();\n\tconst detachedNodes = new Map<DetachedSequenceId, NodeId[]>();\n\n\t// Open edit on revision to update it as changes are walked through\n\tconst editor = TransactionInternal.factory(before);\n\t// Apply `edit`, generating an inverse as we go.\n\tfor (const change of changes) {\n\t\t// Generate an inverse of each change\n\t\tswitch (change.type) {\n\t\t\tcase ChangeTypeInternal.Build: {\n\t\t\t\t// Save nodes added to the detached state for use in future changes\n\t\t\t\tconst { destination, source } = change;\n\t\t\t\tassert(!builtNodes.has(destination), `Cannot revert Build: destination is already used by a Build`);\n\t\t\t\tassert(!detachedNodes.has(destination), `Cannot revert Build: destination is already used by a Detach`);\n\t\t\t\tbuiltNodes.set(\n\t\t\t\t\tdestination,\n\t\t\t\t\tsource.reduce((ids: NodeId[], curr: BuildNodeInternal) => {\n\t\t\t\t\t\tif (isDetachedSequenceId(curr)) {\n\t\t\t\t\t\t\tconst nodesForDetachedSequence =\n\t\t\t\t\t\t\t\tbuiltNodes.get(curr) ?? fail('detached sequence must have associated built nodes');\n\n\t\t\t\t\t\t\tids.push(...nodesForDetachedSequence);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tids.push(curr.identifier);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ids;\n\t\t\t\t\t}, [])\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Insert: {\n\t\t\t\tconst { source } = change;\n\t\t\t\tconst nodesBuilt = builtNodes.get(source);\n\t\t\t\tconst nodesDetached = detachedNodes.get(source);\n\n\t\t\t\tif (nodesBuilt !== undefined) {\n\t\t\t\t\tif (nodesBuilt.length === 0) {\n\t\t\t\t\t\tbuiltNodes.delete(source);\n\t\t\t\t\t\tlogger?.sendTelemetryEvent({ eventName: 'reverting insertion of empty traits' });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tresult.unshift(createInvertedInsert(change, nodesBuilt));\n\t\t\t\t\tbuiltNodes.delete(source);\n\t\t\t\t} else if (nodesDetached !== undefined) {\n\t\t\t\t\tif (nodesDetached.length === 0) {\n\t\t\t\t\t\tdetachedNodes.delete(source);\n\t\t\t\t\t\tlogger?.sendTelemetryEvent({ eventName: 'reverting insertion of empty traits' });\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tresult.unshift(createInvertedInsert(change, nodesDetached, true));\n\t\t\t\t\tdetachedNodes.delete(source);\n\t\t\t\t} else {\n\t\t\t\t\t// Cannot revert an insert whose source is no longer available for inserting (i.e. not just built, and not detached)\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Detach: {\n\t\t\t\tconst { destination } = change;\n\t\t\t\tconst invert = createInvertedDetach(change, editor.view);\n\t\t\t\tif (invert === undefined) {\n\t\t\t\t\t// Cannot revert a detach whose source does not exist in the tree\n\t\t\t\t\t// TODO:68574: May not be possible once associated todo in `createInvertedDetach` is addressed\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tconst { invertedDetach, detachedNodeIds } = invert;\n\n\t\t\t\tif (detachedNodeIds.length === 0) {\n\t\t\t\t\tlogger?.sendTelemetryEvent({ eventName: 'reverting detachment of empty traits' });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (destination !== undefined) {\n\t\t\t\t\tif (builtNodes.has(destination) || detachedNodes.has(destination)) {\n\t\t\t\t\t\t// Malformed: destination was already used by a prior build or detach\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tdetachedNodes.set(destination, detachedNodeIds);\n\t\t\t\t}\n\n\t\t\t\tresult.unshift(...invertedDetach);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.SetValue: {\n\t\t\t\tconst invert = createInvertedSetValue(change, editor.view);\n\t\t\t\tif (invert === undefined) {\n\t\t\t\t\t// Cannot revert a set for a node that does not exist in the tree\n\t\t\t\t\t// TODO:68574: May not be possible once associated todo in `createInvertedSetValue` is addressed\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tresult.unshift(...invert);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ChangeTypeInternal.Constraint:\n\t\t\t\t// TODO:#46759: Support Constraint in reverts\n\t\t\t\tfail('Revert currently does not support Constraints');\n\t\t\tdefault:\n\t\t\t\tfail('Revert does not support the change type.');\n\t\t}\n\n\t\t// Update the revision\n\t\teditor.applyChange(change);\n\t}\n\n\teditor.close();\n\treturn result;\n}\n\n/**\n * The inverse of an Insert is a Detach that starts before the leftmost node inserted and ends after the rightmost.\n */\nfunction createInvertedInsert(\n\tinsert: InsertInternal,\n\tnodesInserted: readonly NodeId[],\n\tsaveDetached = false\n): ChangeInternal {\n\tconst leftmostNode = nodesInserted[0];\n\tconst rightmostNode = nodesInserted[nodesInserted.length - 1];\n\n\tconst source: StableRangeInternal = {\n\t\tstart: {\n\t\t\treferenceSibling: leftmostNode,\n\t\t\tside: Side.Before,\n\t\t},\n\t\tend: {\n\t\t\treferenceSibling: rightmostNode,\n\t\t\tside: Side.After,\n\t\t},\n\t};\n\n\treturn ChangeInternal.detach(source, saveDetached ? insert.source : undefined);\n}\n\n/**\n * If a detach does not include a destination, its inverse is a build and insert. Otherwise, it is just an insert.\n * Information on the nodes that were detached is obtained by going to the revision before the detach.\n *\n * The anchor for the resulting Insert is chosen in the following order:\n *\n * ```markdown\n * 1. If detach.source.start.side is After: detach.source.start\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"After B\", the anchor for the resulting Insert will also be \"After B\".\n *\n * For nodes [A..F] G H where [A..F] represents the detached nodes,\n * if detach.source.start is \"After start of trait\", the anchor for the resulting Insert will also be\n * \"After start of trait\".\n *\n * 2. Else if detach.source.end.side is Before: detach.source.end\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"Before C\" and detach.source.end is \"Before G\",\n * the anchor for the resulting Insert will be \"Before G\".\n *\n * 3. Else: After the node directly to the left of the originally detached nodes\n *\n * ex: For nodes A B [C..F] G H where [C..F] represents the detached nodes,\n * if detach.source.start is \"Before C\" and detach.source.end is \"After F\",\n * the anchor for the resulting Insert will be \"After B\".\n * ```\n *\n * When choosing the anchor, the existing anchors on detach.source are preferred when they have a valid sibling.\n * Otherwise, the valid anchor to the left of the originally detached nodes is chosen.\n */\nfunction createInvertedDetach(\n\tdetach: DetachInternal,\n\tviewBeforeChange: TreeView\n): { invertedDetach: ChangeInternal[]; detachedNodeIds: NodeId[] } | undefined {\n\tconst validatedSource = validateStableRange(viewBeforeChange, detach.source);\n\tif (validatedSource.result !== RangeValidationResultKind.Valid) {\n\t\t// TODO:#68574: having the reference view would potentially allow us to revert some detaches that currently conflict\n\t\treturn undefined;\n\t}\n\n\tconst { start, end } = rangeFromStableRange(viewBeforeChange, validatedSource);\n\tconst { trait: referenceTrait } = start;\n\tconst nodes = viewBeforeChange.getTrait(referenceTrait);\n\n\tconst startIndex = viewBeforeChange.findIndexWithinTrait(start);\n\tconst endIndex = viewBeforeChange.findIndexWithinTrait(end);\n\tconst detachedNodeIds: NodeId[] = nodes.slice(startIndex, endIndex);\n\n\tconst leftOfDetached = nodes.slice(0, startIndex);\n\n\tlet insertDestination: StablePlace;\n\n\tif (start.side === Side.After) {\n\t\tinsertDestination =\n\t\t\tstart.sibling === undefined\n\t\t\t\t? { side: Side.After, referenceTrait }\n\t\t\t\t: { side: Side.After, referenceSibling: start.sibling };\n\t} else if (end.side === Side.Before) {\n\t\tinsertDestination =\n\t\t\tend.sibling === undefined\n\t\t\t\t? { side: Side.Before, referenceTrait }\n\t\t\t\t: { side: Side.Before, referenceSibling: end.sibling };\n\t} else {\n\t\tconst referenceSibling = leftOfDetached.pop();\n\t\tinsertDestination = {\n\t\t\tside: Side.After,\n\t\t\treferenceSibling,\n\t\t\treferenceTrait: referenceSibling === undefined ? referenceTrait : undefined,\n\t\t};\n\t}\n\n\tif (detach.destination !== undefined) {\n\t\treturn {\n\t\t\tinvertedDetach: [ChangeInternal.insert(detach.destination, insertDestination)],\n\t\t\tdetachedNodeIds,\n\t\t};\n\t}\n\n\tconst detachedSequenceId = 0 as DetachedSequenceId;\n\treturn {\n\t\tinvertedDetach: [\n\t\t\tChangeInternal.build(\n\t\t\t\tdetachedNodeIds.map((id) => getChangeNodeFromViewNode(viewBeforeChange, id)),\n\t\t\t\tdetachedSequenceId\n\t\t\t),\n\t\t\tChangeInternal.insert(detachedSequenceId, insertDestination),\n\t\t],\n\t\tdetachedNodeIds,\n\t};\n}\n\n/**\n * The inverse of a SetValue is a SetValue that sets the value to what it was prior to the change.\n */\nfunction createInvertedSetValue(setValue: SetValueInternal, viewBeforeChange: TreeView): ChangeInternal[] | undefined {\n\tconst { nodeToModify } = setValue;\n\tconst node = viewBeforeChange.tryGetViewNode(nodeToModify);\n\tif (node === undefined) {\n\t\t// TODO:68574: With a reference view, may be able to better resolve conflicting sets\n\t\treturn undefined;\n\t}\n\n\t// Rationale: 'undefined' is reserved for future use (see 'SetValue' interface)\n\tif (node.payload !== null) {\n\t\treturn [ChangeInternal.setPayload(nodeToModify, node.payload)];\n\t}\n\treturn [ChangeInternal.clearPayload(nodeToModify)];\n}\n"]}
@@ -133,9 +133,12 @@ export interface LogViewer {
133
133
  * Returns the `TreeView` output associated with the largest revision in `editLog` less than (but not equal to) the supplied revision.
134
134
  *
135
135
  * For example:
136
- * - revision 0 returns the initialRevision.
137
- * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).
138
- * - revision Number.POSITIVE_INFINITY returns the newest revision.
136
+ *
137
+ * - revision 0 returns the initialRevision.
138
+ *
139
+ * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).
140
+ *
141
+ * - revision Number.POSITIVE_INFINITY returns the newest revision.
139
142
  */
140
143
  getRevisionView(revision: Revision): Promise<RevisionView>;
141
144
  /**
@@ -143,9 +146,12 @@ export interface LogViewer {
143
146
  * Can only be used to retrieve revisions added during the current sessions.
144
147
  *
145
148
  * For example:
146
- * - revision 0 returns the initialRevision.
147
- * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).
148
- * - revision Number.POSITIVE_INFINITY returns the newest revision.
149
+ *
150
+ * - revision 0 returns the initialRevision.
151
+ *
152
+ * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).
153
+ *
154
+ * - revision Number.POSITIVE_INFINITY returns the newest revision.
149
155
  */
150
156
  getRevisionViewInSession(revision: Revision): RevisionView;
151
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LogViewer.d.ts","sourceRoot":"","sources":["../src/LogViewer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LogViewer.d.ts","sourceRoot":"","sources":["../src/LogViewer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LogViewer.js","sourceRoot":"","sources":["../src/LogViewer.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 Denque from 'denque';\nimport { assert, fail, noop } from './Common';\nimport { EditLog, SequencedOrderedEditId } from './EditLog';\nimport { EditId } from './Identifiers';\nimport { Revision, RevisionValueCache } from './RevisionValueCache';\nimport { ReconciliationChange, ReconciliationEdit, ReconciliationPath } from './ReconciliationPath';\nimport { ChangeInternal, Edit, EditStatus } from './persisted-types';\nimport { RevisionView } from './RevisionView';\nimport { EditingResult, TransactionInternal } from './TransactionInternal';\n\n/**\n * Callback for when an edit is applied (meaning the result of applying it to a particular revision is computed).\n *\n * Edits may be applied any time a TreeView is computed that includes them.\n * Depending on the caching policy of the LogViewer, a given edit may or may not be applied in order to compute a TreeView containing it.\n *\n * If the same edit occurs in different contexts (ex: a local edit is adjusted for a new remote edit),\n * that it will be reapplied, and this may result in different results.\n *\n * Edits may additionally be reapplied at other times since their previous output might not be cached.\n *\n * If an application requests the current view, this will force all edits to be applied.\n * Such an application can use this callback can be log each edit as it comes it to see its status,\n * however this may include duplicates, as well as entries for reapplications in modified contexts.\n *\n * In the context of this callback,\n * skipping the first evaluation of an edit in a particular context due to setKnownEditingResult is still considered applying.\n * To use this call back to track when the actual computational work of applying edits is done, only count cases when `wasCached` is false.\n */\nexport type EditStatusCallback = (editResult: EditStatus, editId: EditId, wasCached: boolean) => void;\n\n/**\n * Callback for when a sequenced edit is applied.\n * This includes local edits though the callback is only invoked once the sequenced version is received.\n *\n * For edits that were local (see {@link SequencedEditResult.wasLocal}, this callback will only be called once.\n * For non-local edits, it may be called multiple times: the number of calls and when they occur depends on caching and is an implementation\n * detail.\n */\nexport type SequencedEditResultCallback = (args: SequencedEditResult) => void;\n\n/**\n * The relevant information pertaining to the application of a sequenced edit.\n */\nexport interface SequencedEditResult {\n\t/**\n\t * The edit that was applied.\n\t */\n\tedit: Edit<ChangeInternal>;\n\t/**\n\t * true iff the edit was local.\n\t */\n\twasLocal: boolean;\n\t/**\n\t * The result of applying the edit.\n\t */\n\tresult: AttemptedEditResultCacheEntry;\n\t/**\n\t * The reconciliation path for the edit.\n\t */\n\treconciliationPath: ReconciliationPath;\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit.\n */\nexport type EditCacheEntry = SuccessfulEditCacheEntry | UnsuccessfulEditCacheEntry | SummarizedEditResultCacheEntry;\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has attempted to apply locally.\n */\nexport type AttemptedEditResultCacheEntry = SuccessfulEditCacheEntry | UnsuccessfulEditCacheEntry;\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has successfully applied locally.\n */\nexport interface SuccessfulEditCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * The status code for the edit that produced the revision.\n\t */\n\treadonly status: EditStatus.Applied;\n\t/**\n\t * The resolved changes that were applied during the edit and their associated outcome.\n\t */\n\treadonly steps: readonly ReconciliationChange[];\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has unsuccessfully attempted to apply locally.\n */\nexport interface UnsuccessfulEditCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * The status code for the edit that produced the revision.\n\t */\n\treadonly status: EditStatus.Invalid | EditStatus.Malformed;\n\t/**\n\t * Information about the failure encountered by the edit\n\t */\n\treadonly failure: TransactionInternal.Failure;\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has retrieved from a summary.\n * TODO:#57176: once summarized edits carry enough information remove this interface and use `AttemptedEditResultCacheEntry` instead.\n */\nexport interface SummarizedEditResultCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * Not specified on `SummarizedEditResultCacheEntry`.\n\t * Declared to allow checking `entry.status` against undefined.\n\t */\n\treadonly status?: never;\n}\n\nexport type CachedEditingResult = AttemptedEditResultCacheEntry & {\n\t/**\n\t * Unique identifier for this edit. Must never be reused.\n\t * Used for referencing and de-duplicating edits.\n\t */\n\treadonly id: EditId;\n\treadonly before: RevisionView;\n\treadonly changes: readonly ChangeInternal[];\n};\n\n/**\n * Creates `RevisionView`s for the revisions in an `EditLog`\n */\nexport interface LogViewer {\n\t/**\n\t * Returns the `TreeView` output associated with the largest revision in `editLog` less than (but not equal to) the supplied revision.\n\t *\n\t * For example:\n\t * - revision 0 returns the initialRevision.\n\t * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).\n\t * - revision Number.POSITIVE_INFINITY returns the newest revision.\n\t */\n\tgetRevisionView(revision: Revision): Promise<RevisionView>;\n\n\t/**\n\t * Returns the `TreeView` output associated with the largest revision in `editLog` less than (but not equal to) the supplied revision.\n\t * Can only be used to retrieve revisions added during the current sessions.\n\t *\n\t * For example:\n\t * - revision 0 returns the initialRevision.\n\t * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).\n\t * - revision Number.POSITIVE_INFINITY returns the newest revision.\n\t */\n\tgetRevisionViewInSession(revision: Revision): RevisionView;\n}\n\n/**\n * Creates views for revisions associated with an EditLog and caches the results.\n *\n * Does so by listening for edits added to the log. If the underlying EditLog or its listeners need to be reused beyond the lifetime of\n * a CachingLogViewer instance, that instance should be disposed with `detachFromEditLog` to ensure it is garbage-collectable.\n * @internal\n */\nexport class CachingLogViewer implements LogViewer {\n\tpublic readonly log: EditLog<ChangeInternal>;\n\n\t/**\n\t * Maximum size of the sequenced revision cache.\n\t */\n\tpublic static readonly sequencedCacheSizeMax = 50;\n\n\t/**\n\t * A cache for local revisions.\n\t * It is invalidated whenever a new sequenced edit (that was not already a local edit) is added to the log.\n\t * When a previously local edit is sequenced, this cache is adjusted to account for it, not invalidated.\n\t */\n\tprivate readonly localRevisionCache = new Denque<AttemptedEditResultCacheEntry>();\n\n\t/**\n\t * Cache of sequenced revisions.\n\t */\n\tprivate readonly sequencedRevisionCache: RevisionValueCache<EditCacheEntry>;\n\n\t/**\n\t * Called whenever a sequenced edit is applied.\n\t * This will have been called at least once for any edit if a revision after than edit has been requested.\n\t * It may be called multiple times: the number of calls and when they occur depends on caching and is an implementation detail.\n\t */\n\tprivate readonly processSequencedEditResult: SequencedEditResultCallback;\n\n\t/**\n\t * Called whenever an edit is processed.\n\t * This will have been called at least once for any edit if a revision after than edit has been requested.\n\t * It may be called multiple times: the number of calls and when they occur depends on caching and is an implementation detail.\n\t */\n\tprivate readonly processEditStatus: EditStatusCallback;\n\n\t/**\n\t * The ordered queue of edits that originated from this client that have never been applied (by this log viewer) in a sequenced state.\n\t * This means these edits may be local or sequenced, and may have been applied (possibly multiple times) while still local.\n\t * Used to log telemetry about the result of edit application. Edits are removed when first applied after being sequenced.\n\t */\n\tprivate readonly unappliedSelfEdits = new Denque<EditId>();\n\n\t/**\n\t * Cache of applying a edit.\n\t * Due to use of Transactions in checkouts, a common pattern involves applying an edit\n\t * as part of the transaction, then submitting it.\n\t * This cache helps optimize that case by avoiding recomputing the edit if no other edits were added during the transaction.\n\t */\n\tprivate cachedEditResult?: { editId: EditId; result: EditingResult };\n\n\t/**\n\t * Cache entry for the highest revision.\n\t * `undefined` when not cached.\n\t */\n\tprivate highestRevisionCacheEntry?: EditCacheEntry;\n\n\t/**\n\t * Removes this log viewer from the set of handleEditAdded listeners on its underlying log.\n\t * This should be called if the underlying log or its listeners are re-used past the lifetime of this log viewer.\n\t */\n\tpublic readonly detachFromEditLog: () => void;\n\n\t/**\n\t * @returns true if the highest revision is cached.\n\t */\n\tpublic highestRevisionCached(): boolean {\n\t\treturn this.highestRevisionCacheEntry !== undefined;\n\t}\n\n\t/**\n\t * Create a new LogViewer\n\t * @param log - the edit log which revisions will be based on.\n\t * @param baseTree - the tree used in the view corresponding to the 0th revision.\n\t * @param knownRevisions - a set of [sequencedRevision, view] pairs that are known (have been precomputed) at construction time.\n\t * These revisions are guaranteed to never be evicted from the cache.\n\t * @param expensiveValidation - Iff true, additional correctness assertions will be run during LogViewer operations.\n\t * @param processEditStatus - called after applying an edit.\n\t * @param processSequencedEditResult - called after applying a sequenced edit.\n\t */\n\tpublic constructor(\n\t\tlog: EditLog<ChangeInternal>,\n\t\tbaseView: RevisionView,\n\t\tknownRevisions: [Revision, EditCacheEntry][] = [],\n\t\tprocessEditStatus: EditStatusCallback = noop,\n\t\tprocessSequencedEditResult: SequencedEditResultCallback = noop,\n\t\tminimumSequenceNumber = 0\n\t) {\n\t\tthis.log = log;\n\t\tknownRevisions.forEach(([revision]) => {\n\t\t\tassert(Number.isInteger(revision), 'revision must be an integer');\n\t\t\tassert(this.log.isSequencedRevision(revision), 'revision must correspond to the result of a SequencedEdit');\n\t\t});\n\n\t\tthis.sequencedRevisionCache = new RevisionValueCache(\n\t\t\tCachingLogViewer.sequencedCacheSizeMax,\n\t\t\tminimumSequenceNumber,\n\t\t\t[...knownRevisions, [0, { view: baseView }]]\n\t\t);\n\t\tthis.processEditStatus = processEditStatus ?? noop;\n\t\tthis.processSequencedEditResult = processSequencedEditResult ?? noop;\n\t\tthis.detachFromEditLog = this.log.registerEditAddedHandler(this.handleEditAdded.bind(this));\n\t}\n\n\t/**\n\t * As a performance optimization, this method caches views generated by local edits if they are sequenced without\n\t * being interleaved with remote edits.\n\t */\n\tprivate handleEditAdded(edit: Edit<ChangeInternal>, isLocal: boolean, wasLocal: boolean): void {\n\t\t// Clear highestRevisionCacheEntry, since what revision is highest might change.\n\t\t// Note that as an optimization we could skip clearing this when a local edit is sequenced.\n\t\tthis.highestRevisionCacheEntry = undefined;\n\n\t\tif (isLocal) {\n\t\t\tthis.unappliedSelfEdits.push(edit.id);\n\t\t} else if (wasLocal) {\n\t\t\t// If the new sequenced edit was generated by this client, the corresponding cache entry (if there is one)\n\t\t\t// will be at the front of the queue. If the queue is empty, then a concurrent sequenced edit from remote client\n\t\t\t// must have invalidated the queue cache.\n\t\t\tconst entry = this.localRevisionCache.shift();\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst revision = this.log.numberOfSequencedEdits;\n\t\t\t\tconst { view } = entry;\n\t\t\t\tthis.sequencedRevisionCache.cacheValue(\n\t\t\t\t\trevision,\n\t\t\t\t\tentry.status === EditStatus.Applied\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tview,\n\t\t\t\t\t\t\t\tstatus: entry.status,\n\t\t\t\t\t\t\t\tsteps: entry.steps,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tview,\n\t\t\t\t\t\t\t\tstatus: entry.status,\n\t\t\t\t\t\t\t\tfailure: entry.failure,\n\t\t\t\t\t\t }\n\t\t\t\t);\n\t\t\t\tthis.handleSequencedEditResult(edit, entry, []);\n\t\t\t}\n\t\t} else {\n\t\t\t// Invalidate any cached results of applying edits which are ordered after `edit` (which are all remaining local edits)\n\t\t\tthis.localRevisionCache.clear();\n\t\t}\n\t}\n\n\tpublic async getEditResult(revision: Revision): Promise<EditCacheEntry> {\n\t\tconst startingPoint = this.getStartingPoint(revision);\n\t\tconst { startRevision } = startingPoint;\n\t\tlet current: EditCacheEntry = startingPoint;\n\t\tfor (let i = startRevision; i < revision && i < this.log.length; i++) {\n\t\t\tconst edit = await this.log.getEditAtIndex(i);\n\t\t\tcurrent = this.applyEdit(current.view, edit, i);\n\t\t}\n\t\treturn current;\n\t}\n\n\tpublic async getRevisionView(revision: Revision): Promise<RevisionView> {\n\t\treturn (await this.getEditResult(revision)).view;\n\t}\n\n\tpublic getEditResultInSession(revision: Revision): EditCacheEntry {\n\t\tconst startingPoint = this.getStartingPoint(revision);\n\t\tconst { startRevision } = startingPoint;\n\t\tlet current: EditCacheEntry = startingPoint;\n\t\tfor (let i = startRevision; i < revision && i < this.log.length; i++) {\n\t\t\tconst edit = this.log.getEditInSessionAtIndex(i);\n\t\t\tcurrent = this.applyEdit(current.view, edit, i);\n\t\t}\n\t\treturn current;\n\t}\n\n\tpublic getRevisionViewInSession(revision: Revision): RevisionView {\n\t\treturn this.getEditResultInSession(revision).view;\n\t}\n\n\t/**\n\t * Informs the CachingLogViewer of the latest known minimumSequenceNumber for all connected clients.\n\t * This can be used to provide more aggressive caching of revisions within the collaboration window, as those revisions\n\t * are more likely to be demanded to resolve conflicts.\n\t * @param minSequenceNumber - the minimum known sequence number of all connected clients.\n\t */\n\tpublic setMinimumSequenceNumber(minimumSequenceNumber: number): void {\n\t\t// Sequence numbers in Fluid are 1-indexed, meaning they correspond to revisions, and can be used as revisions.\n\t\t// This ensures that all revisions >= minimumSequenceNumber are kept in the cache, meaning that even if all clients are caught up\n\t\t// the most recent sequenced revision will be cached.\n\t\tthis.sequencedRevisionCache.updateRetentionWindow(minimumSequenceNumber);\n\t}\n\n\t/**\n\t * Inform the CachingLogViewer that a particular edit is known to have a specific result when applied to a particular TreeView.\n\t * CachingLogViewer may use this information as an optimization to avoid re-running the edit if re-applied to the same TreeView.\n\t */\n\tpublic setKnownEditingResult(edit: Edit<ChangeInternal>, result: EditingResult): void {\n\t\tthis.cachedEditResult = { editId: edit.id, result };\n\t}\n\n\t/**\n\t * @returns the cached revision view closest to the requested `revision`.\n\t */\n\tprivate getStartingPoint(revision: Revision): { startRevision: Revision } & EditCacheEntry {\n\t\t// Per the documentation for revision, the returned view should be the output of the edit at the largest index <= `revision`.\n\t\tconst revisionClamped = Math.min(revision, this.log.length);\n\n\t\t// If the highest revision is requested, and it's cached, use highestRevisionCacheEntry.\n\t\tif (revisionClamped === this.log.length && this.highestRevisionCacheEntry !== undefined) {\n\t\t\treturn { ...this.highestRevisionCacheEntry, startRevision: revisionClamped };\n\t\t}\n\n\t\tlet current: EditCacheEntry;\n\t\tlet startRevision: Revision;\n\t\tconst { numberOfSequencedEdits } = this.log;\n\t\tconst isLocalRevision = revisionClamped > numberOfSequencedEdits;\n\t\tif (isLocalRevision && !this.localRevisionCache.isEmpty()) {\n\t\t\tconst { length } = this.localRevisionCache;\n\t\t\t// Local revision view cache is indexed such that the view for revision 0 (a local edit) is stored at index 0 in the cache.\n\t\t\t// This is because the local cache does not contain an entry for the implicit initial tree edit.\n\t\t\tconst localCacheIndex = revisionClamped - 1 - numberOfSequencedEdits;\n\t\t\tif (localCacheIndex < length) {\n\t\t\t\tconst cached =\n\t\t\t\t\tthis.localRevisionCache.peekAt(localCacheIndex) ?? fail('missing tail of localRevisionViewCache');\n\t\t\t\treturn {\n\t\t\t\t\t...cached,\n\t\t\t\t\tstartRevision: revisionClamped,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tcurrent = this.localRevisionCache.peekAt(length - 1) ?? fail('missing tail of localRevisionViewCache');\n\t\t\t\tstartRevision = numberOfSequencedEdits + length;\n\t\t\t}\n\t\t} else {\n\t\t\tconst [cachedRevision, cachedView] =\n\t\t\t\tthis.sequencedRevisionCache.getClosestEntry(revisionClamped) ??\n\t\t\t\tfail('No preceding revision view cached.');\n\n\t\t\tstartRevision = cachedRevision;\n\t\t\tcurrent = cachedView;\n\t\t}\n\t\treturn { startRevision, ...current };\n\t}\n\n\t/**\n\t * Helper for applying an edit at the supplied revision view.\n\t * Must only be called in the order that edits appear in the log.\n\t * Must only be called once for a given local edit as long as the local cache has not been invalidated.\n\t * Must only be called once for a given sequenced edit.\n\t * @returns the resulting revision view and the outcome of edit that produced it.\n\t */\n\tprivate applyEdit(\n\t\tprevView: RevisionView,\n\t\tedit: Edit<ChangeInternal>,\n\t\teditIndex: number\n\t): AttemptedEditResultCacheEntry {\n\t\tlet editingResult: EditingResult;\n\t\tlet cached;\n\t\tlet reconciliationPath: ReconciliationPath = [];\n\t\tif (\n\t\t\tthis.cachedEditResult !== undefined &&\n\t\t\tthis.cachedEditResult.editId === edit.id &&\n\t\t\tthis.cachedEditResult.result.before === prevView\n\t\t) {\n\t\t\teditingResult = this.cachedEditResult.result;\n\t\t\tcached = true;\n\t\t} else {\n\t\t\treconciliationPath = this.reconciliationPathFromEdit(edit.id);\n\t\t\teditingResult = TransactionInternal.factory(prevView)\n\t\t\t\t.applyChanges(edit.changes, reconciliationPath)\n\t\t\t\t.close();\n\t\t\tcached = false;\n\t\t}\n\n\t\tconst revision = editIndex + 1;\n\t\tconst nextView: RevisionView = editingResult.status === EditStatus.Applied ? editingResult.after : prevView;\n\n\t\tconst computedCacheEntry =\n\t\t\teditingResult.status === EditStatus.Applied\n\t\t\t\t? { view: nextView, status: editingResult.status, steps: editingResult.steps }\n\t\t\t\t: { view: nextView, status: editingResult.status, failure: editingResult.failure };\n\n\t\tif (this.log.isSequencedRevision(revision)) {\n\t\t\tthis.sequencedRevisionCache.cacheValue(revision, computedCacheEntry);\n\t\t\tthis.handleSequencedEditResult(edit, computedCacheEntry, reconciliationPath);\n\t\t} else {\n\t\t\t// This relies on local edits being append only, and that generating the view for a local revision requires generating\n\t\t\t// the views for all local revisions before it in the log. Thus, generating such a view will necessarily require\n\t\t\t// calls to this method for all local revisions prior, guaranteeing the correct push order.\n\t\t\tassert(\n\t\t\t\trevision === this.log.numberOfSequencedEdits + this.localRevisionCache.length + 1,\n\t\t\t\t'Local revision view cached out of order.'\n\t\t\t);\n\t\t\tthis.localRevisionCache.push(computedCacheEntry);\n\t\t}\n\n\t\t// Only update highestRevisionCacheEntry if this snapshot is the highest revision.\n\t\tif (revision >= this.log.length) {\n\t\t\tthis.highestRevisionCacheEntry = computedCacheEntry;\n\t\t}\n\n\t\tthis.processEditStatus(editingResult.status, this.log.getIdAtIndex(editIndex), cached);\n\t\treturn computedCacheEntry;\n\t}\n\n\t/**\n\t * Helper for performing caching when a sequenced local edit is first applied.\n\t * Invokes the `processSequencedEditResult` handler that was passed to the constructor (if any).\n\t * Must only be called for non-cached sequenced edits.\n\t */\n\tprivate handleSequencedEditResult(\n\t\tedit: Edit<ChangeInternal>,\n\t\tresult: AttemptedEditResultCacheEntry,\n\t\treconciliationPath: ReconciliationPath\n\t): void {\n\t\tlet wasLocal = false;\n\t\t// This is the first time this sequenced edit has been processed by this LogViewer. If it was a local edit, log telemetry\n\t\t// in the event that it was invalid or malformed.\n\t\tif (this.unappliedSelfEdits.length > 0) {\n\t\t\tif (edit.id === this.unappliedSelfEdits.peekFront()) {\n\t\t\t\twasLocal = true;\n\t\t\t\tthis.unappliedSelfEdits.shift();\n\t\t\t}\n\t\t}\n\t\tthis.processSequencedEditResult({ edit, wasLocal, result, reconciliationPath });\n\t}\n\n\t/**\n\t * We currently compute only the \"main branch\" part of the reconciliation path (meaning we don't include inverts of the edits\n\t * that occurred on the rebased branch). Doing so is only needed for the sequential anchor resolution approach which is not\n\t * yet supported.\n\t * @param editId - The ID for the edit to get the reconciliation path for.\n\t */\n\tpublic reconciliationPathFromEdit(editId: EditId): ReconciliationPath {\n\t\tconst reconciliationPath: ReconciliationEdit[] = [];\n\t\tlet cached = false;\n\t\treturn new Proxy(reconciliationPath, {\n\t\t\tget: (target, prop): unknown => {\n\t\t\t\tif (!cached) {\n\t\t\t\t\tcached = true;\n\t\t\t\t\tconst orderedId = this.log.getOrderedEditId(editId);\n\t\t\t\t\tif (orderedId.isLocal === false && orderedId.sequenceInfo !== undefined) {\n\t\t\t\t\t\tconst earliestSequenced = this.earliestSequencedEditInSession();\n\t\t\t\t\t\tif (earliestSequenced !== undefined) {\n\t\t\t\t\t\t\tconst earliestEditSequenceNumber = earliestSequenced.sequenceNumber;\n\t\t\t\t\t\t\tconst targetSequenceNumber = Math.max(\n\t\t\t\t\t\t\t\tearliestEditSequenceNumber,\n\t\t\t\t\t\t\t\torderedId.sequenceInfo.referenceSequenceNumber\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (targetSequenceNumber < orderedId.sequenceInfo.sequenceNumber) {\n\t\t\t\t\t\t\t\tconst firstEdit = this.getEditResultFromSequenceNumber(targetSequenceNumber);\n\t\t\t\t\t\t\t\tif (firstEdit !== undefined) {\n\t\t\t\t\t\t\t\t\tif (firstEdit.status === EditStatus.Applied) {\n\t\t\t\t\t\t\t\t\t\tconst firstEditInfo = this.log.getOrderedEditId(\n\t\t\t\t\t\t\t\t\t\t\tfirstEdit.id\n\t\t\t\t\t\t\t\t\t\t) as SequencedOrderedEditId;\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\tfirstEditInfo.sequenceInfo !== undefined &&\n\t\t\t\t\t\t\t\t\t\t\tfirstEditInfo.sequenceInfo.sequenceNumber >\n\t\t\t\t\t\t\t\t\t\t\t\torderedId.sequenceInfo.referenceSequenceNumber\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\treconciliationPath.push({\n\t\t\t\t\t\t\t\t\t\t\t\t...firstEdit.steps,\n\t\t\t\t\t\t\t\t\t\t\t\tbefore: firstEdit.before,\n\t\t\t\t\t\t\t\t\t\t\t\tafter: firstEdit.view,\n\t\t\t\t\t\t\t\t\t\t\t\tlength: firstEdit.steps.length,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst lowestIndex = this.log.getIndexOfId(firstEdit.id) + 1;\n\t\t\t\t\t\t\t\t\tconst highestIndex = this.log.getIndexOfId(editId) - 1;\n\t\t\t\t\t\t\t\t\tfor (let index = lowestIndex; index <= highestIndex; ++index) {\n\t\t\t\t\t\t\t\t\t\tconst edit = this.getEditResultFromIndex(index);\n\t\t\t\t\t\t\t\t\t\tif (edit.status === EditStatus.Applied) {\n\t\t\t\t\t\t\t\t\t\t\treconciliationPath.push({\n\t\t\t\t\t\t\t\t\t\t\t\t...edit.steps,\n\t\t\t\t\t\t\t\t\t\t\t\tbefore: edit.before,\n\t\t\t\t\t\t\t\t\t\t\t\tafter: edit.view,\n\t\t\t\t\t\t\t\t\t\t\t\tlength: edit.steps.length,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop];\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * @returns Edit information for the earliest known sequenced edit.\n\t */\n\tpublic earliestSequencedEditInSession(): { edit: Edit<ChangeInternal>; sequenceNumber: number } | undefined {\n\t\tconst earliestEditIndex = this.log.earliestAvailableEditIndex;\n\t\tconst lastSequencedEdit = this.log.numberOfSequencedEdits + earliestEditIndex - 1;\n\t\tfor (let index = earliestEditIndex; index <= lastSequencedEdit; ++index) {\n\t\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\t\tconst editOrderedId = this.log.getOrderedEditId(edit.id) as SequencedOrderedEditId;\n\t\t\tif (editOrderedId.sequenceInfo !== undefined) {\n\t\t\t\treturn { edit, sequenceNumber: editOrderedId.sequenceInfo.sequenceNumber };\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * @returns Edit result information for the edit at the given `index`.\n\t */\n\tprivate getEditResultFromIndex(index: number): CachedEditingResult {\n\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\tconst before = this.getRevisionViewInSession(index);\n\t\tconst resultAfter = this.getEditResultInSession(index + 1);\n\t\tif (resultAfter.status === undefined) {\n\t\t\tfail('The status of every edit in session should be known');\n\t\t}\n\t\treturn resultAfter.status === EditStatus.Applied\n\t\t\t? {\n\t\t\t\t\tid: edit.id,\n\t\t\t\t\tstatus: EditStatus.Applied,\n\t\t\t\t\tbefore,\n\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\tsteps: resultAfter.steps,\n\t\t\t }\n\t\t\t: {\n\t\t\t\t\tid: edit.id,\n\t\t\t\t\tstatus: resultAfter.status,\n\t\t\t\t\tfailure: resultAfter.failure,\n\t\t\t\t\tbefore,\n\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\tchanges: edit.changes,\n\t\t\t };\n\t}\n\n\t/**\n\t * @param sequenceNumber - The server-assigned sequenced number assigned to the edit of interest.\n\t * @returns Edit result information for the edit with the given sequence number or the nearest sequenced edit before that.\n\t * Undefined if no sequenced edit occurred at or prior to the given sequenceNumber.\n\t */\n\tpublic getEditResultFromSequenceNumber(sequenceNumber: number): CachedEditingResult | undefined {\n\t\tconst earliestSequenced = this.earliestSequencedEditInSession();\n\t\tif (earliestSequenced !== undefined && sequenceNumber >= earliestSequenced.sequenceNumber) {\n\t\t\tconst lowestIndex = this.log.getIndexOfId(earliestSequenced.edit.id);\n\t\t\tconst highestIndex = this.log.numberOfSequencedEdits - 1;\n\t\t\tfor (let index = highestIndex; index >= lowestIndex; --index) {\n\t\t\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\t\t\tconst orderedId = this.log.getOrderedEditId(edit.id) as SequencedOrderedEditId;\n\t\t\t\t// If `orderedId.sequenceInfo.sequenceNumber` is equal to the requested `sequenceNumber` then we have found the edit of\n\t\t\t\t// interest and simply return its associated information.\n\t\t\t\t// Note that the check bellow also is also satisfied if `orderedId.sequenceInfo.sequenceNumber`is lower than the requested\n\t\t\t\t// `sequenceNumber`. This can happen when the edit for the requested `sequenceNumber` has either not yet been received or\n\t\t\t\t// has been processed by a different DDS (several DDSes can share the same stream of operations and will only see those\n\t\t\t\t// relevant to them). In such cases, we return the edit info for the last known edit before that.\n\t\t\t\tif (orderedId.sequenceInfo && orderedId.sequenceInfo.sequenceNumber <= sequenceNumber) {\n\t\t\t\t\tconst before = this.getRevisionViewInSession(index);\n\t\t\t\t\tconst resultAfter = this.getEditResultInSession(index + 1);\n\t\t\t\t\tif (resultAfter.status === undefined) {\n\t\t\t\t\t\tfail('The status of every edit in session should be known');\n\t\t\t\t\t}\n\t\t\t\t\treturn resultAfter.status === EditStatus.Applied\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: edit.id,\n\t\t\t\t\t\t\t\tstatus: EditStatus.Applied,\n\t\t\t\t\t\t\t\tbefore,\n\t\t\t\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\t\t\t\tsteps: resultAfter.steps,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tid: edit.id,\n\t\t\t\t\t\t\t\tstatus: resultAfter.status,\n\t\t\t\t\t\t\t\tfailure: resultAfter.failure,\n\t\t\t\t\t\t\t\tbefore,\n\t\t\t\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\t\t };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"LogViewer.js","sourceRoot":"","sources":["../src/LogViewer.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 Denque from 'denque';\nimport { assert, fail, noop } from './Common';\nimport { EditLog, SequencedOrderedEditId } from './EditLog';\nimport { EditId } from './Identifiers';\nimport { Revision, RevisionValueCache } from './RevisionValueCache';\nimport { ReconciliationChange, ReconciliationEdit, ReconciliationPath } from './ReconciliationPath';\nimport { ChangeInternal, Edit, EditStatus } from './persisted-types';\nimport { RevisionView } from './RevisionView';\nimport { EditingResult, TransactionInternal } from './TransactionInternal';\n\n/**\n * Callback for when an edit is applied (meaning the result of applying it to a particular revision is computed).\n *\n * Edits may be applied any time a TreeView is computed that includes them.\n * Depending on the caching policy of the LogViewer, a given edit may or may not be applied in order to compute a TreeView containing it.\n *\n * If the same edit occurs in different contexts (ex: a local edit is adjusted for a new remote edit),\n * that it will be reapplied, and this may result in different results.\n *\n * Edits may additionally be reapplied at other times since their previous output might not be cached.\n *\n * If an application requests the current view, this will force all edits to be applied.\n * Such an application can use this callback can be log each edit as it comes it to see its status,\n * however this may include duplicates, as well as entries for reapplications in modified contexts.\n *\n * In the context of this callback,\n * skipping the first evaluation of an edit in a particular context due to setKnownEditingResult is still considered applying.\n * To use this call back to track when the actual computational work of applying edits is done, only count cases when `wasCached` is false.\n */\nexport type EditStatusCallback = (editResult: EditStatus, editId: EditId, wasCached: boolean) => void;\n\n/**\n * Callback for when a sequenced edit is applied.\n * This includes local edits though the callback is only invoked once the sequenced version is received.\n *\n * For edits that were local (see {@link SequencedEditResult.wasLocal}, this callback will only be called once.\n * For non-local edits, it may be called multiple times: the number of calls and when they occur depends on caching and is an implementation\n * detail.\n */\nexport type SequencedEditResultCallback = (args: SequencedEditResult) => void;\n\n/**\n * The relevant information pertaining to the application of a sequenced edit.\n */\nexport interface SequencedEditResult {\n\t/**\n\t * The edit that was applied.\n\t */\n\tedit: Edit<ChangeInternal>;\n\t/**\n\t * true iff the edit was local.\n\t */\n\twasLocal: boolean;\n\t/**\n\t * The result of applying the edit.\n\t */\n\tresult: AttemptedEditResultCacheEntry;\n\t/**\n\t * The reconciliation path for the edit.\n\t */\n\treconciliationPath: ReconciliationPath;\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit.\n */\nexport type EditCacheEntry = SuccessfulEditCacheEntry | UnsuccessfulEditCacheEntry | SummarizedEditResultCacheEntry;\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has attempted to apply locally.\n */\nexport type AttemptedEditResultCacheEntry = SuccessfulEditCacheEntry | UnsuccessfulEditCacheEntry;\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has successfully applied locally.\n */\nexport interface SuccessfulEditCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * The status code for the edit that produced the revision.\n\t */\n\treadonly status: EditStatus.Applied;\n\t/**\n\t * The resolved changes that were applied during the edit and their associated outcome.\n\t */\n\treadonly steps: readonly ReconciliationChange[];\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has unsuccessfully attempted to apply locally.\n */\nexport interface UnsuccessfulEditCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * The status code for the edit that produced the revision.\n\t */\n\treadonly status: EditStatus.Invalid | EditStatus.Malformed;\n\t/**\n\t * Information about the failure encountered by the edit\n\t */\n\treadonly failure: TransactionInternal.Failure;\n}\n\n/**\n * The data cached by `CachingLogViewer` for an edit that it has retrieved from a summary.\n * TODO:#57176: once summarized edits carry enough information remove this interface and use `AttemptedEditResultCacheEntry` instead.\n */\nexport interface SummarizedEditResultCacheEntry {\n\t/**\n\t * The revision view resulting from the edit.\n\t */\n\treadonly view: RevisionView;\n\t/**\n\t * Not specified on `SummarizedEditResultCacheEntry`.\n\t * Declared to allow checking `entry.status` against undefined.\n\t */\n\treadonly status?: never;\n}\n\nexport type CachedEditingResult = AttemptedEditResultCacheEntry & {\n\t/**\n\t * Unique identifier for this edit. Must never be reused.\n\t * Used for referencing and de-duplicating edits.\n\t */\n\treadonly id: EditId;\n\treadonly before: RevisionView;\n\treadonly changes: readonly ChangeInternal[];\n};\n\n/**\n * Creates `RevisionView`s for the revisions in an `EditLog`\n */\nexport interface LogViewer {\n\t/**\n\t * Returns the `TreeView` output associated with the largest revision in `editLog` less than (but not equal to) the supplied revision.\n\t *\n\t * For example:\n\t *\n\t * - revision 0 returns the initialRevision.\n\t *\n\t * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).\n\t *\n\t * - revision Number.POSITIVE_INFINITY returns the newest revision.\n\t */\n\tgetRevisionView(revision: Revision): Promise<RevisionView>;\n\n\t/**\n\t * Returns the `TreeView` output associated with the largest revision in `editLog` less than (but not equal to) the supplied revision.\n\t * Can only be used to retrieve revisions added during the current sessions.\n\t *\n\t * For example:\n\t *\n\t * - revision 0 returns the initialRevision.\n\t *\n\t * - revision 1 returns the output of editLog[0] (or initialRevision if there is no edit 0).\n\t *\n\t * - revision Number.POSITIVE_INFINITY returns the newest revision.\n\t */\n\tgetRevisionViewInSession(revision: Revision): RevisionView;\n}\n\n/**\n * Creates views for revisions associated with an EditLog and caches the results.\n *\n * Does so by listening for edits added to the log. If the underlying EditLog or its listeners need to be reused beyond the lifetime of\n * a CachingLogViewer instance, that instance should be disposed with `detachFromEditLog` to ensure it is garbage-collectable.\n * @internal\n */\nexport class CachingLogViewer implements LogViewer {\n\tpublic readonly log: EditLog<ChangeInternal>;\n\n\t/**\n\t * Maximum size of the sequenced revision cache.\n\t */\n\tpublic static readonly sequencedCacheSizeMax = 50;\n\n\t/**\n\t * A cache for local revisions.\n\t * It is invalidated whenever a new sequenced edit (that was not already a local edit) is added to the log.\n\t * When a previously local edit is sequenced, this cache is adjusted to account for it, not invalidated.\n\t */\n\tprivate readonly localRevisionCache = new Denque<AttemptedEditResultCacheEntry>();\n\n\t/**\n\t * Cache of sequenced revisions.\n\t */\n\tprivate readonly sequencedRevisionCache: RevisionValueCache<EditCacheEntry>;\n\n\t/**\n\t * Called whenever a sequenced edit is applied.\n\t * This will have been called at least once for any edit if a revision after than edit has been requested.\n\t * It may be called multiple times: the number of calls and when they occur depends on caching and is an implementation detail.\n\t */\n\tprivate readonly processSequencedEditResult: SequencedEditResultCallback;\n\n\t/**\n\t * Called whenever an edit is processed.\n\t * This will have been called at least once for any edit if a revision after than edit has been requested.\n\t * It may be called multiple times: the number of calls and when they occur depends on caching and is an implementation detail.\n\t */\n\tprivate readonly processEditStatus: EditStatusCallback;\n\n\t/**\n\t * The ordered queue of edits that originated from this client that have never been applied (by this log viewer) in a sequenced state.\n\t * This means these edits may be local or sequenced, and may have been applied (possibly multiple times) while still local.\n\t * Used to log telemetry about the result of edit application. Edits are removed when first applied after being sequenced.\n\t */\n\tprivate readonly unappliedSelfEdits = new Denque<EditId>();\n\n\t/**\n\t * Cache of applying a edit.\n\t * Due to use of Transactions in checkouts, a common pattern involves applying an edit\n\t * as part of the transaction, then submitting it.\n\t * This cache helps optimize that case by avoiding recomputing the edit if no other edits were added during the transaction.\n\t */\n\tprivate cachedEditResult?: { editId: EditId; result: EditingResult };\n\n\t/**\n\t * Cache entry for the highest revision.\n\t * `undefined` when not cached.\n\t */\n\tprivate highestRevisionCacheEntry?: EditCacheEntry;\n\n\t/**\n\t * Removes this log viewer from the set of handleEditAdded listeners on its underlying log.\n\t * This should be called if the underlying log or its listeners are re-used past the lifetime of this log viewer.\n\t */\n\tpublic readonly detachFromEditLog: () => void;\n\n\t/**\n\t * @returns true if the highest revision is cached.\n\t */\n\tpublic highestRevisionCached(): boolean {\n\t\treturn this.highestRevisionCacheEntry !== undefined;\n\t}\n\n\t/**\n\t * Create a new LogViewer\n\t * @param log - the edit log which revisions will be based on.\n\t * @param baseTree - the tree used in the view corresponding to the 0th revision.\n\t * @param knownRevisions - a set of [sequencedRevision, view] pairs that are known (have been precomputed) at construction time.\n\t * These revisions are guaranteed to never be evicted from the cache.\n\t * @param expensiveValidation - Iff true, additional correctness assertions will be run during LogViewer operations.\n\t * @param processEditStatus - called after applying an edit.\n\t * @param processSequencedEditResult - called after applying a sequenced edit.\n\t */\n\tpublic constructor(\n\t\tlog: EditLog<ChangeInternal>,\n\t\tbaseView: RevisionView,\n\t\tknownRevisions: [Revision, EditCacheEntry][] = [],\n\t\tprocessEditStatus: EditStatusCallback = noop,\n\t\tprocessSequencedEditResult: SequencedEditResultCallback = noop,\n\t\tminimumSequenceNumber = 0\n\t) {\n\t\tthis.log = log;\n\t\tknownRevisions.forEach(([revision]) => {\n\t\t\tassert(Number.isInteger(revision), 'revision must be an integer');\n\t\t\tassert(this.log.isSequencedRevision(revision), 'revision must correspond to the result of a SequencedEdit');\n\t\t});\n\n\t\tthis.sequencedRevisionCache = new RevisionValueCache(\n\t\t\tCachingLogViewer.sequencedCacheSizeMax,\n\t\t\tminimumSequenceNumber,\n\t\t\t[...knownRevisions, [0, { view: baseView }]]\n\t\t);\n\t\tthis.processEditStatus = processEditStatus ?? noop;\n\t\tthis.processSequencedEditResult = processSequencedEditResult ?? noop;\n\t\tthis.detachFromEditLog = this.log.registerEditAddedHandler(this.handleEditAdded.bind(this));\n\t}\n\n\t/**\n\t * As a performance optimization, this method caches views generated by local edits if they are sequenced without\n\t * being interleaved with remote edits.\n\t */\n\tprivate handleEditAdded(edit: Edit<ChangeInternal>, isLocal: boolean, wasLocal: boolean): void {\n\t\t// Clear highestRevisionCacheEntry, since what revision is highest might change.\n\t\t// Note that as an optimization we could skip clearing this when a local edit is sequenced.\n\t\tthis.highestRevisionCacheEntry = undefined;\n\n\t\tif (isLocal) {\n\t\t\tthis.unappliedSelfEdits.push(edit.id);\n\t\t} else if (wasLocal) {\n\t\t\t// If the new sequenced edit was generated by this client, the corresponding cache entry (if there is one)\n\t\t\t// will be at the front of the queue. If the queue is empty, then a concurrent sequenced edit from remote client\n\t\t\t// must have invalidated the queue cache.\n\t\t\tconst entry = this.localRevisionCache.shift();\n\t\t\tif (entry !== undefined) {\n\t\t\t\tconst revision = this.log.numberOfSequencedEdits;\n\t\t\t\tconst { view } = entry;\n\t\t\t\tthis.sequencedRevisionCache.cacheValue(\n\t\t\t\t\trevision,\n\t\t\t\t\tentry.status === EditStatus.Applied\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tview,\n\t\t\t\t\t\t\t\tstatus: entry.status,\n\t\t\t\t\t\t\t\tsteps: entry.steps,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tview,\n\t\t\t\t\t\t\t\tstatus: entry.status,\n\t\t\t\t\t\t\t\tfailure: entry.failure,\n\t\t\t\t\t\t }\n\t\t\t\t);\n\t\t\t\tthis.handleSequencedEditResult(edit, entry, []);\n\t\t\t}\n\t\t} else {\n\t\t\t// Invalidate any cached results of applying edits which are ordered after `edit` (which are all remaining local edits)\n\t\t\tthis.localRevisionCache.clear();\n\t\t}\n\t}\n\n\tpublic async getEditResult(revision: Revision): Promise<EditCacheEntry> {\n\t\tconst startingPoint = this.getStartingPoint(revision);\n\t\tconst { startRevision } = startingPoint;\n\t\tlet current: EditCacheEntry = startingPoint;\n\t\tfor (let i = startRevision; i < revision && i < this.log.length; i++) {\n\t\t\tconst edit = await this.log.getEditAtIndex(i);\n\t\t\tcurrent = this.applyEdit(current.view, edit, i);\n\t\t}\n\t\treturn current;\n\t}\n\n\tpublic async getRevisionView(revision: Revision): Promise<RevisionView> {\n\t\treturn (await this.getEditResult(revision)).view;\n\t}\n\n\tpublic getEditResultInSession(revision: Revision): EditCacheEntry {\n\t\tconst startingPoint = this.getStartingPoint(revision);\n\t\tconst { startRevision } = startingPoint;\n\t\tlet current: EditCacheEntry = startingPoint;\n\t\tfor (let i = startRevision; i < revision && i < this.log.length; i++) {\n\t\t\tconst edit = this.log.getEditInSessionAtIndex(i);\n\t\t\tcurrent = this.applyEdit(current.view, edit, i);\n\t\t}\n\t\treturn current;\n\t}\n\n\tpublic getRevisionViewInSession(revision: Revision): RevisionView {\n\t\treturn this.getEditResultInSession(revision).view;\n\t}\n\n\t/**\n\t * Informs the CachingLogViewer of the latest known minimumSequenceNumber for all connected clients.\n\t * This can be used to provide more aggressive caching of revisions within the collaboration window, as those revisions\n\t * are more likely to be demanded to resolve conflicts.\n\t * @param minSequenceNumber - the minimum known sequence number of all connected clients.\n\t */\n\tpublic setMinimumSequenceNumber(minimumSequenceNumber: number): void {\n\t\t// Sequence numbers in Fluid are 1-indexed, meaning they correspond to revisions, and can be used as revisions.\n\t\t// This ensures that all revisions >= minimumSequenceNumber are kept in the cache, meaning that even if all clients are caught up\n\t\t// the most recent sequenced revision will be cached.\n\t\tthis.sequencedRevisionCache.updateRetentionWindow(minimumSequenceNumber);\n\t}\n\n\t/**\n\t * Inform the CachingLogViewer that a particular edit is known to have a specific result when applied to a particular TreeView.\n\t * CachingLogViewer may use this information as an optimization to avoid re-running the edit if re-applied to the same TreeView.\n\t */\n\tpublic setKnownEditingResult(edit: Edit<ChangeInternal>, result: EditingResult): void {\n\t\tthis.cachedEditResult = { editId: edit.id, result };\n\t}\n\n\t/**\n\t * @returns the cached revision view closest to the requested `revision`.\n\t */\n\tprivate getStartingPoint(revision: Revision): { startRevision: Revision } & EditCacheEntry {\n\t\t// Per the documentation for revision, the returned view should be the output of the edit at the largest index <= `revision`.\n\t\tconst revisionClamped = Math.min(revision, this.log.length);\n\n\t\t// If the highest revision is requested, and it's cached, use highestRevisionCacheEntry.\n\t\tif (revisionClamped === this.log.length && this.highestRevisionCacheEntry !== undefined) {\n\t\t\treturn { ...this.highestRevisionCacheEntry, startRevision: revisionClamped };\n\t\t}\n\n\t\tlet current: EditCacheEntry;\n\t\tlet startRevision: Revision;\n\t\tconst { numberOfSequencedEdits } = this.log;\n\t\tconst isLocalRevision = revisionClamped > numberOfSequencedEdits;\n\t\tif (isLocalRevision && !this.localRevisionCache.isEmpty()) {\n\t\t\tconst { length } = this.localRevisionCache;\n\t\t\t// Local revision view cache is indexed such that the view for revision 0 (a local edit) is stored at index 0 in the cache.\n\t\t\t// This is because the local cache does not contain an entry for the implicit initial tree edit.\n\t\t\tconst localCacheIndex = revisionClamped - 1 - numberOfSequencedEdits;\n\t\t\tif (localCacheIndex < length) {\n\t\t\t\tconst cached =\n\t\t\t\t\tthis.localRevisionCache.peekAt(localCacheIndex) ?? fail('missing tail of localRevisionViewCache');\n\t\t\t\treturn {\n\t\t\t\t\t...cached,\n\t\t\t\t\tstartRevision: revisionClamped,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tcurrent = this.localRevisionCache.peekAt(length - 1) ?? fail('missing tail of localRevisionViewCache');\n\t\t\t\tstartRevision = numberOfSequencedEdits + length;\n\t\t\t}\n\t\t} else {\n\t\t\tconst [cachedRevision, cachedView] =\n\t\t\t\tthis.sequencedRevisionCache.getClosestEntry(revisionClamped) ??\n\t\t\t\tfail('No preceding revision view cached.');\n\n\t\t\tstartRevision = cachedRevision;\n\t\t\tcurrent = cachedView;\n\t\t}\n\t\treturn { startRevision, ...current };\n\t}\n\n\t/**\n\t * Helper for applying an edit at the supplied revision view.\n\t * Must only be called in the order that edits appear in the log.\n\t * Must only be called once for a given local edit as long as the local cache has not been invalidated.\n\t * Must only be called once for a given sequenced edit.\n\t * @returns the resulting revision view and the outcome of edit that produced it.\n\t */\n\tprivate applyEdit(\n\t\tprevView: RevisionView,\n\t\tedit: Edit<ChangeInternal>,\n\t\teditIndex: number\n\t): AttemptedEditResultCacheEntry {\n\t\tlet editingResult: EditingResult;\n\t\tlet cached;\n\t\tlet reconciliationPath: ReconciliationPath = [];\n\t\tif (\n\t\t\tthis.cachedEditResult !== undefined &&\n\t\t\tthis.cachedEditResult.editId === edit.id &&\n\t\t\tthis.cachedEditResult.result.before === prevView\n\t\t) {\n\t\t\teditingResult = this.cachedEditResult.result;\n\t\t\tcached = true;\n\t\t} else {\n\t\t\treconciliationPath = this.reconciliationPathFromEdit(edit.id);\n\t\t\teditingResult = TransactionInternal.factory(prevView)\n\t\t\t\t.applyChanges(edit.changes, reconciliationPath)\n\t\t\t\t.close();\n\t\t\tcached = false;\n\t\t}\n\n\t\tconst revision = editIndex + 1;\n\t\tconst nextView: RevisionView = editingResult.status === EditStatus.Applied ? editingResult.after : prevView;\n\n\t\tconst computedCacheEntry =\n\t\t\teditingResult.status === EditStatus.Applied\n\t\t\t\t? { view: nextView, status: editingResult.status, steps: editingResult.steps }\n\t\t\t\t: { view: nextView, status: editingResult.status, failure: editingResult.failure };\n\n\t\tif (this.log.isSequencedRevision(revision)) {\n\t\t\tthis.sequencedRevisionCache.cacheValue(revision, computedCacheEntry);\n\t\t\tthis.handleSequencedEditResult(edit, computedCacheEntry, reconciliationPath);\n\t\t} else {\n\t\t\t// This relies on local edits being append only, and that generating the view for a local revision requires generating\n\t\t\t// the views for all local revisions before it in the log. Thus, generating such a view will necessarily require\n\t\t\t// calls to this method for all local revisions prior, guaranteeing the correct push order.\n\t\t\tassert(\n\t\t\t\trevision === this.log.numberOfSequencedEdits + this.localRevisionCache.length + 1,\n\t\t\t\t'Local revision view cached out of order.'\n\t\t\t);\n\t\t\tthis.localRevisionCache.push(computedCacheEntry);\n\t\t}\n\n\t\t// Only update highestRevisionCacheEntry if this snapshot is the highest revision.\n\t\tif (revision >= this.log.length) {\n\t\t\tthis.highestRevisionCacheEntry = computedCacheEntry;\n\t\t}\n\n\t\tthis.processEditStatus(editingResult.status, this.log.getIdAtIndex(editIndex), cached);\n\t\treturn computedCacheEntry;\n\t}\n\n\t/**\n\t * Helper for performing caching when a sequenced local edit is first applied.\n\t * Invokes the `processSequencedEditResult` handler that was passed to the constructor (if any).\n\t * Must only be called for non-cached sequenced edits.\n\t */\n\tprivate handleSequencedEditResult(\n\t\tedit: Edit<ChangeInternal>,\n\t\tresult: AttemptedEditResultCacheEntry,\n\t\treconciliationPath: ReconciliationPath\n\t): void {\n\t\tlet wasLocal = false;\n\t\t// This is the first time this sequenced edit has been processed by this LogViewer. If it was a local edit, log telemetry\n\t\t// in the event that it was invalid or malformed.\n\t\tif (this.unappliedSelfEdits.length > 0) {\n\t\t\tif (edit.id === this.unappliedSelfEdits.peekFront()) {\n\t\t\t\twasLocal = true;\n\t\t\t\tthis.unappliedSelfEdits.shift();\n\t\t\t}\n\t\t}\n\t\tthis.processSequencedEditResult({ edit, wasLocal, result, reconciliationPath });\n\t}\n\n\t/**\n\t * We currently compute only the \"main branch\" part of the reconciliation path (meaning we don't include inverts of the edits\n\t * that occurred on the rebased branch). Doing so is only needed for the sequential anchor resolution approach which is not\n\t * yet supported.\n\t * @param editId - The ID for the edit to get the reconciliation path for.\n\t */\n\tpublic reconciliationPathFromEdit(editId: EditId): ReconciliationPath {\n\t\tconst reconciliationPath: ReconciliationEdit[] = [];\n\t\tlet cached = false;\n\t\treturn new Proxy(reconciliationPath, {\n\t\t\tget: (target, prop): unknown => {\n\t\t\t\tif (!cached) {\n\t\t\t\t\tcached = true;\n\t\t\t\t\tconst orderedId = this.log.getOrderedEditId(editId);\n\t\t\t\t\tif (orderedId.isLocal === false && orderedId.sequenceInfo !== undefined) {\n\t\t\t\t\t\tconst earliestSequenced = this.earliestSequencedEditInSession();\n\t\t\t\t\t\tif (earliestSequenced !== undefined) {\n\t\t\t\t\t\t\tconst earliestEditSequenceNumber = earliestSequenced.sequenceNumber;\n\t\t\t\t\t\t\tconst targetSequenceNumber = Math.max(\n\t\t\t\t\t\t\t\tearliestEditSequenceNumber,\n\t\t\t\t\t\t\t\torderedId.sequenceInfo.referenceSequenceNumber\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (targetSequenceNumber < orderedId.sequenceInfo.sequenceNumber) {\n\t\t\t\t\t\t\t\tconst firstEdit = this.getEditResultFromSequenceNumber(targetSequenceNumber);\n\t\t\t\t\t\t\t\tif (firstEdit !== undefined) {\n\t\t\t\t\t\t\t\t\tif (firstEdit.status === EditStatus.Applied) {\n\t\t\t\t\t\t\t\t\t\tconst firstEditInfo = this.log.getOrderedEditId(\n\t\t\t\t\t\t\t\t\t\t\tfirstEdit.id\n\t\t\t\t\t\t\t\t\t\t) as SequencedOrderedEditId;\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\tfirstEditInfo.sequenceInfo !== undefined &&\n\t\t\t\t\t\t\t\t\t\t\tfirstEditInfo.sequenceInfo.sequenceNumber >\n\t\t\t\t\t\t\t\t\t\t\t\torderedId.sequenceInfo.referenceSequenceNumber\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\treconciliationPath.push({\n\t\t\t\t\t\t\t\t\t\t\t\t...firstEdit.steps,\n\t\t\t\t\t\t\t\t\t\t\t\tbefore: firstEdit.before,\n\t\t\t\t\t\t\t\t\t\t\t\tafter: firstEdit.view,\n\t\t\t\t\t\t\t\t\t\t\t\tlength: firstEdit.steps.length,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst lowestIndex = this.log.getIndexOfId(firstEdit.id) + 1;\n\t\t\t\t\t\t\t\t\tconst highestIndex = this.log.getIndexOfId(editId) - 1;\n\t\t\t\t\t\t\t\t\tfor (let index = lowestIndex; index <= highestIndex; ++index) {\n\t\t\t\t\t\t\t\t\t\tconst edit = this.getEditResultFromIndex(index);\n\t\t\t\t\t\t\t\t\t\tif (edit.status === EditStatus.Applied) {\n\t\t\t\t\t\t\t\t\t\t\treconciliationPath.push({\n\t\t\t\t\t\t\t\t\t\t\t\t...edit.steps,\n\t\t\t\t\t\t\t\t\t\t\t\tbefore: edit.before,\n\t\t\t\t\t\t\t\t\t\t\t\tafter: edit.view,\n\t\t\t\t\t\t\t\t\t\t\t\tlength: edit.steps.length,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop];\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * @returns Edit information for the earliest known sequenced edit.\n\t */\n\tpublic earliestSequencedEditInSession(): { edit: Edit<ChangeInternal>; sequenceNumber: number } | undefined {\n\t\tconst earliestEditIndex = this.log.earliestAvailableEditIndex;\n\t\tconst lastSequencedEdit = this.log.numberOfSequencedEdits + earliestEditIndex - 1;\n\t\tfor (let index = earliestEditIndex; index <= lastSequencedEdit; ++index) {\n\t\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\t\tconst editOrderedId = this.log.getOrderedEditId(edit.id) as SequencedOrderedEditId;\n\t\t\tif (editOrderedId.sequenceInfo !== undefined) {\n\t\t\t\treturn { edit, sequenceNumber: editOrderedId.sequenceInfo.sequenceNumber };\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * @returns Edit result information for the edit at the given `index`.\n\t */\n\tprivate getEditResultFromIndex(index: number): CachedEditingResult {\n\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\tconst before = this.getRevisionViewInSession(index);\n\t\tconst resultAfter = this.getEditResultInSession(index + 1);\n\t\tif (resultAfter.status === undefined) {\n\t\t\tfail('The status of every edit in session should be known');\n\t\t}\n\t\treturn resultAfter.status === EditStatus.Applied\n\t\t\t? {\n\t\t\t\t\tid: edit.id,\n\t\t\t\t\tstatus: EditStatus.Applied,\n\t\t\t\t\tbefore,\n\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\tsteps: resultAfter.steps,\n\t\t\t }\n\t\t\t: {\n\t\t\t\t\tid: edit.id,\n\t\t\t\t\tstatus: resultAfter.status,\n\t\t\t\t\tfailure: resultAfter.failure,\n\t\t\t\t\tbefore,\n\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\tchanges: edit.changes,\n\t\t\t };\n\t}\n\n\t/**\n\t * @param sequenceNumber - The server-assigned sequenced number assigned to the edit of interest.\n\t * @returns Edit result information for the edit with the given sequence number or the nearest sequenced edit before that.\n\t * Undefined if no sequenced edit occurred at or prior to the given sequenceNumber.\n\t */\n\tpublic getEditResultFromSequenceNumber(sequenceNumber: number): CachedEditingResult | undefined {\n\t\tconst earliestSequenced = this.earliestSequencedEditInSession();\n\t\tif (earliestSequenced !== undefined && sequenceNumber >= earliestSequenced.sequenceNumber) {\n\t\t\tconst lowestIndex = this.log.getIndexOfId(earliestSequenced.edit.id);\n\t\t\tconst highestIndex = this.log.numberOfSequencedEdits - 1;\n\t\t\tfor (let index = highestIndex; index >= lowestIndex; --index) {\n\t\t\t\tconst edit = this.log.getEditInSessionAtIndex(index);\n\t\t\t\tconst orderedId = this.log.getOrderedEditId(edit.id) as SequencedOrderedEditId;\n\t\t\t\t// If `orderedId.sequenceInfo.sequenceNumber` is equal to the requested `sequenceNumber` then we have found the edit of\n\t\t\t\t// interest and simply return its associated information.\n\t\t\t\t// Note that the check bellow also is also satisfied if `orderedId.sequenceInfo.sequenceNumber`is lower than the requested\n\t\t\t\t// `sequenceNumber`. This can happen when the edit for the requested `sequenceNumber` has either not yet been received or\n\t\t\t\t// has been processed by a different DDS (several DDSes can share the same stream of operations and will only see those\n\t\t\t\t// relevant to them). In such cases, we return the edit info for the last known edit before that.\n\t\t\t\tif (orderedId.sequenceInfo && orderedId.sequenceInfo.sequenceNumber <= sequenceNumber) {\n\t\t\t\t\tconst before = this.getRevisionViewInSession(index);\n\t\t\t\t\tconst resultAfter = this.getEditResultInSession(index + 1);\n\t\t\t\t\tif (resultAfter.status === undefined) {\n\t\t\t\t\t\tfail('The status of every edit in session should be known');\n\t\t\t\t\t}\n\t\t\t\t\treturn resultAfter.status === EditStatus.Applied\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: edit.id,\n\t\t\t\t\t\t\t\tstatus: EditStatus.Applied,\n\t\t\t\t\t\t\t\tbefore,\n\t\t\t\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\t\t\t\tsteps: resultAfter.steps,\n\t\t\t\t\t\t }\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tid: edit.id,\n\t\t\t\t\t\t\t\tstatus: resultAfter.status,\n\t\t\t\t\t\t\t\tfailure: resultAfter.failure,\n\t\t\t\t\t\t\t\tbefore,\n\t\t\t\t\t\t\t\tview: resultAfter.view,\n\t\t\t\t\t\t\t\tchanges: edit.changes,\n\t\t\t\t\t\t };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -7,8 +7,10 @@
7
7
  *
8
8
  * It is associated with the output `RevisionView` of applying the edit at the index to the previous revision.
9
9
  * For example:
10
- * - revision 0 corresponds to the initialRevision.
11
- * - revision 1 corresponds to the output of editLog[0] applied to the initialRevision.
10
+ *
11
+ * - revision 0 corresponds to the initialRevision.
12
+ *
13
+ * - revision 1 corresponds to the output of editLog[0] applied to the initialRevision.
12
14
  */
13
15
  export declare type Revision = number;
14
16
  /**
@@ -17,10 +19,12 @@ export declare type Revision = number;
17
19
  * A value is kept in cache if it meets any of the following criteria:
18
20
  *
19
21
  * - The revision is \>= `retentionWindowStart`
22
+ *
20
23
  * - The value has been used recently, meaning getClosestEntry or cacheValue was called with its revision. Note that
21
- * being returned when a large revision was passed to getClosestEntry does not count.
24
+ * being returned when a large revision was passed to getClosestEntry does not count.
25
+ *
22
26
  * - The value is `retained` meaning it was provided to to constructor in retainedEntries or passed to
23
- * `cacheRetainedValue`
27
+ * `cacheRetainedValue`
24
28
  */
25
29
  export declare class RevisionValueCache<TValue> {
26
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionValueCache.d.ts","sourceRoot":"","sources":["../src/RevisionValueCache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;;;;;GAOG;AACH,oBAAY,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,qBAAa,kBAAkB,CAAC,MAAM;IA0BpC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA7B7B;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgE;IAE9F;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAwB;IAE3D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuB;;IAGxD;;OAEG;IACH,aAAa,EAAE,MAAM;IACrB;;;OAGG;IACK,oBAAoB,EAAE,QAAQ;IACtC;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;IAqBvC;;OAEG;IACI,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAI3D;;;OAGG;IACI,qBAAqB,CAAC,uBAAuB,EAAE,QAAQ,GAAG,IAAI;IAwBrE;;;OAGG;IACI,eAAe,CAAC,iBAAiB,EAAE,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS;IAQpG;;OAEG;IACI,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlE;;;;;;OAMG;IACI,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAS1D"}
1
+ {"version":3,"file":"RevisionValueCache.d.ts","sourceRoot":"","sources":["../src/RevisionValueCache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;;;;;;;GASG;AACH,oBAAY,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB,CAAC,MAAM;IA0BpC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA7B7B;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgE;IAE9F;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAwB;IAE3D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuB;;IAGxD;;OAEG;IACH,aAAa,EAAE,MAAM;IACrB;;;OAGG;IACK,oBAAoB,EAAE,QAAQ;IACtC;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;IAqBvC;;OAEG;IACI,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAI3D;;;OAGG;IACI,qBAAqB,CAAC,uBAAuB,EAAE,QAAQ,GAAG,IAAI;IAwBrE;;;OAGG;IACI,eAAe,CAAC,iBAAiB,EAAE,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS;IAQpG;;OAEG;IACI,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAKlE;;;;;;OAMG;IACI,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAS1D"}
@@ -11,10 +11,12 @@ import { assert, fail, compareFiniteNumbers } from './Common';
11
11
  * A value is kept in cache if it meets any of the following criteria:
12
12
  *
13
13
  * - The revision is \>= `retentionWindowStart`
14
+ *
14
15
  * - The value has been used recently, meaning getClosestEntry or cacheValue was called with its revision. Note that
15
- * being returned when a large revision was passed to getClosestEntry does not count.
16
+ * being returned when a large revision was passed to getClosestEntry does not count.
17
+ *
16
18
  * - The value is `retained` meaning it was provided to to constructor in retainedEntries or passed to
17
- * `cacheRetainedValue`
19
+ * `cacheRetainedValue`
18
20
  */
19
21
  export class RevisionValueCache {
20
22
  constructor(
@@ -1 +1 @@
1
- {"version":3,"file":"RevisionValueCache.js","sourceRoot":"","sources":["../src/RevisionValueCache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,cAAc,CAAC;AACjC,OAAO,GAAG,MAAM,WAAW,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAY9D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAkB;IAqB9B;IACC;;OAEG;IACH,aAAqB;IACrB;;;OAGG;IACK,oBAA8B;IACtC;;OAEG;IACH,eAAsC;QAJ9B,yBAAoB,GAApB,oBAAoB,CAAU;QA7BvC;;;;WAIG;QACc,kBAAa,GAAG,IAAI,KAAK,CAAmB,SAAS,EAAE,oBAAoB,CAAC,CAAC;QAU9F;;WAEG;QACc,sBAAiB,GAAG,IAAI,GAAG,EAAY,CAAC;QAiBxD,MAAM,CAAC,oBAAoB,IAAI,CAAC,EAAE,+CAA+C,CAAC,CAAC;QACnF,IAAI,CAAC,kBAAkB,GAAG,IAAI,GAAG,CAAC;YACjC,GAAG,EAAE,aAAa;YAClB,cAAc,EAAE,IAAI;YACpB,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACrB,IAAI,QAAQ,IAAI,IAAI,CAAC,oBAAoB,EAAE;oBAC1C,IAAI,CAAC,sDAAsD,CAAC,CAAC;iBAC7D;gBACD,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;oBACzC,IAAI,CAAC,wCAAwC,CAAC,CAAC;iBAC/C;gBACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;SACD,CAAC,CAAC;QACH,IAAI,eAAe,KAAK,SAAS,EAAE;YAClC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;SACzF;IACF,CAAC;IAED;;OAEG;IACI,uBAAuB,CAAC,QAAkB;QAChD,OAAO,QAAQ,IAAI,IAAI,CAAC,oBAAoB,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACI,qBAAqB,CAAC,uBAAiC;QAC7D,IAAI,uBAAuB,GAAG,IAAI,CAAC,oBAAoB,EAAE;YACxD,IAAI,CAAC,mDAAmD,CAAC,CAAC;SAC1D;QACD,MAAM,wBAAwB,GAAG,IAAI,CAAC,oBAAoB,CAAC;QAC3D,IAAI,CAAC,oBAAoB,GAAG,uBAAuB,CAAC;QACpD,MAAM,gBAAgB,GAAyB,EAAE,CAAC;QAClD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAC1B,wBAAwB,EACxB,IAAI,CAAC,oBAAoB,EACzB,KAAK,EACL,CAAC,cAAc,EAAE,WAAW,EAAE,EAAE;YAC/B,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE;gBAChD,gHAAgH;gBAChH,iCAAiC;gBACjC,gBAAgB,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;aACrD;QACF,CAAC,CACD,CAAC;QACF,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;YAC9C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACI,eAAe,CAAC,iBAA2B;;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/D,IAAI,OAAO,KAAK,SAAS,EAAE;YAC1B,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;SACpC;QACD,OAAO,MAAA,IAAI,CAAC,aAAa,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,mCAAI,SAAS,CAAC;IAC9E,CAAC;IAED;;OAEG;IACI,kBAAkB,CAAC,QAAkB,EAAE,KAAa;QAC1D,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED;;;;;;OAMG;IACI,UAAU,CAAC,QAAkB,EAAE,KAAa;QAClD,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACzC,OAAO;SACP;QACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,QAAQ,GAAG,IAAI,CAAC,oBAAoB,EAAE;YACzC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;SAC7C;IACF,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport LRU from 'lru-cache';\nimport { assert, fail, compareFiniteNumbers } from './Common';\n\n/**\n * A revision corresponds to an index in an `EditLog`.\n *\n * It is associated with the output `RevisionView` of applying the edit at the index to the previous revision.\n * For example:\n * - revision 0 corresponds to the initialRevision.\n * - revision 1 corresponds to the output of editLog[0] applied to the initialRevision.\n */\nexport type Revision = number;\n\n/**\n * A cache of `TValue`s corresponding to `Revision`s.\n *\n * A value is kept in cache if it meets any of the following criteria:\n *\n * - The revision is \\>= `retentionWindowStart`\n * - The value has been used recently, meaning getClosestEntry or cacheValue was called with its revision. Note that\n * being returned when a large revision was passed to getClosestEntry does not count.\n * - The value is `retained` meaning it was provided to to constructor in retainedEntries or passed to\n * `cacheRetainedValue`\n */\nexport class RevisionValueCache<TValue> {\n\t/**\n\t * A cache of entries for revisions.\n\t * This is sorted to allow efficient access to the nearest preceding entry (see getClosestEntry).\n\t * Contains all cached values, regardless of why they are cached (retained, LRU or window).\n\t */\n\tprivate readonly sortedEntries = new BTree<Revision, TValue>(undefined, compareFiniteNumbers);\n\n\t/**\n\t * Cache of most recently used evictable entries.\n\t * Subset of `sortedValues` eligible for eviction:\n\t * All entries are also in `sortedValues`, and are removed from `sortedValues` when evicted from this cache.\n\t * Evicts least recently used entries.\n\t */\n\tprivate readonly evictableRevisions: LRU<Revision, TValue>;\n\n\t/**\n\t * Set of all revisions that should never be evicted.\n\t */\n\tprivate readonly retainedRevisions = new Set<Revision>();\n\n\tpublic constructor(\n\t\t/**\n\t\t * Maximum capacity for evictable cache entries (those neither marked as retained nor within the retention window).\n\t\t */\n\t\tevictableSize: number,\n\t\t/**\n\t\t * The first revision within the retention window. All entries with revisions \\>= retentionWindowStart will be retained.\n\t\t * Must be \\>= 0.\n\t\t */\n\t\tprivate retentionWindowStart: Revision,\n\t\t/**\n\t\t * Optional list of entries to permanently retain.\n\t\t */\n\t\tretainedEntries?: [Revision, TValue][]\n\t) {\n\t\tassert(retentionWindowStart >= 0, 'retentionWindowStart must be initialized >= 0');\n\t\tthis.evictableRevisions = new LRU({\n\t\t\tmax: evictableSize,\n\t\t\tnoDisposeOnSet: true,\n\t\t\tdispose: (revision) => {\n\t\t\t\tif (revision >= this.retentionWindowStart) {\n\t\t\t\t\tfail('Entries in retention window should never be evicted.');\n\t\t\t\t}\n\t\t\t\tif (this.retainedRevisions.has(revision)) {\n\t\t\t\t\tfail('Retained entries should not be evicted');\n\t\t\t\t}\n\t\t\t\tthis.sortedEntries.delete(revision);\n\t\t\t},\n\t\t});\n\t\tif (retainedEntries !== undefined) {\n\t\t\tretainedEntries.forEach(([revision, entry]) => this.cacheRetainedValue(revision, entry));\n\t\t}\n\t}\n\n\t/**\n\t * @returns if the supplied revision is within the retention window.\n\t */\n\tpublic isWithinRetentionWindow(revision: Revision): boolean {\n\t\treturn revision >= this.retentionWindowStart;\n\t}\n\n\t/**\n\t * Sets the new retention window.\n\t * @param newRetentionWindowStart - defines the trailing edge (inclusive) of the new retention window.\n\t */\n\tpublic updateRetentionWindow(newRetentionWindowStart: Revision): void {\n\t\tif (newRetentionWindowStart < this.retentionWindowStart) {\n\t\t\tfail('retention window boundary must not move backwards');\n\t\t}\n\t\tconst prevRetentionWindowStart = this.retentionWindowStart;\n\t\tthis.retentionWindowStart = newRetentionWindowStart;\n\t\tconst oldWindowEntries: [Revision, TValue][] = [];\n\t\tthis.sortedEntries.forRange(\n\t\t\tprevRetentionWindowStart,\n\t\t\tthis.retentionWindowStart,\n\t\t\tfalse,\n\t\t\t(windowRevision, windowEntry) => {\n\t\t\t\tif (!this.retainedRevisions.has(windowRevision)) {\n\t\t\t\t\t// Adding to the LRU can cause eviction which in turn mutates the b-tree we are enumerating. Thus, store list of\n\t\t\t\t\t// old window entries separately.\n\t\t\t\t\toldWindowEntries.push([windowRevision, windowEntry]);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\toldWindowEntries.forEach(([revision, value]) => {\n\t\t\tthis.evictableRevisions.set(revision, value);\n\t\t});\n\t}\n\n\t/**\n\t * @returns a [cachedRevision, value] where cachedRevision \\<= requestedRevision, or undefined if no such revision\n\t * is cached.\n\t */\n\tpublic getClosestEntry(requestedRevision: Revision): [revision: Revision, value: TValue] | undefined {\n\t\tconst fromLRU = this.evictableRevisions.get(requestedRevision);\n\t\tif (fromLRU !== undefined) {\n\t\t\treturn [requestedRevision, fromLRU];\n\t\t}\n\t\treturn this.sortedEntries.getPairOrNextLower(requestedRevision) ?? undefined;\n\t}\n\n\t/**\n\t * Caches the supplied value and guarantees it will never be evicted.\n\t */\n\tpublic cacheRetainedValue(revision: Revision, value: TValue): void {\n\t\tthis.retainedRevisions.add(revision);\n\t\tthis.sortedEntries.set(revision, value);\n\t}\n\n\t/**\n\t * Caches the supplied value.\n\t * The cached value is subject to eviction unless it is within the retention window or was previously added\n\t * via `cacheRetainedValue`.\n\t * Note that if a non-retained entry starts out within the retention window and passes outside of it due to a call to\n\t * updateRetentionWindow it is then subject to eviction.\n\t */\n\tpublic cacheValue(revision: Revision, value: TValue): void {\n\t\tif (this.retainedRevisions.has(revision)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.sortedEntries.set(revision, value);\n\t\tif (revision < this.retentionWindowStart) {\n\t\t\tthis.evictableRevisions.set(revision, value);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"RevisionValueCache.js","sourceRoot":"","sources":["../src/RevisionValueCache.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 BTree from 'sorted-btree';\nimport LRU from 'lru-cache';\nimport { assert, fail, compareFiniteNumbers } from './Common';\n\n/**\n * A revision corresponds to an index in an `EditLog`.\n *\n * It is associated with the output `RevisionView` of applying the edit at the index to the previous revision.\n * For example:\n *\n * - revision 0 corresponds to the initialRevision.\n *\n * - revision 1 corresponds to the output of editLog[0] applied to the initialRevision.\n */\nexport type Revision = number;\n\n/**\n * A cache of `TValue`s corresponding to `Revision`s.\n *\n * A value is kept in cache if it meets any of the following criteria:\n *\n * - The revision is \\>= `retentionWindowStart`\n *\n * - The value has been used recently, meaning getClosestEntry or cacheValue was called with its revision. Note that\n * being returned when a large revision was passed to getClosestEntry does not count.\n *\n * - The value is `retained` meaning it was provided to to constructor in retainedEntries or passed to\n * `cacheRetainedValue`\n */\nexport class RevisionValueCache<TValue> {\n\t/**\n\t * A cache of entries for revisions.\n\t * This is sorted to allow efficient access to the nearest preceding entry (see getClosestEntry).\n\t * Contains all cached values, regardless of why they are cached (retained, LRU or window).\n\t */\n\tprivate readonly sortedEntries = new BTree<Revision, TValue>(undefined, compareFiniteNumbers);\n\n\t/**\n\t * Cache of most recently used evictable entries.\n\t * Subset of `sortedValues` eligible for eviction:\n\t * All entries are also in `sortedValues`, and are removed from `sortedValues` when evicted from this cache.\n\t * Evicts least recently used entries.\n\t */\n\tprivate readonly evictableRevisions: LRU<Revision, TValue>;\n\n\t/**\n\t * Set of all revisions that should never be evicted.\n\t */\n\tprivate readonly retainedRevisions = new Set<Revision>();\n\n\tpublic constructor(\n\t\t/**\n\t\t * Maximum capacity for evictable cache entries (those neither marked as retained nor within the retention window).\n\t\t */\n\t\tevictableSize: number,\n\t\t/**\n\t\t * The first revision within the retention window. All entries with revisions \\>= retentionWindowStart will be retained.\n\t\t * Must be \\>= 0.\n\t\t */\n\t\tprivate retentionWindowStart: Revision,\n\t\t/**\n\t\t * Optional list of entries to permanently retain.\n\t\t */\n\t\tretainedEntries?: [Revision, TValue][]\n\t) {\n\t\tassert(retentionWindowStart >= 0, 'retentionWindowStart must be initialized >= 0');\n\t\tthis.evictableRevisions = new LRU({\n\t\t\tmax: evictableSize,\n\t\t\tnoDisposeOnSet: true,\n\t\t\tdispose: (revision) => {\n\t\t\t\tif (revision >= this.retentionWindowStart) {\n\t\t\t\t\tfail('Entries in retention window should never be evicted.');\n\t\t\t\t}\n\t\t\t\tif (this.retainedRevisions.has(revision)) {\n\t\t\t\t\tfail('Retained entries should not be evicted');\n\t\t\t\t}\n\t\t\t\tthis.sortedEntries.delete(revision);\n\t\t\t},\n\t\t});\n\t\tif (retainedEntries !== undefined) {\n\t\t\tretainedEntries.forEach(([revision, entry]) => this.cacheRetainedValue(revision, entry));\n\t\t}\n\t}\n\n\t/**\n\t * @returns if the supplied revision is within the retention window.\n\t */\n\tpublic isWithinRetentionWindow(revision: Revision): boolean {\n\t\treturn revision >= this.retentionWindowStart;\n\t}\n\n\t/**\n\t * Sets the new retention window.\n\t * @param newRetentionWindowStart - defines the trailing edge (inclusive) of the new retention window.\n\t */\n\tpublic updateRetentionWindow(newRetentionWindowStart: Revision): void {\n\t\tif (newRetentionWindowStart < this.retentionWindowStart) {\n\t\t\tfail('retention window boundary must not move backwards');\n\t\t}\n\t\tconst prevRetentionWindowStart = this.retentionWindowStart;\n\t\tthis.retentionWindowStart = newRetentionWindowStart;\n\t\tconst oldWindowEntries: [Revision, TValue][] = [];\n\t\tthis.sortedEntries.forRange(\n\t\t\tprevRetentionWindowStart,\n\t\t\tthis.retentionWindowStart,\n\t\t\tfalse,\n\t\t\t(windowRevision, windowEntry) => {\n\t\t\t\tif (!this.retainedRevisions.has(windowRevision)) {\n\t\t\t\t\t// Adding to the LRU can cause eviction which in turn mutates the b-tree we are enumerating. Thus, store list of\n\t\t\t\t\t// old window entries separately.\n\t\t\t\t\toldWindowEntries.push([windowRevision, windowEntry]);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t\toldWindowEntries.forEach(([revision, value]) => {\n\t\t\tthis.evictableRevisions.set(revision, value);\n\t\t});\n\t}\n\n\t/**\n\t * @returns a [cachedRevision, value] where cachedRevision \\<= requestedRevision, or undefined if no such revision\n\t * is cached.\n\t */\n\tpublic getClosestEntry(requestedRevision: Revision): [revision: Revision, value: TValue] | undefined {\n\t\tconst fromLRU = this.evictableRevisions.get(requestedRevision);\n\t\tif (fromLRU !== undefined) {\n\t\t\treturn [requestedRevision, fromLRU];\n\t\t}\n\t\treturn this.sortedEntries.getPairOrNextLower(requestedRevision) ?? undefined;\n\t}\n\n\t/**\n\t * Caches the supplied value and guarantees it will never be evicted.\n\t */\n\tpublic cacheRetainedValue(revision: Revision, value: TValue): void {\n\t\tthis.retainedRevisions.add(revision);\n\t\tthis.sortedEntries.set(revision, value);\n\t}\n\n\t/**\n\t * Caches the supplied value.\n\t * The cached value is subject to eviction unless it is within the retention window or was previously added\n\t * via `cacheRetainedValue`.\n\t * Note that if a non-retained entry starts out within the retention window and passes outside of it due to a call to\n\t * updateRetentionWindow it is then subject to eviction.\n\t */\n\tpublic cacheValue(revision: Revision, value: TValue): void {\n\t\tif (this.retainedRevisions.has(revision)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.sortedEntries.set(revision, value);\n\t\tif (revision < this.retentionWindowStart) {\n\t\t\tthis.evictableRevisions.set(revision, value);\n\t\t}\n\t}\n}\n"]}
@@ -93,8 +93,7 @@ export declare class SharedTreeFactory implements IChannelFactory {
93
93
  * @param options - Configuration options for this tree
94
94
  * @returns A factory that creates `SharedTree`s and loads them from storage.
95
95
  */
96
- constructor(...args: SharedTreeArgs<WriteFormat.v0_0_2>);
97
- constructor(...args: SharedTreeArgs<WriteFormat.v0_1_1>);
96
+ constructor(...args: SharedTreeArgs);
98
97
  /**
99
98
  * {@inheritDoc @fluidframework/shared-object-base#ISharedObjectFactory."type"}
100
99
  */
@@ -217,6 +216,10 @@ export declare class SharedTree extends SharedObject<ISharedTreeEvents> implemen
217
216
  */
218
217
  static getFactory(...args: SharedTreeArgs<WriteFormat.v0_0_2>): SharedTreeFactory;
219
218
  static getFactory(...args: SharedTreeArgs<WriteFormat.v0_1_1>): SharedTreeFactory;
219
+ /**
220
+ * Get a factory for SharedTree to register with the data store, using the latest write version and default options.
221
+ */
222
+ static getFactory(): SharedTreeFactory;
220
223
  /**
221
224
  * The UUID used for attribution of nodes created by this SharedTree. All shared trees with a write format of 0.1.1 or
222
225
  * greater have a unique attribution ID which may be configured in the constructor. All other shared trees (i.e. those
@@ -243,7 +246,10 @@ export declare class SharedTree extends SharedObject<ISharedTreeEvents> implemen
243
246
  * Viewer for trees defined by editLog. This allows access to views of the tree at different revisions (various points in time).
244
247
  */
245
248
  get logViewer(): LogViewer;
246
- protected readonly logger: ITelemetryLogger;
249
+ /**
250
+ * logger for SharedTree events.
251
+ */
252
+ readonly logger: ITelemetryLogger;
247
253
  private readonly sequencedEditAppliedLogger;
248
254
  private readonly encoder_0_0_2;
249
255
  private encoder_0_1_1;
@@ -400,14 +406,19 @@ export declare class SharedTree extends SharedObject<ISharedTreeEvents> implemen
400
406
  * Equality means that the histories as captured by the EditLogs are equivalent.
401
407
  *
402
408
  * Equality does not include:
403
- * - if an edit is open
404
- * - the shared tree's id
405
- * - local vs sequenced status of edits
406
- * - registered event listeners
407
- * - state of caches
409
+ *
410
+ * - if an edit is open
411
+ *
412
+ * - the shared tree's id
413
+ *
414
+ * - local vs sequenced status of edits
415
+ *
416
+ * - registered event listeners
417
+ *
418
+ * - state of caches
408
419
  *
409
420
  * @internal
410
- * */
421
+ */
411
422
  equals(sharedTree: SharedTree): boolean;
412
423
  /**
413
424
  * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
@@ -444,8 +455,8 @@ export declare class SharedTree extends SharedObject<ISharedTreeEvents> implemen
444
455
  * should be used instead.
445
456
  * @public
446
457
  */
447
- applyEdit(...changes: Change[]): Edit<InternalizedChange>;
448
- applyEdit(changes: Change[]): Edit<InternalizedChange>;
458
+ applyEdit(...changes: readonly Change[]): Edit<InternalizedChange>;
459
+ applyEdit(changes: readonly Change[]): Edit<InternalizedChange>;
449
460
  /**
450
461
  * Merges `edits` from `other` into this SharedTree.
451
462
  * @param other - Tree containing the edits that should be applied to this one.