@fluidframework/sequence 2.0.0-internal.4.1.2 → 2.0.0-internal.4.2.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.
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/sequence";
8
- export declare const pkgVersion = "2.0.0-internal.4.1.2";
8
+ export declare const pkgVersion = "2.0.0-internal.4.2.0";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/sequence";
8
- export const pkgVersion = "2.0.0-internal.4.1.2";
8
+ export const pkgVersion = "2.0.0-internal.4.2.0";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/sequence\";\nexport const pkgVersion = \"2.0.0-internal.4.1.2\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/sequence\";\nexport const pkgVersion = \"2.0.0-internal.4.2.0\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/sequence",
3
- "version": "2.0.0-internal.4.1.2",
3
+ "version": "2.0.0-internal.4.2.0",
4
4
  "description": "Distributed sequence",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -37,30 +37,30 @@
37
37
  "dependencies": {
38
38
  "@fluidframework/common-definitions": "^0.20.1",
39
39
  "@fluidframework/common-utils": "^1.1.1",
40
- "@fluidframework/container-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
41
- "@fluidframework/core-interfaces": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
42
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
43
- "@fluidframework/merge-tree": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
40
+ "@fluidframework/container-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
41
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
42
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
43
+ "@fluidframework/merge-tree": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
44
44
  "@fluidframework/protocol-definitions": "^1.1.0",
45
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
46
- "@fluidframework/runtime-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
47
- "@fluidframework/shared-object-base": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
48
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
45
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
46
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
47
+ "@fluidframework/shared-object-base": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
48
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
49
49
  "uuid": "^8.3.1"
50
50
  },
