@fluidframework/sequence 0.59.3003 → 0.59.4000
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/dist/{mapKernel.d.ts → defaultMap.d.ts} +21 -145
- package/dist/defaultMap.d.ts.map +1 -0
- package/dist/defaultMap.js +317 -0
- package/dist/defaultMap.js.map +1 -0
- package/dist/{mapKernelInterfaces.d.ts → defaultMapInterfaces.d.ts} +9 -51
- package/dist/defaultMapInterfaces.d.ts.map +1 -0
- package/dist/{mapKernelInterfaces.js → defaultMapInterfaces.js} +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +12 -3
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +44 -39
- package/dist/intervalCollection.js.map +1 -1
- package/dist/localValues.d.ts +7 -86
- package/dist/localValues.d.ts.map +1 -1
- package/dist/localValues.js +1 -131
- package/dist/localValues.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/dist/sequence.d.ts +5 -1
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +23 -23
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +13 -5
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +16 -12
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/lib/{mapKernel.d.ts → defaultMap.d.ts} +21 -145
- package/lib/defaultMap.d.ts.map +1 -0
- package/lib/defaultMap.js +313 -0
- package/lib/defaultMap.js.map +1 -0
- package/lib/{mapKernelInterfaces.d.ts → defaultMapInterfaces.d.ts} +9 -51
- package/lib/defaultMapInterfaces.d.ts.map +1 -0
- package/lib/{mapKernelInterfaces.js → defaultMapInterfaces.js} +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +12 -3
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +44 -39
- package/lib/intervalCollection.js.map +1 -1
- package/lib/localValues.d.ts +7 -86
- package/lib/localValues.d.ts.map +1 -1
- package/lib/localValues.js +1 -129
- package/lib/localValues.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/lib/sequence.d.ts +5 -1
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +23 -23
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +13 -5
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +16 -12
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/package.json +23 -18
- package/src/defaultMap.ts +453 -0
- package/src/{mapKernelInterfaces.ts → defaultMapInterfaces.ts} +14 -59
- package/src/index.ts +1 -1
- package/src/intervalCollection.ts +58 -43
- package/src/localValues.ts +6 -154
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +32 -33
- package/src/sharedIntervalCollection.ts +22 -25
- package/dist/mapKernel.d.ts.map +0 -1
- package/dist/mapKernel.js +0 -599
- package/dist/mapKernel.js.map +0 -1
- package/dist/mapKernelInterfaces.d.ts.map +0 -1
- package/dist/mapKernelInterfaces.js.map +0 -1
- package/lib/mapKernel.d.ts.map +0 -1
- package/lib/mapKernel.js +0 -595
- package/lib/mapKernel.js.map +0 -1
- package/lib/mapKernelInterfaces.d.ts.map +0 -1
- package/lib/mapKernelInterfaces.js.map +0 -1
- package/src/mapKernel.ts +0 -850
|
@@ -6,10 +6,8 @@ import { IFluidHandle } from "@fluidframework/core-interfaces";
|
|
|
6
6
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
7
7
|
import { IFluidSerializer } from "@fluidframework/shared-object-base";
|
|
8
8
|
import { TypedEventEmitter } from "@fluidframework/common-utils";
|
|
9
|
-
import { ISerializableValue, ISerializedValue, IValueType,
|
|
10
|
-
interface IMapMessageLocalMetadata {
|
|
11
|
-
pendingClearMessageId?: number;
|
|
12
|
-
pendingMessageId?: number;
|
|
9
|
+
import { ISerializableValue, ISerializedValue, IValueType, IValueTypeOperationValue, ISharedDefaultMapEvents } from "./defaultMapInterfaces";
|
|
10
|
+
export interface IMapMessageLocalMetadata {
|
|
13
11
|
lastProcessedSeq: number;
|
|
14
12
|
}
|
|
15
13
|
/**
|
|
@@ -30,53 +28,10 @@ export interface IMapValueTypeOperation {
|
|
|
30
28
|
*/
|
|
31
29
|
value: IValueTypeOperationValue;
|
|
32
30
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Operation indicating a value should be set for a key.
|
|
35
|
-
*/
|
|
36
|
-
export interface IMapSetOperation {
|
|
37
|
-
/**
|
|
38
|
-
* String identifier of the operation type.
|
|
39
|
-
*/
|
|
40
|
-
type: "set";
|
|
41
|
-
/**
|
|
42
|
-
* Map key being modified.
|
|
43
|
-
*/
|
|
44
|
-
key: string;
|
|
45
|
-
/**
|
|
46
|
-
* Value to be set on the key.
|
|
47
|
-
*/
|
|
48
|
-
value: ISerializableValue;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Operation indicating a key should be deleted from the map.
|
|
52
|
-
*/
|
|
53
|
-
export interface IMapDeleteOperation {
|
|
54
|
-
/**
|
|
55
|
-
* String identifier of the operation type.
|
|
56
|
-
*/
|
|
57
|
-
type: "delete";
|
|
58
|
-
/**
|
|
59
|
-
* Map key being modified.
|
|
60
|
-
*/
|
|
61
|
-
key: string;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Map key operations are one of several types.
|
|
65
|
-
*/
|
|
66
|
-
export declare type IMapKeyOperation = IMapValueTypeOperation | IMapSetOperation | IMapDeleteOperation;
|
|
67
|
-
/**
|
|
68
|
-
* Operation indicating the map should be cleared.
|
|
69
|
-
*/
|
|
70
|
-
export interface IMapClearOperation {
|
|
71
|
-
/**
|
|
72
|
-
* String identifier of the operation type.
|
|
73
|
-
*/
|
|
74
|
-
type: "clear";
|
|
75
|
-
}
|
|
76
31
|
/**
|
|
77
32
|
* Description of a map delta operation
|
|
78
33
|
*/
|
|
79
|
-
export declare type IMapOperation =
|
|
34
|
+
export declare type IMapOperation = IMapValueTypeOperation;
|
|
80
35
|
/**
|
|
81
36
|
* Defines the in-memory object structure to be used for the conversion to/from serialized.
|
|
82
37
|
* Directly used in JSON.stringify, direct result from JSON.parse
|
|
@@ -88,14 +43,18 @@ export interface IMapDataObjectSerialized {
|
|
|
88
43
|
[key: string]: ISerializedValue;
|
|
89
44
|
}
|
|
90
45
|
/**
|
|
91
|
-
* A
|
|
46
|
+
* A DefaultMap is a map-like distributed data structure, supporting operations on values stored by
|
|
47
|
+
* string key locations.
|
|
48
|
+
*
|
|
49
|
+
* Creation of values is implicit on access (either via `get` or a remote op application referring to
|
|
50
|
+
* a collection that wasn't previously known)
|
|
92
51
|
*/
|
|
93
|
-
export declare class
|
|
52
|
+
export declare class DefaultMap<T> {
|
|
94
53
|
private readonly serializer;
|
|
95
54
|
private readonly handle;
|
|
96
55
|
private readonly submitMessage;
|
|
97
|
-
private readonly
|
|
98
|
-
readonly eventEmitter: TypedEventEmitter<
|
|
56
|
+
private readonly type;
|
|
57
|
+
readonly eventEmitter: TypedEventEmitter<ISharedDefaultMapEvents>;
|
|
99
58
|
/**
|
|
100
59
|
* The number of key/value pairs stored in the map.
|
|
101
60
|
*/
|
|
@@ -108,34 +67,16 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
108
67
|
* The in-memory data the map is storing.
|
|
109
68
|
*/
|
|
110
69
|
private readonly data;
|
|
111
|
-
/**
|
|
112
|
-
* Keys that have been modified locally but not yet ack'd from the server.
|
|
113
|
-
*/
|
|
114
|
-
private readonly pendingKeys;
|
|
115
|
-
/**
|
|
116
|
-
* This is used to assign a unique id to every outgoing operation and helps in tracking unacked ops.
|
|
117
|
-
*/
|
|
118
|
-
private pendingMessageId;
|
|
119
|
-
/**
|
|
120
|
-
* If a clear has been performed locally but not yet ack'd from the server, then this stores the pending id
|
|
121
|
-
* of that clear operation. Otherwise, is -1.
|
|
122
|
-
*/
|
|
123
|
-
private pendingClearMessageId;
|
|
124
|
-
/**
|
|
125
|
-
* Object to create encapsulations of the values stored in the map.
|
|
126
|
-
*/
|
|
127
|
-
private readonly localValueMaker;
|
|
128
70
|
private lastProcessedSeq;
|
|
129
71
|
/**
|
|
130
|
-
* Create a new
|
|
72
|
+
* Create a new default map.
|
|
131
73
|
* @param serializer - The serializer to serialize / parse handles
|
|
132
74
|
* @param handle - The handle of the shared object using the kernel
|
|
133
75
|
* @param submitMessage - A callback to submit a message through the shared object
|
|
134
|
-
* @param
|
|
135
|
-
* @param valueTypes - The value types to register
|
|
76
|
+
* @param type - The value type to create at values of this map
|
|
136
77
|
* @param eventEmitter - The object that will emit map events
|
|
137
78
|
*/
|
|
138
|
-
constructor(serializer: IFluidSerializer, handle: IFluidHandle, submitMessage: (op: any, localOpMetadata: IMapMessageLocalMetadata) => void,
|
|
79
|
+
constructor(serializer: IFluidSerializer, handle: IFluidHandle, submitMessage: (op: any, localOpMetadata: IMapMessageLocalMetadata) => void, type: IValueType<T>, eventEmitter?: TypedEventEmitter<ISharedDefaultMapEvents>);
|
|
139
80
|
/**
|
|
140
81
|
* Get an iterator over the keys in this map.
|
|
141
82
|
* @returns The iterator
|
|
@@ -164,35 +105,13 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
164
105
|
/**
|
|
165
106
|
* {@inheritDoc ISharedMap.get}
|
|
166
107
|
*/
|
|
167
|
-
get
|
|
168
|
-
/**
|
|
169
|
-
* {@inheritDoc ISharedMap.wait}
|
|
170
|
-
*/
|
|
171
|
-
wait<T = any>(key: string): Promise<T>;
|
|
108
|
+
get(key: string): T;
|
|
172
109
|
/**
|
|
173
110
|
* Check if a key exists in the map.
|
|
174
111
|
* @param key - The key to check
|
|
175
112
|
* @returns True if the key exists, false otherwise
|
|
176
113
|
*/
|
|
177
114
|
has(key: string): boolean;
|
|
178
|
-
/**
|
|
179
|
-
* {@inheritDoc ISharedMap.set}
|
|
180
|
-
*/
|
|
181
|
-
set(key: string, value: any): void;
|
|
182
|
-
/**
|
|
183
|
-
* {@inheritDoc IValueTypeCreator.createValueType}
|
|
184
|
-
*/
|
|
185
|
-
createValueType(key: string, type: string, params: any): this;
|
|
186
|
-
/**
|
|
187
|
-
* Delete a key from the map.
|
|
188
|
-
* @param key - Key to delete
|
|
189
|
-
* @returns True if the key existed and was deleted, false if it did not exist
|
|
190
|
-
*/
|
|
191
|
-
delete(key: string): boolean;
|
|
192
|
-
/**
|
|
193
|
-
* Clear all data from the map.
|
|
194
|
-
*/
|
|
195
|
-
clear(): void;
|
|
196
115
|
/**
|
|
197
116
|
* Serializes the data stored in the shared map to a JSON string
|
|
198
117
|
* @param serializer - The serializer to use to serialize handles in its values.
|
|
@@ -215,7 +134,7 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
215
134
|
* also sent if we are asked to resubmit the message.
|
|
216
135
|
* @returns True if the operation was submitted, false otherwise.
|
|
217
136
|
*/
|
|
218
|
-
trySubmitMessage(op: any, localOpMetadata:
|
|
137
|
+
trySubmitMessage(op: any, localOpMetadata: IMapMessageLocalMetadata): boolean;
|
|
219
138
|
tryGetStashedOpLocalMetadata(op: any): unknown;
|
|
220
139
|
/**
|
|
221
140
|
* Process the given op if a handler is registered.
|
|
@@ -227,31 +146,12 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
227
146
|
*/
|
|
228
147
|
tryProcessMessage(op: IMapOperation, local: boolean, message: ISequencedDocumentMessage | undefined, localOpMetadata: unknown): boolean;
|
|
229
148
|
/**
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* @param
|
|
233
|
-
* @param local - Whether the message originated from the local client
|
|
234
|
-
* @param op - The message if from a remote set, or null if from a local set
|
|
235
|
-
*/
|
|
236
|
-
private setCore;
|
|
237
|
-
/**
|
|
238
|
-
* Clear implementation used for both locally sourced clears as well as incoming remote clears.
|
|
239
|
-
* @param local - Whether the message originated from the local client
|
|
240
|
-
* @param op - The message if from a remote clear, or null if from a local clear
|
|
241
|
-
*/
|
|
242
|
-
private clearCore;
|
|
243
|
-
/**
|
|
244
|
-
* Delete implementation used for both locally sourced deletes as well as incoming remote deletes.
|
|
245
|
-
* @param key - The key being deleted
|
|
149
|
+
* Initializes a default ValueType at the provided key.
|
|
150
|
+
* Should be used when a map operation incurs creation.
|
|
151
|
+
* @param key - The key being initialized
|
|
246
152
|
* @param local - Whether the message originated from the local client
|
|
247
|
-
* @param op - The message if from a remote delete, or null if from a local delete
|
|
248
|
-
* @returns True if the key existed and was deleted, false if it did not exist
|
|
249
|
-
*/
|
|
250
|
-
private deleteCore;
|
|
251
|
-
/**
|
|
252
|
-
* Clear all keys in memory in response to a remote clear, but retain keys we have modified but not yet been ack'd.
|
|
253
153
|
*/
|
|
254
|
-
private
|
|
154
|
+
private createCore;
|
|
255
155
|
/**
|
|
256
156
|
* The remote ISerializableValue we're receiving (either as a result of a load or an incoming set op) will
|
|
257
157
|
* have the information we need to create a real object, but will not be the real object yet. For example,
|
|
@@ -263,34 +163,11 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
263
163
|
* @returns The local value that was produced
|
|
264
164
|
*/
|
|
265
165
|
private makeLocal;
|
|
266
|
-
/**
|
|
267
|
-
* If our local operations that have not yet been ack'd will eventually overwrite an incoming operation, we should
|
|
268
|
-
* not process the incoming operation.
|
|
269
|
-
* @param op - Operation to check
|
|
270
|
-
* @param local - Whether the message originated from the local client
|
|
271
|
-
* @param message - The message
|
|
272
|
-
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
273
|
-
* For messages from a remote client, this will be undefined.
|
|
274
|
-
* @returns True if the operation should be processed, false otherwise
|
|
275
|
-
*/
|
|
276
|
-
private needProcessKeyOperation;
|
|
277
166
|
/**
|
|
278
167
|
* Get the message handlers for the map.
|
|
279
168
|
* @returns A map of string op names to IMapMessageHandlers for those ops
|
|
280
169
|
*/
|
|
281
170
|
private getMessageHandlers;
|
|
282
|
-
private getMapClearMessageLocalMetadata;
|
|
283
|
-
/**
|
|
284
|
-
* Submit a clear message to remote clients.
|
|
285
|
-
* @param op - The clear message
|
|
286
|
-
*/
|
|
287
|
-
private submitMapClearMessage;
|
|
288
|
-
private getMapKeyMessageLocalMetadata;
|
|
289
|
-
/**
|
|
290
|
-
* Submit a map key message to remote clients.
|
|
291
|
-
* @param op - The map key message
|
|
292
|
-
*/
|
|
293
|
-
private submitMapKeyMessage;
|
|
294
171
|
/**
|
|
295
172
|
* Create an emitter for a value type to emit ops from the given key.
|
|
296
173
|
* @alpha
|
|
@@ -299,5 +176,4 @@ export declare class MapKernel implements IValueTypeCreator {
|
|
|
299
176
|
*/
|
|
300
177
|
private makeMapValueOpEmitter;
|
|
301
178
|
}
|
|
302
|
-
|
|
303
|
-
//# sourceMappingURL=mapKernel.d.ts.map
|
|
179
|
+
//# sourceMappingURL=defaultMap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultMap.d.ts","sourceRoot":"","sources":["../src/defaultMap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DefaultMap = void 0;
|
|
8
|
+
const shared_object_base_1 = require("@fluidframework/shared-object-base");
|
|
9
|
+
const common_utils_1 = require("@fluidframework/common-utils");
|
|
10
|
+
const localValues_1 = require("./localValues");
|
|
11
|
+
/**
|
|
12
|
+
* A DefaultMap is a map-like distributed data structure, supporting operations on values stored by
|
|
13
|
+
* string key locations.
|
|
14
|
+
*
|
|
15
|
+
* Creation of values is implicit on access (either via `get` or a remote op application referring to
|
|
16
|
+
* a collection that wasn't previously known)
|
|
17
|
+
*/
|
|
18
|
+
class DefaultMap {
|
|
19
|
+
/**
|
|
20
|
+
* Create a new default map.
|
|
21
|
+
* @param serializer - The serializer to serialize / parse handles
|
|
22
|
+
* @param handle - The handle of the shared object using the kernel
|
|
23
|
+
* @param submitMessage - A callback to submit a message through the shared object
|
|
24
|
+
* @param type - The value type to create at values of this map
|
|
25
|
+
* @param eventEmitter - The object that will emit map events
|
|
26
|
+
*/
|
|
27
|
+
constructor(serializer, handle, submitMessage, type, eventEmitter = new common_utils_1.TypedEventEmitter()) {
|
|
28
|
+
this.serializer = serializer;
|
|
29
|
+
this.handle = handle;
|
|
30
|
+
this.submitMessage = submitMessage;
|
|
31
|
+
this.type = type;
|
|
32
|
+
this.eventEmitter = eventEmitter;
|
|
33
|
+
/**
|
|
34
|
+
* Mapping of op types to message handlers.
|
|
35
|
+
*/
|
|
36
|
+
this.messageHandlers = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* The in-memory data the map is storing.
|
|
39
|
+
*/
|
|
40
|
+
this.data = new Map();
|
|
41
|
+
this.lastProcessedSeq = -1;
|
|
42
|
+
this.messageHandlers = this.getMessageHandlers();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The number of key/value pairs stored in the map.
|
|
46
|
+
*/
|
|
47
|
+
get size() {
|
|
48
|
+
return this.data.size;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get an iterator over the keys in this map.
|
|
52
|
+
* @returns The iterator
|
|
53
|
+
*/
|
|
54
|
+
keys() {
|
|
55
|
+
return this.data.keys();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get an iterator over the entries in this map.
|
|
59
|
+
* @returns The iterator
|
|
60
|
+
*/
|
|
61
|
+
entries() {
|
|
62
|
+
const localEntriesIterator = this.data.entries();
|
|
63
|
+
const iterator = {
|
|
64
|
+
next() {
|
|
65
|
+
const nextVal = localEntriesIterator.next();
|
|
66
|
+
if (nextVal.done) {
|
|
67
|
+
return { value: undefined, done: true };
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Unpack the stored value
|
|
71
|
+
return { value: [nextVal.value[0], nextVal.value[1].value], done: false };
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
[Symbol.iterator]() {
|
|
75
|
+
return this;
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
return iterator;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get an iterator over the values in this map.
|
|
82
|
+
* @returns The iterator
|
|
83
|
+
*/
|
|
84
|
+
values() {
|
|
85
|
+
const localValuesIterator = this.data.values();
|
|
86
|
+
const iterator = {
|
|
87
|
+
next() {
|
|
88
|
+
const nextVal = localValuesIterator.next();
|
|
89
|
+
if (nextVal.done) {
|
|
90
|
+
return { value: undefined, done: true };
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// Unpack the stored value
|
|
94
|
+
return { value: nextVal.value.value, done: false };
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
[Symbol.iterator]() {
|
|
98
|
+
return this;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
return iterator;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get an iterator over the entries in this map.
|
|
105
|
+
* @returns The iterator
|
|
106
|
+
*/
|
|
107
|
+
[Symbol.iterator]() {
|
|
108
|
+
return this.entries();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Executes the given callback on each entry in the map.
|
|
112
|
+
* @param callbackFn - Callback function
|
|
113
|
+
*/
|
|
114
|
+
forEach(callbackFn) {
|
|
115
|
+
this.data.forEach((localValue, key, m) => {
|
|
116
|
+
callbackFn(localValue.value, key, m);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* {@inheritDoc ISharedMap.get}
|
|
121
|
+
*/
|
|
122
|
+
get(key) {
|
|
123
|
+
let localValue = this.data.get(key);
|
|
124
|
+
if (!this.data.has(key)) {
|
|
125
|
+
localValue = this.createCore(key, true);
|
|
126
|
+
}
|
|
127
|
+
return localValue.value;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if a key exists in the map.
|
|
131
|
+
* @param key - The key to check
|
|
132
|
+
* @returns True if the key exists, false otherwise
|
|
133
|
+
*/
|
|
134
|
+
has(key) {
|
|
135
|
+
return this.data.has(key);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Serializes the data stored in the shared map to a JSON string
|
|
139
|
+
* @param serializer - The serializer to use to serialize handles in its values.
|
|
140
|
+
* @returns A JSON string containing serialized map data
|
|
141
|
+
*/
|
|
142
|
+
getSerializedStorage(serializer) {
|
|
143
|
+
const serializableMapData = {};
|
|
144
|
+
this.data.forEach((localValue, key) => {
|
|
145
|
+
serializableMapData[key] = localValue.makeSerialized(serializer, this.handle);
|
|
146
|
+
});
|
|
147
|
+
return serializableMapData;
|
|
148
|
+
}
|
|
149
|
+
getSerializableStorage(serializer) {
|
|
150
|
+
const serializableMapData = {};
|
|
151
|
+
this.data.forEach((localValue, key) => {
|
|
152
|
+
serializableMapData[key] = (0, localValues_1.makeSerializable)(localValue, serializer, this.handle);
|
|
153
|
+
});
|
|
154
|
+
return serializableMapData;
|
|
155
|
+
}
|
|
156
|
+
serialize(serializer) {
|
|
157
|
+
return JSON.stringify(this.getSerializableStorage(serializer));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Populate the kernel with the given map data.
|
|
161
|
+
* @param data - A JSON string containing serialized map data
|
|
162
|
+
*/
|
|
163
|
+
populateFromSerializable(json) {
|
|
164
|
+
for (const [key, serializable] of Object.entries(json)) {
|
|
165
|
+
// Back-compat: legacy documents may have handles to an intervalCollection map kernel.
|
|
166
|
+
// These collections should be empty, and ValueTypes are no longer supported.
|
|
167
|
+
if (serializable.type === shared_object_base_1.ValueType[shared_object_base_1.ValueType.Plain]
|
|
168
|
+
|| serializable.type === shared_object_base_1.ValueType[shared_object_base_1.ValueType.Shared]) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const localValue = {
|
|
172
|
+
key,
|
|
173
|
+
value: this.makeLocal(key, serializable),
|
|
174
|
+
};
|
|
175
|
+
this.data.set(localValue.key, localValue.value);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
populate(json) {
|
|
179
|
+
this.populateFromSerializable(JSON.parse(json));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Submit the given op if a handler is registered.
|
|
183
|
+
* @param op - The operation to attempt to submit
|
|
184
|
+
* @param localOpMetadata - The local metadata associated with the op. This is kept locally by the runtime
|
|
185
|
+
* and not sent to the server. This will be sent back when this message is received back from the server. This is
|
|
186
|
+
* also sent if we are asked to resubmit the message.
|
|
187
|
+
* @returns True if the operation was submitted, false otherwise.
|
|
188
|
+
*/
|
|
189
|
+
trySubmitMessage(op, localOpMetadata) {
|
|
190
|
+
const type = op.type;
|
|
191
|
+
const handler = this.messageHandlers.get(type);
|
|
192
|
+
if (handler !== undefined) {
|
|
193
|
+
const mapLocalMetadata = localOpMetadata;
|
|
194
|
+
// we don't know how to rebase these operations, so if any other op has come in
|
|
195
|
+
// we will fail.
|
|
196
|
+
if (this.lastProcessedSeq !== (mapLocalMetadata === null || mapLocalMetadata === void 0 ? void 0 : mapLocalMetadata.lastProcessedSeq)) {
|
|
197
|
+
throw new Error("SharedInterval does not support reconnect in presence of external changes");
|
|
198
|
+
}
|
|
199
|
+
handler.submit(op);
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
tryGetStashedOpLocalMetadata(op) {
|
|
205
|
+
const type = op.type;
|
|
206
|
+
if (this.messageHandlers.has(type)) {
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
208
|
+
return this.messageHandlers.get(type).getStashedOpLocalMetadata(op);
|
|
209
|
+
}
|
|
210
|
+
throw new Error("no apply stashed op handler");
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Process the given op if a handler is registered.
|
|
214
|
+
* @param message - The message to process
|
|
215
|
+
* @param local - Whether the message originated from the local client
|
|
216
|
+
* @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.
|
|
217
|
+
* For messages from a remote client, this will be undefined.
|
|
218
|
+
* @returns True if the operation was processed, false otherwise.
|
|
219
|
+
*/
|
|
220
|
+
tryProcessMessage(op, local, message, localOpMetadata) {
|
|
221
|
+
// track the seq of every incoming message, so we can detect if any
|
|
222
|
+
// changes happened during a resubmit
|
|
223
|
+
this.lastProcessedSeq = message.sequenceNumber;
|
|
224
|
+
const handler = this.messageHandlers.get(op.type);
|
|
225
|
+
if (handler !== undefined) {
|
|
226
|
+
handler.process(op, local, message, localOpMetadata);
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Initializes a default ValueType at the provided key.
|
|
233
|
+
* Should be used when a map operation incurs creation.
|
|
234
|
+
* @param key - The key being initialized
|
|
235
|
+
* @param local - Whether the message originated from the local client
|
|
236
|
+
*/
|
|
237
|
+
createCore(key, local) {
|
|
238
|
+
const localValue = new localValues_1.ValueTypeLocalValue(this.type.factory.load(this.makeMapValueOpEmitter(key), undefined), this.type);
|
|
239
|
+
const previousValue = this.data.get(key);
|
|
240
|
+
this.data.set(key, localValue);
|
|
241
|
+
const event = { key, previousValue };
|
|
242
|
+
this.eventEmitter.emit("create", event, local, this.eventEmitter);
|
|
243
|
+
return localValue;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The remote ISerializableValue we're receiving (either as a result of a load or an incoming set op) will
|
|
247
|
+
* have the information we need to create a real object, but will not be the real object yet. For example,
|
|
248
|
+
* we might know it's a map and the map's ID but not have the actual map or its data yet. makeLocal's
|
|
249
|
+
* job is to convert that information into a real object for local usage.
|
|
250
|
+
* @param key - The key that the caller intends to store the local value into (used for ops later). But
|
|
251
|
+
* doesn't actually store the local value into that key. So better not lie!
|
|
252
|
+
* @param serializable - The remote information that we can convert into a real object
|
|
253
|
+
* @returns The local value that was produced
|
|
254
|
+
*/
|
|
255
|
+
makeLocal(key, serializable) {
|
|
256
|
+
(0, common_utils_1.assert)(serializable.type !== shared_object_base_1.ValueType[shared_object_base_1.ValueType.Plain] && serializable.type !== shared_object_base_1.ValueType[shared_object_base_1.ValueType.Shared], 0x2e1 /* "Support for plain value types removed." */);
|
|
257
|
+
serializable.value = (0, shared_object_base_1.parseHandles)(serializable.value, this.serializer);
|
|
258
|
+
const localValue = this.type.factory.load(this.makeMapValueOpEmitter(key), serializable.value);
|
|
259
|
+
return new localValues_1.ValueTypeLocalValue(localValue, this.type);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get the message handlers for the map.
|
|
263
|
+
* @returns A map of string op names to IMapMessageHandlers for those ops
|
|
264
|
+
*/
|
|
265
|
+
getMessageHandlers() {
|
|
266
|
+
const messageHandlers = new Map();
|
|
267
|
+
// Ops with type "act" describe actions taken by custom value type handlers of whatever item is
|
|
268
|
+
// being addressed. These custom handlers can be retrieved from the ValueTypeLocalValue which has
|
|
269
|
+
// stashed its valueType (and therefore its handlers). We also emit a valueChanged for anyone
|
|
270
|
+
// watching for manipulations of that item.
|
|
271
|
+
messageHandlers.set("act", {
|
|
272
|
+
process: (op, local, message, localOpMetadata) => {
|
|
273
|
+
var _a;
|
|
274
|
+
const localValue = (_a = this.data.get(op.key)) !== null && _a !== void 0 ? _a : this.createCore(op.key, local);
|
|
275
|
+
const handler = localValue.getOpHandler(op.value.opName);
|
|
276
|
+
const previousValue = localValue.value;
|
|
277
|
+
const translatedValue = (0, shared_object_base_1.parseHandles)(op.value.value, this.serializer);
|
|
278
|
+
handler.process(previousValue, translatedValue, local, message);
|
|
279
|
+
const event = { key: op.key, previousValue };
|
|
280
|
+
this.eventEmitter.emit("valueChanged", event, local, message, this.eventEmitter);
|
|
281
|
+
},
|
|
282
|
+
submit: (op) => {
|
|
283
|
+
this.submitMessage(op, { lastProcessedSeq: this.lastProcessedSeq });
|
|
284
|
+
},
|
|
285
|
+
getStashedOpLocalMetadata: (op) => {
|
|
286
|
+
(0, common_utils_1.assert)(false, 0x016 /* "apply stashed op not implemented for custom value type ops" */);
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
return messageHandlers;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Create an emitter for a value type to emit ops from the given key.
|
|
293
|
+
* @alpha
|
|
294
|
+
* @param key - The key of the map that the value type will be stored on
|
|
295
|
+
* @returns A value op emitter for the given key
|
|
296
|
+
*/
|
|
297
|
+
makeMapValueOpEmitter(key) {
|
|
298
|
+
const emit = (opName, previousValue, params) => {
|
|
299
|
+
const translatedParams = (0, shared_object_base_1.makeHandlesSerializable)(params, this.serializer, this.handle);
|
|
300
|
+
const op = {
|
|
301
|
+
key,
|
|
302
|
+
type: "act",
|
|
303
|
+
value: {
|
|
304
|
+
opName,
|
|
305
|
+
value: translatedParams,
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
// Send the localOpMetadata as undefined because we don't care about the ack.
|
|
309
|
+
this.submitMessage(op, { lastProcessedSeq: this.lastProcessedSeq });
|
|
310
|
+
const event = { key, previousValue };
|
|
311
|
+
this.eventEmitter.emit("valueChanged", event, true, null, this.eventEmitter);
|
|
312
|
+
};
|
|
313
|
+
return { emit };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
exports.DefaultMap = DefaultMap;
|
|
317
|
+
//# sourceMappingURL=defaultMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultMap.js","sourceRoot":"","sources":["../src/defaultMap.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport {\n IFluidSerializer,\n makeHandlesSerializable,\n parseHandles,\n ValueType,\n} from \"@fluidframework/shared-object-base\";\nimport { assert, TypedEventEmitter } from \"@fluidframework/common-utils\";\nimport {\n makeSerializable,\n ValueTypeLocalValue,\n} from \"./localValues\";\nimport {\n ISerializableValue,\n ISerializedValue,\n IValueChanged,\n IValueOpEmitter,\n IValueType,\n IValueTypeOperationValue,\n ISharedDefaultMapEvents,\n} from \"./defaultMapInterfaces\";\n\n/**\n * Defines the means to process and submit a given op on a map.\n */\ninterface IMapMessageHandler {\n /**\n * Apply the given operation.\n * @param op - The map operation to apply\n * @param local - Whether the message originated from the local client\n * @param message - The full message. Not provided for stashed ops.\n * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.\n * For messages from a remote client, this will be undefined.\n */\n process(\n op: IMapOperation,\n local: boolean,\n message: ISequencedDocumentMessage | undefined,\n localOpMetadata: IMapMessageLocalMetadata,\n ): void;\n\n /**\n * Communicate the operation to remote clients.\n * @param op - The map operation to submit\n */\n submit(op: IMapOperation): void;\n\n getStashedOpLocalMetadata(op: IMapOperation): unknown;\n}\n\nexport interface IMapMessageLocalMetadata {\n lastProcessedSeq: number;\n}\n\n/**\n * Describes an operation specific to a value type.\n */\nexport interface IMapValueTypeOperation {\n /**\n * String identifier of the operation type.\n */\n type: \"act\";\n\n /**\n * Map key being modified.\n */\n key: string;\n\n /**\n * Value of the operation, specific to the value type.\n * @alpha\n */\n value: IValueTypeOperationValue;\n}\n\n/**\n * Description of a map delta operation\n */\nexport type IMapOperation = IMapValueTypeOperation;\n\n/**\n * Defines the in-memory object structure to be used for the conversion to/from serialized.\n * Directly used in JSON.stringify, direct result from JSON.parse\n */\nexport interface IMapDataObjectSerializable {\n [key: string]: ISerializableValue;\n}\n\nexport interface IMapDataObjectSerialized {\n [key: string]: ISerializedValue;\n}\n\n/**\n * A DefaultMap is a map-like distributed data structure, supporting operations on values stored by\n * string key locations.\n *\n * Creation of values is implicit on access (either via `get` or a remote op application referring to\n * a collection that wasn't previously known)\n */\nexport class DefaultMap<T> {\n /**\n * The number of key/value pairs stored in the map.\n */\n public get size(): number {\n return this.data.size;\n }\n\n /**\n * Mapping of op types to message handlers.\n */\n private readonly messageHandlers: ReadonlyMap<string, IMapMessageHandler> = new Map();\n\n /**\n * The in-memory data the map is storing.\n */\n private readonly data = new Map<string, ValueTypeLocalValue<T>>();\n\n private lastProcessedSeq: number = -1;\n\n /**\n * Create a new default map.\n * @param serializer - The serializer to serialize / parse handles\n * @param handle - The handle of the shared object using the kernel\n * @param submitMessage - A callback to submit a message through the shared object\n * @param type - The value type to create at values of this map\n * @param eventEmitter - The object that will emit map events\n */\n constructor(\n private readonly serializer: IFluidSerializer,\n private readonly handle: IFluidHandle,\n private readonly submitMessage: (op: any, localOpMetadata: IMapMessageLocalMetadata) => void,\n private readonly type: IValueType<T>,\n public readonly eventEmitter = new TypedEventEmitter<ISharedDefaultMapEvents>(),\n ) {\n this.messageHandlers = this.getMessageHandlers();\n }\n\n /**\n * Get an iterator over the keys in this map.\n * @returns The iterator\n */\n public keys(): IterableIterator<string> {\n return this.data.keys();\n }\n\n /**\n * Get an iterator over the entries in this map.\n * @returns The iterator\n */\n public entries(): IterableIterator<[string, any]> {\n const localEntriesIterator = this.data.entries();\n const iterator = {\n next(): IteratorResult<[string, any]> {\n const nextVal = localEntriesIterator.next();\n if (nextVal.done) {\n return { value: undefined, done: true };\n } else {\n // Unpack the stored value\n return { value: [nextVal.value[0], nextVal.value[1].value], done: false };\n }\n },\n [Symbol.iterator]() {\n return this;\n },\n };\n return iterator;\n }\n\n /**\n * Get an iterator over the values in this map.\n * @returns The iterator\n */\n public values(): IterableIterator<any> {\n const localValuesIterator = this.data.values();\n const iterator = {\n next(): IteratorResult<any> {\n const nextVal = localValuesIterator.next();\n if (nextVal.done) {\n return { value: undefined, done: true };\n } else {\n // Unpack the stored value\n return { value: nextVal.value.value, done: false };\n }\n },\n [Symbol.iterator]() {\n return this;\n },\n };\n return iterator;\n }\n\n /**\n * Get an iterator over the entries in this map.\n * @returns The iterator\n */\n public [Symbol.iterator](): IterableIterator<[string, any]> {\n return this.entries();\n }\n\n /**\n * Executes the given callback on each entry in the map.\n * @param callbackFn - Callback function\n */\n public forEach(callbackFn: (value: any, key: string, map: Map<string, any>) => void): void {\n this.data.forEach((localValue, key, m) => {\n callbackFn(localValue.value, key, m);\n });\n }\n\n /**\n * {@inheritDoc ISharedMap.get}\n */\n public get(key: string): T {\n let localValue = this.data.get(key);\n if (!this.data.has(key)) {\n localValue = this.createCore(key, true);\n }\n return localValue.value;\n }\n\n /**\n * Check if a key exists in the map.\n * @param key - The key to check\n * @returns True if the key exists, false otherwise\n */\n public has(key: string): boolean {\n return this.data.has(key);\n }\n\n /**\n * Serializes the data stored in the shared map to a JSON string\n * @param serializer - The serializer to use to serialize handles in its values.\n * @returns A JSON string containing serialized map data\n */\n public getSerializedStorage(serializer: IFluidSerializer): IMapDataObjectSerialized {\n const serializableMapData: IMapDataObjectSerialized = {};\n this.data.forEach((localValue, key) => {\n serializableMapData[key] = localValue.makeSerialized(serializer, this.handle);\n });\n return serializableMapData;\n }\n\n public getSerializableStorage(serializer: IFluidSerializer): IMapDataObjectSerializable {\n const serializableMapData: IMapDataObjectSerializable = {};\n this.data.forEach((localValue, key) => {\n serializableMapData[key] = makeSerializable(localValue, serializer, this.handle);\n });\n return serializableMapData;\n }\n\n public serialize(serializer: IFluidSerializer): string {\n return JSON.stringify(this.getSerializableStorage(serializer));\n }\n\n /**\n * Populate the kernel with the given map data.\n * @param data - A JSON string containing serialized map data\n */\n public populateFromSerializable(json: IMapDataObjectSerializable): void {\n for (const [key, serializable] of Object.entries(json)) {\n // Back-compat: legacy documents may have handles to an intervalCollection map kernel.\n // These collections should be empty, and ValueTypes are no longer supported.\n if (serializable.type === ValueType[ValueType.Plain]\n || serializable.type === ValueType[ValueType.Shared]) {\n continue;\n }\n\n const localValue = {\n key,\n value: this.makeLocal(key, serializable),\n };\n\n this.data.set(localValue.key, localValue.value);\n }\n }\n\n public populate(json: string): void {\n this.populateFromSerializable(JSON.parse(json) as IMapDataObjectSerializable);\n }\n\n /**\n * Submit the given op if a handler is registered.\n * @param op - The operation to attempt to submit\n * @param localOpMetadata - The local metadata associated with the op. This is kept locally by the runtime\n * and not sent to the server. This will be sent back when this message is received back from the server. This is\n * also sent if we are asked to resubmit the message.\n * @returns True if the operation was submitted, false otherwise.\n */\n public trySubmitMessage(op: any, localOpMetadata: IMapMessageLocalMetadata): boolean {\n const type: string = op.type;\n const handler = this.messageHandlers.get(type);\n if (handler !== undefined) {\n const mapLocalMetadata: Partial<IMapMessageLocalMetadata> = localOpMetadata;\n // we don't know how to rebase these operations, so if any other op has come in\n // we will fail.\n if (this.lastProcessedSeq !== mapLocalMetadata?.lastProcessedSeq) {\n throw new Error(\"SharedInterval does not support reconnect in presence of external changes\");\n }\n handler.submit(op as IMapOperation);\n return true;\n }\n return false;\n }\n\n public tryGetStashedOpLocalMetadata(op: any): unknown {\n const type: string = op.type;\n if (this.messageHandlers.has(type)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.messageHandlers.get(type)!.getStashedOpLocalMetadata(op as IMapOperation);\n }\n throw new Error(\"no apply stashed op handler\");\n }\n\n /**\n * Process the given op if a handler is registered.\n * @param message - The message to process\n * @param local - Whether the message originated from the local client\n * @param localOpMetadata - For local client messages, this is the metadata that was submitted with the message.\n * For messages from a remote client, this will be undefined.\n * @returns True if the operation was processed, false otherwise.\n */\n public tryProcessMessage(\n op: IMapOperation,\n local: boolean,\n message: ISequencedDocumentMessage | undefined,\n localOpMetadata: unknown,\n ): boolean {\n // track the seq of every incoming message, so we can detect if any\n // changes happened during a resubmit\n this.lastProcessedSeq = message.sequenceNumber;\n const handler = this.messageHandlers.get(op.type);\n if (handler !== undefined) {\n handler.process(op, local, message, localOpMetadata as IMapMessageLocalMetadata);\n return true;\n }\n return false;\n }\n\n /**\n * Initializes a default ValueType at the provided key.\n * Should be used when a map operation incurs creation.\n * @param key - The key being initialized\n * @param local - Whether the message originated from the local client\n */\n private createCore(key: string, local: boolean): ValueTypeLocalValue<T> {\n const localValue = new ValueTypeLocalValue(\n this.type.factory.load(this.makeMapValueOpEmitter(key), undefined),\n this.type,\n );\n const previousValue = this.data.get(key);\n this.data.set(key, localValue);\n const event: IValueChanged = { key, previousValue };\n this.eventEmitter.emit(\"create\", event, local, this.eventEmitter);\n return localValue;\n }\n\n /**\n * The remote ISerializableValue we're receiving (either as a result of a load or an incoming set op) will\n * have the information we need to create a real object, but will not be the real object yet. For example,\n * we might know it's a map and the map's ID but not have the actual map or its data yet. makeLocal's\n * job is to convert that information into a real object for local usage.\n * @param key - The key that the caller intends to store the local value into (used for ops later). But\n * doesn't actually store the local value into that key. So better not lie!\n * @param serializable - The remote information that we can convert into a real object\n * @returns The local value that was produced\n */\n private makeLocal(key: string, serializable: ISerializableValue): ValueTypeLocalValue<T> {\n assert(serializable.type !== ValueType[ValueType.Plain] && serializable.type !== ValueType[ValueType.Shared],\n 0x2e1 /* \"Support for plain value types removed.\" */);\n\n serializable.value = parseHandles(serializable.value, this.serializer);\n const localValue = this.type.factory.load(\n this.makeMapValueOpEmitter(key),\n serializable.value,\n );\n return new ValueTypeLocalValue(localValue, this.type);\n }\n\n /**\n * Get the message handlers for the map.\n * @returns A map of string op names to IMapMessageHandlers for those ops\n */\n private getMessageHandlers() {\n const messageHandlers = new Map<string, IMapMessageHandler>();\n // Ops with type \"act\" describe actions taken by custom value type handlers of whatever item is\n // being addressed. These custom handlers can be retrieved from the ValueTypeLocalValue which has\n // stashed its valueType (and therefore its handlers). We also emit a valueChanged for anyone\n // watching for manipulations of that item.\n messageHandlers.set(\n \"act\",\n {\n process: (op: IMapValueTypeOperation, local, message, localOpMetadata) => {\n const localValue = this.data.get(op.key) ?? this.createCore(op.key, local);\n const handler = localValue.getOpHandler(op.value.opName);\n const previousValue = localValue.value;\n const translatedValue = parseHandles(\n op.value.value,\n this.serializer);\n handler.process(previousValue, translatedValue, local, message);\n const event: IValueChanged = { key: op.key, previousValue };\n this.eventEmitter.emit(\"valueChanged\", event, local, message, this.eventEmitter);\n },\n submit: (op: IMapValueTypeOperation) => {\n this.submitMessage(\n op,\n { lastProcessedSeq: this.lastProcessedSeq },\n );\n },\n getStashedOpLocalMetadata: (op: IMapValueTypeOperation) => {\n assert(false, 0x016 /* \"apply stashed op not implemented for custom value type ops\" */);\n },\n });\n\n return messageHandlers;\n }\n\n /**\n * Create an emitter for a value type to emit ops from the given key.\n * @alpha\n * @param key - The key of the map that the value type will be stored on\n * @returns A value op emitter for the given key\n */\n private makeMapValueOpEmitter(key: string): IValueOpEmitter {\n const emit = (opName: string, previousValue: any, params: any) => {\n const translatedParams = makeHandlesSerializable(\n params,\n this.serializer,\n this.handle);\n\n const op: IMapValueTypeOperation = {\n key,\n type: \"act\",\n value: {\n opName,\n value: translatedParams,\n },\n };\n // Send the localOpMetadata as undefined because we don't care about the ack.\n this.submitMessage(op, { lastProcessedSeq: this.lastProcessedSeq });\n\n const event: IValueChanged = { key, previousValue };\n this.eventEmitter.emit(\"valueChanged\", event, true, null, this.eventEmitter);\n };\n\n return { emit };\n }\n}\n"]}
|