@fluidframework/shared-object-base 2.32.0 → 2.33.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 +4 -0
- package/api-report/shared-object-base.legacy.alpha.api.md +8 -8
- package/dist/gcHandleVisitor.d.ts +19 -0
- package/dist/gcHandleVisitor.d.ts.map +1 -0
- package/dist/gcHandleVisitor.js +34 -0
- package/dist/gcHandleVisitor.js.map +1 -0
- package/dist/handle.d.ts +5 -2
- package/dist/handle.d.ts.map +1 -1
- package/dist/handle.js +13 -2
- package/dist/handle.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.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/serializer.d.ts +2 -2
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +32 -32
- package/dist/serializer.js.map +1 -1
- package/dist/sharedObject.d.ts +6 -0
- package/dist/sharedObject.d.ts.map +1 -1
- package/dist/sharedObject.js +20 -11
- package/dist/sharedObject.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -1
- package/lib/gcHandleVisitor.d.ts +19 -0
- package/lib/gcHandleVisitor.d.ts.map +1 -0
- package/lib/gcHandleVisitor.js +30 -0
- package/lib/gcHandleVisitor.js.map +1 -0
- package/lib/handle.d.ts +5 -2
- package/lib/handle.d.ts.map +1 -1
- package/lib/handle.js +13 -2
- package/lib/handle.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.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/serializer.d.ts +2 -2
- package/lib/serializer.d.ts.map +1 -1
- package/lib/serializer.js +32 -32
- package/lib/serializer.js.map +1 -1
- package/lib/sharedObject.d.ts +6 -0
- package/lib/sharedObject.d.ts.map +1 -1
- package/lib/sharedObject.js +21 -12
- package/lib/sharedObject.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -0
- package/lib/utils.js.map +1 -1
- package/package.json +18 -18
- package/src/gcHandleVisitor.ts +36 -0
- package/src/handle.ts +15 -3
- package/src/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/serializer.ts +11 -7
- package/src/sharedObject.ts +23 -12
- package/src/utils.ts +6 -3
- package/dist/summarySerializer.d.ts +0 -17
- package/dist/summarySerializer.d.ts.map +0 -1
- package/dist/summarySerializer.js +0 -27
- package/dist/summarySerializer.js.map +0 -1
- package/lib/summarySerializer.d.ts +0 -17
- package/lib/summarySerializer.d.ts.map +0 -1
- package/lib/summarySerializer.js +0 -23
- package/lib/summarySerializer.js.map +0 -1
- package/src/summarySerializer.ts +0 -28
package/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAI5E;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAc,EACd,UAA4B,EAC5B,IAAkB;IAElB,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CACtC,KAAc,EACd,UAA4B,EAC5B,IAAkB;IAElB,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,UAA4B;IACxE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACtC,GAAW,EACX,OAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACzC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAC1B,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAI5E;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAc,EACd,UAA4B,EAC5B,IAAkB;IAElB,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CACtC,KAAc,EACd,UAA4B,EAC5B,IAAkB;IAElB,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,UAA4B;IACxE,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACtC,GAAW,EACX,OAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,kBAAkB,EAAE,CAAC;IACzC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAC1B,KAAQ,EACR,UAA4B,EAC5B,IAAkB;IAElB,sEAAsE;IACtE,0EAA0E;IAC1E,4EAA4E;IAC5E,sEAAsE;IACtE,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE/B,wFAAwF;IACxF,OAAO,KAAK,CAAC;AACd,CAAC","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 type { IChannel } from \"@fluidframework/datastore-definitions/internal\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions/internal\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils/internal\";\n\nimport { IFluidSerializer } from \"./serializer.js\";\n\n/**\n * Given a mostly-plain object that may have handle objects embedded within, return a string representation of an object\n * where the handle objects have been replaced with a serializable form.\n * @param value - The mostly-plain object\n * @param serializer - The serializer that knows how to convert handles into serializable format\n * @param context - The handle context for the container\n * @param bind - Bind any other handles we find in the object against this given handle.\n * @returns Result of strigifying an object\n * @internal\n */\nexport function serializeHandles(\n\tvalue: unknown,\n\tserializer: IFluidSerializer,\n\tbind: IFluidHandle,\n): string | undefined {\n\treturn value === undefined ? value : serializer.stringify(value, bind);\n}\n\n/**\n * Given a mostly-plain object that may have handle objects embedded within, will return a fully-plain object\n * where any embedded IFluidHandles have been replaced with a serializable form.\n *\n * The original `input` object is not mutated. This method will shallowly clones all objects in the path from\n * the root to any replaced handles. (If no handles are found, returns the original object.)\n *\n * @param input - The mostly-plain object\n * @param context - The handle context for the container\n * @param bind - Bind any other handles we find in the object against this given handle.\n * @returns The fully-plain object\n * @legacy\n * @alpha\n */\nexport function makeHandlesSerializable(\n\tvalue: unknown,\n\tserializer: IFluidSerializer,\n\tbind: IFluidHandle,\n): unknown {\n\treturn serializer.encode(value, bind);\n}\n\n/**\n * Given a fully-plain object that may have serializable-form handles within, will return the mostly-plain object\n * with handle objects created instead.\n * @remarks Idempotent when called multiple times.\n * @param value - The fully-plain object\n * @param serializer - The serializer that knows how to convert serializable-form handles into handle objects\n * @param context - The handle context for the container\n * @returns The mostly-plain object with handle objects within\n * @legacy\n * @alpha\n */\nexport function parseHandles(value: unknown, serializer: IFluidSerializer): unknown {\n\treturn serializer.decode(value);\n}\n\n/**\n * Create a new summary containing one blob\n * @param key - the key for the blob in the summary\n * @param content - blob content\n * @returns The summary containing the blob\n * @internal\n */\nexport function createSingleBlobSummary(\n\tkey: string,\n\tcontent: string | Uint8Array,\n): ISummaryTreeWithStats {\n\tconst builder = new SummaryTreeBuilder();\n\tbuilder.addBlob(key, content);\n\treturn builder.getSummaryTree();\n}\n\n/**\n * Binds all handles found in `value` to `bind`. Does not modify original input.\n *\n * @internal\n */\nexport function bindHandles<T = unknown>(\n\tvalue: T,\n\tserializer: IFluidSerializer,\n\tbind: IFluidHandle,\n): T {\n\t// N.B. AB#7316 this could be made more efficient by writing an ad hoc\n\t// implementation that doesn't clone at all. Today the distinction between\n\t// this function and `encode` is purely semantic -- encoding both serializes\n\t// handles and binds them, but sometimes we only wish to do the latter\n\tserializer.encode(value, bind);\n\n\t// Return the input value so this function can be swapped in for makeHandlesSerializable\n\treturn value;\n}\n\n/**\n * Information about a Fluid channel.\n * @privateRemarks\n * This is distinct from {@link IChannel} as it omits the APIs used by the runtime to manage the channel and instead only has things which are useful (and safe) to expose to users of the channel.\n * @internal\n */\nexport type IChannelView = Pick<IChannel, \"id\" | \"attributes\" | \"isAttached\">;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/shared-object-base",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.33.0",
|
|
4
4
|
"description": "Fluid base class for shared distributed data structures",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -69,33 +69,34 @@
|
|
|
69
69
|
"temp-directory": "nyc/.nyc_output"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@fluid-internal/client-utils": "~2.
|
|
73
|
-
"@fluidframework/container-definitions": "~2.
|
|
74
|
-
"@fluidframework/core-interfaces": "~2.
|
|
75
|
-
"@fluidframework/core-utils": "~2.
|
|
76
|
-
"@fluidframework/datastore": "~2.
|
|
77
|
-
"@fluidframework/datastore-definitions": "~2.
|
|
78
|
-
"@fluidframework/driver-definitions": "~2.
|
|
79
|
-
"@fluidframework/runtime-definitions": "~2.
|
|
80
|
-
"@fluidframework/runtime-utils": "~2.
|
|
81
|
-
"@fluidframework/telemetry-utils": "~2.
|
|
72
|
+
"@fluid-internal/client-utils": "~2.33.0",
|
|
73
|
+
"@fluidframework/container-definitions": "~2.33.0",
|
|
74
|
+
"@fluidframework/core-interfaces": "~2.33.0",
|
|
75
|
+
"@fluidframework/core-utils": "~2.33.0",
|
|
76
|
+
"@fluidframework/datastore": "~2.33.0",
|
|
77
|
+
"@fluidframework/datastore-definitions": "~2.33.0",
|
|
78
|
+
"@fluidframework/driver-definitions": "~2.33.0",
|
|
79
|
+
"@fluidframework/runtime-definitions": "~2.33.0",
|
|
80
|
+
"@fluidframework/runtime-utils": "~2.33.0",
|
|
81
|
+
"@fluidframework/telemetry-utils": "~2.33.0",
|
|
82
82
|
"uuid": "^9.0.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
86
86
|
"@biomejs/biome": "~1.9.3",
|
|
87
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
88
|
-
"@fluid-private/test-pairwise-generator": "~2.
|
|
87
|
+
"@fluid-internal/mocha-test-setup": "~2.33.0",
|
|
88
|
+
"@fluid-private/test-pairwise-generator": "~2.33.0",
|
|
89
89
|
"@fluid-tools/build-cli": "^0.55.0",
|
|
90
90
|
"@fluidframework/build-common": "^2.0.3",
|
|
91
91
|
"@fluidframework/build-tools": "^0.55.0",
|
|
92
92
|
"@fluidframework/eslint-config-fluid": "^5.7.3",
|
|
93
|
-
"@fluidframework/shared-object-base-previous": "npm:@fluidframework/shared-object-base@2.
|
|
94
|
-
"@fluidframework/test-runtime-utils": "~2.
|
|
95
|
-
"@microsoft/api-extractor": "7.
|
|
93
|
+
"@fluidframework/shared-object-base-previous": "npm:@fluidframework/shared-object-base@2.32.0",
|
|
94
|
+
"@fluidframework/test-runtime-utils": "~2.33.0",
|
|
95
|
+
"@microsoft/api-extractor": "7.52.5",
|
|
96
96
|
"@types/benchmark": "^2.1.0",
|
|
97
97
|
"@types/mocha": "^10.0.10",
|
|
98
98
|
"@types/node": "^18.19.0",
|
|
99
|
+
"@types/sinon": "^17.0.3",
|
|
99
100
|
"@types/uuid": "^9.0.2",
|
|
100
101
|
"benchmark": "^2.1.4",
|
|
101
102
|
"c8": "^8.0.1",
|
|
@@ -105,9 +106,8 @@
|
|
|
105
106
|
"eslint": "~8.55.0",
|
|
106
107
|
"mocha": "^10.8.2",
|
|
107
108
|
"mocha-multi-reporters": "^1.5.1",
|
|
108
|
-
"moment": "^2.21.0",
|
|
109
|
-
"replace-in-file": "^6.3.5",
|
|
110
109
|
"rimraf": "^4.4.0",
|
|
110
|
+
"sinon": "^18.0.1",
|
|
111
111
|
"ts-node": "^10.9.1",
|
|
112
112
|
"typescript": "~5.4.5"
|
|
113
113
|
},
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
7
|
+
import { type ISerializedHandle } from "@fluidframework/runtime-utils/internal";
|
|
8
|
+
|
|
9
|
+
import { FluidSerializer } from "./serializer.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Implementation of IFluidSerializer used by GC to visit all the handles in the DDS to collect its outbound routes
|
|
13
|
+
*
|
|
14
|
+
* @remarks - This is given to DDS code that typically produces a serialization of the data, which is then ignored.
|
|
15
|
+
* All that is needed is getSerializedRoutes() to get the routes. This strategy could be optimized if needed.
|
|
16
|
+
*/
|
|
17
|
+
export class GCHandleVisitor extends FluidSerializer {
|
|
18
|
+
private readonly visitedHandlePaths: Set<string> = new Set();
|
|
19
|
+
public getVisitedHandlePaths(): string[] {
|
|
20
|
+
return [...this.visitedHandlePaths];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected bindAndEncodeHandle(
|
|
24
|
+
handle: IFluidHandleInternal,
|
|
25
|
+
bind: IFluidHandleInternal,
|
|
26
|
+
): ISerializedHandle {
|
|
27
|
+
this.visitedHandlePaths.add(handle.absolutePath);
|
|
28
|
+
|
|
29
|
+
// Just return a dummy value. The serialization itself is not used.
|
|
30
|
+
// It's especially important we don't bind since that has side effects that are irrelevant to GC.
|
|
31
|
+
return {
|
|
32
|
+
type: "__fluid_handle__",
|
|
33
|
+
url: "UNUSED (see GCHandleVisitor)",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/handle.ts
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
7
7
|
import { FluidObjectHandle } from "@fluidframework/datastore/internal";
|
|
8
|
+
// eslint-disable-next-line import/no-deprecated
|
|
9
|
+
import type { IFluidDataStoreRuntimeExperimental } from "@fluidframework/datastore-definitions/internal";
|
|
8
10
|
|
|
9
11
|
import { ISharedObject } from "./types.js";
|
|
10
12
|
|
|
@@ -37,9 +39,10 @@ export class SharedObjectHandle extends FluidObjectHandle<ISharedObject> {
|
|
|
37
39
|
constructor(
|
|
38
40
|
protected readonly value: ISharedObject,
|
|
39
41
|
path: string,
|
|
40
|
-
|
|
42
|
+
// eslint-disable-next-line import/no-deprecated
|
|
43
|
+
private readonly runtime: IFluidDataStoreRuntimeExperimental,
|
|
41
44
|
) {
|
|
42
|
-
super(value, path,
|
|
45
|
+
super(value, path, runtime.IFluidHandleContext);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
/**
|
|
@@ -50,4 +53,13 @@ export class SharedObjectHandle extends FluidObjectHandle<ISharedObject> {
|
|
|
50
53
|
this.value.bindToContext();
|
|
51
54
|
super.attachGraph();
|
|
52
55
|
}
|
|
56
|
+
|
|
57
|
+
public bind(handle: IFluidHandleInternal): void {
|
|
58
|
+
// We don't bind handles in staging mode to defer the attachment of any new objects
|
|
59
|
+
// until we've exited staging mode. This way if we discard changes or a new handle is not present in the final
|
|
60
|
+
// committed state, we will never end up attaching the discarded object.
|
|
61
|
+
if (this.runtime.inStagingMode !== true) {
|
|
62
|
+
super.bind(handle);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
53
65
|
}
|
package/src/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED
package/src/serializer.ts
CHANGED
|
@@ -88,7 +88,7 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
88
88
|
// return the result of 'recursivelyReplace()'.
|
|
89
89
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
90
90
|
return !!input && typeof input === "object"
|
|
91
|
-
? this.recursivelyReplace(input, this.encodeValue, bind)
|
|
91
|
+
? this.recursivelyReplace(input, this.encodeValue.bind(this), bind)
|
|
92
92
|
: input;
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -106,7 +106,7 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
106
106
|
// return the result of 'recursivelyReplace()'.
|
|
107
107
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
108
108
|
return !!input && typeof input === "object"
|
|
109
|
-
? this.recursivelyReplace(input, this.decodeValue)
|
|
109
|
+
? this.recursivelyReplace(input, this.decodeValue.bind(this))
|
|
110
110
|
: input;
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -131,20 +131,20 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
131
131
|
* If the given 'value' is an IFluidHandle, returns the encoded IFluidHandle.
|
|
132
132
|
* Otherwise returns the original 'value'. Used by 'encode()' and 'stringify()'.
|
|
133
133
|
*/
|
|
134
|
-
|
|
134
|
+
protected encodeValue(value: unknown, bind?: IFluidHandleInternal): unknown {
|
|
135
135
|
// If 'value' is an IFluidHandle return its encoded form.
|
|
136
136
|
if (isFluidHandle(value)) {
|
|
137
137
|
assert(bind !== undefined, 0xa93 /* Cannot encode a handle without a bind context */);
|
|
138
138
|
return this.bindAndEncodeHandle(toFluidHandleInternal(value), bind);
|
|
139
139
|
}
|
|
140
140
|
return value;
|
|
141
|
-
}
|
|
141
|
+
}
|
|
142
142
|
|
|
143
143
|
/**
|
|
144
144
|
* If the given 'value' is an encoded IFluidHandle, returns the decoded IFluidHandle.
|
|
145
145
|
* Otherwise returns the original 'value'. Used by 'decode()' and 'parse()'.
|
|
146
146
|
*/
|
|
147
|
-
|
|
147
|
+
protected decodeValue(value: unknown): unknown {
|
|
148
148
|
// If 'value' is a serialized IFluidHandle return the deserialized result.
|
|
149
149
|
if (isSerializedHandle(value)) {
|
|
150
150
|
// Old documents may have handles with relative path in their summaries. Convert these to absolute
|
|
@@ -153,11 +153,15 @@ export class FluidSerializer implements IFluidSerializer {
|
|
|
153
153
|
? value.url
|
|
154
154
|
: generateHandleContextPath(value.url, this.context);
|
|
155
155
|
|
|
156
|
-
return new RemoteFluidObjectHandle(
|
|
156
|
+
return new RemoteFluidObjectHandle(
|
|
157
|
+
absolutePath,
|
|
158
|
+
this.root,
|
|
159
|
+
value.payloadPending === true,
|
|
160
|
+
);
|
|
157
161
|
} else {
|
|
158
162
|
return value;
|
|
159
163
|
}
|
|
160
|
-
}
|
|
164
|
+
}
|
|
161
165
|
|
|
162
166
|
/**
|
|
163
167
|
* Invoked for non-null objects to recursively replace references to IFluidHandles.
|
package/src/sharedObject.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type IChannelFactory,
|
|
21
21
|
IFluidDataStoreRuntime,
|
|
22
22
|
type IDeltaHandler,
|
|
23
|
+
type IFluidDataStoreRuntimeInternalConfig,
|
|
23
24
|
} from "@fluidframework/datastore-definitions/internal";
|
|
24
25
|
import {
|
|
25
26
|
type IDocumentMessage,
|
|
@@ -53,11 +54,11 @@ import {
|
|
|
53
54
|
} from "@fluidframework/telemetry-utils/internal";
|
|
54
55
|
import { v4 as uuid } from "uuid";
|
|
55
56
|
|
|
57
|
+
import { GCHandleVisitor } from "./gcHandleVisitor.js";
|
|
56
58
|
import { SharedObjectHandle } from "./handle.js";
|
|
57
59
|
import { FluidSerializer, IFluidSerializer } from "./serializer.js";
|
|
58
|
-
import { SummarySerializer } from "./summarySerializer.js";
|
|
59
60
|
import { ISharedObject, ISharedObjectEvents } from "./types.js";
|
|
60
|
-
import { makeHandlesSerializable, parseHandles } from "./utils.js";
|
|
61
|
+
import { bindHandles, makeHandlesSerializable, parseHandles } from "./utils.js";
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
64
|
* Custom telemetry properties used in {@link SharedObjectCore} to instantiate {@link TelemetryEventBatcher} class.
|
|
@@ -144,7 +145,7 @@ export abstract class SharedObjectCore<
|
|
|
144
145
|
|
|
145
146
|
assert(!id.includes("/"), 0x304 /* Id cannot contain slashes */);
|
|
146
147
|
|
|
147
|
-
this.handle = new SharedObjectHandle(this, id, runtime
|
|
148
|
+
this.handle = new SharedObjectHandle(this, id, runtime);
|
|
148
149
|
|
|
149
150
|
this.logger = createChildLogger({
|
|
150
151
|
logger: runtime.logger,
|
|
@@ -459,8 +460,13 @@ export abstract class SharedObjectCore<
|
|
|
459
460
|
this.verifyNotClosed();
|
|
460
461
|
if (this.isAttached()) {
|
|
461
462
|
// NOTE: We may also be encoding in the ContainerRuntime layer.
|
|
462
|
-
// Once the layer-compat window passes we can
|
|
463
|
-
const
|
|
463
|
+
// Once the layer-compat window passes we can remove the encoding codepath here altogether
|
|
464
|
+
const onlyBind =
|
|
465
|
+
(this.runtime as IFluidDataStoreRuntimeInternalConfig)
|
|
466
|
+
.submitMessagesWithoutEncodingHandles === true;
|
|
467
|
+
const contentToSubmit = onlyBind
|
|
468
|
+
? bindHandles(content, this.serializer, this.handle)
|
|
469
|
+
: makeHandlesSerializable(content, this.serializer, this.handle);
|
|
464
470
|
|
|
465
471
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
466
472
|
this.services!.deltaConnection.submit(contentToSubmit, localOpMetadata);
|
|
@@ -743,10 +749,10 @@ export abstract class SharedObject<
|
|
|
743
749
|
|
|
744
750
|
protected get serializer(): IFluidSerializer {
|
|
745
751
|
/**
|
|
746
|
-
* During garbage collection, the
|
|
752
|
+
* During garbage collection, the GCHandleVisitor "serializer" keeps track of IFluidHandles that are serialized. These
|
|
747
753
|
* handles represent references to other Fluid objects.
|
|
748
754
|
*
|
|
749
|
-
* This is fine for now. However, if we implement delay loading in
|
|
755
|
+
* This is fine for now. However, if we implement delay loading in DDSes, they may load and de-serialize content
|
|
750
756
|
* in summarize. When that happens, they may incorrectly hit this assert and we will have to change this.
|
|
751
757
|
*/
|
|
752
758
|
assert(
|
|
@@ -825,8 +831,7 @@ export abstract class SharedObject<
|
|
|
825
831
|
* {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).getGCData}
|
|
826
832
|
*/
|
|
827
833
|
public getGCData(fullGC: boolean = false): IGarbageCollectionData {
|
|
828
|
-
// Set _isGCing to true. This flag is used to ensure that we only use
|
|
829
|
-
// in this object's data.
|
|
834
|
+
// Set _isGCing to true. This flag is used to ensure that we only use GCHandleVisitor in this codepath and not when trying to truly serialize.
|
|
830
835
|
assert(
|
|
831
836
|
!this._isGCing,
|
|
832
837
|
0x078 /* "Possible re-entrancy! Summary should not already be in progress." */,
|
|
@@ -835,11 +840,11 @@ export abstract class SharedObject<
|
|
|
835
840
|
|
|
836
841
|
let gcData: IGarbageCollectionData;
|
|
837
842
|
try {
|
|
838
|
-
const
|
|
839
|
-
this.processGCDataCore(
|
|
843
|
+
const handleVisitor = new GCHandleVisitor(this.runtime.channelsRoutingContext);
|
|
844
|
+
this.processGCDataCore(handleVisitor);
|
|
840
845
|
// The GC data for this shared object contains a single GC node. The outbound routes of this node are the
|
|
841
846
|
// routes of handles serialized during summarization.
|
|
842
|
-
gcData = { gcNodes: { "/":
|
|
847
|
+
gcData = { gcNodes: { "/": handleVisitor.getVisitedHandlePaths() } };
|
|
843
848
|
assert(
|
|
844
849
|
this._isGCing,
|
|
845
850
|
0x079 /* "Possible re-entrancy! Summary should have been in progress." */,
|
|
@@ -854,6 +859,12 @@ export abstract class SharedObject<
|
|
|
854
859
|
/**
|
|
855
860
|
* Calls the serializer over all data in this object that reference other GC nodes.
|
|
856
861
|
* Derived classes must override this to provide custom list of references to other GC nodes.
|
|
862
|
+
*
|
|
863
|
+
* @remarks Serialization itself doesn't matter (the result is ignored). We're tapping into the serialization infrastructure
|
|
864
|
+
* as a way to visit all the content in this content that may reference other objects via handle.
|
|
865
|
+
*
|
|
866
|
+
* @param serializer - The "serializer" (more like handle visitor) to use.
|
|
867
|
+
* Implementations should ensure that serialize is called on all handles, as the way to visit them.
|
|
857
868
|
*/
|
|
858
869
|
protected processGCDataCore(serializer: IFluidSerializer): void {
|
|
859
870
|
// We run the full summarize logic to get the list of outbound routes from this object. This is a little
|
package/src/utils.ts
CHANGED
|
@@ -86,16 +86,19 @@ export function createSingleBlobSummary(
|
|
|
86
86
|
*
|
|
87
87
|
* @internal
|
|
88
88
|
*/
|
|
89
|
-
export function bindHandles(
|
|
90
|
-
value:
|
|
89
|
+
export function bindHandles<T = unknown>(
|
|
90
|
+
value: T,
|
|
91
91
|
serializer: IFluidSerializer,
|
|
92
92
|
bind: IFluidHandle,
|
|
93
|
-
):
|
|
93
|
+
): T {
|
|
94
94
|
// N.B. AB#7316 this could be made more efficient by writing an ad hoc
|
|
95
95
|
// implementation that doesn't clone at all. Today the distinction between
|
|
96
96
|
// this function and `encode` is purely semantic -- encoding both serializes
|
|
97
97
|
// handles and binds them, but sometimes we only wish to do the latter
|
|
98
98
|
serializer.encode(value, bind);
|
|
99
|
+
|
|
100
|
+
// Return the input value so this function can be swapped in for makeHandlesSerializable
|
|
101
|
+
return value;
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
/**
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
6
|
-
import type { ISerializedHandle } from "@fluidframework/runtime-utils/internal";
|
|
7
|
-
import { FluidSerializer } from "./serializer.js";
|
|
8
|
-
/**
|
|
9
|
-
* Serializer implementation for serializing handles during summary.
|
|
10
|
-
* @internal
|
|
11
|
-
*/
|
|
12
|
-
export declare class SummarySerializer extends FluidSerializer {
|
|
13
|
-
private readonly serializedRoutes;
|
|
14
|
-
getSerializedRoutes(): string[];
|
|
15
|
-
protected bindAndEncodeHandle(handle: IFluidHandleInternal, bind: IFluidHandleInternal): ISerializedHandle;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=summarySerializer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"summarySerializer.d.ts","sourceRoot":"","sources":["../src/summarySerializer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IACpD,mBAAmB,IAAI,MAAM,EAAE;IAItC,SAAS,CAAC,mBAAmB,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,oBAAoB,GACxB,iBAAiB;CAIpB"}
|
|
@@ -1,27 +0,0 @@
|
|
|
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.SummarySerializer = void 0;
|
|
8
|
-
const serializer_js_1 = require("./serializer.js");
|
|
9
|
-
/**
|
|
10
|
-
* Serializer implementation for serializing handles during summary.
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
class SummarySerializer extends serializer_js_1.FluidSerializer {
|
|
14
|
-
constructor() {
|
|
15
|
-
super(...arguments);
|
|
16
|
-
this.serializedRoutes = new Set();
|
|
17
|
-
}
|
|
18
|
-
getSerializedRoutes() {
|
|
19
|
-
return [...this.serializedRoutes];
|
|
20
|
-
}
|
|
21
|
-
bindAndEncodeHandle(handle, bind) {
|
|
22
|
-
this.serializedRoutes.add(handle.absolutePath);
|
|
23
|
-
return super.bindAndEncodeHandle(handle, bind);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
exports.SummarySerializer = SummarySerializer;
|
|
27
|
-
//# sourceMappingURL=summarySerializer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"summarySerializer.js","sourceRoot":"","sources":["../src/summarySerializer.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAKH,mDAAkD;AAElD;;;GAGG;AACH,MAAa,iBAAkB,SAAQ,+BAAe;IAAtD;;QACkB,qBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAY5D,CAAC;IAXO,mBAAmB;QACzB,OAAO,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACnC,CAAC;IAES,mBAAmB,CAC5B,MAA4B,EAC5B,IAA0B;QAE1B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;CACD;AAbD,8CAaC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IFluidHandleInternal } from \"@fluidframework/core-interfaces/internal\";\nimport type { ISerializedHandle } from \"@fluidframework/runtime-utils/internal\";\n\nimport { FluidSerializer } from \"./serializer.js\";\n\n/**\n * Serializer implementation for serializing handles during summary.\n * @internal\n */\nexport class SummarySerializer extends FluidSerializer {\n\tprivate readonly serializedRoutes: Set<string> = new Set();\n\tpublic getSerializedRoutes(): string[] {\n\t\treturn [...this.serializedRoutes];\n\t}\n\n\tprotected bindAndEncodeHandle(\n\t\thandle: IFluidHandleInternal,\n\t\tbind: IFluidHandleInternal,\n\t): ISerializedHandle {\n\t\tthis.serializedRoutes.add(handle.absolutePath);\n\t\treturn super.bindAndEncodeHandle(handle, bind);\n\t}\n}\n"]}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
6
|
-
import type { ISerializedHandle } from "@fluidframework/runtime-utils/internal";
|
|
7
|
-
import { FluidSerializer } from "./serializer.js";
|
|
8
|
-
/**
|
|
9
|
-
* Serializer implementation for serializing handles during summary.
|
|
10
|
-
* @internal
|
|
11
|
-
*/
|
|
12
|
-
export declare class SummarySerializer extends FluidSerializer {
|
|
13
|
-
private readonly serializedRoutes;
|
|
14
|
-
getSerializedRoutes(): string[];
|
|
15
|
-
protected bindAndEncodeHandle(handle: IFluidHandleInternal, bind: IFluidHandleInternal): ISerializedHandle;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=summarySerializer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"summarySerializer.d.ts","sourceRoot":"","sources":["../src/summarySerializer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IACpD,mBAAmB,IAAI,MAAM,EAAE;IAItC,SAAS,CAAC,mBAAmB,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,IAAI,EAAE,oBAAoB,GACxB,iBAAiB;CAIpB"}
|
package/lib/summarySerializer.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { FluidSerializer } from "./serializer.js";
|
|
6
|
-
/**
|
|
7
|
-
* Serializer implementation for serializing handles during summary.
|
|
8
|
-
* @internal
|
|
9
|
-
*/
|
|
10
|
-
export class SummarySerializer extends FluidSerializer {
|
|
11
|
-
constructor() {
|
|
12
|
-
super(...arguments);
|
|
13
|
-
this.serializedRoutes = new Set();
|
|
14
|
-
}
|
|
15
|
-
getSerializedRoutes() {
|
|
16
|
-
return [...this.serializedRoutes];
|
|
17
|
-
}
|
|
18
|
-
bindAndEncodeHandle(handle, bind) {
|
|
19
|
-
this.serializedRoutes.add(handle.absolutePath);
|
|
20
|
-
return super.bindAndEncodeHandle(handle, bind);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=summarySerializer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"summarySerializer.js","sourceRoot":"","sources":["../src/summarySerializer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;GAGG;AACH,MAAM,OAAO,iBAAkB,SAAQ,eAAe;IAAtD;;QACkB,qBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAY5D,CAAC;IAXO,mBAAmB;QACzB,OAAO,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACnC,CAAC;IAES,mBAAmB,CAC5B,MAA4B,EAC5B,IAA0B;QAE1B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChD,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type IFluidHandleInternal } from \"@fluidframework/core-interfaces/internal\";\nimport type { ISerializedHandle } from \"@fluidframework/runtime-utils/internal\";\n\nimport { FluidSerializer } from \"./serializer.js\";\n\n/**\n * Serializer implementation for serializing handles during summary.\n * @internal\n */\nexport class SummarySerializer extends FluidSerializer {\n\tprivate readonly serializedRoutes: Set<string> = new Set();\n\tpublic getSerializedRoutes(): string[] {\n\t\treturn [...this.serializedRoutes];\n\t}\n\n\tprotected bindAndEncodeHandle(\n\t\thandle: IFluidHandleInternal,\n\t\tbind: IFluidHandleInternal,\n\t): ISerializedHandle {\n\t\tthis.serializedRoutes.add(handle.absolutePath);\n\t\treturn super.bindAndEncodeHandle(handle, bind);\n\t}\n}\n"]}
|
package/src/summarySerializer.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
7
|
-
import type { ISerializedHandle } from "@fluidframework/runtime-utils/internal";
|
|
8
|
-
|
|
9
|
-
import { FluidSerializer } from "./serializer.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Serializer implementation for serializing handles during summary.
|
|
13
|
-
* @internal
|
|
14
|
-
*/
|
|
15
|
-
export class SummarySerializer extends FluidSerializer {
|
|
16
|
-
private readonly serializedRoutes: Set<string> = new Set();
|
|
17
|
-
public getSerializedRoutes(): string[] {
|
|
18
|
-
return [...this.serializedRoutes];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
protected bindAndEncodeHandle(
|
|
22
|
-
handle: IFluidHandleInternal,
|
|
23
|
-
bind: IFluidHandleInternal,
|
|
24
|
-
): ISerializedHandle {
|
|
25
|
-
this.serializedRoutes.add(handle.absolutePath);
|
|
26
|
-
return super.bindAndEncodeHandle(handle, bind);
|
|
27
|
-
}
|
|
28
|
-
}
|