51
51
  "devDependencies": {
52
- "@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
53
- "@fluid-internal/test-dds-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
52
+ "@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
53
+ "@fluid-internal/test-dds-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
54
54
  "@fluid-tools/benchmark": "^0.47.0",
55
- "@fluid-tools/build-cli": "^0.15.0",
55
+ "@fluid-tools/build-cli": "^0.17.0",
56
56
  "@fluidframework/build-common": "^1.1.0",
57
- "@fluidframework/build-tools": "^0.15.0",
57
+ "@fluidframework/build-tools": "^0.17.0",
58
58
  "@fluidframework/eslint-config-fluid": "^2.0.0",
59
59
  "@fluidframework/gitresources": "^0.1039.1000",
60
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
60
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
61
61
  "@fluidframework/sequence-previous": "npm:@fluidframework/sequence@2.0.0-internal.4.1.0",
62
62
  "@fluidframework/server-services-client": "^0.1039.1000",
63
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.4.1.2 <2.0.0-internal.4.2.0",
63
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.4.2.0 <2.0.0-internal.4.3.0",
64
64
  "@microsoft/api-extractor": "^7.34.4",
65
65
  "@types/diff": "^3.5.1",
66
66
  "@types/mocha": "^9.1.1",
@@ -101,9 +101,12 @@
101
101
  "format": "npm run prettier:fix",
102
102
  "lint": "npm run prettier && npm run eslint",
103
103
  "lint:fix": "npm run prettier:fix && npm run eslint:fix",
104
+ "perf": "cross-env FLUID_TEST_VERBOSE=1 mocha \"dist/**/*.spec.js\" --node-option unhandled-rejections=strict,expose-gc --exit -r node_modules/@fluidframework/mocha-test-setup --perfMode --fgrep @Benchmark --reporter @fluid-tools/benchmark/dist/MochaReporter.js --timeout 30000",
105
+ "perf:measure": "npm run perf -- --fgrep @Measurement",
104
106
  "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
105
107
  "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
106
108
  "test": "npm run test:mocha",
109
+ "test:benchmark:report": "mocha \"dist/test/*.perf.spec.js\" --node-option unhandled-rejections=strict,expose-gc --exit --perfMode --fgrep @Benchmark -r @fluidframework/mocha-test-setup --reporter @fluid-tools/benchmark/dist/MochaReporter.js --timeout 60000",
107
110
  "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
108
111
  "test:memory": "mocha --config src/test/memory/.mocharc.js",
109
112
  "test:memory-profiling:report": "mocha --config src/test/memory/.mocharc.js",
@@ -12,7 +12,6 @@ import {
12
12
  addProperties,
13
13
  Client,
14
14
  compareReferencePositions,
15
- ConflictAction,
16
15
  createMap,
17
16
  ICombiningOp,
18
17
  ISegment,
@@ -791,97 +790,54 @@ export function createSequenceInterval(
791
790
  return ival;
792
791
  }
793
792
 
794
- export function defaultIntervalConflictResolver(a: Interval, b: Interval) {
795
- a.addPropertySet(b.properties);
796
- return a;
797
- }
798
-
799
- export function createIntervalIndex(conflict?: IntervalConflictResolver<Interval>) {
793
+ export function createIntervalIndex() {
800
794
  const helpers: IIntervalHelpers<Interval> = {
801
795
  compareEnds: compareIntervalEnds,
802
796
  create: createInterval,
803
797
  };
804
798
  const lc = new LocalIntervalCollection<Interval>(undefined as any as Client, "", helpers);
805
- if (conflict) {
806
- lc.addConflictResolver(conflict);
807
- } else {
808
- lc.addConflictResolver(defaultIntervalConflictResolver);
809
- }
810
799
  return lc;
811
800
  }
812
801
 
813
- export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
814
- private readonly intervalTree = new IntervalTree<TInterval>();
815
- private readonly endIntervalTree: RedBlackTree<TInterval, TInterval>;
816
- private readonly intervalIdMap: Map<string, TInterval> = new Map();
817
- private conflictResolver: IntervalConflictResolver<TInterval> | undefined;
818
- private endConflictResolver: ConflictAction<TInterval, TInterval> | undefined;
802
+ /**
803
+ * Collection of intervals.
804
+ *
805
+ * Implementers of this interface will typically implement additional APIs to support efficiently querying a collection
806
+ * of intervals in some manner, for example:
807
+ * - "find all intervals with start endpoint between these two points"
808
+ * - "find all intervals which overlap this range"
809
+ * etc.
810
+ */
811
+ export interface IntervalIndex<TInterval extends ISerializableInterval> {
812
+ /**
813
+ * Adds an interval to the index.
814
+ * @remarks - Application code should never need to invoke this method on their index for production scenarios:
815
+ * Fluid handles adding and removing intervals from an index in response to sequence or interval changes.
816
+ */
817
+ add(interval: TInterval): void;
819
818
 
820
- private static readonly legacyIdPrefix = "legacy";
819
+ /**
820
+ * Removes an interval from the index.
821
+ * @remarks - Application code should never need to invoke this method on their index for production scenarios:
822
+ * Fluid handles adding and removing intervals from an index in response to sequence or interval changes.
823
+ */
824
+ remove(interval: TInterval): void;
825
+ }
826
+
827
+ class OverlappingIntervalsIndex<TInterval extends ISerializableInterval>
828
+ implements IntervalIndex<TInterval>
829
+ {
830
+ private readonly intervalTree = new IntervalTree<TInterval>();
821
831
 
822
832
  constructor(
823
833
  private readonly client: Client,
824
- private readonly label: string,
825
834
  private readonly helpers: IIntervalHelpers<TInterval>,
826
- /** Callback invoked each time one of the endpoints of an interval slides. */
827
- private readonly onPositionChange?: (
828
- interval: TInterval,
829
- previousInterval: TInterval,
830
- ) => void,
831
- ) {
832
- // eslint-disable-next-line @typescript-eslint/unbound-method
833
- this.endIntervalTree = new RedBlackTree<TInterval, TInterval>(helpers.compareEnds);
834
- }
835
-
836
- public addConflictResolver(conflictResolver: IntervalConflictResolver<TInterval>) {
837
- this.conflictResolver = conflictResolver;
838
- this.endConflictResolver = (key: TInterval, currentKey: TInterval) => {
839
- const ival = conflictResolver(key, currentKey);
840
- return {
841
- data: ival,
842
- key: ival,
843
- };
844
- };
845
- }
835
+ ) {}
846
836
 
847
837
  public map(fn: (interval: TInterval) => void) {
848
838
  this.intervalTree.map(fn);
849
839
  }
850
840
 
851
- public createLegacyId(start: number, end: number): string {
852
- // Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
853
- // without ID's.
854
- return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
855
- }
856
-
857
- /**
858
- * Validates that a serialized interval has the ID property. Creates an ID
859
- * if one does not already exist
860
- *
861
- * @param serializedInterval - The interval to be checked
862
- * @returns The interval's existing or newly created id
863
- */
864
- public ensureSerializedId(serializedInterval: ISerializedInterval): string {
865
- let id: string | undefined = serializedInterval.properties?.[reservedIntervalIdKey];
866
- if (id === undefined) {
867
- // An interval came over the wire without an ID, so create a non-unique one based on start/end.
868
- // This will allow all clients to refer to this interval consistently.
869
- id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
870
- const newProps = {
871
- [reservedIntervalIdKey]: id,
872
- };
873
- serializedInterval.properties = addProperties(serializedInterval.properties, newProps);
874
- }
875
- // Make the ID immutable for safety's sake.
876
- Object.defineProperty(serializedInterval.properties, reservedIntervalIdKey, {
877
- configurable: false,
878
- enumerable: true,
879
- writable: false,
880
- });
881
-
882
- return id;
883
- }
884
-
885
841
  public mapUntil(fn: (interval: TInterval) => boolean) {
886
842
  this.intervalTree.mapUntil(fn);
887
843
  }
@@ -988,6 +944,61 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
988
944
  return overlappingIntervalNodes.map((node) => node.key);
989
945
  }
990
946
 
947
+ public remove(interval: TInterval) {
948
+ this.intervalTree.removeExisting(interval);
949
+ }
950
+
951
+ public add(interval: TInterval) {
952
+ this.intervalTree.put(interval);
953
+ }
954
+ }
955
+
956
+ class IdIntervalIndex<TInterval extends ISerializableInterval>
957
+ implements IntervalIndex<TInterval>, Iterable<TInterval>
958
+ {
959
+ private readonly intervalIdMap: Map<string, TInterval> = new Map();
960
+
961
+ public add(interval: TInterval) {
962
+ const id = interval.getIntervalId();
963
+ assert(
964
+ id !== undefined,
965
+ 0x2c0 /* "ID must be created before adding interval to collection" */,
966
+ );
967
+ // Make the ID immutable.
968
+ Object.defineProperty(interval.properties, reservedIntervalIdKey, {
969
+ configurable: false,
970
+ enumerable: true,
971
+ writable: false,
972
+ });
973
+ this.intervalIdMap.set(id, interval);
974
+ }
975
+
976
+ public remove(interval: TInterval) {
977
+ const id = interval.getIntervalId();
978
+ assert(id !== undefined, 0x311 /* expected id to exist on interval */);
979
+ this.intervalIdMap.delete(id);
980
+ }
981
+
982
+ public getIntervalById(id: string) {
983
+ return this.intervalIdMap.get(id);
984
+ }
985
+
986
+ public [Symbol.iterator]() {
987
+ return this.intervalIdMap.values();
988
+ }
989
+ }
990
+
991
+ class EndpointIndex<TInterval extends ISerializableInterval> implements IntervalIndex<TInterval> {
992
+ private readonly endIntervalTree: RedBlackTree<TInterval, TInterval>;
993
+
994
+ constructor(
995
+ private readonly client: Client,
996
+ private readonly helpers: IIntervalHelpers<TInterval>,
997
+ ) {
998
+ // eslint-disable-next-line @typescript-eslint/unbound-method
999
+ this.endIntervalTree = new RedBlackTree<TInterval, TInterval>(helpers.compareEnds);
1000
+ }
1001
+
991
1002
  public previousInterval(pos: number) {
992
1003
  const transientInterval = this.helpers.create(
993
1004
  "transient",
@@ -1016,32 +1027,85 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1016
1027
  }
1017
1028
  }
1018
1029
 
1019
- public removeInterval(startPosition: number, endPosition: number) {
1020
- const transientInterval = this.helpers.create(
1021
- "transient",
1022
- startPosition,
1023
- endPosition,
1024
- this.client,
1025
- IntervalType.Transient,
1026
- );
1027
- this.intervalTree.remove(transientInterval);
1028
- this.endIntervalTree.remove(transientInterval);
1029
- return transientInterval;
1030
+ public add(interval: TInterval): void {
1031
+ this.endIntervalTree.put(interval, interval);
1030
1032
  }
1031
1033
 
1032
- private removeIntervalFromIndex(interval: TInterval) {
1033
- this.intervalTree.removeExisting(interval);
1034
+ public remove(interval: TInterval): void {
1034
1035
  this.endIntervalTree.remove(interval);
1036
+ }
1037
+ }
1035
1038
 
1036
- const id = interval.getIntervalId();
1039
+ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1040
+ private static readonly legacyIdPrefix = "legacy";
1041
+ public readonly overlappingIntervalsIndex: OverlappingIntervalsIndex<TInterval>;
1042
+ public readonly idIntervalIndex: IdIntervalIndex<TInterval>;
1043
+ public readonly endIntervalIndex: EndpointIndex<TInterval>;
1044
+ private readonly indexes: IntervalIndex<TInterval>[];
1037
1045
 
1038
- assert(id !== undefined, 0x311 /* expected id to exist on interval */);
1046
+ constructor(
1047
+ private readonly client: Client,
1048
+ private readonly label: string,
1049
+ private readonly helpers: IIntervalHelpers<TInterval>,
1050
+ /** Callback invoked each time one of the endpoints of an interval slides. */
1051
+ private readonly onPositionChange?: (
1052
+ interval: TInterval,
1053
+ previousInterval: TInterval,
1054
+ ) => void,
1055
+ ) {
1056
+ this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
1057
+ this.idIntervalIndex = new IdIntervalIndex();
1058
+ this.endIntervalIndex = new EndpointIndex(client, helpers);
1059
+ this.indexes = [
1060
+ this.overlappingIntervalsIndex,
1061
+ this.idIntervalIndex,
1062
+ this.endIntervalIndex,
1063
+ ];
1064
+ }
1039
1065
 
1040
- this.intervalIdMap.delete(id);
1066
+ public createLegacyId(start: number, end: number): string {
1067
+ // Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
1068
+ // without ID's.
1069
+ return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
1070
+ }
1071
+
1072
+ /**
1073
+ * Validates that a serialized interval has the ID property. Creates an ID
1074
+ * if one does not already exist
1075
+ *
1076
+ * @param serializedInterval - The interval to be checked
1077
+ * @returns The interval's existing or newly created id
1078
+ */
1079
+ public ensureSerializedId(serializedInterval: ISerializedInterval): string {
1080
+ let id: string | undefined = serializedInterval.properties?.[reservedIntervalIdKey];
1081
+ if (id === undefined) {
1082
+ // Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
1083
+ // comes over the wire, create a non-unique one based on start/end.
1084
+ // This will allow all clients to refer to this interval consistently.
1085
+ id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
1086
+ const newProps = {
1087
+ [reservedIntervalIdKey]: id,
1088
+ };
1089
+ serializedInterval.properties = addProperties(serializedInterval.properties, newProps);
1090
+ }
1091
+ // Make the ID immutable for safety's sake.
1092
+ Object.defineProperty(serializedInterval.properties, reservedIntervalIdKey, {
1093
+ configurable: false,
1094
+ enumerable: true,
1095
+ writable: false,
1096
+ });
1097
+
1098
+ return id;
1099
+ }
1100
+
1101
+ private removeIntervalFromIndexes(interval: TInterval) {
1102
+ for (const index of this.indexes) {
1103
+ index.remove(interval);
1104
+ }
1041
1105
  }
1042
1106
 
1043
1107
  public removeExistingInterval(interval: TInterval) {
1044
- this.removeIntervalFromIndex(interval);
1108
+ this.removeIntervalFromIndexes(interval);
1045
1109
  this.removeIntervalListeners(interval);
1046
1110
  }
1047
1111
 
@@ -1083,33 +1147,18 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1083
1147
  }
1084
1148
  }
1085
1149
 
1086
- private addIntervalToIndex(interval: TInterval) {
1087
- const id = interval.getIntervalId();
1088
- assert(
1089
- id !== undefined,
1090
- 0x2c0 /* "ID must be created before adding interval to collection" */,
1091
- );
1092
- // Make the ID immutable.
1093
- Object.defineProperty(interval.properties, reservedIntervalIdKey, {
1094
- configurable: false,
1095
- enumerable: true,
1096
- writable: false,
1097
- });
1098
- this.intervalTree.put(interval, this.conflictResolver);
1099
- this.endIntervalTree.put(interval, interval, this.endConflictResolver);
1100
- this.intervalIdMap.set(id, interval);
1150
+ private addIntervalToIndexes(interval: TInterval) {
1151
+ for (const index of this.indexes) {
1152
+ index.add(interval);
1153
+ }
1101
1154
  }
1102
1155
 
1103
1156
  public add(interval: TInterval): void {
1104
1157
  this.linkEndpointsToInterval(interval);
1105
- this.addIntervalToIndex(interval);
1158
+ this.addIntervalToIndexes(interval);
1106
1159
  this.addIntervalListeners(interval);
1107
1160
  }
1108
1161
 
1109
- public getIntervalById(id: string) {
1110
- return this.intervalIdMap.get(id);
1111
- }
1112
-
1113
1162
  public changeInterval(
1114
1163
  interval: TInterval,
1115
1164
  start: number | undefined,
@@ -1128,10 +1177,11 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1128
1177
  }
1129
1178
 
1130
1179
  public serialize(): ISerializedIntervalCollectionV2 {
1131
- const intervals = this.intervalTree.intervals.keys();
1132
1180
  return {
1133
1181
  label: this.label,
1134
- intervals: intervals.map((interval) => compressInterval(interval.serialize())),
1182
+ intervals: Array.from(this.idIntervalIndex, (interval) =>
1183
+ compressInterval(interval.serialize()),
1184
+ ),
1135
1185
  version: 2,
1136
1186
  };
1137
1187
  }
@@ -1164,7 +1214,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1164
1214
  previousInterval = interval.clone() as TInterval & SequenceInterval;
1165
1215
  previousInterval.start = cloneRef(previousInterval.start);
1166
1216
  previousInterval.end = cloneRef(previousInterval.end);
1167
- this.removeIntervalFromIndex(interval);
1217
+ this.removeIntervalFromIndexes(interval);
1168
1218
  }
1169
1219
  },
