@fluidframework/merge-tree 0.59.2000-61729 → 0.59.2001

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.
@@ -12,7 +12,7 @@ import { PropertySet } from "./properties";
12
12
  * @param combiningOp - Optional. Specifies how to combine values for the property, such as "incr" for increment.
13
13
  * @returns The annotate op
14
14
  */
15
- export declare function createAnnotateMarkerOp(marker: Marker, props: PropertySet, combiningOp: ICombiningOp): IMergeTreeAnnotateMsg | undefined;
15
+ export declare function createAnnotateMarkerOp(marker: Marker, props: PropertySet, combiningOp?: ICombiningOp): IMergeTreeAnnotateMsg | undefined;
16
16
  /**
17
17
  * Creates the op for annotating the range with the provided properties
18
18
  * @param start - The inclusive start position of the range to annotate
@@ -1 +1 @@
1
- {"version":3,"file":"opBuilder.d.ts","sourceRoot":"","sources":["../src/opBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACH,YAAY,EACZ,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EAEnB,iBAAiB,EACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,GAAG,qBAAqB,GAAG,SAAS,CAapG;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,GAAG,SAAS,GAAG,qBAAqB,CAQhH;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAMnF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,mBAAmB,CAIzF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,mBAAmB,CAM7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CACzB,GAAG,GAAG,EAAE,iBAAiB,EAAE,GAAG,kBAAkB,CAKnD"}
1
+ {"version":3,"file":"opBuilder.d.ts","sourceRoot":"","sources":["../src/opBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACH,YAAY,EACZ,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EAEnB,iBAAiB,EACpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,YAAY,GAAG,qBAAqB,GAAG,SAAS,CAarG;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,GAAG,SAAS,GAAG,qBAAqB,CAQhH;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAMnF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,mBAAmB,CAIzF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,mBAAmB,CAM7E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CACzB,GAAG,GAAG,EAAE,iBAAiB,EAAE,GAAG,kBAAkB,CAKnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"opBuilder.js","sourceRoot":"","sources":["../src/opBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAClC,MAAc,EAAE,KAAkB,EAAE,WAAyB;IAC7D,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,EAAE;QACL,OAAO,SAAS,CAAC;KACpB;IAED,OAAO;QACH,WAAW;QACX,KAAK;QACL,YAAY,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAClC,YAAY,EAAE,EAAE,EAAE,EAAE;QACpB,IAAI,kBAA6B;KACpC,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACjC,KAAa,EAAE,GAAW,EAAE,KAAkB,EAAE,WAAqC;IACrF,OAAO;QACH,WAAW;QACX,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,GAAG;QACT,KAAK;QACL,IAAI,kBAA6B;KACpC,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,GAAW;IAC1D,OAAO;QACH,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,GAAG;QACT,IAAI,gBAA2B;KAClC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,OAAiB;IAChE,OAAO,cAAc,CACjB,GAAG,EACH,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAY;IACpD,OAAO;QACH,IAAI,EAAE,GAAG;QACT,GAAG,EAAE,OAAO;QACZ,IAAI,gBAA2B;KAClC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CACzB,GAAG,GAAwB;IAC3B,OAAO;QACH,GAAG;QACH,IAAI,eAA0B;KACjC,CAAC;AACN,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISegment, Marker } from \"./mergeTree\";\nimport {\n ICombiningOp,\n IMergeTreeAnnotateMsg,\n IMergeTreeGroupMsg,\n IMergeTreeInsertMsg,\n IMergeTreeRemoveMsg,\n MergeTreeDeltaType,\n IMergeTreeDeltaOp,\n} from \"./ops\";\nimport { PropertySet } from \"./properties\";\n\n/**\n * Creates the op for annotating the markers with the provided properties\n * @param marker - The marker to annotate\n * @param props - The properties to annotate the marker with\n * @param combiningOp - Optional. Specifies how to combine values for the property, such as \"incr\" for increment.\n * @returns The annotate op\n */\nexport function createAnnotateMarkerOp(\n marker: Marker, props: PropertySet, combiningOp: ICombiningOp): IMergeTreeAnnotateMsg | undefined {\n const id = marker.getId();\n if (!id) {\n return undefined;\n }\n\n return {\n combiningOp,\n props,\n relativePos1: { id, before: true },\n relativePos2: { id },\n type: MergeTreeDeltaType.ANNOTATE,\n };\n}\n\n/**\n * Creates the op for annotating the range with the provided properties\n * @param start - The inclusive start position of the range to annotate\n * @param end - The exclusive end position of the range to annotate\n * @param props - The properties to annotate the range with\n * @param combiningOp - Optional. Specifies how to combine values for the property, such as \"incr\" for increment.\n * @returns The annotate op\n */\nexport function createAnnotateRangeOp(\n start: number, end: number, props: PropertySet, combiningOp: ICombiningOp | undefined): IMergeTreeAnnotateMsg {\n return {\n combiningOp,\n pos1: start,\n pos2: end,\n props,\n type: MergeTreeDeltaType.ANNOTATE,\n };\n}\n\n/**\n * Creates the op to remove a range\n *\n * @param start - The inclusive start of the range to remove\n * @param end - The exclusive end of the range to remove\n */\nexport function createRemoveRangeOp(start: number, end: number): IMergeTreeRemoveMsg {\n return {\n pos1: start,\n pos2: end,\n type: MergeTreeDeltaType.REMOVE,\n };\n}\n\n/**\n *\n * @param pos - The position to insert the segment at\n * @param segment - The segment to insert\n */\nexport function createInsertSegmentOp(pos: number, segment: ISegment): IMergeTreeInsertMsg {\n return createInsertOp(\n pos,\n segment.toJSONObject());\n}\n\nexport function createInsertOp(pos: number, segSpec: any): IMergeTreeInsertMsg {\n return {\n pos1: pos,\n seg: segSpec,\n type: MergeTreeDeltaType.INSERT,\n };\n}\n\n/**\n *\n * @param ops - The ops to group\n */\nexport function createGroupOp(\n ...ops: IMergeTreeDeltaOp[]): IMergeTreeGroupMsg {\n return {\n ops,\n type: MergeTreeDeltaType.GROUP,\n };\n}\n"]}
1
+ {"version":3,"file":"opBuilder.js","sourceRoot":"","sources":["../src/opBuilder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAClC,MAAc,EAAE,KAAkB,EAAE,WAA0B;IAC9D,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,EAAE;QACL,OAAO,SAAS,CAAC;KACpB;IAED,OAAO;QACH,WAAW;QACX,KAAK;QACL,YAAY,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAClC,YAAY,EAAE,EAAE,EAAE,EAAE;QACpB,IAAI,kBAA6B;KACpC,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACjC,KAAa,EAAE,GAAW,EAAE,KAAkB,EAAE,WAAqC;IACrF,OAAO;QACH,WAAW;QACX,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,GAAG;QACT,KAAK;QACL,IAAI,kBAA6B;KACpC,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,GAAW;IAC1D,OAAO;QACH,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,GAAG;QACT,IAAI,gBAA2B;KAClC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,OAAiB;IAChE,OAAO,cAAc,CACjB,GAAG,EACH,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAY;IACpD,OAAO;QACH,IAAI,EAAE,GAAG;QACT,GAAG,EAAE,OAAO;QACZ,IAAI,gBAA2B;KAClC,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CACzB,GAAG,GAAwB;IAC3B,OAAO;QACH,GAAG;QACH,IAAI,eAA0B;KACjC,CAAC;AACN,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISegment, Marker } from \"./mergeTree\";\nimport {\n ICombiningOp,\n IMergeTreeAnnotateMsg,\n IMergeTreeGroupMsg,\n IMergeTreeInsertMsg,\n IMergeTreeRemoveMsg,\n MergeTreeDeltaType,\n IMergeTreeDeltaOp,\n} from \"./ops\";\nimport { PropertySet } from \"./properties\";\n\n/**\n * Creates the op for annotating the markers with the provided properties\n * @param marker - The marker to annotate\n * @param props - The properties to annotate the marker with\n * @param combiningOp - Optional. Specifies how to combine values for the property, such as \"incr\" for increment.\n * @returns The annotate op\n */\nexport function createAnnotateMarkerOp(\n marker: Marker, props: PropertySet, combiningOp?: ICombiningOp): IMergeTreeAnnotateMsg | undefined {\n const id = marker.getId();\n if (!id) {\n return undefined;\n }\n\n return {\n combiningOp,\n props,\n relativePos1: { id, before: true },\n relativePos2: { id },\n type: MergeTreeDeltaType.ANNOTATE,\n };\n}\n\n/**\n * Creates the op for annotating the range with the provided properties\n * @param start - The inclusive start position of the range to annotate\n * @param end - The exclusive end position of the range to annotate\n * @param props - The properties to annotate the range with\n * @param combiningOp - Optional. Specifies how to combine values for the property, such as \"incr\" for increment.\n * @returns The annotate op\n */\nexport function createAnnotateRangeOp(\n start: number, end: number, props: PropertySet, combiningOp: ICombiningOp | undefined): IMergeTreeAnnotateMsg {\n return {\n combiningOp,\n pos1: start,\n pos2: end,\n props,\n type: MergeTreeDeltaType.ANNOTATE,\n };\n}\n\n/**\n * Creates the op to remove a range\n *\n * @param start - The inclusive start of the range to remove\n * @param end - The exclusive end of the range to remove\n */\nexport function createRemoveRangeOp(start: number, end: number): IMergeTreeRemoveMsg {\n return {\n pos1: start,\n pos2: end,\n type: MergeTreeDeltaType.REMOVE,\n };\n}\n\n/**\n *\n * @param pos - The position to insert the segment at\n * @param segment - The segment to insert\n */\nexport function createInsertSegmentOp(pos: number, segment: ISegment): IMergeTreeInsertMsg {\n return createInsertOp(\n pos,\n segment.toJSONObject());\n}\n\nexport function createInsertOp(pos: number, segSpec: any): IMergeTreeInsertMsg {\n return {\n pos1: pos,\n seg: segSpec,\n type: MergeTreeDeltaType.INSERT,\n };\n}\n\n/**\n *\n * @param ops - The ops to group\n */\nexport function createGroupOp(\n ...ops: IMergeTreeDeltaOp[]): IMergeTreeGroupMsg {\n return {\n ops,\n type: MergeTreeDeltaType.GROUP,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/merge-tree",
3
- "version": "0.59.2000-61729",
3
+ "version": "0.59.2001",
4
4
  "description": "Merge tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -16,7 +16,7 @@
16
16
  "types": "dist/index.d.ts",
17
17
  "scripts": {
18
18
  "build": "concurrently npm:build:compile npm:lint && npm run build:docs",
19
- "build:commonjs": "npm run tsc && npm run build:test",
19
+ "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
20
20
  "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
21
21
  "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
22
22
  "build:esnext": "tsc --project ./tsconfig.esnext.json",
@@ -35,7 +35,8 @@
35
35
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
36
36
  "tsc": "tsc",
37
37
  "tsfmt": "tsfmt --verify",
38
- "tsfmt:fix": "tsfmt --replace"
38
+ "tsfmt:fix": "tsfmt --replace",
39
+ "typetests:gen": "fluid-type-validator -g -d ."
39
40
  },
40
41
  "nyc": {
41
42
  "all": true,
@@ -60,22 +61,22 @@
60
61
  "dependencies": {
61
62
  "@fluidframework/common-definitions": "^0.20.1",
62
63
  "@fluidframework/common-utils": "^0.32.1",
63
- "@fluidframework/container-definitions": "^0.48.1000-0",
64
- "@fluidframework/core-interfaces": "^0.43.1000-0",
65
- "@fluidframework/datastore-definitions": "0.59.2000-61729",
66
- "@fluidframework/protocol-definitions": "^0.1028.1000-0",
67
- "@fluidframework/runtime-definitions": "0.59.2000-61729",
68
- "@fluidframework/runtime-utils": "0.59.2000-61729",
69
- "@fluidframework/shared-object-base": "0.59.2000-61729",
70
- "@fluidframework/telemetry-utils": "0.59.2000-61729"
64
+ "@fluidframework/container-definitions": "^0.48.1000",
65
+ "@fluidframework/core-interfaces": "^0.43.1000",
66
+ "@fluidframework/datastore-definitions": "^0.59.2001",
67
+ "@fluidframework/protocol-definitions": "^0.1028.1000",
68
+ "@fluidframework/runtime-definitions": "^0.59.2001",
69
+ "@fluidframework/runtime-utils": "^0.59.2001",
70
+ "@fluidframework/shared-object-base": "^0.59.2001",
71
+ "@fluidframework/telemetry-utils": "^0.59.2001"
71
72
  },
72
73
  "devDependencies": {
73
74
  "@fluidframework/build-common": "^0.23.0",
74
- "@fluidframework/eslint-config-fluid": "^0.28.1000-61189",
75
+ "@fluidframework/eslint-config-fluid": "^0.28.1000",
75
76
  "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@^0.58.0",
76
- "@fluidframework/mocha-test-setup": "0.59.2000-61729",
77
- "@fluidframework/test-runtime-utils": "0.59.2000-61729",
78
- "@microsoft/api-extractor": "^7.16.1",
77
+ "@fluidframework/mocha-test-setup": "^0.59.2001",
78
+ "@fluidframework/test-runtime-utils": "^0.59.2001",
79
+ "@microsoft/api-extractor": "^7.22.2",
79
80
  "@rushstack/eslint-config": "^2.5.1",
80
81
  "@types/diff": "^3.5.1",
81
82
  "@types/mocha": "^8.2.2",
@@ -91,8 +92,11 @@
91
92
  "eslint-plugin-editorconfig": "~3.2.0",
92
93
  "eslint-plugin-eslint-comments": "~3.2.0",
93
94
  "eslint-plugin-import": "~2.25.4",
94
- "eslint-plugin-no-null": "~1.0.2",
95
+ "eslint-plugin-jest": "~26.1.3",
96
+ "eslint-plugin-mocha": "~10.0.3",
97
+ "eslint-plugin-promise": "~6.0.0",
95
98
  "eslint-plugin-react": "~7.28.0",
99
+ "eslint-plugin-tsdoc": "~0.2.14",
96
100
  "eslint-plugin-unicorn": "~40.0.0",
97
101
  "mocha": "^8.4.0",
98
102
  "nyc": "^15.0.0",
package/src/client.ts CHANGED
@@ -11,7 +11,7 @@ import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol
11
11
  import { IFluidDataStoreRuntime, IChannelStorageService } from "@fluidframework/datastore-definitions";
12
12
  import { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
13
13
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
14
- import { assert, Trace } from "@fluidframework/common-utils";
14
+ import { assert, Trace, unreachableCase } from "@fluidframework/common-utils";
15
15
  import { LoggingError } from "@fluidframework/telemetry-utils";
16
16
  import { IIntegerRange } from "./base";
17
17
  import { RedBlackTree } from "./collections";
@@ -163,7 +163,7 @@ export class Client {
163
163
  public annotateMarker(
164
164
  marker: Marker,
165
165
  props: PropertySet,
166
- combiningOp: ICombiningOp): IMergeTreeAnnotateMsg | undefined {
166
+ combiningOp?: ICombiningOp): IMergeTreeAnnotateMsg | undefined {
167
167
  const annotateOp =
168
168
  createAnnotateMarkerOp(marker, props, combiningOp)!;
169
169
 
@@ -706,11 +706,16 @@ export class Client {
706
706
  case MergeTreeDeltaType.ANNOTATE:
707
707
  assert(segment.propertyManager?.hasPendingProperties() === true,
708
708
  0x036 /* "Segment has no pending properties" */);
709
- newOp = createAnnotateRangeOp(
710
- segmentPosition,
711
- segmentPosition + segment.cachedLength,
712
- resetOp.props,
713
- resetOp.combiningOp);
709
+ // if the segment has been removed, there's no need to send the annotate op
710
+ // unless the remove was local, in which case the annotate must have come
711
+ // before the remove
712
+ if (segment.removedSeq === undefined || segment.localRemovedSeq !== undefined) {
713
+ newOp = createAnnotateRangeOp(
714
+ segmentPosition,
715
+ segmentPosition + segment.cachedLength,
716
+ resetOp.props,
717
+ resetOp.combiningOp);
718
+ }
714
719
  break;
715
720
 
716
721
  case MergeTreeDeltaType.INSERT:
@@ -773,7 +778,27 @@ export class Client {
773
778
  }
774
779
  }
775
780
 
776
- public applyMsg(msg: ISequencedDocumentMessage) {
781
+ public applyStashedOp(op: IMergeTreeDeltaOp): SegmentGroup;
782
+ public applyStashedOp(op: IMergeTreeGroupMsg): SegmentGroup[];
783
+ public applyStashedOp(op: IMergeTreeOp) {
784
+ switch (op.type) {
785
+ case MergeTreeDeltaType.INSERT:
786
+ this.applyInsertOp({ op });
787
+ return this.peekPendingSegmentGroups();
788
+ case MergeTreeDeltaType.REMOVE:
789
+ this.applyRemoveRangeOp({ op });
790
+ return this.peekPendingSegmentGroups();
791
+ case MergeTreeDeltaType.ANNOTATE:
792
+ this.applyAnnotateRangeOp({ op });
793
+ return this.peekPendingSegmentGroups();
794
+ case MergeTreeDeltaType.GROUP:
795
+ return op.ops.map((o) => this.applyStashedOp(o));
796
+ default:
797
+ unreachableCase(op, "unrecognized op type");
798
+ }
799
+ }
800
+
801
+ public applyMsg(msg: ISequencedDocumentMessage, local: boolean = false) {
777
802
  // Ensure client ID is registered
778
803
  this.getOrAddShortClientId(msg.clientId);
779
804
  // Apply if an operation message
@@ -782,7 +807,7 @@ export class Client {
782
807
  op: msg.contents as IMergeTreeOp,
783
808
  sequencedMessage: msg,
784
809
  };
785
- if (opArgs.sequencedMessage?.clientId === this.longClientId) {
810
+ if (opArgs.sequencedMessage?.clientId === this.longClientId || local) {
786
811
  this.ackPendingSegment(opArgs);
787
812
  }
788
813
  else {
@@ -128,6 +128,9 @@ interface IRefsAtOffset {
128
128
  after?: LocalReference[];
129
129
  }
130
130
 
131
+ /**
132
+ * Represents a collection of {@link LocalReference}s associated with one segment in a merge-tree.
133
+ */
131
134
  export class LocalReferenceCollection {
132
135
  public static append(seg1: ISegment, seg2: ISegment) {
133
136
  if (seg2.localRefs && !seg2.localRefs.empty) {
@@ -150,10 +153,11 @@ export class LocalReferenceCollection {
150
153
  private refCount: number = 0;
151
154
 
152
155
  constructor(
156
+ /** Segment this `LocalReferenceCollection` is associated to. */
153
157
  private readonly segment: ISegment,
154
158
  initialRefsByfOffset = new Array<IRefsAtOffset | undefined>(segment.cachedLength)) {
155
159
  // Since javascript arrays are sparse the above won't populate any of the
156
- // indicies, but it will ensure the length property of the array matches
160
+ // indices, but it will ensure the length property of the array matches
157
161
  // the length of the segment.
158
162
  this.refsByOffset = initialRefsByfOffset;
159
163
  }
@@ -296,6 +300,15 @@ export class LocalReferenceCollection {
296
300
  this.refsByOffset.push(...other.refsByOffset);
297
301
  }
298
302
 
303
+ /**
304
+ * Splits this `LocalReferenceCollection` into the intervals [0, offset) and [offset, originalLength).
305
+ * Local references in the former half of this split will remain associated with the segment used on construction.
306
+ * Local references in the latter half of this split will be transferred to `splitSeg`,
307
+ * and its `localRefs` field will be set.
308
+ * @param offset - Offset into the original segment at which the collection should be split
309
+ * @param splitSeg - Split segment which originally corresponded to the indices [offset, originalLength)
310
+ * before splitting.
311
+ */
299
312
  public split(offset: number, splitSeg: ISegment) {
300
313
  if (!this.empty) {
301
314
  const localRefs =
@@ -314,6 +327,9 @@ export class LocalReferenceCollection {
314
327
  this.refCount--;
315
328
  localRefs.refCount++;
316
329
  }
330
+ } else {
331
+ // shrink the offset array when empty and splitting
332
+ this.refsByOffset.length = offset;
317
333
  }
318
334
  }
319
335
 
package/src/mergeTree.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- /* eslint-disable max-lines */
5
+
6
6
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
7
7
  /* eslint-disable @typescript-eslint/consistent-type-assertions */
8
8
 
@@ -2331,7 +2331,7 @@ export class MergeTree {
2331
2331
  this.mapRange({ leaf: annotateSegment }, refSeq, clientId, undefined, start, end);
2332
2332
 
2333
2333
  // OpArgs == undefined => test code
2334
- if (this.mergeTreeDeltaCallback) {
2334
+ if (this.mergeTreeDeltaCallback && deltaSegments.length > 0) {
2335
2335
  this.mergeTreeDeltaCallback(
2336
2336
  opArgs,
2337
2337
  {
@@ -2445,7 +2445,7 @@ export class MergeTree {
2445
2445
  }
2446
2446
 
2447
2447
  // opArgs == undefined => test code
2448
- if (this.mergeTreeDeltaCallback) {
2448
+ if (this.mergeTreeDeltaCallback && removedSegments.length > 0) {
2449
2449
  this.mergeTreeDeltaCallback(
2450
2450
  opArgs,
2451
2451
  {
package/src/opBuilder.ts CHANGED
@@ -23,7 +23,7 @@ import { PropertySet } from "./properties";
23
23
  * @returns The annotate op
24
24
  */
25
25
  export function createAnnotateMarkerOp(
26
- marker: Marker, props: PropertySet, combiningOp: ICombiningOp): IMergeTreeAnnotateMsg | undefined {
26
+ marker: Marker, props: PropertySet, combiningOp?: ICombiningOp): IMergeTreeAnnotateMsg | undefined {
27
27
  const id = marker.getId();
28
28
  if (!id) {
29
29
  return undefined;