@fluidframework/matrix 2.1.0-276985 → 2.1.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.
Files changed (88) hide show
  1. package/.eslintrc.cjs +2 -5
  2. package/CHANGELOG.md +4 -0
  3. package/api-extractor/api-extractor.current.json +5 -0
  4. package/api-extractor/api-extractor.legacy.json +1 -1
  5. package/api-extractor.json +1 -1
  6. package/api-report/matrix.legacy.public.api.md +9 -0
  7. package/dist/handlecache.d.ts +7 -3
  8. package/dist/handlecache.d.ts.map +1 -1
  9. package/dist/handlecache.js +25 -7
  10. package/dist/handlecache.js.map +1 -1
  11. package/dist/handletable.d.ts +3 -1
  12. package/dist/handletable.d.ts.map +1 -1
  13. package/dist/handletable.js.map +1 -1
  14. package/dist/legacy.d.ts +1 -1
  15. package/dist/matrix.d.ts +2 -1
  16. package/dist/matrix.d.ts.map +1 -1
  17. package/dist/matrix.js +23 -9
  18. package/dist/matrix.js.map +1 -1
  19. package/dist/packageVersion.d.ts +1 -1
  20. package/dist/packageVersion.d.ts.map +1 -1
  21. package/dist/packageVersion.js +1 -1
  22. package/dist/packageVersion.js.map +1 -1
  23. package/dist/permutationvector.d.ts +5 -5
  24. package/dist/permutationvector.d.ts.map +1 -1
  25. package/dist/permutationvector.js +11 -4
  26. package/dist/permutationvector.js.map +1 -1
  27. package/dist/public.d.ts +1 -1
  28. package/dist/range.d.ts.map +1 -1
  29. package/dist/range.js.map +1 -1
  30. package/dist/runtime.d.ts.map +1 -1
  31. package/dist/runtime.js.map +1 -1
  32. package/dist/serialization.d.ts.map +1 -1
  33. package/dist/serialization.js.map +1 -1
  34. package/dist/sparsearray2d.d.ts +9 -5
  35. package/dist/sparsearray2d.d.ts.map +1 -1
  36. package/dist/sparsearray2d.js +27 -7
  37. package/dist/sparsearray2d.js.map +1 -1
  38. package/dist/undoprovider.d.ts.map +1 -1
  39. package/dist/undoprovider.js +10 -3
  40. package/dist/undoprovider.js.map +1 -1
  41. package/internal.d.ts +1 -1
  42. package/legacy.d.ts +1 -1
  43. package/lib/handlecache.d.ts +7 -3
  44. package/lib/handlecache.d.ts.map +1 -1
  45. package/lib/handlecache.js +25 -7
  46. package/lib/handlecache.js.map +1 -1
  47. package/lib/handletable.d.ts +3 -1
  48. package/lib/handletable.d.ts.map +1 -1
  49. package/lib/handletable.js.map +1 -1
  50. package/lib/legacy.d.ts +1 -1
  51. package/lib/matrix.d.ts +2 -1
  52. package/lib/matrix.d.ts.map +1 -1
  53. package/lib/matrix.js +23 -9
  54. package/lib/matrix.js.map +1 -1
  55. package/lib/packageVersion.d.ts +1 -1
  56. package/lib/packageVersion.d.ts.map +1 -1
  57. package/lib/packageVersion.js +1 -1
  58. package/lib/packageVersion.js.map +1 -1
  59. package/lib/permutationvector.d.ts +5 -5
  60. package/lib/permutationvector.d.ts.map +1 -1
  61. package/lib/permutationvector.js +11 -4
  62. package/lib/permutationvector.js.map +1 -1
  63. package/lib/public.d.ts +1 -1
  64. package/lib/range.d.ts.map +1 -1
  65. package/lib/range.js.map +1 -1
  66. package/lib/runtime.d.ts.map +1 -1
  67. package/lib/runtime.js.map +1 -1
  68. package/lib/serialization.d.ts.map +1 -1
  69. package/lib/serialization.js.map +1 -1
  70. package/lib/sparsearray2d.d.ts +9 -5
  71. package/lib/sparsearray2d.d.ts.map +1 -1
  72. package/lib/sparsearray2d.js +27 -7
  73. package/lib/sparsearray2d.js.map +1 -1
  74. package/lib/undoprovider.d.ts.map +1 -1
  75. package/lib/undoprovider.js +10 -3
  76. package/lib/undoprovider.js.map +1 -1
  77. package/package.json +36 -30
  78. package/src/handlecache.ts +31 -16
  79. package/src/handletable.ts +11 -9
  80. package/src/matrix.ts +80 -50
  81. package/src/packageVersion.ts +1 -1
  82. package/src/permutationvector.ts +38 -23
  83. package/src/range.ts +1 -1
  84. package/src/runtime.ts +5 -2
  85. package/src/serialization.ts +4 -2
  86. package/src/sparsearray2d.ts +55 -36
  87. package/src/undoprovider.ts +26 -18
  88. package/tsconfig.json +0 -1
