@fluid-experimental/tree 2.21.0 → 2.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluid-experimental/tree
2
2
 
3
+ ## 2.22.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.21.0
4
8
 
5
9
  Dependency updates only.
package/README.md CHANGED
@@ -399,6 +399,7 @@ When making such a request please include if the configuration already works (an
399
399
  ### Supported Runtimes
400
400
 
401
401
  - NodeJs ^20.10.0 except that we will drop support for it [when NodeJs 20 loses its upstream support on 2026-04-30](https://github.com/nodejs/release#release-schedule), and will support a newer LTS version of NodeJS (22) at least 1 year before 20 is end-of-life. This same policy applies to NodeJS 22 when it is end of life (2027-04-30).
402
+ - Running Fluid in a Node.js environment with the `--no-experimental-fetch` flag is not supported.
402
403
  - Modern browsers supporting the es2022 standard library: in response to asks we can add explicit support for using babel to polyfill to target specific standards or runtimes (meaning we can avoid/remove use of things that don't polyfill robustly, but otherwise target modern standards).
403
404
 
404
405
  ### Supported Tools
package/dist/TreeView.js CHANGED
@@ -148,7 +148,7 @@ class TreeView {
148
148
  if (trait.length === 0) {
149
149
  return foundIndex;
150
150
  }
151
- this.traitIndicesCache ?? (this.traitIndicesCache = new Map());
151
+ this.traitIndicesCache ??= new Map();
152
152
  for (let i = 0; i < trait.length; i++) {
153
153
  const nodeInTrait = trait[i];
154
154
  const index = i;
@@ -1 +1 @@
1
- {"version":3,"file":"TreeView.js","sourceRoot":"","sources":["../src/TreeView.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,kEAA6D;AAE7D,2CAA0D;AAC1D,2CAAkE;AAElE,yDAA4D;AAsE5D;;;GAGG;AACH,MAAsB,QAAQ;IAY7B,YAAsB,IAAY,EAAE,MAAc;QACjD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,gDAAgD;IAChD,IAAW,IAAI;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,qEAAqE;IAC9D,OAAO,CAAC,EAAU;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,KAAoB;QAC/C,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,kHAAkH;IAC3G,WAAW,CAAC,EAAU;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,IAAA,gBAAI,EAAC,kBAAkB,CAAC,CAAC;IAC5D,CAAC;IAED,wHAAwH;IACjH,cAAc,CAAC,EAAU;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,UAAU,KAAK,SAAS,IAAI,IAAA,gCAAoB,EAAC,UAAU,CAAC,EAAE,CAAC;YAClE,MAAM,QAAQ,GAAiB;gBAC9B,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,SAAS,EAAE;oBACV,KAAK,EAAE,UAAU,CAAC,WAAW;oBAC7B,MAAM,EAAE,UAAU,CAAC,QAAQ;iBAC3B;aACD,CAAC;YACF,IAAA,iCAAqB,EAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YACvD,OAAO,QAAQ,CAAC;QACjB,CAAC;QAED,OAAO,UAAU,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,aAAa,CAAC,EAAU;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACI,gBAAgB,CAAC,EAAU;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC;IAClD,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,EAAU;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,EAAU;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACI,gBAAgB,CAAC,EAAU;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC7C,OAAO;YACN,MAAM,EAAE,UAAU,CAAC,QAAQ;YAC3B,KAAK,EAAE,UAAU,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,mBAAmB,CAAC,EAAU;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO;YACN,MAAM,EAAE,UAAU,CAAC,QAAQ;YAC3B,KAAK,EAAE,UAAU,CAAC,WAAW;SAC7B,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,eAAe,CAAC,EAAU;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC1C,OAAO,KAAK,IAAI,IAAA,gBAAI,EAAC,kCAAkC,CAAC,CAAC;IAC1D,CAAC;IAED;;;;OAIG;IACI,kBAAkB,CAAC,EAAU;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,WAAW,CAAC;QACpB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAA,gBAAI,EAAC,6CAA6C,CAAC,CAAC;QAC/G,IAAI,UAAsC,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,iBAAiB,KAAtB,IAAI,CAAC,iBAAiB,GAAK,IAAI,GAAG,EAAE,EAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,KAAK,GAAG,CAAmB,CAAC;YAClC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAC/C,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;gBACxB,UAAU,GAAG,KAAK,CAAC;YACpB,CAAC;QACF,CAAC;QAED,OAAO,UAAU,CAAC;IACnB,CAAC;IAED;;OAEG;IACI,QAAQ,CAAC,aAA4B;QAC3C,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACrF,CAAC;IAED,2FAA2F;IACpF,gBAAgB;QACtB,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;IAChC,CAAC;IAEM,CAAC,MAAM,CAAC,QAAQ,CAAC;QACvB,OAAO,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAKD;;;OAGG;IACI,cAAc,CAAC,IAAc,EAAE,MAAM,GAAG,KAAK;QACnD,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7B,+EAA+E;YAC/E,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,CAAC,sBAAsB,CAAC,IAAkB;QACjD,MAAM,IAAI,CAAC;QACX,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACrC,KAAK,MAAM,OAAO,IAAI,KAAK,IAAI,IAAA,gBAAI,EAAC,2BAA2B,CAAC,EAAE,CAAC;gBAClE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBACxC,KAAK,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC;QACF,CAAC;IACF,CAAC;IAEO,cAAc,CAAC,IAAU,EAAE,aAA4B;QAC9D,OAAO,IAAI,KAAK,eAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAgB,CAAC,CAAC,CAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,MAAqB,CAAC;IACtG,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,IAAc;QAC1B,IAAA,iBAAM,EAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAC1G,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;CACD;AA1OD,4BA0OC;AAED,SAAS,QAAQ,CAAC,IAAU,EAAE,KAAqB;IAClD,OAAO,CAAC,IAAI,GAAG,KAAK,CAAe,CAAC;AACrC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from '@fluidframework/core-utils/internal';\n\nimport { copyPropertyIfDefined, fail } from './Common.js';\nimport { Delta, Forest, isParentedForestNode } from './Forest.js';\nimport { NodeId, TraitLabel } from './Identifiers.js';\nimport { NodeData, Side } from './persisted-types/index.js';\n\n/**\n * Specifies the location of a trait (a labeled sequence of nodes) within the tree.\n * @alpha\n */\nexport interface TraitLocation {\n\treadonly parent: NodeId;\n\treadonly label: TraitLabel;\n}\n\n/**\n * An immutable view of a distributed tree node.\n * @alpha\n */\nexport interface TreeViewNode extends NodeData<NodeId> {\n\t/** The IDs of the children under this node */\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n\t/** The parent and trait under which this node resides. Undefined iff this is the root node of the tree (i.e. {@link initialTree}). */\n\treadonly parentage?: TraitLocation;\n}\n\n/**\n * Index of a place within a trait.\n * 0 = before all nodes,\n * 1 = after first node,\n * etc.\n * @alpha\n */\nexport type PlaceIndex = number & { readonly PlaceIndex: unique symbol };\n\n/**\n * Index of a node within a trait.\n * 0 = first node,\n * 1 = second node,\n * etc.\n * @alpha\n */\nexport type TraitNodeIndex = number & { readonly TraitNodeIndex: unique symbol };\n\n/**\n * A place within a particular `TreeView` that is anchored relative to a specific node in the tree, or relative to the outside of the trait.\n * Valid iff 'trait' is valid and, if provided, sibling is in the Location specified by 'trait'.\n * @alpha\n */\nexport interface TreeViewPlace {\n\treadonly sibling?: NodeId;\n\treadonly side: Side;\n\treadonly trait: TraitLocation;\n}\n\n/**\n * Specifies the range of nodes from `start` to `end` within a trait within a particular `TreeView`.\n * Valid iff start and end are valid and are within the same trait.\n * @alpha\n */\nexport interface TreeViewRange {\n\treadonly start: TreeViewPlace;\n\treadonly end: TreeViewPlace;\n}\n\n/**\n * Contains some redundant information. Use only in computations between edits. Do not store.\n * @internal\n */\nexport interface NodeInTrait {\n\treadonly trait: TraitLocation;\n\treadonly index: TraitNodeIndex;\n}\n\n/**\n * A view of a distributed tree.\n * @alpha\n */\nexport abstract class TreeView {\n\tpublic readonly root: NodeId;\n\tprotected readonly forest: Forest;\n\tprivate readonly rootNode: TreeViewNode;\n\n\t/**\n\t * A cache of node's index within their parent trait.\n\t * Used to avoid redundant linear scans of traits.\n\t * Not shared across views; initialized to empty each time a TreeView is created.\n\t */\n\tprivate traitIndicesCache?: Map<NodeId, TraitNodeIndex>;\n\n\tprotected constructor(root: NodeId, forest: Forest) {\n\t\tthis.root = root;\n\t\tthis.forest = forest;\n\t\tthis.rootNode = this.getViewNode(root);\n\t}\n\n\t/** @returns the number of nodes in this view */\n\tpublic get size(): number {\n\t\treturn this.forest.size;\n\t}\n\n\t/** @returns true iff a node with the given id exists in this view */\n\tpublic hasNode(id: NodeId): boolean {\n\t\treturn this.forest.has(id);\n\t}\n\n\t/**\n\t * @returns the index just after place (which specifies a location between items).\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic findIndexWithinTrait(place: TreeViewPlace): PlaceIndex {\n\t\tif (place.sibling === undefined) {\n\t\t\treturn this.getIndexOfSide(place.side, place.trait);\n\t\t}\n\t\treturn getIndex(place.side, this.getIndexInTrait(place.sibling));\n\t}\n\n\t/** @returns the node associated with the given id in this view. Fails if the node does not exist in this view. */\n\tpublic getViewNode(id: NodeId): TreeViewNode {\n\t\treturn this.tryGetViewNode(id) ?? fail('NodeId not found');\n\t}\n\n\t/** @returns the node associated with the given id in this view, or undefined if the node does not exist in this view */\n\tpublic tryGetViewNode(id: NodeId): TreeViewNode | undefined {\n\t\tconst forestNode = this.forest.tryGet(id);\n\t\tif (forestNode !== undefined && isParentedForestNode(forestNode)) {\n\t\t\tconst viewNode: TreeViewNode = {\n\t\t\t\tdefinition: forestNode.definition,\n\t\t\t\tidentifier: forestNode.identifier,\n\t\t\t\ttraits: forestNode.traits,\n\t\t\t\tparentage: {\n\t\t\t\t\tlabel: forestNode.traitParent,\n\t\t\t\t\tparent: forestNode.parentId,\n\t\t\t\t},\n\t\t\t};\n\t\t\tcopyPropertyIfDefined(forestNode, viewNode, 'payload');\n\t\t\treturn viewNode;\n\t\t}\n\n\t\treturn forestNode;\n\t}\n\n\t/**\n\t * @returns the label of the trait under which a node with the given id resides. Fails if the node does not exist in this view or if\n\t * it is the root node.\n\t */\n\tpublic getTraitLabel(id: NodeId): TraitLabel {\n\t\treturn this.forest.getParent(id).traitParent;\n\t}\n\n\t/**\n\t * @returns the label of the trait under which a node with the given id resides, or undefined if the node is not present in this\n\t * view or if it is the root node\n\t */\n\tpublic tryGetTraitLabel(id: NodeId): TraitLabel | undefined {\n\t\treturn this.forest.tryGetParent(id)?.traitParent;\n\t}\n\n\t/**\n\t * @returns the parent of the node with the given id. Fails if the node does not exist in this view or if it is the root node.\n\t */\n\tpublic getParentViewNode(id: NodeId): TreeViewNode {\n\t\tconst parentInfo = this.forest.getParent(id);\n\t\treturn this.getViewNode(parentInfo.parentId);\n\t}\n\n\t/**\n\t * @returns the parent of the node with the given id. Returns undefined if the node does not exist in this view or if it is the root\n\t * node.\n\t */\n\tpublic tryGetParentViewNode(id: NodeId): TreeViewNode | undefined {\n\t\tconst parentInfo = this.forest.tryGetParent(id);\n\t\tif (parentInfo === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.getViewNode(parentInfo.parentId);\n\t}\n\n\t/**\n\t * @returns the trait location of the node with the given id. Fails if the node does not exist in this view or of it is the root\n\t * node\n\t */\n\tpublic getTraitLocation(id: NodeId): TraitLocation {\n\t\tconst parentData = this.forest.getParent(id);\n\t\treturn {\n\t\t\tparent: parentData.parentId,\n\t\t\tlabel: parentData.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * @returns the trait location of the node with the given id, or undefined if the node does not exist in this view or if it is the root\n\t * node\n\t */\n\tpublic tryGetTraitLocation(id: NodeId): TraitLocation | undefined {\n\t\tconst parentData = this.forest.tryGetParent(id);\n\t\tif (parentData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tparent: parentData.parentId,\n\t\t\tlabel: parentData.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * @returns the index within the trait under which the node with the given id resides. The node must exist in this view and must have a\n\t * parent.\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic getIndexInTrait(id: NodeId): TraitNodeIndex {\n\t\tconst index = this.tryGetIndexInTrait(id);\n\t\treturn index ?? fail('ID does not exist in the forest.');\n\t}\n\n\t/**\n\t * @returns the index within the trait under which the node with the given id resides, or undefined if the node does not exist in this\n\t * view or does not have a parent.\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic tryGetIndexInTrait(id: NodeId): TraitNodeIndex | undefined {\n\t\tconst cachedIndex = this.traitIndicesCache?.get(id);\n\t\tif (cachedIndex !== undefined) {\n\t\t\treturn cachedIndex;\n\t\t}\n\n\t\tconst parentData = this.forest.tryGetParent(id);\n\t\tif (parentData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst parent = this.forest.tryGet(parentData.parentId);\n\t\tif (parent === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst trait = parent.traits.get(parentData.traitParent) ?? fail('inconsistent forest: trait parent not found');\n\t\tlet foundIndex: TraitNodeIndex | undefined;\n\t\tif (trait.length === 0) {\n\t\t\treturn foundIndex;\n\t\t}\n\n\t\tthis.traitIndicesCache ??= new Map();\n\t\tfor (let i = 0; i < trait.length; i++) {\n\t\t\tconst nodeInTrait = trait[i];\n\t\t\tconst index = i as TraitNodeIndex;\n\t\t\tthis.traitIndicesCache.set(nodeInTrait, index);\n\t\t\tif (nodeInTrait === id) {\n\t\t\t\tfoundIndex = index;\n\t\t\t}\n\t\t}\n\n\t\treturn foundIndex;\n\t}\n\n\t/**\n\t * @returns the trait at the given location. If no such trait exists, returns an empty trait.\n\t */\n\tpublic getTrait(traitLocation: TraitLocation): readonly NodeId[] {\n\t\treturn this.getViewNode(traitLocation.parent).traits.get(traitLocation.label) ?? [];\n\t}\n\n\t/** Asserts that the view's internal state is consistent. Useful for testing/validation. */\n\tpublic assertConsistent(): void {\n\t\tthis.forest.assertConsistent();\n\t}\n\n\tpublic [Symbol.iterator](): IterableIterator<TreeViewNode> {\n\t\treturn this.iterateNodeDescendants(this.rootNode);\n\t}\n\n\t/** @returns true iff the given view is equal to this view */\n\tpublic abstract equals(view: TreeView): boolean;\n\n\t/**\n\t * @returns true iff the given view's forest of nodes is equivalent to this view's forest of nodes\n\t * @param strict - if true, the views' forests must be the same object, otherwise they must merely be equivalent\n\t */\n\tpublic hasEqualForest(view: TreeView, strict = false): boolean {\n\t\tif (this.root === view.root) {\n\t\t\t// TODO:#49100:Perf: make this faster and/or remove use by PrefetchingCheckout.\n\t\t\treturn strict ? this.forest === view.forest : this.forest.equals(view.forest);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate *iterateNodeDescendants(node: TreeViewNode): IterableIterator<TreeViewNode> {\n\t\tyield node;\n\t\tfor (const label of [...node.traits.keys()].sort()) {\n\t\t\tconst trait = node.traits.get(label);\n\t\t\tfor (const childId of trait ?? fail('Expected trait with label')) {\n\t\t\t\tconst child = this.getViewNode(childId);\n\t\t\t\tyield* this.iterateNodeDescendants(child);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getIndexOfSide(side: Side, traitLocation: TraitLocation): PlaceIndex {\n\t\treturn side === Side.After ? (0 as PlaceIndex) : (this.getTrait(traitLocation).length as PlaceIndex);\n\t}\n\n\t/**\n\t * Calculate the difference between two `TreeView`s\n\t * @param view - the other view to compare to this one\n\t * @returns A {@link Delta} which nodes must be changed, added, and removed to get from `this` to `view`.\n\t * The views must share a root.\n\t */\n\tpublic delta(view: TreeView): Delta<NodeId> {\n\t\tassert(this.root === view.root, 0x63d /* Delta can only be calculated between views that share a root */);\n\t\treturn this.forest.delta(view.forest);\n\t}\n}\n\nfunction getIndex(side: Side, index: TraitNodeIndex): PlaceIndex {\n\treturn (side + index) as PlaceIndex;\n}\n"]}
1
+ {"version":3,"file":"TreeView.js","sourceRoot":"","sources":["../src/TreeView.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from '@fluidframework/core-utils/internal';\n\nimport { copyPropertyIfDefined, fail } from './Common.js';\nimport { Delta, Forest, isParentedForestNode } from './Forest.js';\nimport { NodeId, TraitLabel } from './Identifiers.js';\nimport { NodeData, Side } from './persisted-types/index.js';\n\n/**\n * Specifies the location of a trait (a labeled sequence of nodes) within the tree.\n * @alpha\n */\nexport interface TraitLocation {\n\treadonly parent: NodeId;\n\treadonly label: TraitLabel;\n}\n\n/**\n * An immutable view of a distributed tree node.\n * @alpha\n */\nexport interface TreeViewNode extends NodeData<NodeId> {\n\t/** The IDs of the children under this node */\n\treadonly traits: ReadonlyMap<TraitLabel, readonly NodeId[]>;\n\t/** The parent and trait under which this node resides. Undefined iff this is the root node of the tree (i.e. {@link initialTree}). */\n\treadonly parentage?: TraitLocation;\n}\n\n/**\n * Index of a place within a trait.\n * 0 = before all nodes,\n * 1 = after first node,\n * etc.\n * @alpha\n */\nexport type PlaceIndex = number & { readonly PlaceIndex: unique symbol };\n\n/**\n * Index of a node within a trait.\n * 0 = first node,\n * 1 = second node,\n * etc.\n * @alpha\n */\nexport type TraitNodeIndex = number & { readonly TraitNodeIndex: unique symbol };\n\n/**\n * A place within a particular `TreeView` that is anchored relative to a specific node in the tree, or relative to the outside of the trait.\n * Valid iff 'trait' is valid and, if provided, sibling is in the Location specified by 'trait'.\n * @alpha\n */\nexport interface TreeViewPlace {\n\treadonly sibling?: NodeId;\n\treadonly side: Side;\n\treadonly trait: TraitLocation;\n}\n\n/**\n * Specifies the range of nodes from `start` to `end` within a trait within a particular `TreeView`.\n * Valid iff start and end are valid and are within the same trait.\n * @alpha\n */\nexport interface TreeViewRange {\n\treadonly start: TreeViewPlace;\n\treadonly end: TreeViewPlace;\n}\n\n/**\n * Contains some redundant information. Use only in computations between edits. Do not store.\n * @internal\n */\nexport interface NodeInTrait {\n\treadonly trait: TraitLocation;\n\treadonly index: TraitNodeIndex;\n}\n\n/**\n * A view of a distributed tree.\n * @alpha\n */\nexport abstract class TreeView {\n\tpublic readonly root: NodeId;\n\tprotected readonly forest: Forest;\n\tprivate readonly rootNode: TreeViewNode;\n\n\t/**\n\t * A cache of node's index within their parent trait.\n\t * Used to avoid redundant linear scans of traits.\n\t * Not shared across views; initialized to empty each time a TreeView is created.\n\t */\n\tprivate traitIndicesCache?: Map<NodeId, TraitNodeIndex>;\n\n\tprotected constructor(root: NodeId, forest: Forest) {\n\t\tthis.root = root;\n\t\tthis.forest = forest;\n\t\tthis.rootNode = this.getViewNode(root);\n\t}\n\n\t/** @returns the number of nodes in this view */\n\tpublic get size(): number {\n\t\treturn this.forest.size;\n\t}\n\n\t/** @returns true iff a node with the given id exists in this view */\n\tpublic hasNode(id: NodeId): boolean {\n\t\treturn this.forest.has(id);\n\t}\n\n\t/**\n\t * @returns the index just after place (which specifies a location between items).\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic findIndexWithinTrait(place: TreeViewPlace): PlaceIndex {\n\t\tif (place.sibling === undefined) {\n\t\t\treturn this.getIndexOfSide(place.side, place.trait);\n\t\t}\n\t\treturn getIndex(place.side, this.getIndexInTrait(place.sibling));\n\t}\n\n\t/** @returns the node associated with the given id in this view. Fails if the node does not exist in this view. */\n\tpublic getViewNode(id: NodeId): TreeViewNode {\n\t\treturn this.tryGetViewNode(id) ?? fail('NodeId not found');\n\t}\n\n\t/** @returns the node associated with the given id in this view, or undefined if the node does not exist in this view */\n\tpublic tryGetViewNode(id: NodeId): TreeViewNode | undefined {\n\t\tconst forestNode = this.forest.tryGet(id);\n\t\tif (forestNode !== undefined && isParentedForestNode(forestNode)) {\n\t\t\tconst viewNode: TreeViewNode = {\n\t\t\t\tdefinition: forestNode.definition,\n\t\t\t\tidentifier: forestNode.identifier,\n\t\t\t\ttraits: forestNode.traits,\n\t\t\t\tparentage: {\n\t\t\t\t\tlabel: forestNode.traitParent,\n\t\t\t\t\tparent: forestNode.parentId,\n\t\t\t\t},\n\t\t\t};\n\t\t\tcopyPropertyIfDefined(forestNode, viewNode, 'payload');\n\t\t\treturn viewNode;\n\t\t}\n\n\t\treturn forestNode;\n\t}\n\n\t/**\n\t * @returns the label of the trait under which a node with the given id resides. Fails if the node does not exist in this view or if\n\t * it is the root node.\n\t */\n\tpublic getTraitLabel(id: NodeId): TraitLabel {\n\t\treturn this.forest.getParent(id).traitParent;\n\t}\n\n\t/**\n\t * @returns the label of the trait under which a node with the given id resides, or undefined if the node is not present in this\n\t * view or if it is the root node\n\t */\n\tpublic tryGetTraitLabel(id: NodeId): TraitLabel | undefined {\n\t\treturn this.forest.tryGetParent(id)?.traitParent;\n\t}\n\n\t/**\n\t * @returns the parent of the node with the given id. Fails if the node does not exist in this view or if it is the root node.\n\t */\n\tpublic getParentViewNode(id: NodeId): TreeViewNode {\n\t\tconst parentInfo = this.forest.getParent(id);\n\t\treturn this.getViewNode(parentInfo.parentId);\n\t}\n\n\t/**\n\t * @returns the parent of the node with the given id. Returns undefined if the node does not exist in this view or if it is the root\n\t * node.\n\t */\n\tpublic tryGetParentViewNode(id: NodeId): TreeViewNode | undefined {\n\t\tconst parentInfo = this.forest.tryGetParent(id);\n\t\tif (parentInfo === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.getViewNode(parentInfo.parentId);\n\t}\n\n\t/**\n\t * @returns the trait location of the node with the given id. Fails if the node does not exist in this view or of it is the root\n\t * node\n\t */\n\tpublic getTraitLocation(id: NodeId): TraitLocation {\n\t\tconst parentData = this.forest.getParent(id);\n\t\treturn {\n\t\t\tparent: parentData.parentId,\n\t\t\tlabel: parentData.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * @returns the trait location of the node with the given id, or undefined if the node does not exist in this view or if it is the root\n\t * node\n\t */\n\tpublic tryGetTraitLocation(id: NodeId): TraitLocation | undefined {\n\t\tconst parentData = this.forest.tryGetParent(id);\n\t\tif (parentData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tparent: parentData.parentId,\n\t\t\tlabel: parentData.traitParent,\n\t\t};\n\t}\n\n\t/**\n\t * @returns the index within the trait under which the node with the given id resides. The node must exist in this view and must have a\n\t * parent.\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic getIndexInTrait(id: NodeId): TraitNodeIndex {\n\t\tconst index = this.tryGetIndexInTrait(id);\n\t\treturn index ?? fail('ID does not exist in the forest.');\n\t}\n\n\t/**\n\t * @returns the index within the trait under which the node with the given id resides, or undefined if the node does not exist in this\n\t * view or does not have a parent.\n\t * Performance note: this is O(siblings in trait).\n\t */\n\tpublic tryGetIndexInTrait(id: NodeId): TraitNodeIndex | undefined {\n\t\tconst cachedIndex = this.traitIndicesCache?.get(id);\n\t\tif (cachedIndex !== undefined) {\n\t\t\treturn cachedIndex;\n\t\t}\n\n\t\tconst parentData = this.forest.tryGetParent(id);\n\t\tif (parentData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst parent = this.forest.tryGet(parentData.parentId);\n\t\tif (parent === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst trait = parent.traits.get(parentData.traitParent) ?? fail('inconsistent forest: trait parent not found');\n\t\tlet foundIndex: TraitNodeIndex | undefined;\n\t\tif (trait.length === 0) {\n\t\t\treturn foundIndex;\n\t\t}\n\n\t\tthis.traitIndicesCache ??= new Map();\n\t\tfor (let i = 0; i < trait.length; i++) {\n\t\t\tconst nodeInTrait = trait[i];\n\t\t\tconst index = i as TraitNodeIndex;\n\t\t\tthis.traitIndicesCache.set(nodeInTrait, index);\n\t\t\tif (nodeInTrait === id) {\n\t\t\t\tfoundIndex = index;\n\t\t\t}\n\t\t}\n\n\t\treturn foundIndex;\n\t}\n\n\t/**\n\t * @returns the trait at the given location. If no such trait exists, returns an empty trait.\n\t */\n\tpublic getTrait(traitLocation: TraitLocation): readonly NodeId[] {\n\t\treturn this.getViewNode(traitLocation.parent).traits.get(traitLocation.label) ?? [];\n\t}\n\n\t/** Asserts that the view's internal state is consistent. Useful for testing/validation. */\n\tpublic assertConsistent(): void {\n\t\tthis.forest.assertConsistent();\n\t}\n\n\tpublic [Symbol.iterator](): IterableIterator<TreeViewNode> {\n\t\treturn this.iterateNodeDescendants(this.rootNode);\n\t}\n\n\t/** @returns true iff the given view is equal to this view */\n\tpublic abstract equals(view: TreeView): boolean;\n\n\t/**\n\t * @returns true iff the given view's forest of nodes is equivalent to this view's forest of nodes\n\t * @param strict - if true, the views' forests must be the same object, otherwise they must merely be equivalent\n\t */\n\tpublic hasEqualForest(view: TreeView, strict = false): boolean {\n\t\tif (this.root === view.root) {\n\t\t\t// TODO:#49100:Perf: make this faster and/or remove use by PrefetchingCheckout.\n\t\t\treturn strict ? this.forest === view.forest : this.forest.equals(view.forest);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate *iterateNodeDescendants(node: TreeViewNode): IterableIterator<TreeViewNode> {\n\t\tyield node;\n\t\tfor (const label of [...node.traits.keys()].sort()) {\n\t\t\tconst trait = node.traits.get(label);\n\t\t\tfor (const childId of trait ?? fail('Expected trait with label')) {\n\t\t\t\tconst child = this.getViewNode(childId);\n\t\t\t\tyield* this.iterateNodeDescendants(child);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getIndexOfSide(side: Side, traitLocation: TraitLocation): PlaceIndex {\n\t\treturn side === Side.After ? (0 as PlaceIndex) : (this.getTrait(traitLocation).length as PlaceIndex);\n\t}\n\n\t/**\n\t * Calculate the difference between two `TreeView`s\n\t * @param view - the other view to compare to this one\n\t * @returns A {@link Delta} which nodes must be changed, added, and removed to get from `this` to `view`.\n\t * The views must share a root.\n\t */\n\tpublic delta(view: TreeView): Delta<NodeId> {\n\t\tassert(this.root === view.root, 0x63d /* Delta can only be calculated between views that share a root */);\n\t\treturn this.forest.delta(view.forest);\n\t}\n}\n\nfunction getIndex(side: Side, index: TraitNodeIndex): PlaceIndex {\n\treturn (side + index) as PlaceIndex;\n}\n"]}
@@ -512,7 +512,7 @@ class IdCompressor {
512
512
  (normalizedLastFinalizedLocal - overriddenLocal) -
513
513
  1);
514
514
  }
515
- cluster.overrides ?? (cluster.overrides = new Map());
515
+ cluster.overrides ??= new Map();
516
516
  const inversionKey = IdCompressor.createInversionKey(override);
517
517
  const existingIds = this.getExistingIdsForNewOverride(inversionKey, true);
518
518
  let overrideForCluster;
@@ -838,7 +838,7 @@ class IdCompressor {
838
838
  return undefined;
839
839
  }
840
840
  const { clusterBase: closestBaseFinalId, cluster: closestCluster } = compressionMapping;
841
- numericUuid ?? (numericUuid = (0, NumericUuid_js_1.numericUuidFromStableId)(inversionKey));
841
+ numericUuid ??= (0, NumericUuid_js_1.numericUuidFromStableId)(inversionKey);
842
842
  const uuidOffset = (0, NumericUuid_js_1.getPositiveDelta)(numericUuid, closestCluster.baseUuid, closestCluster.count - 1);
843
843
  if (uuidOffset !== undefined) {
844
844
  let targetFinalId = (closestBaseFinalId + uuidOffset);
@@ -1145,7 +1145,7 @@ class IdCompressor {
1145
1145
  if (session.attributionId !== sessionId) {
1146
1146
  // As an optimization, don't include the attributionId if it is its default (the sessionId)
1147
1147
  // Get the index into the array for the given attribution ID. If it doesn't exist, push it onto the array and update the map.
1148
- sessionData.push((0, Common_js_1.getOrCreate)(attributionIdToAttributionIndex, session.attributionId, (id) => (serializedAttributionIds ?? (serializedAttributionIds = [])).push(id) - 1));
1148
+ sessionData.push((0, Common_js_1.getOrCreate)(attributionIdToAttributionIndex, session.attributionId, (id) => (serializedAttributionIds ??= []).push(id) - 1));
1149
1149
  }
1150
1150
  sessionIdToSessionIndex.set(sessionId, serializedSessions.length);
1151
1151
  serializedSessions.push(sessionData);