@fluidframework/shared-object-base 2.11.0 → 2.13.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/.eslintrc.cjs +1 -4
- package/CHANGELOG.md +8 -0
- package/api-report/shared-object-base.legacy.alpha.api.md +2 -2
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/remoteObjectHandle.d.ts +0 -1
- package/dist/remoteObjectHandle.d.ts.map +1 -1
- package/dist/remoteObjectHandle.js +0 -3
- package/dist/remoteObjectHandle.js.map +1 -1
- package/dist/serializer.d.ts +6 -8
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +16 -10
- package/dist/serializer.js.map +1 -1
- package/dist/sharedObject.d.ts.map +1 -1
- package/dist/sharedObject.js +11 -6
- package/dist/sharedObject.js.map +1 -1
- package/dist/summarySerializer.d.ts +2 -4
- package/dist/summarySerializer.d.ts.map +1 -1
- package/dist/summarySerializer.js +1 -1
- package/dist/summarySerializer.js.map +1 -1
- package/dist/utils.d.ts +4 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -4
- package/dist/utils.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/remoteObjectHandle.d.ts +0 -1
- package/lib/remoteObjectHandle.d.ts.map +1 -1
- package/lib/remoteObjectHandle.js +0 -3
- package/lib/remoteObjectHandle.js.map +1 -1
- package/lib/serializer.d.ts +6 -8
- package/lib/serializer.d.ts.map +1 -1
- package/lib/serializer.js +11 -5
- package/lib/serializer.js.map +1 -1
- package/lib/sharedObject.d.ts.map +1 -1
- package/lib/sharedObject.js +11 -6
- package/lib/sharedObject.js.map +1 -1
- package/lib/summarySerializer.d.ts +2 -4
- package/lib/summarySerializer.d.ts.map +1 -1
- package/lib/summarySerializer.js +1 -1
- package/lib/summarySerializer.js.map +1 -1
- package/lib/utils.d.ts +4 -4
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -4
- package/lib/utils.js.map +1 -1
- package/package.json +18 -18
- package/src/packageVersion.ts +1 -1
- package/src/remoteObjectHandle.ts +1 -5
- package/src/serializer.ts +34 -23
- package/src/sharedObject.ts +44 -31
- package/src/summarySerializer.ts +6 -2
- package/src/utils.ts +8 -9
|
@@ -20,10 +20,6 @@ import { FluidHandleBase, responseToException } from "@fluidframework/runtime-ut
|
|
|
20
20
|
* IFluidHandle can be retrieved by calling `get` on it.
|
|
21
21
|
*/
|
|
22
22
|
export class RemoteFluidObjectHandle extends FluidHandleBase<FluidObject> {
|
|
23
|
-
public get IFluidHandleContext() {
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
23
|
public readonly isAttached = true;
|
|
28
24
|
private objectP: Promise<FluidObject> | undefined;
|
|
29
25
|
|
|
@@ -52,7 +48,7 @@ export class RemoteFluidObjectHandle extends FluidHandleBase<FluidObject> {
|
|
|
52
48
|
};
|
|
53
49
|
this.objectP = this.routeContext.resolveHandle(request).then<FluidObject>((response) => {
|
|
54
50
|
if (response.mimeType === "fluid/object") {
|
|
55
|
-
const fluidObject: FluidObject = response.value;
|
|
51
|
+
const fluidObject: FluidObject = response.value as FluidObject;
|
|
56
52
|
return fluidObject;
|
|
57
53
|
}
|
|
58
54
|
throw responseToException(response, request);
|
package/src/serializer.ts
CHANGED
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
// RATIONALE: Many methods consume and return 'any' by necessity.
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
8
|
-
|
|
9
6
|
import { IFluidHandle } from "@fluidframework/core-interfaces";
|
|
10
7
|
import {
|
|
11
8
|
IFluidHandleContext,
|
|
12
9
|
type IFluidHandleInternal,
|
|
13
10
|
} from "@fluidframework/core-interfaces/internal";
|
|
11
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
14
12
|
import {
|
|
15
13
|
generateHandleContextPath,
|
|
16
14
|
isSerializedHandle,
|
|
17
15
|
isFluidHandle,
|
|
18
16
|
toFluidHandleInternal,
|
|
17
|
+
type ISerializedHandle,
|
|
19
18
|
} from "@fluidframework/runtime-utils/internal";
|
|
20
19
|
|
|
21
20
|
import { RemoteFluidObjectHandle } from "./remoteObjectHandle.js";
|
|
@@ -32,6 +31,7 @@ export interface IFluidSerializer {
|
|
|
32
31
|
* The original `input` object is not mutated. This method will shallowly clones all objects in the path from
|
|
33
32
|
* the root to any replaced handles. (If no handles are found, returns the original object.)
|
|
34
33
|
*/
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
35
35
|
encode(value: any, bind: IFluidHandle): any;
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -43,17 +43,20 @@ export interface IFluidSerializer {
|
|
|
43
43
|
*
|
|
44
44
|
* The decoded handles are implicitly bound to the handle context of this serializer.
|
|
45
45
|
*/
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
46
47
|
decode(input: any): any;
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Stringifies a given value. Converts any IFluidHandle to its stringified equivalent.
|
|
50
51
|
*/
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
51
53
|
stringify(value: any, bind: IFluidHandle): string;
|
|
52
54
|
|
|
53
55
|
/**
|
|
54
56
|
* Parses the given JSON input string and returns the JavaScript object defined by it. Any Fluid
|
|
55
57
|
* handles will be realized as part of the parse
|
|
56
58
|
*/
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
57
60
|
parse(value: string): any;
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -71,7 +74,7 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
public get IFluidSerializer() {
|
|
77
|
+
public get IFluidSerializer(): IFluidSerializer {
|
|
75
78
|
return this;
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -84,12 +87,14 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
84
87
|
*
|
|
85
88
|
* Any unbound handles encountered are bound to the provided IFluidHandle.
|
|
86
89
|
*/
|
|
87
|
-
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown
|
|
91
|
+
public encode(input: any, bind: IFluidHandleInternal): any {
|
|
88
92
|
// If the given 'input' cannot contain handles, return it immediately. Otherwise,
|
|
89
93
|
// return the result of 'recursivelyReplace()'.
|
|
90
94
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
91
95
|
return !!input && typeof input === "object"
|
|
92
|
-
?
|
|
96
|
+
? // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown
|
|
97
|
+
this.recursivelyReplace(input, this.encodeValue, bind)
|
|
93
98
|
: input;
|
|
94
99
|
}
|
|
95
100
|
|
|
@@ -102,7 +107,8 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
102
107
|
*
|
|
103
108
|
* The decoded handles are implicitly bound to the handle context of this serializer.
|
|
104
109
|
*/
|
|
105
|
-
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown
|
|
111
|
+
public decode(input: unknown): any {
|
|
106
112
|
// If the given 'input' cannot contain handles, return it immediately. Otherwise,
|
|
107
113
|
// return the result of 'recursivelyReplace()'.
|
|
108
114
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
@@ -111,28 +117,30 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
111
117
|
: input;
|
|
112
118
|
}
|
|
113
119
|
|
|
114
|
-
public stringify(input: unknown, bind: IFluidHandle) {
|
|
120
|
+
public stringify(input: unknown, bind: IFluidHandle): string {
|
|
115
121
|
const bindInternal = toFluidHandleInternal(bind);
|
|
116
122
|
return JSON.stringify(input, (key, value) => this.encodeValue(value, bindInternal));
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
// Parses the serialized data - context must match the context with which the JSON was stringified
|
|
120
|
-
public parse(input: string) {
|
|
126
|
+
public parse(input: string): unknown {
|
|
121
127
|
return JSON.parse(input, (key, value) => this.decodeValue(value));
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
// If the given 'value' is an IFluidHandle, returns the encoded IFluidHandle.
|
|
125
131
|
// Otherwise returns the original 'value'. Used by 'encode()' and 'stringify()'.
|
|
126
|
-
private readonly encodeValue = (value: unknown, bind
|
|
132
|
+
private readonly encodeValue = (value: unknown, bind?: IFluidHandleInternal): unknown => {
|
|
127
133
|
// If 'value' is an IFluidHandle return its encoded form.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
if (isFluidHandle(value)) {
|
|
135
|
+
assert(bind !== undefined, 0xa93 /* Cannot encode a handle without a bind context */);
|
|
136
|
+
return this.serializeHandle(toFluidHandleInternal(value), bind);
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
131
139
|
};
|
|
132
140
|
|
|
133
141
|
// If the given 'value' is an encoded IFluidHandle, returns the decoded IFluidHandle.
|
|
134
142
|
// Otherwise returns the original 'value'. Used by 'decode()' and 'parse()'.
|
|
135
|
-
private readonly decodeValue = (value:
|
|
143
|
+
private readonly decodeValue = (value: unknown): unknown => {
|
|
136
144
|
// If 'value' is a serialized IFluidHandle return the deserialized result.
|
|
137
145
|
if (isSerializedHandle(value)) {
|
|
138
146
|
// Old documents may have handles with relative path in their summaries. Convert these to absolute
|
|
@@ -150,11 +158,11 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
150
158
|
// Invoked for non-null objects to recursively replace references to IFluidHandles.
|
|
151
159
|
// Clones as-needed to avoid mutating the `input` object. If no IFluidHandes are present,
|
|
152
160
|
// returns the original `input`.
|
|
153
|
-
private recursivelyReplace(
|
|
154
|
-
input:
|
|
155
|
-
replacer: (input:
|
|
156
|
-
context?:
|
|
157
|
-
) {
|
|
161
|
+
private recursivelyReplace<TContext = unknown>(
|
|
162
|
+
input: object,
|
|
163
|
+
replacer: (input: unknown, context?: TContext) => unknown,
|
|
164
|
+
context?: TContext,
|
|
165
|
+
): unknown {
|
|
158
166
|
// Note: Caller is responsible for ensuring that `input` is defined / non-null.
|
|
159
167
|
// (Required for Object.keys() below.)
|
|
160
168
|
|
|
@@ -171,7 +179,7 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
171
179
|
// Otherwise descend into the object graph looking for IFluidHandle instances.
|
|
172
180
|
let clone: object | undefined;
|
|
173
181
|
for (const key of Object.keys(input)) {
|
|
174
|
-
const value = input[key];
|
|
182
|
+
const value: unknown = input[key];
|
|
175
183
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
176
184
|
if (!!value && typeof value === "object") {
|
|
177
185
|
// Note: Except for IFluidHandle, `input` must not contain circular references (as object must
|
|
@@ -184,18 +192,21 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
184
192
|
// current property is replaced by the `replaced` value.
|
|
185
193
|
if (replaced !== value) {
|
|
186
194
|
// Lazily create a shallow clone of the `input` object if we haven't done so already.
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- TODO: not sure if there's a good solution
|
|
187
196
|
clone = clone ?? (Array.isArray(input) ? [...input] : { ...input });
|
|
188
197
|
|
|
189
198
|
// Overwrite the current property `key` in the clone with the `replaced` value.
|
|
190
|
-
|
|
191
|
-
clone![key] = replaced;
|
|
199
|
+
clone[key] = replaced;
|
|
192
200
|
}
|
|
193
201
|
}
|
|
194
202
|
}
|
|
195
203
|
return clone ?? input;
|
|
196
204
|
}
|
|
197
205
|
|
|
198
|
-
protected serializeHandle(
|
|
206
|
+
protected serializeHandle(
|
|
207
|
+
handle: IFluidHandleInternal,
|
|
208
|
+
bind: IFluidHandleInternal,
|
|
209
|
+
): ISerializedHandle {
|
|
199
210
|
bind.bind(handle);
|
|
200
211
|
return {
|
|
201
212
|
type: "__fluid_handle__",
|
package/src/sharedObject.ts
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
loggerToMonitoringContext,
|
|
49
49
|
tagCodeArtifacts,
|
|
50
50
|
type ICustomData,
|
|
51
|
+
type IFluidErrorBase,
|
|
51
52
|
} from "@fluidframework/telemetry-utils/internal";
|
|
52
53
|
import { v4 as uuid } from "uuid";
|
|
53
54
|
|
|
@@ -77,7 +78,7 @@ export abstract class SharedObjectCore<
|
|
|
77
78
|
extends EventEmitterWithErrorHandling<TEvent>
|
|
78
79
|
implements ISharedObject<TEvent>
|
|
79
80
|
{
|
|
80
|
-
public get IFluidLoadable() {
|
|
81
|
+
public get IFluidLoadable(): this {
|
|
81
82
|
return this;
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -136,7 +137,9 @@ export abstract class SharedObjectCore<
|
|
|
136
137
|
protected runtime: IFluidDataStoreRuntime,
|
|
137
138
|
public readonly attributes: IChannelAttributes,
|
|
138
139
|
) {
|
|
139
|
-
super((event: EventEmitterEventType, e:
|
|
140
|
+
super((event: EventEmitterEventType, e: unknown) =>
|
|
141
|
+
this.eventListenerErrorHandler(event, e),
|
|
142
|
+
);
|
|
140
143
|
|
|
141
144
|
assert(!id.includes("/"), 0x304 /* Id cannot contain slashes */);
|
|
142
145
|
|
|
@@ -217,7 +220,7 @@ export abstract class SharedObjectCore<
|
|
|
217
220
|
* would result in same error thrown. If called multiple times, only first error is remembered.
|
|
218
221
|
* @param error - error object that is thrown whenever an attempt is made to modify this object
|
|
219
222
|
*/
|
|
220
|
-
private closeWithError(error:
|
|
223
|
+
private closeWithError(error: IFluidErrorBase | undefined): void {
|
|
221
224
|
if (this.closeError === undefined) {
|
|
222
225
|
this.closeError = error;
|
|
223
226
|
}
|
|
@@ -226,7 +229,7 @@ export abstract class SharedObjectCore<
|
|
|
226
229
|
/**
|
|
227
230
|
* Verifies that this object is not closed via closeWithError(). If it is, throws an error used to close it.
|
|
228
231
|
*/
|
|
229
|
-
private verifyNotClosed() {
|
|
232
|
+
private verifyNotClosed(): void {
|
|
230
233
|
if (this.closeError !== undefined) {
|
|
231
234
|
throw this.closeError;
|
|
232
235
|
}
|
|
@@ -242,7 +245,7 @@ export abstract class SharedObjectCore<
|
|
|
242
245
|
* DDS state does not match what user sees. Because of it DDS moves to "corrupted state" and does not
|
|
243
246
|
* allow processing of ops or local changes, which very quickly results in container closure.
|
|
244
247
|
*/
|
|
245
|
-
private eventListenerErrorHandler(event: EventEmitterEventType, e:
|
|
248
|
+
private eventListenerErrorHandler(event: EventEmitterEventType, e: unknown): void {
|
|
246
249
|
const error = DataProcessingError.wrapIfUnrecognized(
|
|
247
250
|
e,
|
|
248
251
|
"SharedObjectEventListenerException",
|
|
@@ -253,13 +256,14 @@ export abstract class SharedObjectCore<
|
|
|
253
256
|
throw error;
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
private setBoundAndHandleAttach() {
|
|
259
|
+
private setBoundAndHandleAttach(): void {
|
|
257
260
|
// Ensure didAttach is only called once, and we only register a single event
|
|
258
261
|
// but we still call setConnectionState as our existing mocks don't
|
|
259
262
|
// always propagate connection state
|
|
260
263
|
this.setBoundAndHandleAttach = () => this.setConnectionState(this.runtime.connected);
|
|
261
264
|
this._isBoundToContext = true;
|
|
262
|
-
|
|
265
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
266
|
+
const runDidAttach: () => void = () => {
|
|
263
267
|
// Allows objects to do any custom processing if it is attached.
|
|
264
268
|
this.didAttach();
|
|
265
269
|
this.setConnectionState(this.runtime.connected);
|
|
@@ -312,7 +316,7 @@ export abstract class SharedObjectCore<
|
|
|
312
316
|
/**
|
|
313
317
|
* {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).connect}
|
|
314
318
|
*/
|
|
315
|
-
public connect(services: IChannelServices) {
|
|
319
|
+
public connect(services: IChannelServices): void {
|
|
316
320
|
// handle the case where load is called
|
|
317
321
|
// before connect; loading detached data stores
|
|
318
322
|
if (this.services === undefined) {
|
|
@@ -362,7 +366,7 @@ export abstract class SharedObjectCore<
|
|
|
362
366
|
/**
|
|
363
367
|
* Allows the distributed data type to perform custom local loading.
|
|
364
368
|
*/
|
|
365
|
-
protected initializeLocalCore() {
|
|
369
|
+
protected initializeLocalCore(): void {
|
|
366
370
|
return;
|
|
367
371
|
}
|
|
368
372
|
|
|
@@ -370,7 +374,7 @@ export abstract class SharedObjectCore<
|
|
|
370
374
|
* Allows the distributive data type the ability to perform custom processing once an attach has happened.
|
|
371
375
|
* Also called after non-local data type get loaded.
|
|
372
376
|
*/
|
|
373
|
-
protected didAttach() {
|
|
377
|
+
protected didAttach(): void {
|
|
374
378
|
return;
|
|
375
379
|
}
|
|
376
380
|
|
|
@@ -385,12 +389,15 @@ export abstract class SharedObjectCore<
|
|
|
385
389
|
message: ISequencedDocumentMessage,
|
|
386
390
|
local: boolean,
|
|
387
391
|
localOpMetadata: unknown,
|
|
388
|
-
|
|
392
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use void instead of any (legacy breaking)
|
|
393
|
+
): any;
|
|
389
394
|
|
|
390
395
|
/**
|
|
391
396
|
* Called when the object has disconnected from the delta stream.
|
|
392
397
|
*/
|
|
393
|
-
|
|
398
|
+
|
|
399
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 change return type to void (legacy breaking)
|
|
400
|
+
protected abstract onDisconnect(): any;
|
|
394
401
|
|
|
395
402
|
/**
|
|
396
403
|
* The serializer to serialize / parse handles.
|
|
@@ -405,6 +412,7 @@ export abstract class SharedObjectCore<
|
|
|
405
412
|
* and not sent to the server. This will be sent back when this message is received back from the server. This is
|
|
406
413
|
* also sent if we are asked to resubmit the message.
|
|
407
414
|
*/
|
|
415
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
408
416
|
protected submitLocalMessage(content: any, localOpMetadata: unknown = undefined): void {
|
|
409
417
|
this.verifyNotClosed();
|
|
410
418
|
if (this.isAttached()) {
|
|
@@ -433,7 +441,7 @@ export abstract class SharedObjectCore<
|
|
|
433
441
|
* Called when the object has fully connected to the delta stream
|
|
434
442
|
* Default implementation for DDS, override if different behavior is required.
|
|
435
443
|
*/
|
|
436
|
-
protected onConnect() {}
|
|
444
|
+
protected onConnect(): void {}
|
|
437
445
|
|
|
438
446
|
/**
|
|
439
447
|
* Called when a message has to be resubmitted. This typically happens after a reconnection for unacked messages.
|
|
@@ -443,7 +451,8 @@ export abstract class SharedObjectCore<
|
|
|
443
451
|
* @param content - The content of the original message.
|
|
444
452
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
445
453
|
*/
|
|
446
|
-
|
|
454
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
455
|
+
protected reSubmitCore(content: any, localOpMetadata: unknown): void {
|
|
447
456
|
this.submitLocalMessage(content, localOpMetadata);
|
|
448
457
|
}
|
|
449
458
|
|
|
@@ -456,6 +465,7 @@ export abstract class SharedObjectCore<
|
|
|
456
465
|
protected async newAckBasedPromise<T>(
|
|
457
466
|
executor: (
|
|
458
467
|
resolve: (value: T | PromiseLike<T>) => void,
|
|
468
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
459
469
|
reject: (reason?: any) => void,
|
|
460
470
|
) => void,
|
|
461
471
|
): Promise<T> {
|
|
@@ -479,7 +489,7 @@ export abstract class SharedObjectCore<
|
|
|
479
489
|
});
|
|
480
490
|
}
|
|
481
491
|
|
|
482
|
-
private attachDeltaHandler() {
|
|
492
|
+
private attachDeltaHandler(): void {
|
|
483
493
|
// Services should already be there in case we are attaching delta handler.
|
|
484
494
|
assert(
|
|
485
495
|
this.services !== undefined,
|
|
@@ -504,13 +514,13 @@ export abstract class SharedObjectCore<
|
|
|
504
514
|
setConnectionState: (connected: boolean) => {
|
|
505
515
|
this.setConnectionState(connected);
|
|
506
516
|
},
|
|
507
|
-
reSubmit: (content:
|
|
517
|
+
reSubmit: (content: unknown, localOpMetadata: unknown) => {
|
|
508
518
|
this.reSubmit(content, localOpMetadata);
|
|
509
519
|
},
|
|
510
|
-
applyStashedOp: (content:
|
|
520
|
+
applyStashedOp: (content: unknown): void => {
|
|
511
521
|
this.applyStashedOp(parseHandles(content, this.serializer));
|
|
512
522
|
},
|
|
513
|
-
rollback: (content:
|
|
523
|
+
rollback: (content: unknown, localOpMetadata: unknown) => {
|
|
514
524
|
this.rollback(content, localOpMetadata);
|
|
515
525
|
},
|
|
516
526
|
} satisfies IDeltaHandler);
|
|
@@ -520,7 +530,7 @@ export abstract class SharedObjectCore<
|
|
|
520
530
|
* Set the state of connection to services.
|
|
521
531
|
* @param connected - true if connected, false otherwise.
|
|
522
532
|
*/
|
|
523
|
-
private setConnectionState(connected: boolean) {
|
|
533
|
+
private setConnectionState(connected: boolean): void {
|
|
524
534
|
// only an attached shared object can transition its
|
|
525
535
|
// connected state. This is defensive, as some
|
|
526
536
|
// of our test harnesses don't handle this correctly
|
|
@@ -532,17 +542,17 @@ export abstract class SharedObjectCore<
|
|
|
532
542
|
// Should I change the state at the end? So that we *can't* send new stuff before we send old?
|
|
533
543
|
this._connected = connected;
|
|
534
544
|
|
|
535
|
-
if (
|
|
545
|
+
if (connected) {
|
|
546
|
+
// Call this for now so that DDSes like ConsensusOrderedCollection that maintain their own pending
|
|
547
|
+
// messages will work.
|
|
548
|
+
this.onConnect();
|
|
549
|
+
} else {
|
|
536
550
|
// Things that are true now...
|
|
537
551
|
// - if we had a connection we can no longer send messages over it
|
|
538
552
|
// - if we had outbound messages some may or may not be ACK'd. Won't know until next message
|
|
539
553
|
//
|
|
540
554
|
// - nack could get a new msn - but might as well do it in the join?
|
|
541
555
|
this.onDisconnect();
|
|
542
|
-
} else {
|
|
543
|
-
// Call this for now so that DDSes like ConsensusOrderedCollection that maintain their own pending
|
|
544
|
-
// messages will work.
|
|
545
|
-
this.onConnect();
|
|
546
556
|
}
|
|
547
557
|
}
|
|
548
558
|
|
|
@@ -557,7 +567,7 @@ export abstract class SharedObjectCore<
|
|
|
557
567
|
message: ISequencedDocumentMessage,
|
|
558
568
|
local: boolean,
|
|
559
569
|
localOpMetadata: unknown,
|
|
560
|
-
) {
|
|
570
|
+
): void {
|
|
561
571
|
this.verifyNotClosed(); // This will result in container closure.
|
|
562
572
|
this.emitInternal("pre-op", message, local, this);
|
|
563
573
|
|
|
@@ -581,7 +591,7 @@ export abstract class SharedObjectCore<
|
|
|
581
591
|
* Process messages for this shared object. The messages here are contiguous messages for this object in a batch.
|
|
582
592
|
* @param messageCollection - The collection of messages to process.
|
|
583
593
|
*/
|
|
584
|
-
private processMessages(messagesCollection: IRuntimeMessageCollection) {
|
|
594
|
+
private processMessages(messagesCollection: IRuntimeMessageCollection): void {
|
|
585
595
|
const { envelope, messagesContent, local } = messagesCollection;
|
|
586
596
|
for (const { contents, localOpMetadata, clientSequenceNumber } of messagesContent) {
|
|
587
597
|
this.process(
|
|
@@ -602,14 +612,15 @@ export abstract class SharedObjectCore<
|
|
|
602
612
|
* @param content - The content of the original message.
|
|
603
613
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
604
614
|
*/
|
|
605
|
-
private reSubmit(content:
|
|
615
|
+
private reSubmit(content: unknown, localOpMetadata: unknown): void {
|
|
606
616
|
this.reSubmitCore(content, localOpMetadata);
|
|
607
617
|
}
|
|
608
618
|
|
|
609
619
|
/**
|
|
610
620
|
* Revert an op
|
|
611
621
|
*/
|
|
612
|
-
|
|
622
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
623
|
+
protected rollback(content: any, localOpMetadata: unknown): void {
|
|
613
624
|
throw new Error("rollback not supported");
|
|
614
625
|
}
|
|
615
626
|
|
|
@@ -630,6 +641,7 @@ export abstract class SharedObjectCore<
|
|
|
630
641
|
*
|
|
631
642
|
* @param content - Contents of a stashed op.
|
|
632
643
|
*/
|
|
644
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
633
645
|
protected abstract applyStashedOp(content: any): void;
|
|
634
646
|
|
|
635
647
|
/**
|
|
@@ -644,6 +656,7 @@ export abstract class SharedObjectCore<
|
|
|
644
656
|
*/
|
|
645
657
|
public emit(event: EventEmitterEventType, ...args: any[]): boolean {
|
|
646
658
|
return this.callbacksHelper.measure(() => {
|
|
659
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
647
660
|
return super.emit(event, ...args);
|
|
648
661
|
});
|
|
649
662
|
}
|
|
@@ -655,7 +668,7 @@ export abstract class SharedObjectCore<
|
|
|
655
668
|
* @param args - Arguments for the event
|
|
656
669
|
* @returns Whatever `super.emit()` returns.
|
|
657
670
|
*/
|
|
658
|
-
private emitInternal(event: EventEmitterEventType, ...args:
|
|
671
|
+
private emitInternal(event: EventEmitterEventType, ...args: unknown[]): boolean {
|
|
659
672
|
return super.emit(event, ...args);
|
|
660
673
|
}
|
|
661
674
|
}
|
|
@@ -793,7 +806,7 @@ export abstract class SharedObject<
|
|
|
793
806
|
* Calls the serializer over all data in this object that reference other GC nodes.
|
|
794
807
|
* Derived classes must override this to provide custom list of references to other GC nodes.
|
|
795
808
|
*/
|
|
796
|
-
protected processGCDataCore(serializer: IFluidSerializer) {
|
|
809
|
+
protected processGCDataCore(serializer: IFluidSerializer): void {
|
|
797
810
|
// We run the full summarize logic to get the list of outbound routes from this object. This is a little
|
|
798
811
|
// expensive but its okay for now. It will be updated to not use full summarize and make it more efficient.
|
|
799
812
|
// See: https://github.com/microsoft/FluidFramework/issues/4547
|
|
@@ -814,7 +827,7 @@ export abstract class SharedObject<
|
|
|
814
827
|
propertyName: string,
|
|
815
828
|
incrementBy: number,
|
|
816
829
|
telemetryContext?: ITelemetryContext,
|
|
817
|
-
) {
|
|
830
|
+
): void {
|
|
818
831
|
if (telemetryContext !== undefined) {
|
|
819
832
|
// TelemetryContext needs to implment a get function
|
|
820
833
|
assert(
|
package/src/summarySerializer.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
7
|
+
import type { ISerializedHandle } from "@fluidframework/runtime-utils/internal";
|
|
7
8
|
|
|
8
9
|
import { FluidSerializer } from "./serializer.js";
|
|
9
10
|
|
|
@@ -14,10 +15,13 @@ import { FluidSerializer } from "./serializer.js";
|
|
|
14
15
|
export class SummarySerializer extends FluidSerializer {
|
|
15
16
|
private readonly serializedRoutes: Set<string> = new Set();
|
|
16
17
|
public getSerializedRoutes(): string[] {
|
|
17
|
-
return
|
|
18
|
+
return [...this.serializedRoutes];
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
protected serializeHandle(
|
|
21
|
+
protected serializeHandle(
|
|
22
|
+
handle: IFluidHandleInternal,
|
|
23
|
+
bind: IFluidHandleInternal,
|
|
24
|
+
): ISerializedHandle {
|
|
21
25
|
this.serializedRoutes.add(handle.absolutePath);
|
|
22
26
|
return super.serializeHandle(handle, bind);
|
|
23
27
|
}
|
package/src/utils.ts
CHANGED
|
@@ -20,12 +20,11 @@ import { IFluidSerializer } from "./serializer.js";
|
|
|
20
20
|
* @internal
|
|
21
21
|
*/
|
|
22
22
|
export function serializeHandles(
|
|
23
|
-
value:
|
|
23
|
+
value: unknown,
|
|
24
24
|
serializer: IFluidSerializer,
|
|
25
25
|
bind: IFluidHandle,
|
|
26
26
|
): string | undefined {
|
|
27
|
-
|
|
28
|
-
return value !== undefined ? serializer.stringify(value, bind) : value;
|
|
27
|
+
return value === undefined ? value : serializer.stringify(value, bind);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
/**
|
|
@@ -43,11 +42,11 @@ export function serializeHandles(
|
|
|
43
42
|
* @alpha
|
|
44
43
|
*/
|
|
45
44
|
export function makeHandlesSerializable(
|
|
46
|
-
value:
|
|
45
|
+
value: unknown,
|
|
47
46
|
serializer: IFluidSerializer,
|
|
48
47
|
bind: IFluidHandle,
|
|
49
|
-
)
|
|
50
|
-
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
49
|
+
): any {
|
|
51
50
|
return serializer.encode(value, bind);
|
|
52
51
|
}
|
|
53
52
|
|
|
@@ -62,8 +61,8 @@ export function makeHandlesSerializable(
|
|
|
62
61
|
* @legacy
|
|
63
62
|
* @alpha
|
|
64
63
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking)
|
|
65
|
+
export function parseHandles(value: unknown, serializer: IFluidSerializer): any {
|
|
67
66
|
return serializer.decode(value);
|
|
68
67
|
}
|
|
69
68
|
|
|
@@ -89,7 +88,7 @@ export function createSingleBlobSummary(
|
|
|
89
88
|
* @internal
|
|
90
89
|
*/
|
|
91
90
|
export function bindHandles(
|
|
92
|
-
value:
|
|
91
|
+
value: unknown,
|
|
93
92
|
serializer: IFluidSerializer,
|
|
94
93
|
bind: IFluidHandle,
|
|
95
94
|
): void {
|