1170
1220
  () => {
@@ -1174,7 +1224,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
1174
1224
  );
1175
1225
  pendingChanges--;
1176
1226
  if (pendingChanges === 0) {
1177
- this.addIntervalToIndex(interval);
1227
+ this.addIntervalToIndexes(interval);
1178
1228
  this.onPositionChange?.(interval, previousInterval);
1179
1229
  previousInterval = undefined;
1180
1230
  }
@@ -1646,7 +1696,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
1646
1696
  if (!this.localCollection) {
1647
1697
  throw new LoggingError("attach must be called before accessing intervals");
1648
1698
  }
1649
- return this.localCollection.getIntervalById(id);
1699
+ return this.localCollection.idIntervalIndex.getIntervalById(id);
1650
1700
  }
1651
1701
 
1652
1702
  /**
@@ -1734,7 +1784,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
1734
1784
  if (!this.localCollection) {
1735
1785
  throw new LoggingError("Attach must be called before accessing intervals");
1736
1786
  }
1737
- const interval = this.localCollection.getIntervalById(id);
1787
+ const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
1738
1788
  if (interval) {
1739
1789
  this.deleteExistingInterval(interval, true, undefined);
1740
1790
  }
@@ -1965,11 +2015,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
1965
2015
  *
1966
2016
  * As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
1967
2017
  */
