@fluidframework/tree 2.31.0 → 2.32.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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +44 -0
- package/api-extractor/api-extractor.current.json +5 -1
- package/api-report/tree.alpha.api.md +44 -20
- package/dist/alpha.d.ts +6 -2
- package/dist/feature-libraries/flex-tree/context.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +1 -2
- 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/lazyEntity.d.ts +6 -15
- package/dist/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyEntity.js +9 -18
- package/dist/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +3 -3
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +14 -14
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts +4 -4
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +12 -12
- package/dist/feature-libraries/flex-tree/lazyNode.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/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- 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/shared-tree/sharedTree.js +2 -2
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeApiAlpha.d.ts +6 -6
- package/dist/shared-tree/treeApiAlpha.d.ts.map +1 -1
- package/dist/shared-tree/treeApiAlpha.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +0 -6
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +0 -17
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/conciseTree.d.ts +2 -2
- package/dist/simple-tree/api/conciseTree.d.ts.map +1 -1
- package/dist/simple-tree/api/conciseTree.js.map +1 -1
- package/dist/simple-tree/api/customTree.d.ts +14 -12
- package/dist/simple-tree/api/customTree.d.ts.map +1 -1
- package/dist/simple-tree/api/customTree.js.map +1 -1
- package/dist/simple-tree/api/getJsonSchema.d.ts +21 -7
- package/dist/simple-tree/api/getJsonSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/getJsonSchema.js +8 -16
- package/dist/simple-tree/api/getJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.d.ts +3 -10
- package/dist/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.js +4 -16
- package/dist/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +4 -3
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +2 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +17 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.js +4 -0
- package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.d.ts +5 -2
- package/dist/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.js +24 -8
- package/dist/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts +11 -3
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +40 -28
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/tree.d.ts +32 -5
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js +17 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/api/verboseTree.d.ts +4 -28
- package/dist/simple-tree/api/verboseTree.d.ts.map +1 -1
- package/dist/simple-tree/api/verboseTree.js.map +1 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js +7 -3
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +7 -6
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +12 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/dist/simple-tree/index.d.ts +1 -1
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +3 -2
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/simpleSchema.d.ts +4 -11
- package/dist/simple-tree/simpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/simpleSchema.js.map +1 -1
- package/dist/tableSchema.d.ts +227 -0
- package/dist/tableSchema.d.ts.map +1 -0
- package/dist/tableSchema.js +234 -0
- package/dist/tableSchema.js.map +1 -0
- package/dist/treeFactory.d.ts +4 -4
- package/dist/treeFactory.d.ts.map +1 -1
- package/dist/treeFactory.js.map +1 -1
- package/dist/util/breakable.d.ts.map +1 -1
- package/dist/util/breakable.js +9 -7
- package/dist/util/breakable.js.map +1 -1
- package/lib/alpha.d.ts +6 -2
- package/lib/feature-libraries/flex-tree/context.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +1 -2
- 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/lazyEntity.d.ts +6 -15
- package/lib/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyEntity.js +8 -17
- package/lib/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +3 -3
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +15 -15
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts +4 -4
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +13 -13
- package/lib/feature-libraries/flex-tree/lazyNode.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/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -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/shared-tree/sharedTree.js +2 -2
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeApiAlpha.d.ts +6 -6
- package/lib/shared-tree/treeApiAlpha.d.ts.map +1 -1
- package/lib/shared-tree/treeApiAlpha.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +0 -6
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +0 -17
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/conciseTree.d.ts +2 -2
- package/lib/simple-tree/api/conciseTree.d.ts.map +1 -1
- package/lib/simple-tree/api/conciseTree.js.map +1 -1
- package/lib/simple-tree/api/customTree.d.ts +14 -12
- package/lib/simple-tree/api/customTree.d.ts.map +1 -1
- package/lib/simple-tree/api/customTree.js.map +1 -1
- package/lib/simple-tree/api/getJsonSchema.d.ts +21 -7
- package/lib/simple-tree/api/getJsonSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/getJsonSchema.js +8 -16
- package/lib/simple-tree/api/getJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.d.ts +3 -10
- package/lib/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.js +4 -16
- package/lib/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +4 -3
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +1 -1
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +17 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.js +4 -0
- package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.d.ts +5 -2
- package/lib/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.js +24 -8
- package/lib/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts +11 -3
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +41 -29
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/tree.d.ts +32 -5
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js +16 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/api/verboseTree.d.ts +4 -28
- package/lib/simple-tree/api/verboseTree.d.ts.map +1 -1
- package/lib/simple-tree/api/verboseTree.js.map +1 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js +7 -3
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +8 -7
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +12 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
- package/lib/simple-tree/index.d.ts +1 -1
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/simpleSchema.d.ts +4 -11
- package/lib/simple-tree/simpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/simpleSchema.js.map +1 -1
- package/lib/tableSchema.d.ts +227 -0
- package/lib/tableSchema.d.ts.map +1 -0
- package/lib/tableSchema.js +231 -0
- package/lib/tableSchema.js.map +1 -0
- package/lib/treeFactory.d.ts +4 -4
- package/lib/treeFactory.d.ts.map +1 -1
- package/lib/treeFactory.js.map +1 -1
- package/lib/util/breakable.d.ts.map +1 -1
- package/lib/util/breakable.js +9 -7
- package/lib/util/breakable.js.map +1 -1
- package/package.json +25 -37
- package/src/feature-libraries/flex-tree/context.ts +2 -2
- package/src/feature-libraries/flex-tree/index.ts +0 -1
- package/src/feature-libraries/flex-tree/lazyEntity.ts +11 -21
- package/src/feature-libraries/flex-tree/lazyField.ts +17 -26
- package/src/feature-libraries/flex-tree/lazyNode.ts +13 -19
- package/src/feature-libraries/index.ts +0 -1
- package/src/index.ts +6 -2
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/sharedTree.ts +2 -2
- package/src/shared-tree/treeApiAlpha.ts +17 -15
- package/src/shared-tree-core/sharedTreeCore.ts +0 -23
- package/src/simple-tree/api/conciseTree.ts +4 -4
- package/src/simple-tree/api/customTree.ts +16 -14
- package/src/simple-tree/api/getJsonSchema.ts +25 -16
- package/src/simple-tree/api/getSimpleSchema.ts +4 -18
- package/src/simple-tree/api/index.ts +4 -2
- package/src/simple-tree/api/schemaFactoryAlpha.ts +18 -1
- package/src/simple-tree/api/schemaFromSimple.ts +45 -16
- package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +53 -34
- package/src/simple-tree/api/tree.ts +51 -4
- package/src/simple-tree/api/verboseTree.ts +7 -32
- package/src/simple-tree/api/viewSchemaToSimpleSchema.ts +8 -3
- package/src/simple-tree/core/treeNodeKernel.ts +11 -7
- package/src/simple-tree/core/unhydratedFlexTree.ts +17 -4
- package/src/simple-tree/index.ts +4 -2
- package/src/simple-tree/simpleSchema.ts +4 -12
- package/src/tableSchema.ts +609 -0
- package/src/treeFactory.ts +4 -3
- package/src/util/breakable.ts +9 -6
package/lib/util/breakable.js
CHANGED
|
@@ -141,16 +141,18 @@ function isBreaker(f) {
|
|
|
141
141
|
* Methods already marked as {@link breakingMethod} or {@link throwIfBroken} are unaffected.
|
|
142
142
|
*/
|
|
143
143
|
export function breakingClass(target, context) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// Keep track of what keys we have seen
|
|
147
|
-
//
|
|
148
|
-
|
|
144
|
+
// This could extend target, but doing so adds an extra step in the prototype chain and makes the instances just show up as "DecoratedBreakable" in the debugger.
|
|
145
|
+
const DecoratedBreakable = target;
|
|
146
|
+
// Keep track of what keys we have seen (and already wrapped if needed).
|
|
147
|
+
// Used to avoid rewrapping already wrapped properties.
|
|
148
|
+
// Preloaded with "constructor" to avoid wrapping the constructor as there is no need to set the broken flag when the constructor throws and does not return an object.
|
|
149
|
+
// Avoiding wrapping the constructor also avoids messing up the displayed name in the debugger.
|
|
150
|
+
const doNotWrap = new Set(["constructor"]);
|
|
149
151
|
let prototype = target.prototype;
|
|
150
152
|
while (prototype !== null) {
|
|
151
153
|
for (const key of Reflect.ownKeys(prototype)) {
|
|
152
|
-
if (!
|
|
153
|
-
|
|
154
|
+
if (!doNotWrap.has(key)) {
|
|
155
|
+
doNotWrap.add(key);
|
|
154
156
|
const descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);
|
|
155
157
|
if (descriptor !== undefined) {
|
|
156
158
|
// Method
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"breakable.js","sourceRoot":"","sources":["../../src/util/breakable.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * An object which can enter a \"broken\" state where trying to use it is a UsageError.\n */\nexport class Breakable {\n\tprivate brokenBy?: Error;\n\n\tpublic constructor(private readonly name: string) {}\n\n\t/**\n\t * Throws if the object is in the broken state.\n\t * @remarks\n\t * Can use {@link throwIfBroken} to apply this to a method.\n\t */\n\tpublic use(): void {\n\t\tif (this.brokenBy !== undefined) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Invalid use of ${this.name} after it was put into an invalid state by another error.\\nOriginal Error:\\n${this.brokenBy}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Puts this object into the broken state, and throws an error.\n\t *\n\t * @throws If already broken by a different error, throws a UsageError, otherwise throws `brokenBy`.\n\t */\n\tpublic break(brokenBy: Error): never {\n\t\t// If already broken by this error, let it bubble up without rethrowing a modified version.\n\t\t// This prevents internal errors like asserts getting rethrown as different errors when wrapped with multiple call to `{@link Breakable.run}` or `{@link breakingMethod}`.\n\t\tif (this.brokenBy !== brokenBy) {\n\t\t\tthis.use();\n\t\t\tthis.brokenBy = brokenBy;\n\t\t}\n\t\tthrow brokenBy;\n\t}\n\n\t/**\n\t * {@link Breakable.break}, except tolerates `unknown` to be more easily used by catch blocks.\n\t * @privateRemarks\n\t * If there is a use-case, this should be made public.\n\t */\n\tpublic rethrowCaught(brokenBy: unknown): never {\n\t\tif (brokenBy instanceof Error) {\n\t\t\tthis.break(brokenBy);\n\t\t}\n\t\tthis.break(\n\t\t\tnew Error(`Non-error thrown breaking ${this.name}. Thrown value: \"${brokenBy}\"`),\n\t\t);\n\t}\n\n\t/**\n\t * Runs code which should break the object if it throws.\n\t * @remarks\n\t * This also throws if already broken like {@link Breakable.use}.\n\t * Any exceptions this catches are re-thrown.\n\t * Can use {@link breakingMethod} to apply this to a method.\n\t */\n\tpublic run<TResult>(breaker: () => TResult): TResult {\n\t\tthis.use();\n\t\ttry {\n\t\t\treturn breaker();\n\t\t} catch (error: unknown) {\n\t\t\tthis.rethrowCaught(error);\n\t\t}\n\t}\n\n\t/**\n\t * Clears the existing broken state.\n\t * @remarks\n\t * This is rarely safe to to: it is only ok when all objects using this breaker are known to not have been left in an invalid state.\n\t * This is pretty much only safe in tests which just were checking a specific error was thrown, and which know that error closepath is actually exception safe.\n\t */\n\tpublic clearError(): void {\n\t\tassert(this.brokenBy !== undefined, 0x9b6 /* No error to clear */);\n\t\tthis.brokenBy = undefined;\n\t}\n}\n\n/**\n * Marks an object as being able to be in a broken state (unknown/unspecified/broken state due to unhandled exception).\n * @remarks\n * See decorators {@link breakingMethod} and {@link throwIfBroken} for ease of use.\n */\nexport interface WithBreakable {\n\treadonly breaker: Breakable;\n}\n\n/**\n * Decorator for methods which should break the object when they throw.\n * @remarks\n * This also throws if already broken like {@link throwIfBroken}.\n * See {@link Breakable.run} for details.\n *\n * This should be used on methods which modify data that could result in an unsupported/broken state if an exception is thrown while modifying.\n * It is ok for breakingMethods to call each-other.\n * @privateRemarks\n * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.\n */\nexport function breakingMethod<\n\tTarget extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return),\n\tThis extends WithBreakable,\n\tArgs extends never[],\n\tReturn,\n>(target: Target, context?: ClassMethodDecoratorContext<This, Target>): Target {\n\tfunction replacementMethod(this: This, ...args: Args): Return {\n\t\tif (this.breaker === undefined) {\n\t\t\t// This case is necessary for when wrapping methods which are invoked inside the constructor of the base class before `breaker` is set.\n\t\t\t// Since the constructor throwing does not return an object, failing to put it into a broken state is not too bad.\n\t\t\t// However when more than just the constructed object should be broken, this can result in missing a break.\n\t\t\treturn target.call(this, ...args);\n\t\t}\n\t\treturn this.breaker.run(() => {\n\t\t\treturn target.call(this, ...args);\n\t\t});\n\t}\n\tmarkBreaker(replacementMethod);\n\tnameFunctionFrom(replacementMethod, target);\n\treturn replacementMethod as Target;\n}\n\n/**\n * Decorator for methods which should throw if the object is in a broken state.\n * @remarks\n * This should be used on methods which read data that could be invalid when the object is broken.\n * @privateRemarks\n * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.\n */\nexport function throwIfBroken<\n\tTarget extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return),\n\tThis extends WithBreakable,\n\tArgs extends never[],\n\tReturn,\n>(target: Target, context: ClassMethodDecoratorContext<This, Target>): Target {\n\tfunction replacementMethod(this: This, ...args: Args): Return {\n\t\tthis.breaker.use();\n\t\treturn target.call(this, ...args);\n\t}\n\tmarkBreaker(replacementMethod);\n\tnameFunctionFrom(replacementMethod, target);\n\treturn replacementMethod as Target;\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype PossiblyNamedFunction = Function & { displayName?: undefined | string };\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction nameFunctionFrom(toName: Function, nameFrom: Function): void {\n\t(toName as PossiblyNamedFunction).displayName =\n\t\t(nameFrom as PossiblyNamedFunction).displayName ?? nameFrom.name;\n}\n\nconst isBreakerSymbol: unique symbol = Symbol(\"isBreaker\");\n\n// Accepting any function like value is desired and safe here as this does not call the provided function.\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction markBreaker(f: Function): void {\n\t(f as unknown as Record<typeof isBreakerSymbol, true>)[isBreakerSymbol] = true;\n}\n\n// Accepting any function like value is desired and safe here as this does not call the provided function.\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction isBreaker(f: Function): boolean {\n\treturn isBreakerSymbol in (f as unknown as Record<typeof isBreakerSymbol, true>);\n}\n\n/**\n * Decorator for classes which should break when their methods throw.\n * @remarks\n * Applies {@link breakingMethod} to all methods declared directly by class or its base classes.\n * Does not include those on derived classes.\n * Does not include getters or setters, or value properties.\n * Methods already marked as {@link breakingMethod} or {@link throwIfBroken} are unaffected.\n */\nexport function breakingClass<Target extends abstract new (...args: any[]) => WithBreakable>(\n\ttarget: Target,\n\tcontext: ClassDecoratorContext<Target>,\n): Target {\n\tabstract class DecoratedBreakable extends target {}\n\n\t// Keep track of what keys we have seen,\n\t// since we visit most derived properties first and need to avoid wrapping base properties overriding more derived ones.\n\tconst overriddenKeys: Set<string | symbol> = new Set();\n\n\tlet prototype: object | null = target.prototype;\n\twhile (prototype !== null) {\n\t\tfor (const key of Reflect.ownKeys(prototype)) {\n\t\t\tif (!overriddenKeys.has(key)) {\n\t\t\t\toverriddenKeys.add(key);\n\t\t\t\tconst descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);\n\t\t\t\tif (descriptor !== undefined) {\n\t\t\t\t\t// Method\n\t\t\t\t\tif (typeof descriptor.value === \"function\") {\n\t\t\t\t\t\tif (!isBreaker(descriptor.value)) {\n\t\t\t\t\t\t\t// This does not affect the original class, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor\n\t\t\t\t\t\t\tdescriptor.value = breakingMethod(descriptor.value);\n\t\t\t\t\t\t\tObject.defineProperty(DecoratedBreakable.prototype, key, descriptor);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprototype = Reflect.getPrototypeOf(prototype);\n\t}\n\n\treturn DecoratedBreakable;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"breakable.js","sourceRoot":"","sources":["../../src/util/breakable.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\n\n/**\n * An object which can enter a \"broken\" state where trying to use it is a UsageError.\n */\nexport class Breakable {\n\tprivate brokenBy?: Error;\n\n\tpublic constructor(private readonly name: string) {}\n\n\t/**\n\t * Throws if the object is in the broken state.\n\t * @remarks\n\t * Can use {@link throwIfBroken} to apply this to a method.\n\t */\n\tpublic use(): void {\n\t\tif (this.brokenBy !== undefined) {\n\t\t\tthrow new UsageError(\n\t\t\t\t`Invalid use of ${this.name} after it was put into an invalid state by another error.\\nOriginal Error:\\n${this.brokenBy}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Puts this object into the broken state, and throws an error.\n\t *\n\t * @throws If already broken by a different error, throws a UsageError, otherwise throws `brokenBy`.\n\t */\n\tpublic break(brokenBy: Error): never {\n\t\t// If already broken by this error, let it bubble up without rethrowing a modified version.\n\t\t// This prevents internal errors like asserts getting rethrown as different errors when wrapped with multiple call to `{@link Breakable.run}` or `{@link breakingMethod}`.\n\t\tif (this.brokenBy !== brokenBy) {\n\t\t\tthis.use();\n\t\t\tthis.brokenBy = brokenBy;\n\t\t}\n\t\tthrow brokenBy;\n\t}\n\n\t/**\n\t * {@link Breakable.break}, except tolerates `unknown` to be more easily used by catch blocks.\n\t * @privateRemarks\n\t * If there is a use-case, this should be made public.\n\t */\n\tpublic rethrowCaught(brokenBy: unknown): never {\n\t\tif (brokenBy instanceof Error) {\n\t\t\tthis.break(brokenBy);\n\t\t}\n\t\tthis.break(\n\t\t\tnew Error(`Non-error thrown breaking ${this.name}. Thrown value: \"${brokenBy}\"`),\n\t\t);\n\t}\n\n\t/**\n\t * Runs code which should break the object if it throws.\n\t * @remarks\n\t * This also throws if already broken like {@link Breakable.use}.\n\t * Any exceptions this catches are re-thrown.\n\t * Can use {@link breakingMethod} to apply this to a method.\n\t */\n\tpublic run<TResult>(breaker: () => TResult): TResult {\n\t\tthis.use();\n\t\ttry {\n\t\t\treturn breaker();\n\t\t} catch (error: unknown) {\n\t\t\tthis.rethrowCaught(error);\n\t\t}\n\t}\n\n\t/**\n\t * Clears the existing broken state.\n\t * @remarks\n\t * This is rarely safe to to: it is only ok when all objects using this breaker are known to not have been left in an invalid state.\n\t * This is pretty much only safe in tests which just were checking a specific error was thrown, and which know that error closepath is actually exception safe.\n\t */\n\tpublic clearError(): void {\n\t\tassert(this.brokenBy !== undefined, 0x9b6 /* No error to clear */);\n\t\tthis.brokenBy = undefined;\n\t}\n}\n\n/**\n * Marks an object as being able to be in a broken state (unknown/unspecified/broken state due to unhandled exception).\n * @remarks\n * See decorators {@link breakingMethod} and {@link throwIfBroken} for ease of use.\n */\nexport interface WithBreakable {\n\treadonly breaker: Breakable;\n}\n\n/**\n * Decorator for methods which should break the object when they throw.\n * @remarks\n * This also throws if already broken like {@link throwIfBroken}.\n * See {@link Breakable.run} for details.\n *\n * This should be used on methods which modify data that could result in an unsupported/broken state if an exception is thrown while modifying.\n * It is ok for breakingMethods to call each-other.\n * @privateRemarks\n * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.\n */\nexport function breakingMethod<\n\tTarget extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return),\n\tThis extends WithBreakable,\n\tArgs extends never[],\n\tReturn,\n>(target: Target, context?: ClassMethodDecoratorContext<This, Target>): Target {\n\tfunction replacementMethod(this: This, ...args: Args): Return {\n\t\tif (this.breaker === undefined) {\n\t\t\t// This case is necessary for when wrapping methods which are invoked inside the constructor of the base class before `breaker` is set.\n\t\t\t// Since the constructor throwing does not return an object, failing to put it into a broken state is not too bad.\n\t\t\t// However when more than just the constructed object should be broken, this can result in missing a break.\n\t\t\treturn target.call(this, ...args);\n\t\t}\n\t\treturn this.breaker.run(() => {\n\t\t\treturn target.call(this, ...args);\n\t\t});\n\t}\n\tmarkBreaker(replacementMethod);\n\tnameFunctionFrom(replacementMethod, target);\n\treturn replacementMethod as Target;\n}\n\n/**\n * Decorator for methods which should throw if the object is in a broken state.\n * @remarks\n * This should be used on methods which read data that could be invalid when the object is broken.\n * @privateRemarks\n * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.\n */\nexport function throwIfBroken<\n\tTarget extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return),\n\tThis extends WithBreakable,\n\tArgs extends never[],\n\tReturn,\n>(target: Target, context: ClassMethodDecoratorContext<This, Target>): Target {\n\tfunction replacementMethod(this: This, ...args: Args): Return {\n\t\tthis.breaker.use();\n\t\treturn target.call(this, ...args);\n\t}\n\tmarkBreaker(replacementMethod);\n\tnameFunctionFrom(replacementMethod, target);\n\treturn replacementMethod as Target;\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype PossiblyNamedFunction = Function & { displayName?: undefined | string };\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction nameFunctionFrom(toName: Function, nameFrom: Function): void {\n\t(toName as PossiblyNamedFunction).displayName =\n\t\t(nameFrom as PossiblyNamedFunction).displayName ?? nameFrom.name;\n}\n\nconst isBreakerSymbol: unique symbol = Symbol(\"isBreaker\");\n\n// Accepting any function like value is desired and safe here as this does not call the provided function.\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction markBreaker(f: Function): void {\n\t(f as unknown as Record<typeof isBreakerSymbol, true>)[isBreakerSymbol] = true;\n}\n\n// Accepting any function like value is desired and safe here as this does not call the provided function.\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction isBreaker(f: Function): boolean {\n\treturn isBreakerSymbol in (f as unknown as Record<typeof isBreakerSymbol, true>);\n}\n\n/**\n * Decorator for classes which should break when their methods throw.\n * @remarks\n * Applies {@link breakingMethod} to all methods declared directly by class or its base classes.\n * Does not include those on derived classes.\n * Does not include getters or setters, or value properties.\n * Methods already marked as {@link breakingMethod} or {@link throwIfBroken} are unaffected.\n */\nexport function breakingClass<Target extends abstract new (...args: any[]) => WithBreakable>(\n\ttarget: Target,\n\tcontext: ClassDecoratorContext<Target>,\n): Target {\n\t// This could extend target, but doing so adds an extra step in the prototype chain and makes the instances just show up as \"DecoratedBreakable\" in the debugger.\n\tconst DecoratedBreakable = target;\n\n\t// Keep track of what keys we have seen (and already wrapped if needed).\n\t// Used to avoid rewrapping already wrapped properties.\n\t// Preloaded with \"constructor\" to avoid wrapping the constructor as there is no need to set the broken flag when the constructor throws and does not return an object.\n\t// Avoiding wrapping the constructor also avoids messing up the displayed name in the debugger.\n\tconst doNotWrap: Set<string | symbol> = new Set([\"constructor\"]);\n\n\tlet prototype: object | null = target.prototype;\n\twhile (prototype !== null) {\n\t\tfor (const key of Reflect.ownKeys(prototype)) {\n\t\t\tif (!doNotWrap.has(key)) {\n\t\t\t\tdoNotWrap.add(key);\n\t\t\t\tconst descriptor = Reflect.getOwnPropertyDescriptor(prototype, key);\n\t\t\t\tif (descriptor !== undefined) {\n\t\t\t\t\t// Method\n\t\t\t\t\tif (typeof descriptor.value === \"function\") {\n\t\t\t\t\t\tif (!isBreaker(descriptor.value)) {\n\t\t\t\t\t\t\t// This does not affect the original class, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor\n\t\t\t\t\t\t\tdescriptor.value = breakingMethod(descriptor.value);\n\t\t\t\t\t\t\tObject.defineProperty(DecoratedBreakable.prototype, key, descriptor);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tprototype = Reflect.getPrototypeOf(prototype);\n\t}\n\n\treturn DecoratedBreakable;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/tree",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.32.0",
|
|
4
4
|
"description": "Distributed tree",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -89,17 +89,17 @@
|
|
|
89
89
|
"temp-directory": "nyc/.nyc_output"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@fluid-internal/client-utils": "~2.
|
|
93
|
-
"@fluidframework/container-runtime": "~2.
|
|
94
|
-
"@fluidframework/core-interfaces": "~2.
|
|
95
|
-
"@fluidframework/core-utils": "~2.
|
|
96
|
-
"@fluidframework/datastore-definitions": "~2.
|
|
97
|
-
"@fluidframework/driver-definitions": "~2.
|
|
98
|
-
"@fluidframework/id-compressor": "~2.
|
|
99
|
-
"@fluidframework/runtime-definitions": "~2.
|
|
100
|
-
"@fluidframework/runtime-utils": "~2.
|
|
101
|
-
"@fluidframework/shared-object-base": "~2.
|
|
102
|
-
"@fluidframework/telemetry-utils": "~2.
|
|
92
|
+
"@fluid-internal/client-utils": "~2.32.0",
|
|
93
|
+
"@fluidframework/container-runtime": "~2.32.0",
|
|
94
|
+
"@fluidframework/core-interfaces": "~2.32.0",
|
|
95
|
+
"@fluidframework/core-utils": "~2.32.0",
|
|
96
|
+
"@fluidframework/datastore-definitions": "~2.32.0",
|
|
97
|
+
"@fluidframework/driver-definitions": "~2.32.0",
|
|
98
|
+
"@fluidframework/id-compressor": "~2.32.0",
|
|
99
|
+
"@fluidframework/runtime-definitions": "~2.32.0",
|
|
100
|
+
"@fluidframework/runtime-utils": "~2.32.0",
|
|
101
|
+
"@fluidframework/shared-object-base": "~2.32.0",
|
|
102
|
+
"@fluidframework/telemetry-utils": "~2.32.0",
|
|
103
103
|
"@sinclair/typebox": "^0.34.13",
|
|
104
104
|
"@tylerbu/sorted-btree-es6": "^1.8.0",
|
|
105
105
|
"@types/ungap__structured-clone": "^1.2.0",
|
|
@@ -109,20 +109,20 @@
|
|
|
109
109
|
"devDependencies": {
|
|
110
110
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
111
111
|
"@biomejs/biome": "~1.9.3",
|
|
112
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
113
|
-
"@fluid-private/stochastic-test-utils": "~2.
|
|
114
|
-
"@fluid-private/test-dds-utils": "~2.
|
|
115
|
-
"@fluid-private/test-drivers": "~2.
|
|
112
|
+
"@fluid-internal/mocha-test-setup": "~2.32.0",
|
|
113
|
+
"@fluid-private/stochastic-test-utils": "~2.32.0",
|
|
114
|
+
"@fluid-private/test-dds-utils": "~2.32.0",
|
|
115
|
+
"@fluid-private/test-drivers": "~2.32.0",
|
|
116
116
|
"@fluid-tools/benchmark": "^0.50.0",
|
|
117
|
-
"@fluid-tools/build-cli": "^0.
|
|
117
|
+
"@fluid-tools/build-cli": "^0.55.0",
|
|
118
118
|
"@fluidframework/build-common": "^2.0.3",
|
|
119
|
-
"@fluidframework/build-tools": "^0.
|
|
120
|
-
"@fluidframework/container-definitions": "~2.
|
|
121
|
-
"@fluidframework/container-loader": "~2.
|
|
119
|
+
"@fluidframework/build-tools": "^0.55.0",
|
|
120
|
+
"@fluidframework/container-definitions": "~2.32.0",
|
|
121
|
+
"@fluidframework/container-loader": "~2.32.0",
|
|
122
122
|
"@fluidframework/eslint-config-fluid": "^5.7.3",
|
|
123
|
-
"@fluidframework/test-runtime-utils": "~2.
|
|
124
|
-
"@fluidframework/test-utils": "~2.
|
|
125
|
-
"@fluidframework/tree-previous": "npm:@fluidframework/tree@2.
|
|
123
|
+
"@fluidframework/test-runtime-utils": "~2.32.0",
|
|
124
|
+
"@fluidframework/test-utils": "~2.32.0",
|
|
125
|
+
"@fluidframework/tree-previous": "npm:@fluidframework/tree@2.31.0",
|
|
126
126
|
"@microsoft/api-extractor": "7.50.1",
|
|
127
127
|
"@types/diff": "^3.5.1",
|
|
128
128
|
"@types/easy-table": "^0.0.32",
|
|
@@ -162,20 +162,7 @@
|
|
|
162
162
|
}
|
|
163
163
|
},
|
|
164
164
|
"typeValidation": {
|
|
165
|
-
"broken": {
|
|
166
|
-
"Interface_FieldSchemaUnsafe": {
|
|
167
|
-
"forwardCompat": false
|
|
168
|
-
},
|
|
169
|
-
"Interface_ITreeViewConfiguration": {
|
|
170
|
-
"forwardCompat": false
|
|
171
|
-
},
|
|
172
|
-
"TypeAlias_ImplicitAllowedTypes": {
|
|
173
|
-
"forwardCompat": false
|
|
174
|
-
},
|
|
175
|
-
"TypeAlias_ImplicitFieldSchema": {
|
|
176
|
-
"forwardCompat": false
|
|
177
|
-
}
|
|
178
|
-
},
|
|
165
|
+
"broken": {},
|
|
179
166
|
"entrypoint": "public"
|
|
180
167
|
},
|
|
181
168
|
"scripts": {
|
|
@@ -222,6 +209,7 @@
|
|
|
222
209
|
"format:biome": "biome check . --write",
|
|
223
210
|
"lint": "fluid-build . --task lint",
|
|
224
211
|
"lint:fix": "fluid-build . --task eslint:fix --task format",
|
|
212
|
+
"pack:tests": "tar -cf ./tree.test-files.tar ./src/test ./dist/test ./lib/test",
|
|
225
213
|
"test": "npm run test:mocha",
|
|
226
214
|
"test:benchmark:report": "mocha --exit --perfMode --parentProcess --fgrep @Benchmark --reporter @fluid-tools/benchmark/dist/MochaReporter.js --timeout 60000",
|
|
227
215
|
"test:coverage": "c8 npm test",
|
|
@@ -17,7 +17,7 @@ import { type IDisposable, disposeSymbol } from "../../util/index.js";
|
|
|
17
17
|
import type { NodeIdentifierManager } from "../node-identifier/index.js";
|
|
18
18
|
|
|
19
19
|
import type { FlexTreeField } from "./flexTreeTypes.js";
|
|
20
|
-
import {
|
|
20
|
+
import type { LazyEntity } from "./lazyEntity.js";
|
|
21
21
|
import { makeField } from "./lazyField.js";
|
|
22
22
|
import type { ITreeCheckout } from "../../shared-tree/index.js";
|
|
23
23
|
|
|
@@ -120,7 +120,7 @@ export class Context implements FlexTreeHydratedContext, IDisposable {
|
|
|
120
120
|
private prepareForEdit(): void {
|
|
121
121
|
assert(this.disposed === false, 0x802 /* use after dispose */);
|
|
122
122
|
for (const target of this.withCursors) {
|
|
123
|
-
target
|
|
123
|
+
target.prepareForEdit();
|
|
124
124
|
}
|
|
125
125
|
assert(this.withCursors.size === 0, 0x773 /* prepareForEdit should remove all cursors */);
|
|
126
126
|
}
|
|
@@ -19,16 +19,6 @@ import {
|
|
|
19
19
|
flexTreeMarker,
|
|
20
20
|
} from "./flexTreeTypes.js";
|
|
21
21
|
|
|
22
|
-
export const prepareForEditSymbol = Symbol("prepareForEdit");
|
|
23
|
-
export const isFreedSymbol = Symbol("isFreed");
|
|
24
|
-
export const tryMoveCursorToAnchorSymbol = Symbol("tryMoveCursorToAnchor");
|
|
25
|
-
export const forgetAnchorSymbol = Symbol("forgetAnchor");
|
|
26
|
-
export const cursorSymbol = Symbol("cursor");
|
|
27
|
-
/**
|
|
28
|
-
* Symbol used to access the (generic) anchor of a {@link LazyEntity}.
|
|
29
|
-
*/
|
|
30
|
-
export const anchorSymbol = Symbol("anchor");
|
|
31
|
-
|
|
32
22
|
/**
|
|
33
23
|
* Assert `entity` is not deleted.
|
|
34
24
|
* @privateRemarks
|
|
@@ -37,7 +27,7 @@ export const anchorSymbol = Symbol("anchor");
|
|
|
37
27
|
*/
|
|
38
28
|
export function assertFlexTreeEntityNotFreed(entity: FlexTreeEntity): void {
|
|
39
29
|
assert(entity instanceof LazyEntity, 0x8c9 /* unexpected implementation */);
|
|
40
|
-
assert(!entity
|
|
30
|
+
assert(!entity.isFreed(), 0x8ca /* Use after free */);
|
|
41
31
|
}
|
|
42
32
|
|
|
43
33
|
/**
|
|
@@ -45,14 +35,14 @@ export function assertFlexTreeEntityNotFreed(entity: FlexTreeEntity): void {
|
|
|
45
35
|
*/
|
|
46
36
|
export abstract class LazyEntity<TAnchor = unknown> implements FlexTreeEntity, IDisposable {
|
|
47
37
|
readonly #lazyCursor: ITreeSubscriptionCursor;
|
|
48
|
-
public readonly
|
|
38
|
+
public readonly anchor: TAnchor;
|
|
49
39
|
|
|
50
40
|
protected constructor(
|
|
51
41
|
public readonly context: Context,
|
|
52
42
|
cursor: ITreeSubscriptionCursor,
|
|
53
43
|
anchor: TAnchor,
|
|
54
44
|
) {
|
|
55
|
-
this
|
|
45
|
+
this.anchor = anchor;
|
|
56
46
|
this.#lazyCursor = cursor.fork("LazyEntity Fork");
|
|
57
47
|
context.withCursors.add(this);
|
|
58
48
|
this.context.withAnchors.add(this);
|
|
@@ -64,30 +54,30 @@ export abstract class LazyEntity<TAnchor = unknown> implements FlexTreeEntity, I
|
|
|
64
54
|
public [disposeSymbol](): void {
|
|
65
55
|
this.#lazyCursor.free();
|
|
66
56
|
this.context.withCursors.delete(this);
|
|
67
|
-
this
|
|
57
|
+
this.forgetAnchor();
|
|
68
58
|
this.context.withAnchors.delete(this);
|
|
69
59
|
}
|
|
70
60
|
|
|
71
|
-
public
|
|
61
|
+
public prepareForEdit(): void {
|
|
72
62
|
this.#lazyCursor.clear();
|
|
73
63
|
this.context.withCursors.delete(this);
|
|
74
64
|
}
|
|
75
65
|
|
|
76
|
-
public
|
|
66
|
+
public isFreed(): boolean {
|
|
77
67
|
return this.#lazyCursor.state === ITreeSubscriptionCursorState.Freed;
|
|
78
68
|
}
|
|
79
69
|
|
|
80
|
-
public get
|
|
70
|
+
public get cursor(): ITreeSubscriptionCursor {
|
|
81
71
|
if (this.#lazyCursor.state !== ITreeSubscriptionCursorState.Current) {
|
|
82
72
|
assert(
|
|
83
73
|
this.#lazyCursor.state === ITreeSubscriptionCursorState.Cleared,
|
|
84
74
|
0x778 /* Unset cursor should be in cleared state */,
|
|
85
75
|
);
|
|
86
76
|
assert(
|
|
87
|
-
this
|
|
77
|
+
this.anchor !== undefined,
|
|
88
78
|
0x779 /* FlexTree should have an anchor if it does not have a cursor */,
|
|
89
79
|
);
|
|
90
|
-
const result = this
|
|
80
|
+
const result = this.tryMoveCursorToAnchor(this.#lazyCursor);
|
|
91
81
|
assert(
|
|
92
82
|
result === TreeNavigationResult.Ok,
|
|
93
83
|
0x77a /* It is invalid to access a FlexTree node which no longer exists */,
|
|
@@ -97,12 +87,12 @@ export abstract class LazyEntity<TAnchor = unknown> implements FlexTreeEntity, I
|
|
|
97
87
|
return this.#lazyCursor;
|
|
98
88
|
}
|
|
99
89
|
|
|
100
|
-
protected abstract
|
|
90
|
+
protected abstract tryMoveCursorToAnchor(
|
|
101
91
|
cursor: ITreeSubscriptionCursor,
|
|
102
92
|
): TreeNavigationResult;
|
|
103
93
|
|
|
104
94
|
/**
|
|
105
95
|
* Called when disposing of this target, iff it has an anchor.
|
|
106
96
|
*/
|
|
107
|
-
protected abstract
|
|
97
|
+
protected abstract forgetAnchor(): void;
|
|
108
98
|
}
|
|
@@ -46,14 +46,7 @@ import {
|
|
|
46
46
|
flexTreeMarker,
|
|
47
47
|
flexTreeSlot,
|
|
48
48
|
} from "./flexTreeTypes.js";
|
|
49
|
-
import {
|
|
50
|
-
LazyEntity,
|
|
51
|
-
anchorSymbol,
|
|
52
|
-
cursorSymbol,
|
|
53
|
-
forgetAnchorSymbol,
|
|
54
|
-
isFreedSymbol,
|
|
55
|
-
tryMoveCursorToAnchorSymbol,
|
|
56
|
-
} from "./lazyEntity.js";
|
|
49
|
+
import { LazyEntity } from "./lazyEntity.js";
|
|
57
50
|
import { type LazyTreeNode, makeTree } from "./lazyNode.js";
|
|
58
51
|
import { indexForAt, treeStatusFromAnchorCache } from "./utilities.js";
|
|
59
52
|
import { cursorForMapTreeField } from "../mapTreeCursor.js";
|
|
@@ -167,36 +160,36 @@ export abstract class LazyField extends LazyEntity<FieldAnchor> implements FlexT
|
|
|
167
160
|
}
|
|
168
161
|
|
|
169
162
|
public get parent(): FlexTreeNode | undefined {
|
|
170
|
-
if (this
|
|
163
|
+
if (this.anchor.parent === undefined) {
|
|
171
164
|
return undefined;
|
|
172
165
|
}
|
|
173
166
|
|
|
174
|
-
const cursor = this
|
|
167
|
+
const cursor = this.cursor;
|
|
175
168
|
cursor.exitField();
|
|
176
169
|
const output = makeTree(this.context, cursor);
|
|
177
170
|
cursor.enterField(this.key);
|
|
178
171
|
return output;
|
|
179
172
|
}
|
|
180
173
|
|
|
181
|
-
protected override
|
|
174
|
+
protected override tryMoveCursorToAnchor(
|
|
182
175
|
cursor: ITreeSubscriptionCursor,
|
|
183
176
|
): TreeNavigationResult {
|
|
184
|
-
return this.context.checkout.forest.tryMoveCursorToField(this
|
|
177
|
+
return this.context.checkout.forest.tryMoveCursorToField(this.anchor, cursor);
|
|
185
178
|
}
|
|
186
179
|
|
|
187
|
-
protected override
|
|
180
|
+
protected override forgetAnchor(): void {
|
|
188
181
|
this.offAfterDestroy?.();
|
|
189
|
-
if (this
|
|
190
|
-
this.context.checkout.forest.anchors.forget(this
|
|
182
|
+
if (this.anchor.parent === undefined) return;
|
|
183
|
+
this.context.checkout.forest.anchors.forget(this.anchor.parent);
|
|
191
184
|
}
|
|
192
185
|
|
|
193
186
|
public get length(): number {
|
|
194
|
-
return this
|
|
187
|
+
return this.cursor.getFieldLength();
|
|
195
188
|
}
|
|
196
189
|
|
|
197
190
|
public atIndex(index: number): FlexTreeUnknownUnboxed {
|
|
198
|
-
return inCursorNode(this
|
|
199
|
-
unboxedFlexNode(this.context, cursor, this
|
|
191
|
+
return inCursorNode(this.cursor, index, (cursor) =>
|
|
192
|
+
unboxedFlexNode(this.context, cursor, this.anchor),
|
|
200
193
|
);
|
|
201
194
|
}
|
|
202
195
|
|
|
@@ -207,9 +200,7 @@ export abstract class LazyField extends LazyEntity<FieldAnchor> implements FlexT
|
|
|
207
200
|
return undefined;
|
|
208
201
|
}
|
|
209
202
|
|
|
210
|
-
return inCursorNode(this
|
|
211
|
-
makeTree(this.context, cursor),
|
|
212
|
-
);
|
|
203
|
+
return inCursorNode(this.cursor, finalIndex, (cursor) => makeTree(this.context, cursor));
|
|
213
204
|
}
|
|
214
205
|
|
|
215
206
|
public map<U>(callbackfn: (value: FlexTreeUnknownUnboxed, index: number) => U): U[] {
|
|
@@ -217,12 +208,12 @@ export abstract class LazyField extends LazyEntity<FieldAnchor> implements FlexT
|
|
|
217
208
|
}
|
|
218
209
|
|
|
219
210
|
public boxedIterator(): IterableIterator<FlexTreeNode> {
|
|
220
|
-
return iterateCursorField(this
|
|
211
|
+
return iterateCursorField(this.cursor, (cursor) => makeTree(this.context, cursor));
|
|
221
212
|
}
|
|
222
213
|
|
|
223
214
|
public [Symbol.iterator](): IterableIterator<FlexTreeUnknownUnboxed> {
|
|
224
|
-
return iterateCursorField(this
|
|
225
|
-
unboxedFlexNode(this.context, cursor, this
|
|
215
|
+
return iterateCursorField(this.cursor, (cursor) =>
|
|
216
|
+
unboxedFlexNode(this.context, cursor, this.anchor),
|
|
226
217
|
);
|
|
227
218
|
}
|
|
228
219
|
|
|
@@ -235,10 +226,10 @@ export abstract class LazyField extends LazyEntity<FieldAnchor> implements FlexT
|
|
|
235
226
|
* This path is not valid to hold onto across edits: this must be recalled for each edit.
|
|
236
227
|
*/
|
|
237
228
|
public getFieldPathForEditing(): NormalizedFieldUpPath {
|
|
238
|
-
if (!this
|
|
229
|
+
if (!this.isFreed()) {
|
|
239
230
|
if (
|
|
240
231
|
// Only allow editing if we are the root document field...
|
|
241
|
-
(this.parent === undefined && this
|
|
232
|
+
(this.parent === undefined && this.anchor.fieldKey === rootFieldKey) ||
|
|
242
233
|
// ...or are under a node in the document
|
|
243
234
|
(this.parent !== undefined &&
|
|
244
235
|
treeStatusFromAnchorCache(this.parent.anchorNode) === TreeStatus.InDocument)
|
|
@@ -32,17 +32,11 @@ import {
|
|
|
32
32
|
flexTreeMarker,
|
|
33
33
|
flexTreeSlot,
|
|
34
34
|
} from "./flexTreeTypes.js";
|
|
35
|
-
import {
|
|
36
|
-
LazyEntity,
|
|
37
|
-
anchorSymbol,
|
|
38
|
-
cursorSymbol,
|
|
39
|
-
forgetAnchorSymbol,
|
|
40
|
-
tryMoveCursorToAnchorSymbol,
|
|
41
|
-
} from "./lazyEntity.js";
|
|
35
|
+
import { LazyEntity } from "./lazyEntity.js";
|
|
42
36
|
import { makeField } from "./lazyField.js";
|
|
43
37
|
|
|
44
38
|
/**
|
|
45
|
-
*
|
|
39
|
+
* This does not take ownership of this cursor: Node will fork it as needed.
|
|
46
40
|
*/
|
|
47
41
|
export function makeTree(context: Context, cursor: ITreeSubscriptionCursor): LazyTreeNode {
|
|
48
42
|
const anchor = cursor.buildAnchor();
|
|
@@ -95,31 +89,31 @@ export class LazyTreeNode extends LazyEntity<Anchor> implements FlexTreeNode {
|
|
|
95
89
|
}
|
|
96
90
|
|
|
97
91
|
public borrowCursor(): ITreeCursorSynchronous {
|
|
98
|
-
return this
|
|
92
|
+
return this.cursor as ITreeCursorSynchronous;
|
|
99
93
|
}
|
|
100
94
|
|
|
101
|
-
protected override
|
|
95
|
+
protected override tryMoveCursorToAnchor(
|
|
102
96
|
cursor: ITreeSubscriptionCursor,
|
|
103
97
|
): TreeNavigationResult {
|
|
104
|
-
return this.context.checkout.forest.tryMoveCursorToNode(this
|
|
98
|
+
return this.context.checkout.forest.tryMoveCursorToNode(this.anchor, cursor);
|
|
105
99
|
}
|
|
106
100
|
|
|
107
|
-
protected override
|
|
101
|
+
protected override forgetAnchor(): void {
|
|
108
102
|
// This type unconditionally has an anchor, so `forgetAnchor` is always called and cleanup can be done here:
|
|
109
103
|
// After this point this node will not be usable,
|
|
110
104
|
// so remove it from the anchor incase a different context (or the same context later) uses this AnchorSet.
|
|
111
105
|
this.anchorNode.slots.delete(flexTreeSlot);
|
|
112
106
|
this.#removeDeleteCallback();
|
|
113
|
-
this.context.checkout.forest.anchors.forget(this
|
|
107
|
+
this.context.checkout.forest.anchors.forget(this.anchor);
|
|
114
108
|
}
|
|
115
109
|
|
|
116
110
|
public get value(): Value {
|
|
117
|
-
return this
|
|
111
|
+
return this.cursor.value;
|
|
118
112
|
}
|
|
119
113
|
|
|
120
114
|
public tryGetField(fieldKey: FieldKey): FlexTreeField | undefined {
|
|
121
115
|
const schema = this.storedSchema.getFieldSchema(fieldKey);
|
|
122
|
-
return inCursorField(this
|
|
116
|
+
return inCursorField(this.cursor, fieldKey, (cursor) => {
|
|
123
117
|
if (cursor.getFieldLength() === 0) {
|
|
124
118
|
return undefined;
|
|
125
119
|
}
|
|
@@ -129,13 +123,13 @@ export class LazyTreeNode extends LazyEntity<Anchor> implements FlexTreeNode {
|
|
|
129
123
|
|
|
130
124
|
public getBoxed(key: FieldKey): FlexTreeField {
|
|
131
125
|
const fieldSchema = this.storedSchema.getFieldSchema(key);
|
|
132
|
-
return inCursorField(this
|
|
126
|
+
return inCursorField(this.cursor, key, (cursor) => {
|
|
133
127
|
return makeField(this.context, fieldSchema.kind, cursor);
|
|
134
128
|
});
|
|
135
129
|
}
|
|
136
130
|
|
|
137
131
|
public boxedIterator(): IterableIterator<FlexTreeField> {
|
|
138
|
-
return mapCursorFields(this
|
|
132
|
+
return mapCursorFields(this.cursor, (cursor) =>
|
|
139
133
|
makeField(
|
|
140
134
|
this.context,
|
|
141
135
|
this.storedSchema.getFieldSchema(cursor.getFieldKey()).kind,
|
|
@@ -145,7 +139,7 @@ export class LazyTreeNode extends LazyEntity<Anchor> implements FlexTreeNode {
|
|
|
145
139
|
}
|
|
146
140
|
|
|
147
141
|
public get parentField(): { readonly parent: FlexTreeField; readonly index: number } {
|
|
148
|
-
const cursor = this
|
|
142
|
+
const cursor = this.cursor;
|
|
149
143
|
const index = this.anchorNode.parentIndex;
|
|
150
144
|
assert(cursor.fieldIndex === index, 0x786 /* mismatched indexes */);
|
|
151
145
|
const key = this.anchorNode.parentField;
|
|
@@ -193,6 +187,6 @@ export class LazyTreeNode extends LazyEntity<Anchor> implements FlexTreeNode {
|
|
|
193
187
|
}
|
|
194
188
|
|
|
195
189
|
public keys(): IterableIterator<FieldKey> {
|
|
196
|
-
return mapCursorFields(this
|
|
190
|
+
return mapCursorFields(this.cursor, (cursor) => cursor.getFieldKey()).values();
|
|
197
191
|
}
|
|
198
192
|
}
|
package/src/index.ts
CHANGED
|
@@ -169,9 +169,12 @@ export {
|
|
|
169
169
|
// Beta APIs
|
|
170
170
|
TreeBeta,
|
|
171
171
|
type TreeChangeEventsBeta,
|
|
172
|
+
// Other
|
|
172
173
|
type VerboseTreeNode,
|
|
173
|
-
type
|
|
174
|
-
type
|
|
174
|
+
type TreeEncodingOptions,
|
|
175
|
+
type TreeSchemaEncodingOptions,
|
|
176
|
+
type TreeSchema,
|
|
177
|
+
TreeViewConfigurationAlpha,
|
|
175
178
|
type VerboseTree,
|
|
176
179
|
extractPersistedSchema,
|
|
177
180
|
comparePersistedSchema,
|
|
@@ -291,3 +294,4 @@ export type { MapNodeInsertableData } from "./simple-tree/index.js";
|
|
|
291
294
|
|
|
292
295
|
export { JsonAsTree } from "./jsonDomainSchema.js";
|
|
293
296
|
export { FluidSerializableAsTree } from "./serializableDomainSchema.js";
|
|
297
|
+
export { TableSchema } from "./tableSchema.js";
|
package/src/packageVersion.ts
CHANGED
|
@@ -250,7 +250,7 @@ export class SharedTree extends SharedObject implements ISharedTree {
|
|
|
250
250
|
local: boolean,
|
|
251
251
|
localOpMetadata: unknown,
|
|
252
252
|
): void {
|
|
253
|
-
|
|
253
|
+
fail(0xb75 /* processCore should not be called on SharedTree */);
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
protected override processMessagesCore(messagesCollection: IRuntimeMessageCollection): void {
|
|
@@ -569,7 +569,7 @@ class SharedTreeKernel extends SharedTreeCore<SharedTreeEditBuilder, SharedTreeC
|
|
|
569
569
|
|
|
570
570
|
export function exportSimpleSchema(storedSchema: TreeStoredSchema): SimpleTreeSchema {
|
|
571
571
|
return {
|
|
572
|
-
|
|
572
|
+
root: exportSimpleFieldSchemaStored(storedSchema.rootFieldSchema),
|
|
573
573
|
definitions: new Map(
|
|
574
574
|
[...storedSchema.nodeSchema].map(([key, schema]) => {
|
|
575
575
|
return [key, exportSimpleNodeSchemaStored(schema)];
|