@fluidframework/tree 2.50.0-345060 → 2.50.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 +100 -0
- 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-core/defaultResubmitMachine.d.ts +8 -12
- package/dist/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/dist/shared-tree-core/defaultResubmitMachine.js +54 -46
- package/dist/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/dist/shared-tree-core/resubmitMachine.d.ts +6 -0
- package/dist/shared-tree-core/resubmitMachine.d.ts.map +1 -1
- package/dist/shared-tree-core/resubmitMachine.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +1 -0
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +16 -3
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/configuration.js +4 -4
- package/dist/simple-tree/api/configuration.js.map +1 -1
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.js +1 -1
- package/dist/simple-tree/unhydratedFlexTreeFromInsertable.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-core/defaultResubmitMachine.d.ts +8 -12
- package/lib/shared-tree-core/defaultResubmitMachine.d.ts.map +1 -1
- package/lib/shared-tree-core/defaultResubmitMachine.js +55 -47
- package/lib/shared-tree-core/defaultResubmitMachine.js.map +1 -1
- package/lib/shared-tree-core/resubmitMachine.d.ts +6 -0
- package/lib/shared-tree-core/resubmitMachine.d.ts.map +1 -1
- package/lib/shared-tree-core/resubmitMachine.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +1 -0
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +16 -3
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/configuration.js +4 -4
- package/lib/simple-tree/api/configuration.js.map +1 -1
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js +1 -1
- package/lib/simple-tree/unhydratedFlexTreeFromInsertable.js.map +1 -1
- package/package.json +20 -20
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree-core/defaultResubmitMachine.ts +99 -52
- package/src/shared-tree-core/resubmitMachine.ts +7 -0
- package/src/shared-tree-core/sharedTreeCore.ts +18 -6
- package/src/simple-tree/api/configuration.ts +4 -4
- package/src/simple-tree/unhydratedFlexTreeFromInsertable.ts +1 -1
|
@@ -108,7 +108,7 @@ function unhydratedFlexTreeFromInsertableNode(data, allowedTypes) {
|
|
|
108
108
|
result = objectToFlexContent(data, schema);
|
|
109
109
|
break;
|
|
110
110
|
case NodeKind.Record:
|
|
111
|
-
assert(isRecordNodeSchema(schema),
|
|
111
|
+
assert(isRecordNodeSchema(schema), 0xbdd /* Expected a Record schema. */);
|
|
112
112
|
result = recordToFlexContent(data, schema);
|
|
113
113
|
break;
|
|
114
114
|
default:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unhydratedFlexTreeFromInsertable.js","sourceRoot":"","sources":["../../src/simple-tree/unhydratedFlexTreeFromInsertable.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 type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert, fail, unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { isFluidHandle } from \"@fluidframework/runtime-utils/internal\";\n\nimport {\n\tEmptyKey,\n\ttype FieldKey,\n\ttype NodeData,\n\ttype TreeValue,\n\ttype ValueSchema,\n} from \"../core/index.js\";\nimport { FieldKinds, isTreeValue, valueSchemaAllows } from \"../feature-libraries/index.js\";\nimport { brand, isReadonlyArray, hasSingle } from \"../util/index.js\";\n\nimport { nullSchema } from \"./leafNodeSchema.js\";\nimport {\n\ttype ImplicitAllowedTypes,\n\tnormalizeAllowedTypes,\n\tisConstant,\n\ttype ImplicitFieldSchema,\n\tnormalizeFieldSchema,\n\tFieldKind,\n\ttype TreeLeafValue,\n\textractFieldProvider,\n\ttype ContextualFieldProvider,\n\tunannotateImplicitAllowedTypes,\n} from \"./schemaTypes.js\";\nimport {\n\tcreateField,\n\tgetKernel,\n\tisTreeNode,\n\tNodeKind,\n\ttype TreeNode,\n\ttype TreeNodeSchema,\n\ttype Unhydrated,\n\ttype UnhydratedFlexTreeField,\n\tUnhydratedFlexTreeNode,\n\tUnhydratedSequenceField,\n} from \"./core/index.js\";\nimport { getUnhydratedContext } from \"./createContext.js\";\nimport { convertFieldKind } from \"./toStoredSchema.js\";\n\n// Required to prevent the introduction of new circular dependencies\n// TODO: Having the schema provide their own policy functions for compatibility which\n// `unhydratedFlexTreeFromInsertable` invokes instead of manually handling each kind would remove this bad\n// dependency, and reduce coupling.\n/* eslint-disable import/no-internal-modules */\nimport { isArrayNodeSchema, type ArrayNodeSchema } from \"./node-kinds/array/arrayNodeTypes.js\";\nimport { isMapNodeSchema, type MapNodeSchema } from \"./node-kinds/map/mapNodeTypes.js\";\nimport {\n\tisObjectNodeSchema,\n\ttype ObjectNodeSchemaPrivate,\n} from \"./node-kinds/object/objectNodeTypes.js\";\nimport {\n\tisRecordNodeSchema,\n\ttype RecordNodeSchema,\n} from \"./node-kinds/record/recordNodeTypes.js\";\n/* eslint-enable import/no-internal-modules */\n\n/**\n * Module notes:\n *\n * The flow of the below code is in terms of the structure of the input data. We then verify that the associated\n * schema is appropriate for that kind of data. This is fine while we have a 1:1 mapping of kind of input data to\n * the kind of schema we expect for it (e.g. an input that is an array always need to be associated with a sequence in\n * the schema). If/when we begin accepting kinds of input data that are ambiguous (e.g. accepting an input that is an\n * array of key/value tuples to instantiate a map) we may need to rethink the structure here to be based more on the\n * schema than on the input data.\n */\n\n/**\n * Transforms an input {@link TypedNode} tree to an {@link UnhydratedFlexTreeNode}.\n * @param data - The input tree to be converted.\n * If the data is an unsupported value (e.g. NaN), a fallback value will be used when supported,\n * otherwise an error will be thrown.\n *\n * Fallbacks:\n *\n * * `NaN` =\\> `null`\n *\n * * `+/-∞` =\\> `null`\n *\n * * `-0` =\\> `+0`\n *\n * For fields with a default value, the field may be omitted.\n * If `context` is not provided, defaults which require a context will be left empty which can be out of schema.\n *\n * @param allowedTypes - The set of types allowed by the parent context. Used to validate the input tree.\n * @remarks\n * The resulting tree will be populated with any defaults from {@link FieldProvider}s in the schema.\n *\n * Often throws UsageErrors for invalid data, but may miss some cases.\n *\n * Output should comply with the provided view schema, but this is not explicitly validated:\n * validation against stored schema (to guard against document corruption) is done elsewhere.\n */\nexport function unhydratedFlexTreeFromInsertable<TIn extends InsertableContent | undefined>(\n\tdata: TIn,\n\tallowedTypes: ImplicitFieldSchema,\n): TIn extends undefined ? undefined : UnhydratedFlexTreeNode {\n\tconst normalizedFieldSchema = normalizeFieldSchema(allowedTypes);\n\n\tif (data === undefined) {\n\t\t// TODO: this code-path should support defaults\n\t\tif (normalizedFieldSchema.kind !== FieldKind.Optional) {\n\t\t\tthrow new UsageError(\"Got undefined for non-optional field.\");\n\t\t}\n\t\treturn undefined as TIn extends undefined ? undefined : UnhydratedFlexTreeNode;\n\t}\n\n\tconst flexTree: UnhydratedFlexTreeNode = unhydratedFlexTreeFromInsertableNode(\n\t\tdata,\n\t\tnormalizedFieldSchema.allowedTypeSet,\n\t);\n\n\treturn flexTree as TIn extends undefined ? undefined : UnhydratedFlexTreeNode;\n}\n\n/**\n * Copy content from `data` into a UnhydratedFlexTreeNode.\n */\nfunction unhydratedFlexTreeFromInsertableNode(\n\tdata: InsertableContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): UnhydratedFlexTreeNode {\n\tif (isTreeNode(data)) {\n\t\tconst kernel = getKernel(data);\n\t\tconst inner = kernel.getInnerNodeIfUnhydrated();\n\t\tif (inner === undefined) {\n\t\t\t// The node is already hydrated, meaning that it already got inserted into the tree previously\n\t\t\tthrow new UsageError(\"A node may not be inserted into the tree more than once\");\n\t\t} else {\n\t\t\tif (!allowedTypes.has(kernel.schema)) {\n\t\t\t\tthrow new UsageError(\"Invalid schema for this context.\");\n\t\t\t}\n\t\t\treturn inner;\n\t\t}\n\t}\n\n\tconst schema = getType(data, allowedTypes);\n\n\tlet result: FlexContent;\n\tswitch (schema.kind) {\n\t\tcase NodeKind.Leaf:\n\t\t\tresult = leafToFlexContent(data, schema, allowedTypes);\n\t\t\tbreak;\n\t\tcase NodeKind.Array:\n\t\t\tassert(isArrayNodeSchema(schema), 0x922 /* Expected an array schema. */);\n\t\t\tresult = arrayToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Map:\n\t\t\tassert(isMapNodeSchema(schema), 0x923 /* Expected a Map schema. */);\n\t\t\tresult = mapToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Object:\n\t\t\tassert(isObjectNodeSchema(schema), 0x924 /* Expected an Object schema. */);\n\t\t\tresult = objectToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Record:\n\t\t\tassert(isRecordNodeSchema(schema), \"Expected a Record schema.\");\n\t\t\tresult = recordToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tunreachableCase(schema.kind);\n\t}\n\n\treturn new UnhydratedFlexTreeNode(...result, getUnhydratedContext(schema));\n}\n\ntype FlexContent = [NodeData, Map<FieldKey, UnhydratedFlexTreeField>];\n\n/**\n * Transforms data under a Leaf schema.\n * @param data - The tree data to be transformed. Must be a {@link TreeValue}.\n * @param schema - The schema associated with the value.\n * @param allowedTypes - The allowed types specified by the parent.\n * Used to determine which fallback values may be appropriate.\n */\nfunction leafToFlexContent(\n\tdata: FactoryContent,\n\tschema: TreeNodeSchema,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): FlexContent {\n\tassert(schema.kind === NodeKind.Leaf, 0x921 /* Expected a leaf schema. */);\n\tif (!isTreeValue(data)) {\n\t\t// This rule exists to protect against useless `toString` output like `[object Object]`.\n\t\t// In this case, that's actually reasonable behavior, since object input is not compatible with Leaf schemas.\n\t\t// eslint-disable-next-line @typescript-eslint/no-base-to-string\n\t\tthrow new UsageError(`Input data is incompatible with leaf schema: ${data}`);\n\t}\n\n\tconst mappedValue = mapValueWithFallbacks(data, allowedTypes);\n\tconst mappedSchema = getType(mappedValue, allowedTypes);\n\n\tassert(\n\t\tallowsValue(mappedSchema, mappedValue),\n\t\t0x84a /* Unsupported schema for provided primitive. */,\n\t);\n\n\treturn [\n\t\t{\n\t\t\tvalue: mappedValue,\n\t\t\ttype: brand(mappedSchema.identifier),\n\t\t},\n\t\tnew Map<FieldKey, UnhydratedFlexTreeField>(),\n\t];\n}\n\n/**\n * Checks an incoming {@link TreeLeafValue} to ensure it is compatible with its requirements.\n * For unsupported values with a schema-compatible replacement, return the replacement value.\n * For unsupported values without a schema-compatible replacement, throw.\n * For supported values, return the input.\n */\nfunction mapValueWithFallbacks(\n\tvalue: TreeLeafValue,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): TreeValue {\n\tswitch (typeof value) {\n\t\tcase \"number\": {\n\t\t\tif (Object.is(value, -0)) {\n\t\t\t\t// Our serialized data format does not support -0.\n\t\t\t\t// Map such input to +0.\n\t\t\t\treturn 0;\n\t\t\t} else if (!Number.isFinite(value)) {\n\t\t\t\t// Our serialized data format does not support NaN nor +/-∞.\n\t\t\t\t// If the schema supports `null`, fall back to that. Otherwise, throw.\n\t\t\t\t// This is intended to match JSON's behavior for such values.\n\t\t\t\tif (allowedTypes.has(nullSchema)) {\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UsageError(`Received unsupported numeric value: ${value}.`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\tcase \"string\":\n\t\t// TODO:\n\t\t// This should detect invalid strings. Something like @stdlib/regexp-utf16-unpaired-surrogate could be used to do this.\n\t\t// See SchemaFactory.string for details.\n\t\tcase \"boolean\":\n\t\t\treturn value;\n\t\tcase \"object\": {\n\t\t\tif (value === null || isFluidHandle(value)) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\tdefault:\n\t\t\tthrow new UsageError(`Received unsupported leaf value: ${value}.`);\n\t}\n}\n\n/**\n * Transforms data under an Array schema.\n * @param data - The tree data to be transformed.\n * @param allowedTypes - The set of types allowed by the parent context. Used to validate the input tree.\n */\nfunction arrayChildToFlexTree(\n\tchild: InsertableContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): UnhydratedFlexTreeNode {\n\t// We do not support undefined sequence entries.\n\t// If we encounter an undefined entry, use null instead if supported by the schema, otherwise throw.\n\tlet childWithFallback = child;\n\tif (child === undefined) {\n\t\tif (allowedTypes.has(nullSchema)) {\n\t\t\tchildWithFallback = null;\n\t\t} else {\n\t\t\tthrow new TypeError(`Received unsupported array entry value: ${child}.`);\n\t\t}\n\t}\n\treturn unhydratedFlexTreeFromInsertableNode(childWithFallback, allowedTypes);\n}\n\n/**\n * Transforms data under an Array schema.\n * @param data - The tree data to be transformed. Must be an iterable.\n * @param schema - The schema associated with the value.\n */\nfunction arrayToFlexContent(data: FactoryContent, schema: ArrayNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null && Symbol.iterator in data)) {\n\t\tthrow new UsageError(`Input data is incompatible with Array schema: ${data}`);\n\t}\n\n\tconst allowedChildTypes = normalizeAllowedTypes(schema.info as ImplicitAllowedTypes);\n\n\tconst mappedData = Array.from(data, (child) =>\n\t\tarrayChildToFlexTree(child, allowedChildTypes),\n\t);\n\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\t// Array nodes have a single `EmptyKey` field:\n\tconst fieldsEntries =\n\t\tmappedData.length === 0\n\t\t\t? []\n\t\t\t: ([\n\t\t\t\t\t[\n\t\t\t\t\t\tEmptyKey,\n\t\t\t\t\t\tnew UnhydratedSequenceField(\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tFieldKinds.sequence.identifier,\n\t\t\t\t\t\t\tEmptyKey,\n\t\t\t\t\t\t\tmappedData,\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t] as const);\n\n\treturn [\n\t\t{\n\t\t\ttype: brand(schema.identifier),\n\t\t},\n\t\tnew Map(fieldsEntries),\n\t];\n}\n\n/**\n * Transforms data under a Map schema.\n * @param data - The tree data to be transformed. Must be an iterable.\n * @param schema - The schema associated with the value.\n */\nfunction mapToFlexContent(data: FactoryContent, schema: MapNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null)) {\n\t\tthrow new UsageError(`Input data is incompatible with Map schema: ${data}`);\n\t}\n\n\tconst fieldsIterator = (\n\t\tSymbol.iterator in data\n\t\t\t? // Support iterables of key value pairs (including Map objects)\n\t\t\t\tdata\n\t\t\t: // Support record objects for JSON style Map data\n\t\t\t\tObject.entries(data)\n\t) as Iterable<readonly [string, InsertableContent]>;\n\n\treturn recordLikeDataToFlexContent(fieldsIterator, schema);\n}\n\n/**\n * Transforms data under an Object schema.\n * @param data - The tree data to be transformed. Must be a Record-like object.\n * @param schema - The schema associated with the value.\n */\nfunction objectToFlexContent(\n\tdata: FactoryContent,\n\tschema: ObjectNodeSchemaPrivate,\n): FlexContent {\n\tif (\n\t\ttypeof data !== \"object\" ||\n\t\tdata === null ||\n\t\tSymbol.iterator in data ||\n\t\tisFluidHandle(data)\n\t) {\n\t\tthrow new UsageError(`Input data is incompatible with Object schema: ${data}`);\n\t}\n\n\tconst fields = new Map<FieldKey, UnhydratedFlexTreeField>();\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\tfor (const [key, fieldInfo] of schema.flexKeyMap) {\n\t\tconst value = getFieldProperty(data, key);\n\n\t\tlet children: UnhydratedFlexTreeNode[] | ContextualFieldProvider;\n\t\tif (value === undefined) {\n\t\t\tconst defaultProvider =\n\t\t\t\tfieldInfo.schema.props?.defaultProvider ??\n\t\t\t\tfail(0xbb1 /* missing field has no default provider */);\n\t\t\tconst fieldProvider = extractFieldProvider(defaultProvider);\n\t\t\tchildren = isConstant(fieldProvider) ? fieldProvider() : fieldProvider;\n\t\t} else {\n\t\t\tchildren = [\n\t\t\t\tunhydratedFlexTreeFromInsertableNode(value, fieldInfo.schema.allowedTypeSet),\n\t\t\t];\n\t\t}\n\n\t\tconst kind =\n\t\t\tconvertFieldKind.get(fieldInfo.schema.kind) ?? fail(0xbb2 /* Invalid field kind */);\n\t\tfields.set(\n\t\t\tfieldInfo.storedKey,\n\t\t\tcreateField(context, kind.identifier, fieldInfo.storedKey, children),\n\t\t);\n\t}\n\n\treturn [{ type: brand(schema.identifier) }, fields];\n}\n\n/**\n * Transforms data under an Object schema.\n * @param data - The tree data to be transformed. Must be a Record-like object.\n * @param schema - The schema associated with the value.\n */\nfunction recordToFlexContent(data: FactoryContent, schema: RecordNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null)) {\n\t\tthrow new UsageError(`Input data is incompatible with Record schema: ${data}`);\n\t}\n\n\tconst fieldsIterator: Iterable<readonly [string, InsertableContent]> = Object.entries(data);\n\treturn recordLikeDataToFlexContent(fieldsIterator, schema);\n}\n\n/**\n * Converts record-like data to a FlexContent representation for map/record schema.\n */\nfunction recordLikeDataToFlexContent(\n\tfieldsIterator: Iterable<readonly [string, InsertableContent]>,\n\tschema: MapNodeSchema | RecordNodeSchema,\n): FlexContent {\n\tconst allowedChildTypes = normalizeAllowedTypes(unannotateImplicitAllowedTypes(schema.info));\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\tconst transformedFields = new Map<FieldKey, UnhydratedFlexTreeField>();\n\tfor (const item of fieldsIterator) {\n\t\tconst [key, value] = item;\n\t\tassert(!transformedFields.has(brand(key)), 0x84c /* Keys should not be duplicated */);\n\n\t\t// Omit undefined values - an entry with an undefined value is equivalent to one that has been removed or omitted\n\t\tif (value !== undefined) {\n\t\t\tconst child = unhydratedFlexTreeFromInsertableNode(value, allowedChildTypes);\n\t\t\tconst field = createField(context, FieldKinds.optional.identifier, brand(key), [child]);\n\t\t\ttransformedFields.set(brand(key), field);\n\t\t}\n\t}\n\n\treturn [\n\t\t{\n\t\t\ttype: brand(schema.identifier),\n\t\t},\n\t\ttransformedFields,\n\t];\n}\n\n/**\n * Check {@link FactoryContentObject} for a property which could be store a field.\n *\n * @returns If the property exists, return its value. Otherwise, returns undefined.\n * @remarks\n * The currently policy is to only consider own properties.\n * See {@link InsertableObjectFromSchemaRecord} for where this policy is documented in the public API.\n *\n * Explicit undefined values are treated the same as missing properties to allow explicit use of undefined with defaulted identifiers.\n *\n * @privateRemarks\n * If we ever want to have an optional field which defaults to something other than undefined, this will need changes.\n * It would need to adjusting the handling of explicit undefined in contexts where undefined is allowed, and a default provider also exists.\n */\nfunction getFieldProperty(\n\tdata: FactoryContentObject,\n\tkey: string | symbol,\n): InsertableContent | undefined {\n\t// This policy only allows own properties.\n\tif (Object.hasOwnProperty.call(data, key)) {\n\t\treturn (data as Record<string, InsertableContent>)[key as string];\n\t}\n\treturn undefined;\n}\n\nfunction getType(\n\tdata: FactoryContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): TreeNodeSchema {\n\tconst possibleTypes = getPossibleTypes(allowedTypes, data);\n\tif (possibleTypes.length === 0) {\n\t\tthrow new UsageError(\n\t\t\t`The provided data is incompatible with all of the types allowed by the schema. The set of allowed types is: ${JSON.stringify(\n\t\t\t\t[...allowedTypes].map((schema) => schema.identifier),\n\t\t\t)}.`,\n\t\t);\n\t}\n\tif (!hasSingle(possibleTypes)) {\n\t\tthrow new UsageError(\n\t\t\t`The provided data is compatible with more than one type allowed by the schema.\nThe set of possible types is ${JSON.stringify([\n\t\t\t\t...possibleTypes.map((schema) => schema.identifier),\n\t\t\t])}.\nExplicitly construct an unhydrated node of the desired type to disambiguate.\nFor class-based schema, this can be done by replacing an expression like \"{foo: 1}\" with \"new MySchema({foo: 1})\".`,\n\t\t);\n\t}\n\treturn possibleTypes[0];\n}\n\n/**\n * Returns all types for which the data is schema-compatible.\n */\nexport function getPossibleTypes(\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n\tdata: FactoryContent,\n): TreeNodeSchema[] {\n\tlet best = CompatibilityLevel.None;\n\tconst possibleTypes: TreeNodeSchema[] = [];\n\tfor (const schema of allowedTypes) {\n\t\tconst level = shallowCompatibilityTest(schema, data);\n\t\tif (level > best) {\n\t\t\tpossibleTypes.length = 0;\n\t\t\tbest = level;\n\t\t}\n\t\tif (best === level) {\n\t\t\tpossibleTypes.push(schema);\n\t\t}\n\t}\n\treturn best === CompatibilityLevel.None ? [] : possibleTypes;\n}\n\n/**\n * Indicates a compatibility level for inferring a schema to apply to insertable data.\n * @remarks\n * Only the highest compatibility options are used.\n * This approach allows adding new possible matching at a new lower compatibility level as a non breaking change,\n * since that way they can't make a case that was compatible before ambiguous now.\n */\nenum CompatibilityLevel {\n\t/**\n\t * Not compatible. Constructor typing indicates incompatibility.\n\t */\n\tNone = 0,\n\t/**\n\t * Additional compatibility cases added in Fluid Framework 2.2.\n\t */\n\tLow = 1,\n\t/**\n\t * Compatible in Fluid Framework 2.0.\n\t */\n\tNormal = 2,\n}\n\n/**\n * Checks if data might be schema-compatible.\n *\n * @returns false if `data` is incompatible with `type` based on a cheap/shallow check.\n *\n * Note that this may return true for cases where data is incompatible, but it must not return false in cases where the data is compatible.\n */\nfunction shallowCompatibilityTest(\n\tschema: TreeNodeSchema,\n\tdata: FactoryContent,\n): CompatibilityLevel {\n\tassert(data !== undefined, 0x889 /* undefined cannot be used as FactoryContent. */);\n\n\tif (isTreeValue(data)) {\n\t\treturn allowsValue(schema, data) ? CompatibilityLevel.Normal : CompatibilityLevel.None;\n\t}\n\tif (schema.kind === NodeKind.Leaf) {\n\t\treturn CompatibilityLevel.None;\n\t}\n\n\t// Typing (of schema based constructors and thus implicit node construction)\n\t// allows iterables for constructing maps and arrays.\n\t// Some users of this API may have unions of maps and arrays,\n\t// and rely on Arrays ending up as array nodes and maps as Map nodes,\n\t// despite both being iterable and thus compatible with both.\n\t// This uses a priority based system where an array would be parsed as an array when unioned with a map,\n\t// but if in a map only context, could still be used as a map.\n\n\tif (data instanceof Map) {\n\t\tswitch (schema.kind) {\n\t\t\tcase NodeKind.Map:\n\t\t\t\treturn CompatibilityLevel.Normal;\n\t\t\tcase NodeKind.Array:\n\t\t\t\t// Maps are iterable, so type checking does allow constructing an ArrayNode from a map if the array's type is an array that includes the key and value types of the map.\n\t\t\t\treturn CompatibilityLevel.Low;\n\t\t\tdefault:\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t}\n\t}\n\n\tif (isReadonlyArray(data)) {\n\t\tswitch (schema.kind) {\n\t\t\tcase NodeKind.Array:\n\t\t\t\treturn CompatibilityLevel.Normal;\n\t\t\tcase NodeKind.Map:\n\t\t\t\t// Arrays are iterable, so type checking does allow constructing an array from a MapNode from an if the array's type is key values pairs for the map.\n\t\t\t\treturn CompatibilityLevel.Low;\n\t\t\tdefault:\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t}\n\t}\n\n\tconst mapOrArray = schema.kind === NodeKind.Array || schema.kind === NodeKind.Map;\n\n\tif (Symbol.iterator in data) {\n\t\treturn mapOrArray ? CompatibilityLevel.Normal : CompatibilityLevel.None;\n\t}\n\n\t// At this point, it is assumed data is a record-like object since all the other cases have been eliminated.\n\n\tif (schema.kind === NodeKind.Record) {\n\t\treturn CompatibilityLevel.Normal;\n\t}\n\n\tif (schema.kind === NodeKind.Array) {\n\t\treturn CompatibilityLevel.None;\n\t}\n\n\tif (schema.kind === NodeKind.Map) {\n\t\t// When not unioned with an ObjectNode, allow objects to be used to create maps.\n\t\treturn CompatibilityLevel.Low;\n\t}\n\n\tassert(isObjectNodeSchema(schema), 0x9e6 /* unexpected schema kind */);\n\n\t// TODO: Improve type inference by making this logic more thorough. Handle at least:\n\t// * Types which are strict subsets of other types in the same polymorphic union\n\t// * Types which have the same keys but different types for those keys in the polymorphic union\n\t// * Types which have the same required fields but different optional fields and enough of those optional fields are populated to disambiguate\n\n\t// TODO#7441: Consider allowing data to be inserted which has keys that are extraneous/unknown to the schema (those keys are ignored)\n\n\t// If the schema has a required key which is not present in the input object, reject it.\n\tfor (const [fieldKey, fieldSchema] of schema.fields) {\n\t\tif (fieldSchema.requiresValue) {\n\t\t\tif (getFieldProperty(data, fieldKey) === undefined) {\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn CompatibilityLevel.Normal;\n}\n\nfunction allowsValue(schema: TreeNodeSchema, value: TreeValue): boolean {\n\tif (schema.kind === NodeKind.Leaf) {\n\t\treturn valueSchemaAllows(schema.info as ValueSchema, value);\n\t}\n\treturn false;\n}\n\n/**\n * Content which can be used to build a node.\n * @remarks\n * Can contain unhydrated nodes, but can not be an unhydrated node at the root.\n * @system @alpha\n */\nexport type FactoryContent =\n\t| IFluidHandle\n\t| string\n\t| number\n\t| boolean\n\t// eslint-disable-next-line @rushstack/no-new-null\n\t| null\n\t| Iterable<readonly [string, InsertableContent]>\n\t| readonly InsertableContent[]\n\t| FactoryContentObject;\n\n/**\n * Record-like object which can be used to build some kinds of nodes.\n * @remarks\n * Can contain unhydrated nodes, but can not be an unhydrated node at the root.\n *\n * Supports object and map nodes.\n * @system @alpha\n */\nexport type FactoryContentObject = {\n\treadonly [P in string]?: InsertableContent;\n};\n\n/**\n * Content which can be inserted into a tree.\n * @system @alpha\n */\nexport type InsertableContent = Unhydrated<TreeNode> | FactoryContent;\n"]}
|
|
1
|
+
{"version":3,"file":"unhydratedFlexTreeFromInsertable.js","sourceRoot":"","sources":["../../src/simple-tree/unhydratedFlexTreeFromInsertable.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 type { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { assert, fail, unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { isFluidHandle } from \"@fluidframework/runtime-utils/internal\";\n\nimport {\n\tEmptyKey,\n\ttype FieldKey,\n\ttype NodeData,\n\ttype TreeValue,\n\ttype ValueSchema,\n} from \"../core/index.js\";\nimport { FieldKinds, isTreeValue, valueSchemaAllows } from \"../feature-libraries/index.js\";\nimport { brand, isReadonlyArray, hasSingle } from \"../util/index.js\";\n\nimport { nullSchema } from \"./leafNodeSchema.js\";\nimport {\n\ttype ImplicitAllowedTypes,\n\tnormalizeAllowedTypes,\n\tisConstant,\n\ttype ImplicitFieldSchema,\n\tnormalizeFieldSchema,\n\tFieldKind,\n\ttype TreeLeafValue,\n\textractFieldProvider,\n\ttype ContextualFieldProvider,\n\tunannotateImplicitAllowedTypes,\n} from \"./schemaTypes.js\";\nimport {\n\tcreateField,\n\tgetKernel,\n\tisTreeNode,\n\tNodeKind,\n\ttype TreeNode,\n\ttype TreeNodeSchema,\n\ttype Unhydrated,\n\ttype UnhydratedFlexTreeField,\n\tUnhydratedFlexTreeNode,\n\tUnhydratedSequenceField,\n} from \"./core/index.js\";\nimport { getUnhydratedContext } from \"./createContext.js\";\nimport { convertFieldKind } from \"./toStoredSchema.js\";\n\n// Required to prevent the introduction of new circular dependencies\n// TODO: Having the schema provide their own policy functions for compatibility which\n// `unhydratedFlexTreeFromInsertable` invokes instead of manually handling each kind would remove this bad\n// dependency, and reduce coupling.\n/* eslint-disable import/no-internal-modules */\nimport { isArrayNodeSchema, type ArrayNodeSchema } from \"./node-kinds/array/arrayNodeTypes.js\";\nimport { isMapNodeSchema, type MapNodeSchema } from \"./node-kinds/map/mapNodeTypes.js\";\nimport {\n\tisObjectNodeSchema,\n\ttype ObjectNodeSchemaPrivate,\n} from \"./node-kinds/object/objectNodeTypes.js\";\nimport {\n\tisRecordNodeSchema,\n\ttype RecordNodeSchema,\n} from \"./node-kinds/record/recordNodeTypes.js\";\n/* eslint-enable import/no-internal-modules */\n\n/**\n * Module notes:\n *\n * The flow of the below code is in terms of the structure of the input data. We then verify that the associated\n * schema is appropriate for that kind of data. This is fine while we have a 1:1 mapping of kind of input data to\n * the kind of schema we expect for it (e.g. an input that is an array always need to be associated with a sequence in\n * the schema). If/when we begin accepting kinds of input data that are ambiguous (e.g. accepting an input that is an\n * array of key/value tuples to instantiate a map) we may need to rethink the structure here to be based more on the\n * schema than on the input data.\n */\n\n/**\n * Transforms an input {@link TypedNode} tree to an {@link UnhydratedFlexTreeNode}.\n * @param data - The input tree to be converted.\n * If the data is an unsupported value (e.g. NaN), a fallback value will be used when supported,\n * otherwise an error will be thrown.\n *\n * Fallbacks:\n *\n * * `NaN` =\\> `null`\n *\n * * `+/-∞` =\\> `null`\n *\n * * `-0` =\\> `+0`\n *\n * For fields with a default value, the field may be omitted.\n * If `context` is not provided, defaults which require a context will be left empty which can be out of schema.\n *\n * @param allowedTypes - The set of types allowed by the parent context. Used to validate the input tree.\n * @remarks\n * The resulting tree will be populated with any defaults from {@link FieldProvider}s in the schema.\n *\n * Often throws UsageErrors for invalid data, but may miss some cases.\n *\n * Output should comply with the provided view schema, but this is not explicitly validated:\n * validation against stored schema (to guard against document corruption) is done elsewhere.\n */\nexport function unhydratedFlexTreeFromInsertable<TIn extends InsertableContent | undefined>(\n\tdata: TIn,\n\tallowedTypes: ImplicitFieldSchema,\n): TIn extends undefined ? undefined : UnhydratedFlexTreeNode {\n\tconst normalizedFieldSchema = normalizeFieldSchema(allowedTypes);\n\n\tif (data === undefined) {\n\t\t// TODO: this code-path should support defaults\n\t\tif (normalizedFieldSchema.kind !== FieldKind.Optional) {\n\t\t\tthrow new UsageError(\"Got undefined for non-optional field.\");\n\t\t}\n\t\treturn undefined as TIn extends undefined ? undefined : UnhydratedFlexTreeNode;\n\t}\n\n\tconst flexTree: UnhydratedFlexTreeNode = unhydratedFlexTreeFromInsertableNode(\n\t\tdata,\n\t\tnormalizedFieldSchema.allowedTypeSet,\n\t);\n\n\treturn flexTree as TIn extends undefined ? undefined : UnhydratedFlexTreeNode;\n}\n\n/**\n * Copy content from `data` into a UnhydratedFlexTreeNode.\n */\nfunction unhydratedFlexTreeFromInsertableNode(\n\tdata: InsertableContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): UnhydratedFlexTreeNode {\n\tif (isTreeNode(data)) {\n\t\tconst kernel = getKernel(data);\n\t\tconst inner = kernel.getInnerNodeIfUnhydrated();\n\t\tif (inner === undefined) {\n\t\t\t// The node is already hydrated, meaning that it already got inserted into the tree previously\n\t\t\tthrow new UsageError(\"A node may not be inserted into the tree more than once\");\n\t\t} else {\n\t\t\tif (!allowedTypes.has(kernel.schema)) {\n\t\t\t\tthrow new UsageError(\"Invalid schema for this context.\");\n\t\t\t}\n\t\t\treturn inner;\n\t\t}\n\t}\n\n\tconst schema = getType(data, allowedTypes);\n\n\tlet result: FlexContent;\n\tswitch (schema.kind) {\n\t\tcase NodeKind.Leaf:\n\t\t\tresult = leafToFlexContent(data, schema, allowedTypes);\n\t\t\tbreak;\n\t\tcase NodeKind.Array:\n\t\t\tassert(isArrayNodeSchema(schema), 0x922 /* Expected an array schema. */);\n\t\t\tresult = arrayToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Map:\n\t\t\tassert(isMapNodeSchema(schema), 0x923 /* Expected a Map schema. */);\n\t\t\tresult = mapToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Object:\n\t\t\tassert(isObjectNodeSchema(schema), 0x924 /* Expected an Object schema. */);\n\t\t\tresult = objectToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tcase NodeKind.Record:\n\t\t\tassert(isRecordNodeSchema(schema), 0xbdd /* Expected a Record schema. */);\n\t\t\tresult = recordToFlexContent(data, schema);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tunreachableCase(schema.kind);\n\t}\n\n\treturn new UnhydratedFlexTreeNode(...result, getUnhydratedContext(schema));\n}\n\ntype FlexContent = [NodeData, Map<FieldKey, UnhydratedFlexTreeField>];\n\n/**\n * Transforms data under a Leaf schema.\n * @param data - The tree data to be transformed. Must be a {@link TreeValue}.\n * @param schema - The schema associated with the value.\n * @param allowedTypes - The allowed types specified by the parent.\n * Used to determine which fallback values may be appropriate.\n */\nfunction leafToFlexContent(\n\tdata: FactoryContent,\n\tschema: TreeNodeSchema,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): FlexContent {\n\tassert(schema.kind === NodeKind.Leaf, 0x921 /* Expected a leaf schema. */);\n\tif (!isTreeValue(data)) {\n\t\t// This rule exists to protect against useless `toString` output like `[object Object]`.\n\t\t// In this case, that's actually reasonable behavior, since object input is not compatible with Leaf schemas.\n\t\t// eslint-disable-next-line @typescript-eslint/no-base-to-string\n\t\tthrow new UsageError(`Input data is incompatible with leaf schema: ${data}`);\n\t}\n\n\tconst mappedValue = mapValueWithFallbacks(data, allowedTypes);\n\tconst mappedSchema = getType(mappedValue, allowedTypes);\n\n\tassert(\n\t\tallowsValue(mappedSchema, mappedValue),\n\t\t0x84a /* Unsupported schema for provided primitive. */,\n\t);\n\n\treturn [\n\t\t{\n\t\t\tvalue: mappedValue,\n\t\t\ttype: brand(mappedSchema.identifier),\n\t\t},\n\t\tnew Map<FieldKey, UnhydratedFlexTreeField>(),\n\t];\n}\n\n/**\n * Checks an incoming {@link TreeLeafValue} to ensure it is compatible with its requirements.\n * For unsupported values with a schema-compatible replacement, return the replacement value.\n * For unsupported values without a schema-compatible replacement, throw.\n * For supported values, return the input.\n */\nfunction mapValueWithFallbacks(\n\tvalue: TreeLeafValue,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): TreeValue {\n\tswitch (typeof value) {\n\t\tcase \"number\": {\n\t\t\tif (Object.is(value, -0)) {\n\t\t\t\t// Our serialized data format does not support -0.\n\t\t\t\t// Map such input to +0.\n\t\t\t\treturn 0;\n\t\t\t} else if (!Number.isFinite(value)) {\n\t\t\t\t// Our serialized data format does not support NaN nor +/-∞.\n\t\t\t\t// If the schema supports `null`, fall back to that. Otherwise, throw.\n\t\t\t\t// This is intended to match JSON's behavior for such values.\n\t\t\t\tif (allowedTypes.has(nullSchema)) {\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UsageError(`Received unsupported numeric value: ${value}.`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\tcase \"string\":\n\t\t// TODO:\n\t\t// This should detect invalid strings. Something like @stdlib/regexp-utf16-unpaired-surrogate could be used to do this.\n\t\t// See SchemaFactory.string for details.\n\t\tcase \"boolean\":\n\t\t\treturn value;\n\t\tcase \"object\": {\n\t\t\tif (value === null || isFluidHandle(value)) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\tdefault:\n\t\t\tthrow new UsageError(`Received unsupported leaf value: ${value}.`);\n\t}\n}\n\n/**\n * Transforms data under an Array schema.\n * @param data - The tree data to be transformed.\n * @param allowedTypes - The set of types allowed by the parent context. Used to validate the input tree.\n */\nfunction arrayChildToFlexTree(\n\tchild: InsertableContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): UnhydratedFlexTreeNode {\n\t// We do not support undefined sequence entries.\n\t// If we encounter an undefined entry, use null instead if supported by the schema, otherwise throw.\n\tlet childWithFallback = child;\n\tif (child === undefined) {\n\t\tif (allowedTypes.has(nullSchema)) {\n\t\t\tchildWithFallback = null;\n\t\t} else {\n\t\t\tthrow new TypeError(`Received unsupported array entry value: ${child}.`);\n\t\t}\n\t}\n\treturn unhydratedFlexTreeFromInsertableNode(childWithFallback, allowedTypes);\n}\n\n/**\n * Transforms data under an Array schema.\n * @param data - The tree data to be transformed. Must be an iterable.\n * @param schema - The schema associated with the value.\n */\nfunction arrayToFlexContent(data: FactoryContent, schema: ArrayNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null && Symbol.iterator in data)) {\n\t\tthrow new UsageError(`Input data is incompatible with Array schema: ${data}`);\n\t}\n\n\tconst allowedChildTypes = normalizeAllowedTypes(schema.info as ImplicitAllowedTypes);\n\n\tconst mappedData = Array.from(data, (child) =>\n\t\tarrayChildToFlexTree(child, allowedChildTypes),\n\t);\n\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\t// Array nodes have a single `EmptyKey` field:\n\tconst fieldsEntries =\n\t\tmappedData.length === 0\n\t\t\t? []\n\t\t\t: ([\n\t\t\t\t\t[\n\t\t\t\t\t\tEmptyKey,\n\t\t\t\t\t\tnew UnhydratedSequenceField(\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tFieldKinds.sequence.identifier,\n\t\t\t\t\t\t\tEmptyKey,\n\t\t\t\t\t\t\tmappedData,\n\t\t\t\t\t\t),\n\t\t\t\t\t],\n\t\t\t\t] as const);\n\n\treturn [\n\t\t{\n\t\t\ttype: brand(schema.identifier),\n\t\t},\n\t\tnew Map(fieldsEntries),\n\t];\n}\n\n/**\n * Transforms data under a Map schema.\n * @param data - The tree data to be transformed. Must be an iterable.\n * @param schema - The schema associated with the value.\n */\nfunction mapToFlexContent(data: FactoryContent, schema: MapNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null)) {\n\t\tthrow new UsageError(`Input data is incompatible with Map schema: ${data}`);\n\t}\n\n\tconst fieldsIterator = (\n\t\tSymbol.iterator in data\n\t\t\t? // Support iterables of key value pairs (including Map objects)\n\t\t\t\tdata\n\t\t\t: // Support record objects for JSON style Map data\n\t\t\t\tObject.entries(data)\n\t) as Iterable<readonly [string, InsertableContent]>;\n\n\treturn recordLikeDataToFlexContent(fieldsIterator, schema);\n}\n\n/**\n * Transforms data under an Object schema.\n * @param data - The tree data to be transformed. Must be a Record-like object.\n * @param schema - The schema associated with the value.\n */\nfunction objectToFlexContent(\n\tdata: FactoryContent,\n\tschema: ObjectNodeSchemaPrivate,\n): FlexContent {\n\tif (\n\t\ttypeof data !== \"object\" ||\n\t\tdata === null ||\n\t\tSymbol.iterator in data ||\n\t\tisFluidHandle(data)\n\t) {\n\t\tthrow new UsageError(`Input data is incompatible with Object schema: ${data}`);\n\t}\n\n\tconst fields = new Map<FieldKey, UnhydratedFlexTreeField>();\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\tfor (const [key, fieldInfo] of schema.flexKeyMap) {\n\t\tconst value = getFieldProperty(data, key);\n\n\t\tlet children: UnhydratedFlexTreeNode[] | ContextualFieldProvider;\n\t\tif (value === undefined) {\n\t\t\tconst defaultProvider =\n\t\t\t\tfieldInfo.schema.props?.defaultProvider ??\n\t\t\t\tfail(0xbb1 /* missing field has no default provider */);\n\t\t\tconst fieldProvider = extractFieldProvider(defaultProvider);\n\t\t\tchildren = isConstant(fieldProvider) ? fieldProvider() : fieldProvider;\n\t\t} else {\n\t\t\tchildren = [\n\t\t\t\tunhydratedFlexTreeFromInsertableNode(value, fieldInfo.schema.allowedTypeSet),\n\t\t\t];\n\t\t}\n\n\t\tconst kind =\n\t\t\tconvertFieldKind.get(fieldInfo.schema.kind) ?? fail(0xbb2 /* Invalid field kind */);\n\t\tfields.set(\n\t\t\tfieldInfo.storedKey,\n\t\t\tcreateField(context, kind.identifier, fieldInfo.storedKey, children),\n\t\t);\n\t}\n\n\treturn [{ type: brand(schema.identifier) }, fields];\n}\n\n/**\n * Transforms data under an Object schema.\n * @param data - The tree data to be transformed. Must be a Record-like object.\n * @param schema - The schema associated with the value.\n */\nfunction recordToFlexContent(data: FactoryContent, schema: RecordNodeSchema): FlexContent {\n\tif (!(typeof data === \"object\" && data !== null)) {\n\t\tthrow new UsageError(`Input data is incompatible with Record schema: ${data}`);\n\t}\n\n\tconst fieldsIterator: Iterable<readonly [string, InsertableContent]> = Object.entries(data);\n\treturn recordLikeDataToFlexContent(fieldsIterator, schema);\n}\n\n/**\n * Converts record-like data to a FlexContent representation for map/record schema.\n */\nfunction recordLikeDataToFlexContent(\n\tfieldsIterator: Iterable<readonly [string, InsertableContent]>,\n\tschema: MapNodeSchema | RecordNodeSchema,\n): FlexContent {\n\tconst allowedChildTypes = normalizeAllowedTypes(unannotateImplicitAllowedTypes(schema.info));\n\tconst context = getUnhydratedContext(schema).flexContext;\n\n\tconst transformedFields = new Map<FieldKey, UnhydratedFlexTreeField>();\n\tfor (const item of fieldsIterator) {\n\t\tconst [key, value] = item;\n\t\tassert(!transformedFields.has(brand(key)), 0x84c /* Keys should not be duplicated */);\n\n\t\t// Omit undefined values - an entry with an undefined value is equivalent to one that has been removed or omitted\n\t\tif (value !== undefined) {\n\t\t\tconst child = unhydratedFlexTreeFromInsertableNode(value, allowedChildTypes);\n\t\t\tconst field = createField(context, FieldKinds.optional.identifier, brand(key), [child]);\n\t\t\ttransformedFields.set(brand(key), field);\n\t\t}\n\t}\n\n\treturn [\n\t\t{\n\t\t\ttype: brand(schema.identifier),\n\t\t},\n\t\ttransformedFields,\n\t];\n}\n\n/**\n * Check {@link FactoryContentObject} for a property which could be store a field.\n *\n * @returns If the property exists, return its value. Otherwise, returns undefined.\n * @remarks\n * The currently policy is to only consider own properties.\n * See {@link InsertableObjectFromSchemaRecord} for where this policy is documented in the public API.\n *\n * Explicit undefined values are treated the same as missing properties to allow explicit use of undefined with defaulted identifiers.\n *\n * @privateRemarks\n * If we ever want to have an optional field which defaults to something other than undefined, this will need changes.\n * It would need to adjusting the handling of explicit undefined in contexts where undefined is allowed, and a default provider also exists.\n */\nfunction getFieldProperty(\n\tdata: FactoryContentObject,\n\tkey: string | symbol,\n): InsertableContent | undefined {\n\t// This policy only allows own properties.\n\tif (Object.hasOwnProperty.call(data, key)) {\n\t\treturn (data as Record<string, InsertableContent>)[key as string];\n\t}\n\treturn undefined;\n}\n\nfunction getType(\n\tdata: FactoryContent,\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n): TreeNodeSchema {\n\tconst possibleTypes = getPossibleTypes(allowedTypes, data);\n\tif (possibleTypes.length === 0) {\n\t\tthrow new UsageError(\n\t\t\t`The provided data is incompatible with all of the types allowed by the schema. The set of allowed types is: ${JSON.stringify(\n\t\t\t\t[...allowedTypes].map((schema) => schema.identifier),\n\t\t\t)}.`,\n\t\t);\n\t}\n\tif (!hasSingle(possibleTypes)) {\n\t\tthrow new UsageError(\n\t\t\t`The provided data is compatible with more than one type allowed by the schema.\nThe set of possible types is ${JSON.stringify([\n\t\t\t\t...possibleTypes.map((schema) => schema.identifier),\n\t\t\t])}.\nExplicitly construct an unhydrated node of the desired type to disambiguate.\nFor class-based schema, this can be done by replacing an expression like \"{foo: 1}\" with \"new MySchema({foo: 1})\".`,\n\t\t);\n\t}\n\treturn possibleTypes[0];\n}\n\n/**\n * Returns all types for which the data is schema-compatible.\n */\nexport function getPossibleTypes(\n\tallowedTypes: ReadonlySet<TreeNodeSchema>,\n\tdata: FactoryContent,\n): TreeNodeSchema[] {\n\tlet best = CompatibilityLevel.None;\n\tconst possibleTypes: TreeNodeSchema[] = [];\n\tfor (const schema of allowedTypes) {\n\t\tconst level = shallowCompatibilityTest(schema, data);\n\t\tif (level > best) {\n\t\t\tpossibleTypes.length = 0;\n\t\t\tbest = level;\n\t\t}\n\t\tif (best === level) {\n\t\t\tpossibleTypes.push(schema);\n\t\t}\n\t}\n\treturn best === CompatibilityLevel.None ? [] : possibleTypes;\n}\n\n/**\n * Indicates a compatibility level for inferring a schema to apply to insertable data.\n * @remarks\n * Only the highest compatibility options are used.\n * This approach allows adding new possible matching at a new lower compatibility level as a non breaking change,\n * since that way they can't make a case that was compatible before ambiguous now.\n */\nenum CompatibilityLevel {\n\t/**\n\t * Not compatible. Constructor typing indicates incompatibility.\n\t */\n\tNone = 0,\n\t/**\n\t * Additional compatibility cases added in Fluid Framework 2.2.\n\t */\n\tLow = 1,\n\t/**\n\t * Compatible in Fluid Framework 2.0.\n\t */\n\tNormal = 2,\n}\n\n/**\n * Checks if data might be schema-compatible.\n *\n * @returns false if `data` is incompatible with `type` based on a cheap/shallow check.\n *\n * Note that this may return true for cases where data is incompatible, but it must not return false in cases where the data is compatible.\n */\nfunction shallowCompatibilityTest(\n\tschema: TreeNodeSchema,\n\tdata: FactoryContent,\n): CompatibilityLevel {\n\tassert(data !== undefined, 0x889 /* undefined cannot be used as FactoryContent. */);\n\n\tif (isTreeValue(data)) {\n\t\treturn allowsValue(schema, data) ? CompatibilityLevel.Normal : CompatibilityLevel.None;\n\t}\n\tif (schema.kind === NodeKind.Leaf) {\n\t\treturn CompatibilityLevel.None;\n\t}\n\n\t// Typing (of schema based constructors and thus implicit node construction)\n\t// allows iterables for constructing maps and arrays.\n\t// Some users of this API may have unions of maps and arrays,\n\t// and rely on Arrays ending up as array nodes and maps as Map nodes,\n\t// despite both being iterable and thus compatible with both.\n\t// This uses a priority based system where an array would be parsed as an array when unioned with a map,\n\t// but if in a map only context, could still be used as a map.\n\n\tif (data instanceof Map) {\n\t\tswitch (schema.kind) {\n\t\t\tcase NodeKind.Map:\n\t\t\t\treturn CompatibilityLevel.Normal;\n\t\t\tcase NodeKind.Array:\n\t\t\t\t// Maps are iterable, so type checking does allow constructing an ArrayNode from a map if the array's type is an array that includes the key and value types of the map.\n\t\t\t\treturn CompatibilityLevel.Low;\n\t\t\tdefault:\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t}\n\t}\n\n\tif (isReadonlyArray(data)) {\n\t\tswitch (schema.kind) {\n\t\t\tcase NodeKind.Array:\n\t\t\t\treturn CompatibilityLevel.Normal;\n\t\t\tcase NodeKind.Map:\n\t\t\t\t// Arrays are iterable, so type checking does allow constructing an array from a MapNode from an if the array's type is key values pairs for the map.\n\t\t\t\treturn CompatibilityLevel.Low;\n\t\t\tdefault:\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t}\n\t}\n\n\tconst mapOrArray = schema.kind === NodeKind.Array || schema.kind === NodeKind.Map;\n\n\tif (Symbol.iterator in data) {\n\t\treturn mapOrArray ? CompatibilityLevel.Normal : CompatibilityLevel.None;\n\t}\n\n\t// At this point, it is assumed data is a record-like object since all the other cases have been eliminated.\n\n\tif (schema.kind === NodeKind.Record) {\n\t\treturn CompatibilityLevel.Normal;\n\t}\n\n\tif (schema.kind === NodeKind.Array) {\n\t\treturn CompatibilityLevel.None;\n\t}\n\n\tif (schema.kind === NodeKind.Map) {\n\t\t// When not unioned with an ObjectNode, allow objects to be used to create maps.\n\t\treturn CompatibilityLevel.Low;\n\t}\n\n\tassert(isObjectNodeSchema(schema), 0x9e6 /* unexpected schema kind */);\n\n\t// TODO: Improve type inference by making this logic more thorough. Handle at least:\n\t// * Types which are strict subsets of other types in the same polymorphic union\n\t// * Types which have the same keys but different types for those keys in the polymorphic union\n\t// * Types which have the same required fields but different optional fields and enough of those optional fields are populated to disambiguate\n\n\t// TODO#7441: Consider allowing data to be inserted which has keys that are extraneous/unknown to the schema (those keys are ignored)\n\n\t// If the schema has a required key which is not present in the input object, reject it.\n\tfor (const [fieldKey, fieldSchema] of schema.fields) {\n\t\tif (fieldSchema.requiresValue) {\n\t\t\tif (getFieldProperty(data, fieldKey) === undefined) {\n\t\t\t\treturn CompatibilityLevel.None;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn CompatibilityLevel.Normal;\n}\n\nfunction allowsValue(schema: TreeNodeSchema, value: TreeValue): boolean {\n\tif (schema.kind === NodeKind.Leaf) {\n\t\treturn valueSchemaAllows(schema.info as ValueSchema, value);\n\t}\n\treturn false;\n}\n\n/**\n * Content which can be used to build a node.\n * @remarks\n * Can contain unhydrated nodes, but can not be an unhydrated node at the root.\n * @system @alpha\n */\nexport type FactoryContent =\n\t| IFluidHandle\n\t| string\n\t| number\n\t| boolean\n\t// eslint-disable-next-line @rushstack/no-new-null\n\t| null\n\t| Iterable<readonly [string, InsertableContent]>\n\t| readonly InsertableContent[]\n\t| FactoryContentObject;\n\n/**\n * Record-like object which can be used to build some kinds of nodes.\n * @remarks\n * Can contain unhydrated nodes, but can not be an unhydrated node at the root.\n *\n * Supports object and map nodes.\n * @system @alpha\n */\nexport type FactoryContentObject = {\n\treadonly [P in string]?: InsertableContent;\n};\n\n/**\n * Content which can be inserted into a tree.\n * @system @alpha\n */\nexport type InsertableContent = Unhydrated<TreeNode> | FactoryContent;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/tree",
|
|
3
|
-
"version": "2.50.0
|
|
3
|
+
"version": "2.50.0",
|
|
4
4
|
"description": "Distributed tree",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -101,17 +101,17 @@
|
|
|
101
101
|
"temp-directory": "nyc/.nyc_output"
|
|
102
102
|
},
|
|
103
103
|
"dependencies": {
|
|
104
|
-
"@fluid-internal/client-utils": "2.50.0
|
|
105
|
-
"@fluidframework/container-runtime": "2.50.0
|
|
106
|
-
"@fluidframework/core-interfaces": "2.50.0
|
|
107
|
-
"@fluidframework/core-utils": "2.50.0
|
|
108
|
-
"@fluidframework/datastore-definitions": "2.50.0
|
|
109
|
-
"@fluidframework/driver-definitions": "2.50.0
|
|
110
|
-
"@fluidframework/id-compressor": "2.50.0
|
|
111
|
-
"@fluidframework/runtime-definitions": "2.50.0
|
|
112
|
-
"@fluidframework/runtime-utils": "2.50.0
|
|
113
|
-
"@fluidframework/shared-object-base": "2.50.0
|
|
114
|
-
"@fluidframework/telemetry-utils": "2.50.0
|
|
104
|
+
"@fluid-internal/client-utils": "~2.50.0",
|
|
105
|
+
"@fluidframework/container-runtime": "~2.50.0",
|
|
106
|
+
"@fluidframework/core-interfaces": "~2.50.0",
|
|
107
|
+
"@fluidframework/core-utils": "~2.50.0",
|
|
108
|
+
"@fluidframework/datastore-definitions": "~2.50.0",
|
|
109
|
+
"@fluidframework/driver-definitions": "~2.50.0",
|
|
110
|
+
"@fluidframework/id-compressor": "~2.50.0",
|
|
111
|
+
"@fluidframework/runtime-definitions": "~2.50.0",
|
|
112
|
+
"@fluidframework/runtime-utils": "~2.50.0",
|
|
113
|
+
"@fluidframework/shared-object-base": "~2.50.0",
|
|
114
|
+
"@fluidframework/telemetry-utils": "~2.50.0",
|
|
115
115
|
"@sinclair/typebox": "^0.34.13",
|
|
116
116
|
"@tylerbu/sorted-btree-es6": "^1.8.0",
|
|
117
117
|
"@types/ungap__structured-clone": "^1.2.0",
|
|
@@ -121,19 +121,19 @@
|
|
|
121
121
|
"devDependencies": {
|
|
122
122
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
123
123
|
"@biomejs/biome": "~1.9.3",
|
|
124
|
-
"@fluid-internal/mocha-test-setup": "2.50.0
|
|
125
|
-
"@fluid-private/stochastic-test-utils": "2.50.0
|
|
126
|
-
"@fluid-private/test-dds-utils": "2.50.0
|
|
127
|
-
"@fluid-private/test-drivers": "2.50.0
|
|
124
|
+
"@fluid-internal/mocha-test-setup": "~2.50.0",
|
|
125
|
+
"@fluid-private/stochastic-test-utils": "~2.50.0",
|
|
126
|
+
"@fluid-private/test-dds-utils": "~2.50.0",
|
|
127
|
+
"@fluid-private/test-drivers": "~2.50.0",
|
|
128
128
|
"@fluid-tools/benchmark": "^0.51.0",
|
|
129
129
|
"@fluid-tools/build-cli": "^0.56.0",
|
|
130
130
|
"@fluidframework/build-common": "^2.0.3",
|
|
131
131
|
"@fluidframework/build-tools": "^0.56.0",
|
|
132
|
-
"@fluidframework/container-definitions": "2.50.0
|
|
133
|
-
"@fluidframework/container-loader": "2.50.0
|
|
132
|
+
"@fluidframework/container-definitions": "~2.50.0",
|
|
133
|
+
"@fluidframework/container-loader": "~2.50.0",
|
|
134
134
|
"@fluidframework/eslint-config-fluid": "^5.7.4",
|
|
135
|
-
"@fluidframework/test-runtime-utils": "2.50.0
|
|
136
|
-
"@fluidframework/test-utils": "2.50.0
|
|
135
|
+
"@fluidframework/test-runtime-utils": "~2.50.0",
|
|
136
|
+
"@fluidframework/test-utils": "~2.50.0",
|
|
137
137
|
"@fluidframework/tree-previous": "npm:@fluidframework/tree@2.43.0",
|
|
138
138
|
"@microsoft/api-extractor": "7.52.8",
|
|
139
139
|
"@types/diff": "^3.5.1",
|
package/src/packageVersion.ts
CHANGED
|
@@ -3,13 +3,25 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
assert,
|
|
8
|
+
DoublyLinkedList,
|
|
9
|
+
oob,
|
|
10
|
+
type ListNode,
|
|
11
|
+
type ListNodeRange,
|
|
12
|
+
} from "@fluidframework/core-utils/internal";
|
|
7
13
|
|
|
8
14
|
import type { GraphCommit, TaggedChange } from "../core/index.js";
|
|
9
15
|
import { disposeSymbol, hasSome } from "../util/index.js";
|
|
10
16
|
|
|
11
17
|
import type { ChangeEnricherReadonlyCheckout, ResubmitMachine } from "./index.js";
|
|
12
18
|
|
|
19
|
+
interface PendingChange<TChange> {
|
|
20
|
+
commit: GraphCommit<TChange>;
|
|
21
|
+
lastEnrichment: number;
|
|
22
|
+
}
|
|
23
|
+
type PendingChangeNode<TChange> = ListNode<PendingChange<TChange>>;
|
|
24
|
+
|
|
13
25
|
/**
|
|
14
26
|
* Default implementation of {@link ResubmitMachine}.
|
|
15
27
|
*/
|
|
@@ -17,24 +29,20 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
17
29
|
/**
|
|
18
30
|
* The list of commits (from oldest to most recent) that have been submitted but not sequenced.
|
|
19
31
|
*/
|
|
20
|
-
private inFlightQueue:
|
|
32
|
+
private readonly inFlightQueue: DoublyLinkedList<PendingChange<TChange>> =
|
|
33
|
+
new DoublyLinkedList();
|
|
21
34
|
|
|
22
35
|
/**
|
|
23
|
-
* The
|
|
36
|
+
* The range of in-flight commits that are currently being resubmitted.
|
|
37
|
+
* Defined only during the resubmit phase.
|
|
24
38
|
*/
|
|
25
|
-
private
|
|
39
|
+
private pendingResubmitRange: ListNodeRange<PendingChange<TChange>> | undefined;
|
|
26
40
|
|
|
27
41
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* All in-flight commits with an index inferior or equal to this number have stale enrichments.
|
|
31
|
-
*
|
|
32
|
-
* Is -1 when *any* of the following is true:
|
|
33
|
-
* - There are no in-flight commits (i.e., no local commits have been made or they have all been sequenced)
|
|
34
|
-
* - None of the in-flight commits have been rebased
|
|
35
|
-
* - In-flight commits that have been rebased have all had their enrichments updated
|
|
42
|
+
* The current enrichment version for in-flight commits.
|
|
43
|
+
* Incremented when a peer commit is sequenced.
|
|
36
44
|
*/
|
|
37
|
-
private
|
|
45
|
+
private currentEnrichment: number = 0;
|
|
38
46
|
|
|
39
47
|
public constructor(
|
|
40
48
|
/**
|
|
@@ -49,14 +57,31 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
49
57
|
) {}
|
|
50
58
|
|
|
51
59
|
public onCommitSubmitted(commit: GraphCommit<TChange>): void {
|
|
52
|
-
if (this.
|
|
53
|
-
const toResubmit = this.
|
|
60
|
+
if (this.pendingResubmitRange !== undefined) {
|
|
61
|
+
const toResubmit = this.pendingResubmitRange?.first;
|
|
54
62
|
assert(
|
|
55
|
-
toResubmit === commit,
|
|
63
|
+
toResubmit?.data.commit === commit,
|
|
56
64
|
0x981 /* Unexpected commit submitted during resubmit phase */,
|
|
57
65
|
);
|
|
66
|
+
// If we are not at the last commit to resubmit, advance the range to the next node.
|
|
67
|
+
// Otherwise, clear the resubmit range as we are done resubmitting.
|
|
68
|
+
if (toResubmit !== this.pendingResubmitRange.last) {
|
|
69
|
+
assert(toResubmit.next !== undefined, 0xbd6 /* must be more in the list */);
|
|
70
|
+
this.pendingResubmitRange.first = toResubmit.next;
|
|
71
|
+
} else {
|
|
72
|
+
this.pendingResubmitRange = undefined;
|
|
73
|
+
}
|
|
74
|
+
toResubmit.remove();
|
|
58
75
|
}
|
|
59
|
-
this.inFlightQueue.push(commit);
|
|
76
|
+
this.inFlightQueue.push({ commit, lastEnrichment: this.currentEnrichment });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public onCommitRollback(commit: GraphCommit<TChange>): void {
|
|
80
|
+
assert(
|
|
81
|
+
commit.revision === this.inFlightQueue.last?.data.commit.revision,
|
|
82
|
+
0xbd7 /* must rollback latest commit in the in flight queue */,
|
|
83
|
+
);
|
|
84
|
+
this.inFlightQueue.pop();
|
|
60
85
|
}
|
|
61
86
|
|
|
62
87
|
public prepareForResubmit(toResubmit: readonly GraphCommit<TChange>[]): void {
|
|
@@ -64,16 +89,33 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
64
89
|
!this.isInResubmitPhase,
|
|
65
90
|
0x957 /* Invalid resubmit phase start during incomplete resubmit phase */,
|
|
66
91
|
);
|
|
92
|
+
|
|
93
|
+
if (!hasSome(toResubmit)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
67
97
|
assert(
|
|
68
|
-
toResubmit.length
|
|
69
|
-
|
|
98
|
+
toResubmit.length <= this.inFlightQueue.length,
|
|
99
|
+
0xbd8 /* Unexpected resubmit of more commits than are in flight */,
|
|
70
100
|
);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
101
|
+
|
|
102
|
+
// Find the first in-flight commit to resubmit.
|
|
103
|
+
const first = this.inFlightQueue.find(
|
|
104
|
+
(v) => v.data.commit.revision === toResubmit[0].revision,
|
|
105
|
+
);
|
|
106
|
+
// Always resubmit to the end of all outstanding ops, but the list may grow during resubmit,
|
|
107
|
+
// so we must track the current end at the start of the phase.
|
|
108
|
+
const last = this.inFlightQueue.last;
|
|
109
|
+
assert(
|
|
110
|
+
first !== undefined && last !== undefined,
|
|
111
|
+
0xbd9 /* there must be inflight commits to resubmit */,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
this.pendingResubmitRange = { first, last };
|
|
115
|
+
// If any in-flight commits have stale enrichments, recompute them.
|
|
116
|
+
if (first.data.lastEnrichment < this.currentEnrichment) {
|
|
76
117
|
const checkout = this.tip.fork();
|
|
118
|
+
|
|
77
119
|
// Roll back the checkout to the state before the oldest commit
|
|
78
120
|
for (let iCommit = toResubmit.length - 1; iCommit >= 0; iCommit -= 1) {
|
|
79
121
|
const commit = toResubmit[iCommit] ?? oob();
|
|
@@ -83,32 +125,37 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
83
125
|
// forwards from an earlier fork instead of backwards.
|
|
84
126
|
checkout.applyTipChange(rollback);
|
|
85
127
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const enrichedChange = checkout.updateChangeEnrichments(
|
|
94
|
-
commit.change,
|
|
95
|
-
commit.revision,
|
|
128
|
+
|
|
129
|
+
// Update the enrichments of the stale commits in the in-flight queue.
|
|
130
|
+
let current: PendingChangeNode<TChange> | undefined = first;
|
|
131
|
+
for (const commit of toResubmit) {
|
|
132
|
+
assert(
|
|
133
|
+
current !== undefined,
|
|
134
|
+
0xbda /* there must be an inflight commit for each resubmit commit */,
|
|
96
135
|
);
|
|
97
|
-
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
|
|
136
|
+
current.data.commit = commit;
|
|
137
|
+
if (current.data.lastEnrichment < this.currentEnrichment) {
|
|
138
|
+
const enrichedChange = checkout.updateChangeEnrichments(
|
|
139
|
+
commit.change,
|
|
140
|
+
commit.revision,
|
|
141
|
+
);
|
|
142
|
+
const enrichedCommit = { ...commit, change: enrichedChange };
|
|
143
|
+
|
|
144
|
+
// Optimization: only apply the enriched change if the next commit also needs enrichment.
|
|
145
|
+
if (
|
|
146
|
+
current.next !== undefined &&
|
|
147
|
+
current.next.data.lastEnrichment < this.currentEnrichment
|
|
148
|
+
) {
|
|
149
|
+
checkout.applyTipChange(enrichedChange, commit.revision);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
current.data.commit = enrichedCommit;
|
|
153
|
+
current.data.lastEnrichment = this.currentEnrichment;
|
|
101
154
|
}
|
|
102
|
-
|
|
155
|
+
current = current.next;
|
|
103
156
|
}
|
|
104
157
|
checkout[disposeSymbol]();
|
|
105
|
-
// Whatever commits are left do not have stale enrichments
|
|
106
|
-
for (const commit of this.inFlightQueue) {
|
|
107
|
-
this.resubmitQueue.push(commit);
|
|
108
|
-
}
|
|
109
|
-
this.inFlightQueue.length = 0;
|
|
110
158
|
}
|
|
111
|
-
this.latestInFlightCommitWithStaleEnrichments = -1;
|
|
112
159
|
}
|
|
113
160
|
|
|
114
161
|
public peekNextCommit(): GraphCommit<TChange> {
|
|
@@ -116,12 +163,15 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
116
163
|
this.isInResubmitPhase,
|
|
117
164
|
0x982 /* No available commit to resubmit outside of resubmit phase */,
|
|
118
165
|
);
|
|
119
|
-
assert(
|
|
120
|
-
|
|
166
|
+
assert(
|
|
167
|
+
this.pendingResubmitRange !== undefined,
|
|
168
|
+
0xa87 /* Expected resubmit queue to be non-empty */,
|
|
169
|
+
);
|
|
170
|
+
return this.pendingResubmitRange.first.data.commit;
|
|
121
171
|
}
|
|
122
172
|
|
|
123
173
|
public get isInResubmitPhase(): boolean {
|
|
124
|
-
return this.
|
|
174
|
+
return this.pendingResubmitRange !== undefined;
|
|
125
175
|
}
|
|
126
176
|
|
|
127
177
|
public onSequencedCommitApplied(isLocal: boolean): void {
|
|
@@ -129,12 +179,9 @@ export class DefaultResubmitMachine<TChange> implements ResubmitMachine<TChange>
|
|
|
129
179
|
// The oldest in-flight commit has been sequenced
|
|
130
180
|
assert(this.inFlightQueue.length > 0, 0x959 /* Sequencing of unknown local commit */);
|
|
131
181
|
this.inFlightQueue.shift();
|
|
132
|
-
if (this.latestInFlightCommitWithStaleEnrichments >= 0) {
|
|
133
|
-
this.latestInFlightCommitWithStaleEnrichments -= 1;
|
|
134
|
-
}
|
|
135
182
|
} else {
|
|
136
183
|
// A peer commit has been sequenced
|
|
137
|
-
this.
|
|
184
|
+
this.currentEnrichment++;
|
|
138
185
|
}
|
|
139
186
|
}
|
|
140
187
|
}
|
|
@@ -37,6 +37,13 @@ export interface ResubmitMachine<TChange> {
|
|
|
37
37
|
*/
|
|
38
38
|
onCommitSubmitted(commit: GraphCommit<TChange>): void;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Must be called on a commit after rollback, so it can be removed
|
|
42
|
+
* as it will never be (re)submitted.
|
|
43
|
+
* @param commit - The commit that was rolled back
|
|
44
|
+
*/
|
|
45
|
+
onCommitRollback(commit: GraphCommit<TChange>): void;
|
|
46
|
+
|
|
40
47
|
/**
|
|
41
48
|
* Must be called after a sequenced commit is applied.
|
|
42
49
|
* Note that this may be called multiples times in a row after a number of sequenced commits have been applied
|
|
@@ -397,14 +397,12 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
|
|
|
397
397
|
} = this.messageCodec.decode(this.serializer.decode(content), {
|
|
398
398
|
idCompressor: this.idCompressor,
|
|
399
399
|
});
|
|
400
|
-
const [commit] = this.editManager.findLocalCommit(revision);
|
|
401
400
|
// If a resubmit phase is not already in progress, then this must be the first commit of a new resubmit phase.
|
|
402
401
|
if (this.resubmitMachine.isInResubmitPhase === false) {
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
);
|
|
402
|
+
const localCommits = this.editManager.getLocalCommits();
|
|
403
|
+
const revisionIndex = localCommits.findIndex((c) => c.revision === revision);
|
|
404
|
+
assert(revisionIndex >= 0, 0xbdb /* revision must exist in local commits */);
|
|
405
|
+
const toResubmit = localCommits.slice(revisionIndex);
|
|
408
406
|
this.resubmitMachine.prepareForResubmit(toResubmit);
|
|
409
407
|
}
|
|
410
408
|
assert(
|
|
@@ -418,6 +416,20 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
|
|
|
418
416
|
const enrichedCommit = this.resubmitMachine.peekNextCommit();
|
|
419
417
|
this.submitCommit(enrichedCommit, localOpMetadata, true);
|
|
420
418
|
}
|
|
419
|
+
public rollback(content: JsonCompatibleReadOnly, localOpMetadata: unknown): void {
|
|
420
|
+
// Empty context object is passed in, as our decode function is schema-agnostic.
|
|
421
|
+
const {
|
|
422
|
+
commit: { revision },
|
|
423
|
+
} = this.messageCodec.decode(this.serializer.decode(content), {
|
|
424
|
+
idCompressor: this.idCompressor,
|
|
425
|
+
});
|
|
426
|
+
const [commit] = this.editManager.findLocalCommit(revision);
|
|
427
|
+
const { parent } = commit;
|
|
428
|
+
assert(parent !== undefined, 0xbdc /* must have parent */);
|
|
429
|
+
const [precedingCommit] = this.editManager.findLocalCommit(parent.revision);
|
|
430
|
+
this.editManager.localBranch.removeAfter(precedingCommit);
|
|
431
|
+
this.resubmitMachine.onCommitRollback(commit);
|
|
432
|
+
}
|
|
421
433
|
|
|
422
434
|
public applyStashedOp(content: JsonCompatibleReadOnly): void {
|
|
423
435
|
// Empty context object is passed in, as our decode function is schema-agnostic.
|
|
@@ -327,7 +327,7 @@ export function checkUnion(
|
|
|
327
327
|
break;
|
|
328
328
|
}
|
|
329
329
|
case NodeKind.Object: {
|
|
330
|
-
assert(isObjectNodeSchema(schema),
|
|
330
|
+
assert(isObjectNodeSchema(schema), 0xbde /* Expected object schema. */);
|
|
331
331
|
objects.push(schema);
|
|
332
332
|
for (const key of schema.fields.keys()) {
|
|
333
333
|
getOrCreate(allObjectKeys, key, () => new Set()).add(schema);
|
|
@@ -335,17 +335,17 @@ export function checkUnion(
|
|
|
335
335
|
break;
|
|
336
336
|
}
|
|
337
337
|
case NodeKind.Array: {
|
|
338
|
-
assert(isArrayNodeSchema(schema),
|
|
338
|
+
assert(isArrayNodeSchema(schema), 0xbdf /* Expected array schema. */);
|
|
339
339
|
arrays.push(schema);
|
|
340
340
|
break;
|
|
341
341
|
}
|
|
342
342
|
case NodeKind.Map: {
|
|
343
|
-
assert(isMapNodeSchema(schema),
|
|
343
|
+
assert(isMapNodeSchema(schema), 0xbe0 /* Expected map schema. */);
|
|
344
344
|
maps.push(schema);
|
|
345
345
|
break;
|
|
346
346
|
}
|
|
347
347
|
case NodeKind.Record: {
|
|
348
|
-
assert(isRecordNodeSchema(schema),
|
|
348
|
+
assert(isRecordNodeSchema(schema), 0xbe1 /* Expected record schema. */);
|
|
349
349
|
records.push(schema);
|
|
350
350
|
break;
|
|
351
351
|
}
|
|
@@ -163,7 +163,7 @@ function unhydratedFlexTreeFromInsertableNode(
|
|
|
163
163
|
result = objectToFlexContent(data, schema);
|
|
164
164
|
break;
|
|
165
165
|
case NodeKind.Record:
|
|
166
|
-
assert(isRecordNodeSchema(schema),
|
|
166
|
+
assert(isRecordNodeSchema(schema), 0xbdd /* Expected a Record schema. */);
|
|
167
167
|
result = recordToFlexContent(data, schema);
|
|
168
168
|
break;
|
|
169
169
|
default:
|