1968
- public addConflictResolver(conflictResolver: IntervalConflictResolver<TInterval>): void {
2018
+ public addConflictResolver(_: IntervalConflictResolver<TInterval>): void {
1969
2019
  if (!this.localCollection) {
1970
2020
  throw new LoggingError("attachSequence must be called");
1971
2021
  }
1972
- this.localCollection.addConflictResolver(conflictResolver);
1973
2022
  }
1974
2023
 
1975
2024
  public attachDeserializer(onDeserialize: DeserializeCallback): void {
@@ -1982,9 +2031,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
1982
2031
  this.onDeserialize = onDeserialize;
1983
2032
 
1984
2033
  // Trigger the async prepare work across all values in the collection
1985
- this.localCollection?.map((interval) => {
1986
- onDeserialize(interval);
1987
- });
2034
+ if (this.attached) {
2035
+ this.map(onDeserialize);
2036
+ }
1988
2037
  }
1989
2038
 
1990
2039
  /**
@@ -2013,7 +2062,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2013
2062
  this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
2014
2063
 
2015
2064
  const intervalId = properties?.[reservedIntervalIdKey];
2016
- const localInterval = this.localCollection?.getIntervalById(intervalId);
2065
+ const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
2017
2066
 
2018
2067
  const rebased: SerializedIntervalDelta = {
2019
2068
  start: startRebased,
@@ -2235,7 +2284,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2235
2284
  }
2236
2285
 
2237
2286
  const id = this.localCollection.ensureSerializedId(serializedInterval);
2238
- const interval = this.localCollection.getIntervalById(id);
2287
+ const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
2239
2288
  if (interval) {
2240
2289
  this.deleteExistingInterval(interval, local, op);
2241
2290
  }
@@ -2328,7 +2377,12 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2328
2377
  return;
2329
2378
  }
2330
2379
 
2331
- this.localCollection.gatherIterationResults(results, iteratesForward, start, end);
2380
+ this.localCollection.overlappingIntervalsIndex.gatherIterationResults(
2381
+ results,
2382
+ iteratesForward,
2383
+ start,
2384
+ end,
2385
+ );
2332
2386
  }
2333
2387
 
2334
2388
  /**
@@ -2340,7 +2394,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2340
2394
  throw new LoggingError("attachSequence must be called");
2341
2395
  }
2342
2396
 
2343
- return this.localCollection.findOverlappingIntervals(startPosition, endPosition);
2397
+ return this.localCollection.overlappingIntervalsIndex.findOverlappingIntervals(
2398
+ startPosition,
2399
+ endPosition,
2400
+ );
2344
2401
  }
2345
2402
 
2346
2403
  /**
@@ -2351,7 +2408,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2351
2408
  throw new LoggingError("attachSequence must be called");
2352
2409
  }
2353
2410
 
2354
- this.localCollection.map(fn);
2411
+ for (const interval of this.localCollection.idIntervalIndex) {
2412
+ fn(interval);
2413
+ }
2355
2414
  }
2356
2415
 
2357
2416
  public previousInterval(pos: number): TInterval | undefined {
@@ -2359,7 +2418,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2359
2418
  throw new LoggingError("attachSequence must be called");
2360
2419
  }
2361
2420
 
2362
- return this.localCollection.previousInterval(pos);
2421
+ return this.localCollection.endIntervalIndex.previousInterval(pos);
2363
2422
  }
2364
2423
 
2365
2424
  public nextInterval(pos: number): TInterval | undefined {
@@ -2367,7 +2426,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
2367
2426
  throw new LoggingError("attachSequence must be called");
2368
2427
  }
2369
2428
 
2370
- return this.localCollection.nextInterval(pos);
2429
+ return this.localCollection.endIntervalIndex.nextInterval(pos);
2371
2430
  }
2372
2431
  }
2373
2432
 
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/sequence";
9
- export const pkgVersion = "2.0.0-internal.4.1.2";
9
+ export const pkgVersion = "2.0.0-internal.4.2.0";