@fluidframework/tree 2.40.0 → 2.41.0-338186
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/api-report/tree.alpha.api.md +1 -1
- package/dist/feature-libraries/default-schema/schemaChecker.d.ts.map +1 -1
- package/dist/feature-libraries/default-schema/schemaChecker.js +0 -7
- package/dist/feature-libraries/default-schema/schemaChecker.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +16 -14
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +12 -18
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/index.js +1 -2
- package/dist/feature-libraries/flex-tree/index.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +1 -5
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +2 -16
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/utilities.d.ts +6 -6
- package/dist/feature-libraries/flex-tree/utilities.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/utilities.js +6 -7
- package/dist/feature-libraries/flex-tree/utilities.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +1 -2
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/checkoutFlexTreeView.d.ts +7 -3
- package/dist/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/dist/shared-tree/checkoutFlexTreeView.js +11 -2
- package/dist/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/dist/shared-tree/schematizeTree.d.ts +1 -1
- package/dist/shared-tree/schematizeTree.js +1 -1
- package/dist/shared-tree/schematizeTree.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +3 -0
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +13 -7
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/treeAlpha.d.ts +1 -4
- package/dist/shared-tree/treeAlpha.d.ts.map +1 -1
- package/dist/shared-tree/treeAlpha.js +6 -1
- package/dist/shared-tree/treeAlpha.js.map +1 -1
- package/dist/simple-tree/api/create.d.ts +5 -1
- package/dist/simple-tree/api/create.d.ts.map +1 -1
- package/dist/simple-tree/api/create.js +10 -11
- package/dist/simple-tree/api/create.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +2 -2
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +2 -2
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/storedSchema.d.ts +1 -8
- package/dist/simple-tree/api/storedSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/storedSchema.js +3 -14
- package/dist/simple-tree/api/storedSchema.js.map +1 -1
- package/dist/simple-tree/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/arrayNode.js +3 -9
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +4 -4
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +9 -5
- package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/dist/simple-tree/index.d.ts +3 -2
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +6 -4
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/mapNode.d.ts.map +1 -1
- package/dist/simple-tree/mapNode.js +17 -20
- package/dist/simple-tree/mapNode.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js +2 -4
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/prepareForInsertion.d.ts +30 -0
- package/dist/simple-tree/prepareForInsertion.d.ts.map +1 -0
- package/dist/simple-tree/prepareForInsertion.js +137 -0
- package/dist/simple-tree/prepareForInsertion.js.map +1 -0
- package/dist/simple-tree/proxies.d.ts +1 -12
- package/dist/simple-tree/proxies.d.ts.map +1 -1
- package/dist/simple-tree/proxies.js +10 -106
- package/dist/simple-tree/proxies.js.map +1 -1
- package/dist/simple-tree/toMapTree.d.ts +1 -1
- package/dist/simple-tree/toMapTree.js +1 -1
- package/dist/simple-tree/toMapTree.js.map +1 -1
- package/dist/tableSchema.d.ts +108 -59
- package/dist/tableSchema.d.ts.map +1 -1
- package/dist/tableSchema.js +93 -44
- package/dist/tableSchema.js.map +1 -1
- package/lib/feature-libraries/default-schema/schemaChecker.d.ts.map +1 -1
- package/lib/feature-libraries/default-schema/schemaChecker.js +0 -7
- package/lib/feature-libraries/default-schema/schemaChecker.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +16 -14
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +11 -16
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/index.js +1 -1
- package/lib/feature-libraries/flex-tree/index.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +1 -5
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +1 -14
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/utilities.d.ts +6 -6
- package/lib/feature-libraries/flex-tree/utilities.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/utilities.js +6 -7
- package/lib/feature-libraries/flex-tree/utilities.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/checkoutFlexTreeView.d.ts +7 -3
- package/lib/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/lib/shared-tree/checkoutFlexTreeView.js +12 -3
- package/lib/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/lib/shared-tree/schematizeTree.d.ts +1 -1
- package/lib/shared-tree/schematizeTree.js +1 -1
- package/lib/shared-tree/schematizeTree.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +3 -0
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +14 -8
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/treeAlpha.d.ts +1 -4
- package/lib/shared-tree/treeAlpha.d.ts.map +1 -1
- package/lib/shared-tree/treeAlpha.js +7 -2
- package/lib/shared-tree/treeAlpha.js.map +1 -1
- package/lib/simple-tree/api/create.d.ts +5 -1
- package/lib/simple-tree/api/create.d.ts.map +1 -1
- package/lib/simple-tree/api/create.js +8 -10
- package/lib/simple-tree/api/create.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +2 -2
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +2 -2
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/storedSchema.d.ts +1 -8
- package/lib/simple-tree/api/storedSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/storedSchema.js +2 -12
- package/lib/simple-tree/api/storedSchema.js.map +1 -1
- package/lib/simple-tree/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/arrayNode.js +4 -10
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +4 -4
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +9 -5
- package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/lib/simple-tree/index.d.ts +3 -2
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +3 -2
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/mapNode.d.ts.map +1 -1
- package/lib/simple-tree/mapNode.js +3 -6
- package/lib/simple-tree/mapNode.js.map +1 -1
- package/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js +4 -6
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/prepareForInsertion.d.ts +30 -0
- package/lib/simple-tree/prepareForInsertion.d.ts.map +1 -0
- package/lib/simple-tree/prepareForInsertion.js +131 -0
- package/lib/simple-tree/prepareForInsertion.js.map +1 -0
- package/lib/simple-tree/proxies.d.ts +1 -12
- package/lib/simple-tree/proxies.d.ts.map +1 -1
- package/lib/simple-tree/proxies.js +1 -96
- package/lib/simple-tree/proxies.js.map +1 -1
- package/lib/simple-tree/toMapTree.d.ts +1 -1
- package/lib/simple-tree/toMapTree.js +1 -1
- package/lib/simple-tree/toMapTree.js.map +1 -1
- package/lib/tableSchema.d.ts +108 -59
- package/lib/tableSchema.d.ts.map +1 -1
- package/lib/tableSchema.js +94 -45
- package/lib/tableSchema.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +25 -25
- package/src/feature-libraries/default-schema/schemaChecker.ts +0 -8
- package/src/feature-libraries/flex-tree/context.ts +18 -20
- package/src/feature-libraries/flex-tree/index.ts +0 -1
- package/src/feature-libraries/flex-tree/lazyField.ts +2 -14
- package/src/feature-libraries/flex-tree/utilities.ts +8 -8
- package/src/feature-libraries/index.ts +0 -1
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/checkoutFlexTreeView.ts +10 -6
- package/src/shared-tree/schematizeTree.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +14 -14
- package/src/shared-tree/treeAlpha.ts +21 -5
- package/src/simple-tree/api/create.ts +15 -15
- package/src/simple-tree/api/index.ts +6 -2
- package/src/simple-tree/api/storedSchema.ts +2 -19
- package/src/simple-tree/arrayNode.ts +9 -20
- package/src/simple-tree/core/unhydratedFlexTree.ts +10 -5
- package/src/simple-tree/index.ts +6 -5
- package/src/simple-tree/mapNode.ts +8 -12
- package/src/simple-tree/objectNode.ts +3 -12
- package/src/simple-tree/prepareForInsertion.ts +236 -0
- package/src/simple-tree/proxies.ts +2 -147
- package/src/simple-tree/toMapTree.ts +1 -1
- package/src/tableSchema.ts +310 -158
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ExclusiveMapTree,
|
|
8
|
+
SchemaAndPolicy,
|
|
9
|
+
IForestSubscription,
|
|
10
|
+
MapTree,
|
|
11
|
+
UpPath,
|
|
12
|
+
NodeIndex,
|
|
13
|
+
FieldKey,
|
|
14
|
+
DetachedField,
|
|
15
|
+
} from "../core/index.js";
|
|
16
|
+
import {
|
|
17
|
+
type FlexTreeContext,
|
|
18
|
+
getSchemaAndPolicy,
|
|
19
|
+
type FlexTreeHydratedContext,
|
|
20
|
+
} from "../feature-libraries/index.js";
|
|
21
|
+
import type { ImplicitAllowedTypes, ImplicitFieldSchema } from "./schemaTypes.js";
|
|
22
|
+
import { type InsertableContent, mapTreeFromNodeData } from "./toMapTree.js";
|
|
23
|
+
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
24
|
+
import { brand } from "../util/index.js";
|
|
25
|
+
import {
|
|
26
|
+
getKernel,
|
|
27
|
+
type TreeNode,
|
|
28
|
+
tryUnhydratedFlexTreeNode,
|
|
29
|
+
unhydratedFlexTreeNodeToTreeNode,
|
|
30
|
+
} from "./core/index.js";
|
|
31
|
+
import { debugAssert } from "@fluidframework/core-utils/internal";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Prepare content from a user for insertion into a tree.
|
|
35
|
+
* @remarks
|
|
36
|
+
* This validates and converts the input, and if necessary invokes {@link prepareContentForHydration}.
|
|
37
|
+
*/
|
|
38
|
+
export function prepareForInsertion<TIn extends InsertableContent | undefined>(
|
|
39
|
+
data: TIn,
|
|
40
|
+
schema: ImplicitFieldSchema,
|
|
41
|
+
destinationContext: FlexTreeContext,
|
|
42
|
+
): TIn extends undefined ? undefined : ExclusiveMapTree {
|
|
43
|
+
return prepareForInsertionContextless(
|
|
44
|
+
data,
|
|
45
|
+
schema,
|
|
46
|
+
getSchemaAndPolicy(destinationContext),
|
|
47
|
+
destinationContext.isHydrated() ? destinationContext : undefined,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* {@link prepareForInsertion} but batched for array content.
|
|
53
|
+
* @privateRemarks
|
|
54
|
+
* TODO:
|
|
55
|
+
* Experimentally it was determined that making separate calls to prepareContentForHydration for each array item did not work.
|
|
56
|
+
* This should be understood and fixed or have the factors that cause it clearly documented.
|
|
57
|
+
* If fixed, this function should be removed, and arrays can just map over prepareForInsertion.
|
|
58
|
+
*/
|
|
59
|
+
export function prepareArrayForInsertion(
|
|
60
|
+
data: readonly InsertableContent[],
|
|
61
|
+
schema: ImplicitAllowedTypes,
|
|
62
|
+
destinationContext: FlexTreeContext,
|
|
63
|
+
): ExclusiveMapTree[] {
|
|
64
|
+
const mapTrees: ExclusiveMapTree[] = data.map((item) =>
|
|
65
|
+
mapTreeFromNodeData(
|
|
66
|
+
item,
|
|
67
|
+
schema,
|
|
68
|
+
destinationContext.isHydrated() ? destinationContext.nodeKeyManager : undefined,
|
|
69
|
+
getSchemaAndPolicy(destinationContext),
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
if (destinationContext.isHydrated()) {
|
|
74
|
+
prepareContentForHydration(mapTrees, destinationContext.checkout.forest);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return mapTrees;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Split out from {@link prepareForInsertion} as to allow use without a context.
|
|
82
|
+
* @remarks
|
|
83
|
+
* Adding this entry point is a workaround for initialize not currently having a context.
|
|
84
|
+
*/
|
|
85
|
+
export function prepareForInsertionContextless<TIn extends InsertableContent | undefined>(
|
|
86
|
+
data: TIn,
|
|
87
|
+
schema: ImplicitFieldSchema,
|
|
88
|
+
schemaAndPolicy: SchemaAndPolicy,
|
|
89
|
+
hydratedData: Pick<FlexTreeHydratedContext, "checkout" | "nodeKeyManager"> | undefined,
|
|
90
|
+
): TIn extends undefined ? undefined : ExclusiveMapTree {
|
|
91
|
+
const mapTree = mapTreeFromNodeData(
|
|
92
|
+
data,
|
|
93
|
+
schema,
|
|
94
|
+
hydratedData?.nodeKeyManager,
|
|
95
|
+
schemaAndPolicy,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (mapTree !== undefined && hydratedData !== undefined) {
|
|
99
|
+
prepareContentForHydration([mapTree], hydratedData.checkout.forest);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return mapTree as TIn extends undefined ? undefined : ExclusiveMapTree;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* An {@link UpPath} that is just index zero in a {@link DetachedField} which can be modified at a later time.
|
|
107
|
+
*/
|
|
108
|
+
interface Root extends UpPath {
|
|
109
|
+
readonly parent: undefined;
|
|
110
|
+
parentField: DetachedField & FieldKey;
|
|
111
|
+
readonly parentIndex: NodeIndex & 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The path from the included node to the root of the content tree it was inserted as part of.
|
|
116
|
+
*/
|
|
117
|
+
interface RelativeNodePath {
|
|
118
|
+
readonly path: UpPath;
|
|
119
|
+
readonly node: TreeNode;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* {@link RelativeNodePath}s for every {@link TreeNode} in the content tree inserted as an atomic operation.
|
|
124
|
+
*/
|
|
125
|
+
interface LocatedNodesBatch {
|
|
126
|
+
/**
|
|
127
|
+
* UpPath shared by all {@link RelativeNodePath}s in this batch corresponding to the root of the inserted content.
|
|
128
|
+
*/
|
|
129
|
+
readonly rootPath: Root;
|
|
130
|
+
readonly paths: RelativeNodePath[];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A dummy key value used in {@link LocatedNodesBatch.rootPath} which will be replaced with the actual detached field once it is known.
|
|
135
|
+
*/
|
|
136
|
+
const placeholderKey: DetachedField & FieldKey = brand("placeholder" as const);
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Records any proxies in the given content tree and does the necessary bookkeeping to ensure they are synchronized with subsequent reads of the tree.
|
|
140
|
+
* @remarks If the content tree contains any proxies, this function must be called just prior to inserting the content into the tree.
|
|
141
|
+
* Specifically, no other content may be inserted into the tree between the invocation of this function and the insertion of `content`.
|
|
142
|
+
* The insertion of `content` must occur or else this function will cause memory leaks.
|
|
143
|
+
* @param content - the content subsequence to be inserted, of which might deeply contain {@link TreeNode}s which need to be hydrated.
|
|
144
|
+
* @param forest - the forest the content is being inserted into.
|
|
145
|
+
* See {@link extractFactoryContent} for more details.
|
|
146
|
+
*/
|
|
147
|
+
function prepareContentForHydration(
|
|
148
|
+
content: readonly MapTree[],
|
|
149
|
+
forest: IForestSubscription,
|
|
150
|
+
): void {
|
|
151
|
+
const batches: LocatedNodesBatch[] = [];
|
|
152
|
+
for (const item of content) {
|
|
153
|
+
const batch: LocatedNodesBatch = {
|
|
154
|
+
rootPath: {
|
|
155
|
+
parent: undefined,
|
|
156
|
+
parentField: placeholderKey,
|
|
157
|
+
parentIndex: 0,
|
|
158
|
+
},
|
|
159
|
+
paths: [],
|
|
160
|
+
};
|
|
161
|
+
batches.push(batch);
|
|
162
|
+
walkMapTree(item, batch.rootPath, (p, node) => {
|
|
163
|
+
batch.paths.push({ path: p, node });
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
bindTreeNodes(batches, forest);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function walkMapTree(
|
|
171
|
+
mapTree: MapTree,
|
|
172
|
+
path: UpPath,
|
|
173
|
+
onVisitTreeNode: (path: UpPath, treeNode: TreeNode) => void,
|
|
174
|
+
): void {
|
|
175
|
+
if (tryUnhydratedFlexTreeNode(mapTree)?.parentField.parent.parent !== undefined) {
|
|
176
|
+
throw new UsageError(
|
|
177
|
+
"Attempted to insert a node which is already under a parent. If this is desired, remove the node from its parent before inserting it elsewhere.",
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
type Next = [path: UpPath, tree: MapTree];
|
|
182
|
+
const nexts: Next[] = [];
|
|
183
|
+
for (let next: Next | undefined = [path, mapTree]; next !== undefined; next = nexts.pop()) {
|
|
184
|
+
const [p, m] = next;
|
|
185
|
+
const mapTreeNode = tryUnhydratedFlexTreeNode(m);
|
|
186
|
+
if (mapTreeNode !== undefined) {
|
|
187
|
+
const treeNode = unhydratedFlexTreeNodeToTreeNode.get(mapTreeNode);
|
|
188
|
+
if (treeNode !== undefined) {
|
|
189
|
+
onVisitTreeNode(p, treeNode);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for (const [key, field] of m.fields) {
|
|
194
|
+
for (const [i, child] of field.entries()) {
|
|
195
|
+
nexts.push([
|
|
196
|
+
{
|
|
197
|
+
parent: p,
|
|
198
|
+
parentField: key,
|
|
199
|
+
parentIndex: i,
|
|
200
|
+
},
|
|
201
|
+
child,
|
|
202
|
+
]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Register a collection of nodes with the forest so that they can be hydrated.
|
|
210
|
+
* @param locatedNodes - the nodes to register with the forest.
|
|
211
|
+
* Each index in this array expects its content to be added and produce its own `afterRootFieldCreated` event.
|
|
212
|
+
* If array subsequence insertion is optimized to produce a single event, this will not work correctly as is, and will need to be modified to take in a single {@link LocatedNodesBatch}.
|
|
213
|
+
*/
|
|
214
|
+
function bindTreeNodes(
|
|
215
|
+
locatedNodes: readonly LocatedNodesBatch[],
|
|
216
|
+
forest: IForestSubscription,
|
|
217
|
+
): void {
|
|
218
|
+
// Only subscribe to the event if there is at least one TreeNode tree to hydrate - this is not the case when inserting an empty array [].
|
|
219
|
+
if (locatedNodes.length > 0) {
|
|
220
|
+
// Creating a new array emits one event per element in the array, so listen to the event once for each element
|
|
221
|
+
let i = 0;
|
|
222
|
+
const off = forest.events.on("afterRootFieldCreated", (fieldKey) => {
|
|
223
|
+
// Non null asserting here because of the length check above
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
225
|
+
const batch = locatedNodes[i]!;
|
|
226
|
+
debugAssert(() => batch.rootPath.parentField === placeholderKey);
|
|
227
|
+
batch.rootPath.parentField = brand(fieldKey);
|
|
228
|
+
for (const { path, node } of batch.paths) {
|
|
229
|
+
getKernel(node).anchorProxy(forest.anchors, path);
|
|
230
|
+
}
|
|
231
|
+
if (++i === locatedNodes.length) {
|
|
232
|
+
off();
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -3,16 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
7
6
|
import { fail } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import {
|
|
9
|
-
EmptyKey,
|
|
10
|
-
type IForestSubscription,
|
|
11
|
-
type MapTree,
|
|
12
|
-
type TreeValue,
|
|
13
|
-
type UpPath,
|
|
14
|
-
} from "../core/index.js";
|
|
15
|
-
|
|
7
|
+
import type { TreeValue } from "../core/index.js";
|
|
16
8
|
import {
|
|
17
9
|
FieldKinds,
|
|
18
10
|
type FlexTreeField,
|
|
@@ -20,14 +12,7 @@ import {
|
|
|
20
12
|
type FlexTreeRequiredField,
|
|
21
13
|
type FlexTreeOptionalField,
|
|
22
14
|
} from "../feature-libraries/index.js";
|
|
23
|
-
import { type
|
|
24
|
-
import {
|
|
25
|
-
getKernel,
|
|
26
|
-
type TreeNode,
|
|
27
|
-
getOrCreateNodeFromInnerNode,
|
|
28
|
-
tryUnhydratedFlexTreeNode,
|
|
29
|
-
unhydratedFlexTreeNodeToTreeNode,
|
|
30
|
-
} from "./core/index.js";
|
|
15
|
+
import { type TreeNode, getOrCreateNodeFromInnerNode } from "./core/index.js";
|
|
31
16
|
|
|
32
17
|
/**
|
|
33
18
|
* Retrieve the associated {@link TreeNode} for the given field's content.
|
|
@@ -59,133 +44,3 @@ export function getTreeNodeForField(field: FlexTreeField): TreeNode | TreeValue
|
|
|
59
44
|
fail(0xadf /* invalid field kind */);
|
|
60
45
|
}
|
|
61
46
|
}
|
|
62
|
-
|
|
63
|
-
// #region Content insertion and proxy binding
|
|
64
|
-
|
|
65
|
-
/** The path of a proxy, relative to the root of the content tree that the proxy belongs to */
|
|
66
|
-
interface RelativeProxyPath {
|
|
67
|
-
readonly path: UpPath;
|
|
68
|
-
readonly proxy: TreeNode;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** All {@link RelativeProxyPath}s that are under the given root path */
|
|
72
|
-
interface RootedProxyPaths {
|
|
73
|
-
readonly rootPath: UpPath;
|
|
74
|
-
readonly proxyPaths: RelativeProxyPath[];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Records any proxies in the given content tree and does the necessary bookkeeping to ensure they are synchronized with subsequent reads of the tree.
|
|
79
|
-
* @remarks If the content tree contains any proxies, this function must be called just prior to inserting the content into the tree.
|
|
80
|
-
* Specifically, no other content may be inserted into the tree between the invocation of this function and the insertion of `content`.
|
|
81
|
-
* The insertion of `content` must occur or else this function will cause memory leaks.
|
|
82
|
-
* @param content - the tree of content to be inserted, of which any of its object/map/array nodes might be a proxy
|
|
83
|
-
* @param anchors - the {@link AnchorSet} for the tree
|
|
84
|
-
* @returns The content after having all proxies replaced inline with plain javascript objects.
|
|
85
|
-
* See {@link extractFactoryContent} for more details.
|
|
86
|
-
*/
|
|
87
|
-
export function prepareContentForHydration(
|
|
88
|
-
content: MapTree | readonly MapTree[] | undefined,
|
|
89
|
-
forest: IForestSubscription,
|
|
90
|
-
): void {
|
|
91
|
-
if (isReadonlyArray(content)) {
|
|
92
|
-
return prepareArrayContentForHydration(content, forest);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (content !== undefined) {
|
|
96
|
-
const proxies: RootedProxyPaths = {
|
|
97
|
-
rootPath: { parent: undefined, parentField: EmptyKey, parentIndex: 0 },
|
|
98
|
-
proxyPaths: [],
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
walkMapTree(content, proxies.rootPath, (p, proxy) => {
|
|
102
|
-
proxies.proxyPaths.push({ path: p, proxy });
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
bindProxies([proxies], forest);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function prepareArrayContentForHydration(
|
|
110
|
-
content: readonly MapTree[],
|
|
111
|
-
forest: IForestSubscription,
|
|
112
|
-
): void {
|
|
113
|
-
const proxyPaths: RootedProxyPaths[] = [];
|
|
114
|
-
for (const item of content) {
|
|
115
|
-
const proxyPath: RootedProxyPaths = {
|
|
116
|
-
rootPath: {
|
|
117
|
-
parent: undefined,
|
|
118
|
-
parentField: EmptyKey,
|
|
119
|
-
parentIndex: 0,
|
|
120
|
-
},
|
|
121
|
-
proxyPaths: [],
|
|
122
|
-
};
|
|
123
|
-
proxyPaths.push(proxyPath);
|
|
124
|
-
walkMapTree(item, proxyPath.rootPath, (p, proxy) => {
|
|
125
|
-
proxyPath.proxyPaths.push({ path: p, proxy });
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
bindProxies(proxyPaths, forest);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function walkMapTree(
|
|
133
|
-
mapTree: MapTree,
|
|
134
|
-
path: UpPath,
|
|
135
|
-
onVisitTreeNode: (path: UpPath, treeNode: TreeNode) => void,
|
|
136
|
-
): void {
|
|
137
|
-
if (tryUnhydratedFlexTreeNode(mapTree)?.parentField.parent.parent !== undefined) {
|
|
138
|
-
throw new UsageError(
|
|
139
|
-
"Attempted to insert a node which is already under a parent. If this is desired, remove the node from its parent before inserting it elsewhere.",
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
type Next = [path: UpPath, tree: MapTree];
|
|
144
|
-
const nexts: Next[] = [];
|
|
145
|
-
for (let next: Next | undefined = [path, mapTree]; next !== undefined; next = nexts.pop()) {
|
|
146
|
-
const [p, m] = next;
|
|
147
|
-
const mapTreeNode = tryUnhydratedFlexTreeNode(m);
|
|
148
|
-
if (mapTreeNode !== undefined) {
|
|
149
|
-
const treeNode = unhydratedFlexTreeNodeToTreeNode.get(mapTreeNode);
|
|
150
|
-
if (treeNode !== undefined) {
|
|
151
|
-
onVisitTreeNode(p, treeNode);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
for (const [key, field] of m.fields) {
|
|
156
|
-
for (const [i, child] of field.entries()) {
|
|
157
|
-
nexts.push([
|
|
158
|
-
{
|
|
159
|
-
parent: p,
|
|
160
|
-
parentField: key,
|
|
161
|
-
parentIndex: i,
|
|
162
|
-
},
|
|
163
|
-
child,
|
|
164
|
-
]);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function bindProxies(proxies: RootedProxyPaths[], forest: IForestSubscription): void {
|
|
171
|
-
// Only subscribe to the event if there is at least one proxy tree to hydrate - this is not the case when inserting an empty array [].
|
|
172
|
-
if (proxies.length > 0) {
|
|
173
|
-
// Creating a new array emits one event per element in the array, so listen to the event once for each element
|
|
174
|
-
let i = 0;
|
|
175
|
-
const off = forest.events.on("afterRootFieldCreated", (fieldKey) => {
|
|
176
|
-
// Non null asserting here because of the length check above
|
|
177
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
178
|
-
(proxies[i]!.rootPath as Mutable<UpPath>).parentField = fieldKey;
|
|
179
|
-
// Non null asserting here because of the length check above
|
|
180
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
181
|
-
for (const { path, proxy } of proxies[i]!.proxyPaths) {
|
|
182
|
-
getKernel(proxy).anchorProxy(forest.anchors, path);
|
|
183
|
-
}
|
|
184
|
-
if (++i === proxies.length) {
|
|
185
|
-
off();
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// #endregion Content insertion and proxy binding
|
|
@@ -482,7 +482,7 @@ For class-based schema, this can be done by replacing an expression like "{foo:
|
|
|
482
482
|
}
|
|
483
483
|
|
|
484
484
|
/**
|
|
485
|
-
*
|
|
485
|
+
* Returns all types for which the data is schema-compatible.
|
|
486
486
|
*/
|
|
487
487
|
export function getPossibleTypes(
|
|
488
488
|
allowedTypes: ReadonlySet<TreeNodeSchema>,
|