@fluidframework/merge-tree 2.101.1 → 2.103.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.
@@ -15,7 +15,7 @@ import type {
15
15
  import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
16
16
  import type { IFluidSerializer } from "@fluidframework/shared-object-base/internal";
17
17
  import {
18
- type ITelemetryLoggerExt,
18
+ type TelemetryLoggerExt,
19
19
  UsageError,
20
20
  createChildLogger,
21
21
  } from "@fluidframework/telemetry-utils/internal";
@@ -43,14 +43,14 @@ import type { RemoveOperationStamp } from "./stamps.js";
43
43
  import * as opstampUtils from "./stamps.js";
44
44
 
45
45
  export class SnapshotLoader {
46
- private readonly logger: ITelemetryLoggerExt;
46
+ private readonly logger: TelemetryLoggerExt;
47
47
 
48
48
  constructor(
49
49
  private readonly runtime: IFluidDataStoreRuntime,
50
50
 
51
51
  private readonly client: Client,
52
52
  private readonly mergeTree: MergeTree,
53
- logger: ITelemetryLoggerExt,
53
+ logger: TelemetryLoggerExt,
54
54
  private readonly serializer: IFluidSerializer,
55
55
  ) {
56
56
  this.logger = createChildLogger({ logger, namespace: "SnapshotLoader" });
@@ -135,16 +135,13 @@ export class SnapshotLoader {
135
135
  // out ok since none of these values end up being used. (specifically, the 'firstRemovedSeq' is fake
136
136
  // for all values other than the actual first remove).
137
137
  // This issue only affects V1 summaries, as the strategy in snapshotlegacy avoids storing merge info directly.
138
- removes.push(
139
- ...spec.removedClientIds.map(
140
- (id) =>
141
- ({
142
- type: "setRemove",
143
- seq: firstRemovedSeq,
144
- clientId: this.client.getOrAddShortClientId(id),
145
- }) as const,
146
- ),
147
- );
138
+ for (const id of spec.removedClientIds) {
139
+ removes.push({
140
+ type: "setRemove",
141
+ seq: firstRemovedSeq,
142
+ clientId: this.client.getOrAddShortClientId(id),
143
+ } as const);
144
+ }
148
145
  }
149
146
  if (spec.movedSeq !== undefined) {
150
147
  assert(
@@ -156,16 +153,15 @@ export class SnapshotLoader {
156
153
  0xb5f /* Expected same length for client ids and seqs */,
157
154
  );
158
155
 
159
- removes.push(
160
- ...spec.movedClientIds.map(
161
- (id, i) =>
162
- ({
163
- type: "sliceRemove",
164
- seq: spec.movedSeqs![i],
165
- clientId: this.client.getOrAddShortClientId(id),
166
- }) as const,
167
- ),
168
- );
156
+ // Avoid spreading into push: a large array could exceed the engine's
157
+ // argument-count limit and throw RangeError.
158
+ for (let i = 0; i < spec.movedClientIds.length; i++) {
159
+ removes.push({
160
+ type: "sliceRemove",
161
+ seq: spec.movedSeqs[i],
162
+ clientId: this.client.getOrAddShortClientId(spec.movedClientIds[i]),
163
+ } as const);
164
+ }
169
165
  }
170
166
 
171
167
  if (removes.length > 0) {
@@ -258,7 +254,11 @@ export class SnapshotLoader {
258
254
  const newSegs = chunk.segments.map((element) => this.specToSegment(element));
259
255
  this.extractAttribution(newSegs, chunk);
260
256
  chunksWithAttribution += chunk.attribution === undefined ? 0 : 1;
261
- segs.push(...newSegs);
257
+ // Avoid `push(...newSegs)`: spreading a large array into a variadic call
258
+ // can exceed the engine's argument-count limit and throw RangeError.
259
+ for (const seg of newSegs) {
260
+ segs.push(seg);
261
+ }
262
262
  }
263
263
 
264
264
  assert(
package/src/snapshotV1.ts CHANGED
@@ -14,7 +14,7 @@ import type {
14
14
  import { SummaryTreeBuilder } from "@fluidframework/runtime-utils/internal";
15
15
  import type { IFluidSerializer } from "@fluidframework/shared-object-base/internal";
16
16
  import {
17
- type ITelemetryLoggerExt,
17
+ type TelemetryLoggerExt,
18
18
  createChildLogger,
19
19
  } from "@fluidframework/telemetry-utils/internal";
20
20
 
@@ -52,12 +52,12 @@ export class SnapshotV1 {
52
52
  private readonly segments: JsonSegmentSpecs[];
53
53
  private readonly segmentLengths: number[];
54
54
  private readonly attributionCollections: IAttributionCollection<AttributionKey>[];
55
- private readonly logger: ITelemetryLoggerExt;
55
+ private readonly logger: TelemetryLoggerExt;
56
56
  private readonly chunkSize: number;
57
57
 
58
58
  constructor(
59
59
  public mergeTree: MergeTree,
60
- logger: ITelemetryLoggerExt,
60
+ logger: TelemetryLoggerExt,
61
61
  private readonly getLongClientId: (id: number) => string,
62
62
  public filename?: string,
63
63
  public onCompletion?: () => void,
@@ -367,7 +367,7 @@ export class SnapshotV1 {
367
367
  public static async loadChunk(
368
368
  storage: IChannelStorageService,
369
369
  path: string,
370
- logger: ITelemetryLoggerExt,
370
+ logger: TelemetryLoggerExt,
371
371
  options: PropertySet | undefined,
372
372
  serializer?: IFluidSerializer,
373
373
  ): Promise<MergeTreeChunkV1> {
@@ -379,7 +379,7 @@ export class SnapshotV1 {
379
379
  public static processChunk(
380
380
  path: string,
381
381
  chunk: string,
382
- logger: ITelemetryLoggerExt,
382
+ logger: TelemetryLoggerExt,
383
383
  options: PropertySet | undefined,
384
384
  serializer?: IFluidSerializer,
385
385
  ): MergeTreeChunkV1 {
@@ -12,7 +12,7 @@ import type { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions/
12
12
  import { SummaryTreeBuilder } from "@fluidframework/runtime-utils/internal";
13
13
  import type { IFluidSerializer } from "@fluidframework/shared-object-base/internal";
14
14
  import {
15
- type ITelemetryLoggerExt,
15
+ type TelemetryLoggerExt,
16
16
  createChildLogger,
17
17
  } from "@fluidframework/telemetry-utils/internal";
18
18
 
@@ -57,12 +57,12 @@ export class SnapshotLegacy {
57
57
  private header: SnapshotHeader | undefined;
58
58
  private seq: number | undefined;
59
59
  private segments: ISegmentPrivate[] | undefined;
60
- private readonly logger: ITelemetryLoggerExt;
60
+ private readonly logger: TelemetryLoggerExt;
61
61
  private readonly chunkSize: number;
62
62
 
63
63
  constructor(
64
64
  public mergeTree: MergeTree,
65
- logger: ITelemetryLoggerExt,
65
+ logger: TelemetryLoggerExt,
66
66
  public filename?: string,
67
67
  public onCompletion?: () => void,
68
68
  ) {