@fluidframework/map 2.20.0 → 2.22.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.
- package/CHANGELOG.md +18 -0
- package/README.md +1 -0
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +15 -12
- package/dist/directory.js.map +1 -1
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +12 -12
- package/dist/map.js.map +1 -1
- package/dist/mapKernel.d.ts +9 -2
- package/dist/mapKernel.d.ts.map +1 -1
- package/dist/mapKernel.js +10 -3
- package/dist/mapKernel.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/directory.d.ts.map +1 -1
- package/lib/directory.js +15 -12
- package/lib/directory.js.map +1 -1
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +3 -3
- package/lib/map.js.map +1 -1
- package/lib/mapKernel.d.ts +9 -2
- package/lib/mapKernel.d.ts.map +1 -1
- package/lib/mapKernel.js +10 -3
- package/lib/mapKernel.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +35 -23
- package/src/directory.ts +21 -13
- package/src/map.ts +10 -3
- package/src/mapKernel.ts +10 -3
- package/src/packageVersion.ts +1 -1
- package/tsconfig.json +0 -1
package/src/directory.ts
CHANGED
|
@@ -805,7 +805,10 @@ export class SharedDirectory
|
|
|
805
805
|
if (message.type === MessageType.Operation) {
|
|
806
806
|
const op: IDirectoryOperation = message.contents as IDirectoryOperation;
|
|
807
807
|
const handler = this.messageHandlers.get(op.type);
|
|
808
|
-
assert(
|
|
808
|
+
assert(
|
|
809
|
+
handler !== undefined,
|
|
810
|
+
0x00e /* "Missing message handler for message type: op may be from a newer version */,
|
|
811
|
+
);
|
|
809
812
|
handler.process(message, op, local, localOpMetadata);
|
|
810
813
|
}
|
|
811
814
|
}
|
|
@@ -864,18 +867,15 @@ export class SharedDirectory
|
|
|
864
867
|
return false;
|
|
865
868
|
}
|
|
866
869
|
let currentParent = this.root;
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const subDirName = nodeList[start];
|
|
871
|
-
if (currentParent.isSubDirectoryDeletePending(subDirName)) {
|
|
870
|
+
const pathParts = absolutePath.split(posix.sep).slice(1);
|
|
871
|
+
for (const dirName of pathParts) {
|
|
872
|
+
if (currentParent.isSubDirectoryDeletePending(dirName)) {
|
|
872
873
|
return true;
|
|
873
874
|
}
|
|
874
|
-
currentParent = currentParent.getSubDirectory(
|
|
875
|
+
currentParent = currentParent.getSubDirectory(dirName) as SubDirectory;
|
|
875
876
|
if (currentParent === undefined) {
|
|
876
877
|
return true;
|
|
877
878
|
}
|
|
878
|
-
start += 1;
|
|
879
879
|
}
|
|
880
880
|
return false;
|
|
881
881
|
}
|
|
@@ -1492,7 +1492,9 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1492
1492
|
dirs: this._subdirectories,
|
|
1493
1493
|
next(): IteratorResult<[string, IDirectory]> {
|
|
1494
1494
|
if (this.index < subdirNames.length) {
|
|
1495
|
-
|
|
1495
|
+
// Bounds check above guarantees non-null (at least at compile time, assuming all types are respected)
|
|
1496
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1497
|
+
const subdirName = subdirNames[this.index++]!;
|
|
1496
1498
|
const subdir = this.dirs.get(subdirName);
|
|
1497
1499
|
assert(subdir !== undefined, 0x8ac /* Could not find expected sub-directory. */);
|
|
1498
1500
|
return { value: [subdirName, subdir], done: false };
|
|
@@ -2181,21 +2183,27 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
2181
2183
|
local: boolean,
|
|
2182
2184
|
localOpMetadata: unknown,
|
|
2183
2185
|
): boolean {
|
|
2184
|
-
|
|
2186
|
+
const firstPendingClearMessageId = this.pendingClearMessageIds[0];
|
|
2187
|
+
if (firstPendingClearMessageId !== undefined) {
|
|
2185
2188
|
if (local) {
|
|
2186
2189
|
assert(
|
|
2187
2190
|
localOpMetadata !== undefined &&
|
|
2188
2191
|
isKeyEditLocalOpMetadata(localOpMetadata) &&
|
|
2189
|
-
localOpMetadata.pendingMessageId <
|
|
2192
|
+
localOpMetadata.pendingMessageId < firstPendingClearMessageId,
|
|
2190
2193
|
0x010 /* "Received out of order storage op when there is an unackd clear message" */,
|
|
2191
2194
|
);
|
|
2192
2195
|
// Remove all pendingMessageIds lower than first pendingClearMessageId.
|
|
2193
|
-
const lowestPendingClearMessageId =
|
|
2196
|
+
const lowestPendingClearMessageId = firstPendingClearMessageId;
|
|
2194
2197
|
const pendingKeyMessageIdArray = this.pendingKeys.get(op.key);
|
|
2195
2198
|
if (pendingKeyMessageIdArray !== undefined) {
|
|
2196
2199
|
let index = 0;
|
|
2197
|
-
|
|
2200
|
+
let pendingKeyMessageId = pendingKeyMessageIdArray[index];
|
|
2201
|
+
while (
|
|
2202
|
+
pendingKeyMessageId !== undefined &&
|
|
2203
|
+
pendingKeyMessageId < lowestPendingClearMessageId
|
|
2204
|
+
) {
|
|
2198
2205
|
index += 1;
|
|
2206
|
+
pendingKeyMessageId = pendingKeyMessageIdArray[index];
|
|
2199
2207
|
}
|
|
2200
2208
|
const newPendingKeyMessageId = pendingKeyMessageIdArray.splice(index);
|
|
2201
2209
|
if (newPendingKeyMessageId.length === 0) {
|
package/src/map.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
6
7
|
import type {
|
|
7
8
|
IChannelAttributes,
|
|
8
9
|
IFluidDataStoreRuntime,
|
|
@@ -202,8 +203,7 @@ export class SharedMap extends SharedObject<ISharedMapEvents> implements IShared
|
|
|
202
203
|
// and result in non-incremental snapshot.
|
|
203
204
|
// This can be improved in the future, without being format breaking change, as loading sequence
|
|
204
205
|
// loads all blobs at once and partitioning schema has no impact on that process.
|
|
205
|
-
for (const key of Object.
|
|
206
|
-
const value = data[key];
|
|
206
|
+
for (const [key, value] of Object.entries(data)) {
|
|
207
207
|
if (value.value && value.value.length >= MinValueSizeSeparateSnapshotBlob) {
|
|
208
208
|
const blobName = `blob${counter}`;
|
|
209
209
|
counter++;
|
|
@@ -293,7 +293,14 @@ export class SharedMap extends SharedObject<ISharedMapEvents> implements IShared
|
|
|
293
293
|
): void {
|
|
294
294
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
295
295
|
if (message.type === MessageType.Operation) {
|
|
296
|
-
|
|
296
|
+
assert(
|
|
297
|
+
this.kernel.tryProcessMessage(
|
|
298
|
+
message.contents as IMapOperation,
|
|
299
|
+
local,
|
|
300
|
+
localOpMetadata,
|
|
301
|
+
),
|
|
302
|
+
0xab2 /* Map received an unrecognized op, possibly from a newer version */,
|
|
303
|
+
);
|
|
297
304
|
}
|
|
298
305
|
}
|
|
299
306
|
|
package/src/mapKernel.ts
CHANGED
|
@@ -437,11 +437,18 @@ export class MapKernel {
|
|
|
437
437
|
|
|
438
438
|
/**
|
|
439
439
|
* Process the given op if a handler is registered.
|
|
440
|
-
* @param
|
|
440
|
+
* @param message - The message to process
|
|
441
441
|
* @param local - Whether the message originated from the local client
|
|
442
442
|
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
443
443
|
* For messages from a remote client, this will be undefined.
|
|
444
|
-
* @returns True if the operation was processed, false otherwise.
|
|
444
|
+
* @returns True if the operation was recognized and thus processed, false otherwise.
|
|
445
|
+
*
|
|
446
|
+
* @remarks
|
|
447
|
+
* When this returns false and the caller doesn't handle the op itself, then the op could be from a different version of this code.
|
|
448
|
+
* In such a case, not applying the op would result in this client becoming out of sync with clients that do handle the op
|
|
449
|
+
* and could result in data corruption or data loss as well.
|
|
450
|
+
* Therefore, in such cases the caller should typically throw an error, ensuring that this client treats the situation as data corruption
|
|
451
|
+
* (since its data no longer matches what other clients think the data should be) and will avoid overriding document content or misleading the users into thinking their current state is accurate.
|
|
445
452
|
*/
|
|
446
453
|
public tryProcessMessage(
|
|
447
454
|
op: IMapOperation,
|
|
@@ -607,7 +614,7 @@ export class MapKernel {
|
|
|
607
614
|
local: boolean,
|
|
608
615
|
localOpMetadata: MapLocalOpMetadata,
|
|
609
616
|
): boolean {
|
|
610
|
-
if (this.pendingClearMessageIds
|
|
617
|
+
if (this.pendingClearMessageIds[0] !== undefined) {
|
|
611
618
|
if (local) {
|
|
612
619
|
assert(
|
|
613
620
|
localOpMetadata !== undefined &&
|
package/src/packageVersion.ts
CHANGED