package/src/runtime.ts CHANGED
@@ -30,11 +30,11 @@ export class SharedMatrixFactory implements IChannelFactory<ISharedMatrix> {
30
30
  packageVersion: pkgVersion,
31
31
  };
32
32
 
33
- public get type() {
33
+ public get type(): string {
34
34
  return SharedMatrixFactory.Type;
35
35
  }
36
36
 
37
- public get attributes() {
37
+ public get attributes(): IChannelAttributes {
38
38
  return SharedMatrixFactory.Attributes;
39
39
  }
40
40
 
@@ -74,4 +74,7 @@ export const SharedMatrix = createSharedObjectKind<ISharedMatrix>(SharedMatrixFa
74
74
  * @privateRemarks
75
75
  * This alias is for legacy compat from when the SharedMatrix class was exported as public.
76
76
  */
77
+ // Changing this to `unknown` would be a breaking change.
78
+ // TODO: if possible, transition SharedMatrix to not use `any`.
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
80
  export type SharedMatrix<T = any> = ISharedMatrix<T>;
@@ -17,13 +17,15 @@ export const serializeBlob = <T>(
17
17
  path: string,
18
18
  snapshot: Serializable<T>,
19
19
  serializer: IFluidSerializer,
20
- ) => new BlobTreeEntry(path, serializer.stringify(snapshot, handle));
20
+ ): BlobTreeEntry => new BlobTreeEntry(path, serializer.stringify(snapshot, handle));
21
21
 
22
22
  export async function deserializeBlob(
23
23
  storage: IChannelStorageService,
24
24
  path: string,
25
25
  serializer: IFluidSerializer,
26
- ) {
26
+ // Allowing parsed content to remain in its original (any) form.
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ ): Promise<any> {
27
29
  const blob = await storage.readBlob(path);
28
30
  const utf8 = bufferToString(blob, "utf8");
29
31
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -5,45 +5,51 @@
5
5
 
6
6
  /* eslint-disable no-bitwise */
7
7
 
8
- import { IMatrixReader, IMatrixWriter } from "@tiny-calc/nano";
8
+ import { IMatrixReader, IMatrixWriter, type IMatrixProducer } from "@tiny-calc/nano";
9
9
 
10
10
  // Build a lookup table that maps a uint8 to the corresponding uint16 where 0s
11
11
  // are interleaved between the original bits. (e.g., 1111... -> 01010101...).
12
12
  //
13
13
  // (Lookup table ~17% faster than inlining the bit-twiddling on Node v12 x64)
14
14
  // (Array<T> ~2% faster than typed array on Node v12 x64)
15
- const x8ToInterlacedX16 = new Array(256).fill(0).map((value, i) => {
16
- let j = i;
17
- j = (j | (j << 4)) & 0x0f0f; // .... 7654 .... 3210
18
- j = (j | (j << 2)) & 0x3333; // ..76 ..54 ..32 ..10
19
- j = (j | (j << 1)) & 0x5555; // .7.6 .5.4 .3.2 .1.0
20
- return j;
21
- });
15
+ const x8ToInterlacedX16 = Array.from({ length: 256 })
16
+ .fill(0)
17
+ .map((value, i) => {
18
+ let j = i;
19
+ j = (j | (j << 4)) & 0x0f0f; // .... 7654 .... 3210
20
+ j = (j | (j << 2)) & 0x3333; // ..76 ..54 ..32 ..10
21
+ j = (j | (j << 1)) & 0x5555; // .7.6 .5.4 .3.2 .1.0
22
+ return j;
23
+ });
22
24
 
23
25
  // Selects individual bytes from a given 32b integer. The left shift are used to
24
26
  // clear upper bits (faster than using masks on Node 10 x64).
25
- const byte0 = (x32: number) => x32 >>> 24;
26
- const byte1 = (x32: number) => (x32 << 8) >>> 24;
27
- const byte2 = (x32: number) => (x32 << 16) >>> 24;
28
- const byte3 = (x32: number) => (x32 << 24) >>> 24;
27
+ const byte0 = (x32: number): number => x32 >>> 24;
28
+ const byte1 = (x32: number): number => (x32 << 8) >>> 24;
29
+ const byte2 = (x32: number): number => (x32 << 16) >>> 24;
30
+ const byte3 = (x32: number): number => (x32 << 24) >>> 24;
29
31
 
30
32
  // Given a uint16 returns the corresponding uint32 integer where 0s are
31
33
  // interleaved between the original bits. (e.g., 1111... -> 01010101...).
32
- const interlaceBitsX16 = (x16: number) =>
33
- (x8ToInterlacedX16[byte2(x16)] << 16) | x8ToInterlacedX16[byte3(x16)];
34
+ const interlaceBitsX16 = (x16: number): number =>
35
+ // TODO Non null asserting, why is this not null?
36
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
37
+ (x8ToInterlacedX16[byte2(x16)]! << 16) | x8ToInterlacedX16[byte3(x16)]!;
34
38
 
35
- const r0ToMorton16 = (row: number) => (interlaceBitsX16(row) << 1) >>> 0;
36
- const c0ToMorton16 = (col: number) => interlaceBitsX16(col) >>> 0;
39
+ const r0ToMorton16 = (row: number): number => (interlaceBitsX16(row) << 1) >>> 0;
40
+ const c0ToMorton16 = (col: number): number => interlaceBitsX16(col) >>> 0;
37
41
 
38
42
  // Given a 2D uint16 coordinate returns the corresponding unt32 Morton coded
39
43
  // coordinate. (See https://en.wikipedia.org/wiki/Z-order_curve)
40
- const r0c0ToMorton2x16 = (row: number, col: number) =>
44
+ const r0c0ToMorton2x16 = (row: number, col: number): number =>
41
45
  (r0ToMorton16(row) | c0ToMorton16(col)) >>> 0;
42
46
 
43
47
  type RecurArrayHelper<T> = RecurArray<T> | T;
44
- type RecurArray<T> = RecurArrayHelper<T>[];
48
+ export type RecurArray<T> = RecurArrayHelper<T>[];
45
49
 
46
- /** Undo JSON serialization's coercion of 'undefined' to null. */
50
+ /**
51
+ * Undo JSON serialization's coercion of 'undefined' to null.
52
+ */
47
53
  // eslint-disable-next-line @rushstack/no-new-null -- Private use of 'null' to preserve 'undefined'
48
54
  const nullToUndefined = <T>(array: RecurArray<T | null>): RecurArray<T | undefined> =>
49
55
  array.map((value) => {
@@ -83,12 +89,13 @@ export class SparseArray2D<T>
83
89
  return undefined;
84
90
  }
85
91
 
86
- public get matrixProducer() {
87
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
88
- return undefined as any;
92
+ public get matrixProducer(): IMatrixProducer<T> {
93
+ // Cast is needed to satisfy the interface declaration while also not returning
94
+ // an IMatrixProducer for this class.
95
+ return undefined as unknown as IMatrixProducer<T>;
89
96
  }
90
97
 
91
- public setCell(row: number, col: number, value: T | undefined) {
98
+ public setCell(row: number, col: number, value: T | undefined): void {
92
99
  const keyHi = r0c0ToMorton2x16(row >>> 16, col >>> 16);
93
100
  const keyLo = r0c0ToMorton2x16(row, col);
94
101
 
@@ -105,7 +112,7 @@ export class SparseArray2D<T>
105
112
  * (Note that 'rowBits' is the appropriate byte from 'r0ToMorton16' for the current
106
113
  * level being traversed.)
107
114
  */
108
- private forEachKeyInRow(rowBits: number, callback: (key: number) => void) {
115
+ private forEachKeyInRow(rowBits: number, callback: (key: number) => void): void {
109
116
  for (let col = 0; col < 16; col++) {
110
117
  // Perf: Potentially faster to replace 'c0ToMorton16()' with a short look up table?
111
118
  callback((rowBits | c0ToMorton16(col)) >>> 0);
@@ -118,7 +125,7 @@ export class SparseArray2D<T>
118
125
  * (Note that 'colBits' is the appropriate byte from 'c0ToMorton16' for the current
119
126
  * level being traversed.)
120
127
  */
121
- private forEachKeyInCol(col: number, callback: (key: number) => void) {
128
+ private forEachKeyInCol(col: number, callback: (key: number) => void): void {
122
129
  for (let row = 0; row < 16; row++) {
123
130
  // Perf: Potentially faster to replace 'r0ToMorton16()' with a short look up table?
124
131
  callback((r0ToMorton16(row) | col) >>> 0);
@@ -132,11 +139,14 @@ export class SparseArray2D<T>
132
139
  * (Note that 'rowBits' is the appropriate byte from 'r0ToMorton16' for the current
133
140
  * level being traversed.)
134
141
  */
142
+ // The suppression is needed because forEachInRow is called in a loop, and expected to
143
+ // use various abstractions on UA<T> at each level of the loop.
144
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
135
145
  private forEachInRow<V extends UA<any>, U extends UA<V>>(
136
146
  currentLevel: U,
137
147
  rowBits: number,
138
148
  callback: (level: V) => void,
139
- ) {
149
+ ): void {
140
150
  this.forEachKeyInRow(rowBits, (key) => {
141
151
  const nextLevel = currentLevel[key];
142
152
  if (nextLevel !== undefined) {
@@ -152,11 +162,14 @@ export class SparseArray2D<T>
152
162
  * (Note that 'colBits' is the appropriate byte from 'c0ToMorton16' for the current
153
163
  * level being traversed.)
154
164
  */
165
+ // The suppression is needed because forEachInRow is called in a loop, and expected to
166
+ // use various abstractions on UA<T> at each level of the loop.
167
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
168
  private forEachInCol<V extends UA<any>, U extends UA<V>>(
156
169
  currentLevel: U,
157
170
  colBits: number,
158
171
  callback: (level: V) => void,
159
- ) {
172
+ ): void {
160
173
  this.forEachKeyInCol(colBits, (key) => {
161
174
  const nextLevel = currentLevel[key];
162
175
  if (nextLevel !== undefined) {
@@ -165,8 +178,10 @@ export class SparseArray2D<T>
165
178
  });
166
179
  }
167
180
 
168
- /** Clears the all cells contained within the specified span of rows. */
169
- public clearRows(rowStart: number, rowCount: number) {
181
+ /**
182
+ * Clears the all cells contained within the specified span of rows.
183
+ */
184
+ public clearRows(rowStart: number, rowCount: number): void {
170
185
  const rowEnd = rowStart + rowCount;
171
186
  for (let row = rowStart; row < rowEnd; row++) {
172
187
  const rowHi = r0ToMorton16(row >>> 16);
@@ -192,8 +207,10 @@ export class SparseArray2D<T>
192
207
  }
193
208
  }
194
209
 
195
- /** Clears the all cells contained within the specifed span of cols. */
196
- public clearCols(colStart: number, colCount: number) {
210
+ /**
211
+ * Clears the all cells contained within the specifed span of cols.
212
+ */
213
+ public clearCols(colStart: number, colCount: number): void {
197
214
  const colEnd = colStart + colCount;
198
215
  for (let col = colStart; col < colEnd; col++) {
199
216
  const colHi = c0ToMorton16(col >>> 16);
@@ -219,17 +236,19 @@ export class SparseArray2D<T>
219
236
  }
220
237
  }
221
238
 
222
- private getLevel<T>(parent: UA<UA<T>>, subKey: number) {
239
+ private getLevel<T>(parent: UA<UA<T>>, subKey: number): UA<T> {
223
240
  const level = parent[subKey];
224
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
225
- return level ?? (parent[subKey] = new Array(256).fill(undefined));
241
+ // Using new Array is needed because the array created with Array.from does not
242
+ // satisfy (T|undefined)[].
243
+ // eslint-disable-next-line unicorn/no-new-array
244
+ return level ?? (parent[subKey] = new Array<T | undefined>(256).fill(undefined));
226
245
  }
227
246
 
228
- public snapshot() {
247
+ public snapshot(): UA<UA<UA<UA<UA<T>>>>> {
229
248
  return this.root;
230
249
  }
231
250
 
232
- public static load<T>(data: RecurArray<T>) {
251
+ public static load<T>(data: RecurArray<T>): SparseArray2D<T> {
233
252
  return new SparseArray2D<T>(nullToUndefined<T>(data) as SparseArray2D<T>["root"]);
234
253
  }
235
254
  }
@@ -35,7 +35,7 @@ export class VectorUndoProvider {
35
35
  private readonly driver: MergeTreeRevertibleDriver,
36
36
  ) {}
37
37
 
38
- public record(deltaArgs: IMergeTreeDeltaCallbackArgs) {
38
+ public record(deltaArgs: IMergeTreeDeltaCallbackArgs): void {
39
39
  if (deltaArgs.deltaSegments.length > 0) {
40
40
  // If we are in the process of reverting, the `IRevertible.revert()` will provide the tracking
41
41
  // group so that we can preserve the original segment ranges as a single op/group as we move
@@ -63,21 +63,22 @@ export class VectorUndoProvider {
63
63
  // the tracking group provides one.
64
64
  const trackingGroup = (removeTrackingGroup =
65
65
  this.currentRemoveTrackingGroup ?? new TrackingGroup());
66
- deltaArgs.deltaSegments.forEach((d) =>
67
- d.segment.trackingCollection.link(trackingGroup),
68
- );
66
+ for (const d of deltaArgs.deltaSegments)
67
+ d.segment.trackingCollection.link(trackingGroup);
69
68
  }
70
69
 
71
70
  switch (deltaArgs.operation) {
72
71
  case MergeTreeDeltaType.REMOVE:
73
- case MergeTreeDeltaType.INSERT:
72
+ case MergeTreeDeltaType.INSERT: {
74
73
  if (this.currentOp !== deltaArgs.operation) {
75
74
  this.pushRevertible(revertibles, removeTrackingGroup);
76
75
  }
77
76
  break;
77
+ }
78
78
 
79
- default:
79
+ default: {
80
80
  throw new Error("operation type not revertible");
81
+ }
81
82
  }
82
83
 
83
84
  // If we are in the process of reverting, set 'currentOp' to remind ourselves not to push
@@ -93,9 +94,12 @@ export class VectorUndoProvider {
93
94
  private pushRevertible(
94
95
  revertibles: MergeTreeDeltaRevertible[],
95
96
  removedTrackingGroup: ITrackingGroup | undefined,
96
- ) {
97
+ ): {
98
+ revert: () => void;
99
+ discard: () => void;
100
+ } {
97
101
  const reverter = {
98
- revert: () => {
102
+ revert: (): void => {
99
103
  assert(
100
104
  this.currentGroup === undefined && this.currentOp === undefined,
101
105
  0x02b /* "Must not nest calls to IRevertible.revert()" */,
@@ -106,7 +110,9 @@ export class VectorUndoProvider {
106
110
  try {
107
111
  if (removedTrackingGroup !== undefined) {
108
112
  while (removedTrackingGroup.size > 0) {
109
- const tracked = removedTrackingGroup.tracked[0];
113
+ // TODO Non null asserting, why is this not null?
114
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
115
+ const tracked = removedTrackingGroup.tracked[0]!;
110
116
  removedTrackingGroup.unlink(tracked);
111
117
  // if there are groups tracked, this in a revert of a remove.
112
118
  // this means we are about to re-insert the row/column
@@ -124,10 +130,12 @@ export class VectorUndoProvider {
124
130
  this.currentRemoveTrackingGroup = undefined;
125
131
  }
126
132
  },
127
- discard: () => {
133
+ discard: (): void => {
128
134
  if (removedTrackingGroup !== undefined) {
129
135
  while (removedTrackingGroup.size > 0) {
130
- removedTrackingGroup.unlink(removedTrackingGroup.tracked[0]);
136
+ // TODO Non null asserting, why is this not null?
137
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
138
+ removedTrackingGroup.unlink(removedTrackingGroup.tracked[0]!);
131
139
  }
132
140
  }
133
141
  discardMergeTreeDeltaRevertible(revertibles);
@@ -148,30 +156,30 @@ export class MatrixUndoProvider<T> {
148
156
  private readonly cols: PermutationVector,
149
157
  ) {
150
158
  rows.undo = new VectorUndoProvider(consumer, {
151
- annotateRange() {
159
+ annotateRange(): void {
152
160
  throw new Error("not implemented");
153
161
  },
154
- insertFromSpec(pos, spec) {
162
+ insertFromSpec(pos, spec): void {
155
163
  matrix._undoRemoveRows(pos, spec);
156
164
  },
157
- removeRange(start, end) {
165
+ removeRange(start, end): void {
158
166
  matrix.removeRows(start, end - start);
159
167
  },
160
168
  });
161
169
  cols.undo = new VectorUndoProvider(consumer, {
162
- annotateRange() {
170
+ annotateRange(): void {
163
171
  throw new Error("not implemented");
164
172
  },
165
- insertFromSpec(pos, spec) {
173
+ insertFromSpec(pos, spec): void {
166
174
  matrix._undoRemoveCols(pos, spec);
167
175
  },
168
- removeRange(start, end) {
176
+ removeRange(start, end): void {
169
177
  matrix.removeCols(start, end - start);
170
178
  },
171
179
  });
172
180
  }
173
181
 
174
- cellSet(rowHandle: Handle, colHandle: Handle, oldValue: MatrixItem<T>) {
182
+ cellSet(rowHandle: Handle, colHandle: Handle, oldValue: MatrixItem<T>): void {
175
183
  assert(
176
184
  isHandleValid(rowHandle) && isHandleValid(colHandle),
177
185
  0x02c /* "On cellSet(), invalid row and/or column handles!" */,
package/tsconfig.json CHANGED
@@ -6,7 +6,6 @@
6
6
  "rootDir": "./src",
7
7
  "outDir": "./lib",
8
8
  "noImplicitAny": true,
9
- "noUncheckedIndexedAccess": false,
10
9
  "exactOptionalPropertyTypes": false,
11
10
  },
12
11
  }