@fluidframework/matrix 2.41.0-338401 → 2.42.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.
@@ -18,7 +18,6 @@ import {
18
18
  IMergeTreeDeltaOpArgs,
19
19
  IMergeTreeMaintenanceCallbackArgs,
20
20
  ISegment,
21
- ISegmentInternal,
22
21
  MergeTreeDeltaType,
23
22
  MergeTreeMaintenanceType,
24
23
  segmentIsRemoved,
@@ -199,23 +198,50 @@ export class PermutationVector extends Client {
199
198
  }
200
199
 
201
200
  public adjustPosition(
202
- pos: number,
203
- op: Pick<ISequencedDocumentMessage, "referenceSequenceNumber" | "clientId">,
204
- ): number | undefined {
205
- const { segment, offset } = this.getContainingSegment<ISegmentInternal>(pos, {
201
+ posToAdjust: number,
202
+ op: ISequencedDocumentMessage,
203
+ ): { pos: number | undefined; handle: Handle } {
204
+ const { segment, offset } = this.getContainingSegment<PermutationSegment>(posToAdjust, {
206
205
  referenceSequenceNumber: op.referenceSequenceNumber,
207
206
  clientId: op.clientId,
208
207
  });
209
208
 
210
- // Note that until the MergeTree GCs, the segment is still reachable via `getContainingSegment()` with
211
- // a `refSeq` in the past. Prevent remote ops from accidentally allocating or using recycled handles
212
- // by checking for the presence of 'removedSeq'.
213
- if (segment === undefined || segmentIsRemoved(segment)) {
214
- return undefined;
215
- }
209
+ assert(
210
+ segment !== undefined && offset !== undefined,
211
+ 0xbac /* segment must be available for operations in the collab window */,
212
+ );
216
213
 
217
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
218
- return this.getPosition(segment) + offset!;
214
+ if (segmentIsRemoved(segment)) {
215
+ // this case is tricky. the segment which the row or column data is remove
216
+ // but an op before that remove references a cell. we still want to apply
217
+ // the op, as the row/col could become active again in the case where
218
+ // the remove was local and it get's rolled back. so we allocate a handle
219
+ // for the row/col if not allocated, but don't put it in the cache
220
+ // as the cache can only contain live positions.
221
+ let handle = segment.start;
222
+ if (!isHandleValid(handle)) {
223
+ this.walkSegments(
224
+ (s) => {
225
+ const asPerm = s as PermutationSegment;
226
+ asPerm.start = handle = this.handleTable.allocate();
227
+ return true;
228
+ },
229
+ posToAdjust,
230
+ posToAdjust + 1,
231
+ /* accum: */ undefined,
232
+ /* splitRange: */ true,
233
+ op,
234
+ );
235
+ }
236
+
237
+ return { handle, pos: undefined };
238
+ } else {
239
+ const pos = this.getPosition(segment) + offset;
240
+ return {
241
+ pos,
242
+ handle: this.getAllocatedHandle(pos),
243
+ };
244
+ }
219
245
  }
220
246
 
221
247
  public handleToPosition(handle: Handle, localSeq = this.getCollabWindow().localSeq): number {
@@ -342,10 +368,12 @@ export class PermutationVector extends Client {
342
368
  case MergeTreeDeltaType.INSERT: {
343
369
  // Pass 1: Perform any internal maintenance first to avoid reentrancy.
344
370
  for (const { segment, position } of ranges) {
345
- // HACK: We need to include the allocated handle in the segment's JSON representation
346
- // for snapshots, but need to ignore the remote client's handle allocations when
347
- // processing remote ops.
348
- segment.reset();
371
+ if (opArgs.rollback !== true) {
372
+ // HACK: We need to include the allocated handle in the segment's JSON representation
373
+ // for snapshots, but need to ignore the remote client's handle allocations when
374
+ // processing remote ops.
375
+ segment.reset();
376
+ }
349
377
 
350
378
  this.handleCache.itemsChanged(
351
379
  position,
@@ -364,7 +392,6 @@ export class PermutationVector extends Client {
364
392
  }
365
393
  break;
366
394
  }
367
-
368
395
  case MergeTreeDeltaType.REMOVE: {
369
396
  // Pass 1: Perform any internal maintenance first to avoid reentrancy.
370
397
  for (const { segment, position } of ranges) {
@@ -385,7 +412,6 @@ export class PermutationVector extends Client {
385
412
  }
386
413
  break;
387
414
  }
388
-
389
415
  default: {
390
416
  throw new Error("Unhandled MergeTreeDeltaType");
391
417
  }