Skip to content

Commit

Permalink
(tree) Add constraint to the output context of a change
Browse files Browse the repository at this point in the history
  • Loading branch information
agarwal-navin committed Dec 4, 2024
1 parent a8f10a7 commit 704e854
Show file tree
Hide file tree
Showing 16 changed files with 377 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,17 @@ export interface IDefaultEditBuilder {
destinationIndex: number,
): void;

// TODO: document
addNodeExistsConstraint(path: UpPath): void;
/**
* Add a constraint that the node at the given path must exist.
* @param path - The path to the node that must exist.
*/
addInputNodeExistsConstraint(path: UpPath): void;

/**
* Add a constraint that the node at the given path must exist when undoing a change.
* @param path - The path to the node that must exist when undoing a change.
*/
addUndoNodeExistsConstraint(path: UpPath): void;
}

/**
Expand All @@ -187,8 +196,12 @@ export class DefaultEditBuilder implements ChangeFamilyEditor, IDefaultEditBuild
this.modularBuilder.exitTransaction();
}

public addNodeExistsConstraint(path: UpPath): void {
this.modularBuilder.addNodeExistsConstraint(path, this.mintRevisionTag());
public addInputNodeExistsConstraint(path: UpPath): void {
this.modularBuilder.addInputNodeExistsConstraint(path, this.mintRevisionTag());
}

public addUndoNodeExistsConstraint(path: UpPath): void {
this.modularBuilder.addOutputNodeExistsConstraint(path, this.mintRevisionTag());
}

public valueField(field: FieldUpPath): ValueFieldEditBuilder<ITreeCursorSynchronous> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import type { CrossFieldManager } from "./crossFieldQueries.js";
import type { CrossFieldKeyRange, NodeId } from "./modularChangeTypes.js";
import type { EncodedNodeChangeset } from "./modularChangeFormat.js";

export type NestedChangesIndices = [
NodeId,
number | undefined /* inputIndex */,
number | undefined /* outputIndex */,
][];

/**
* Functionality provided by a field kind which will be composed with other `FieldChangeHandler`s to
* implement a unified ChangeFamily supporting documents with multiple field kinds.
Expand Down Expand Up @@ -75,13 +81,16 @@ export interface FieldChangeHandler<
* @param change - The field change to get the child changes from.
*
* @returns The set of `NodeId`s that correspond to nested changes in the given `change`.
* Each `NodeId` is associated with the index of the node in the field in the input context of the changeset
* (or `undefined` if the node is not attached in the input context).
* Each `NodeId` is associated with the following:
* - index of the node in the field in the input context of the changeset (or `undefined` if the node is not
* attached in the input context).
* - index of the node in the field in the output context of the changeset (or `undefined` if the node is not
* attached in the output context).
* For all returned entries where the index is defined,
* the indices are are ordered from smallest to largest (with no duplicates).
* The returned array is owned by the caller.
*/
getNestedChanges(change: TChangeset): [NodeId, number | undefined][];
getNestedChanges(change: TChangeset): NestedChangesIndices;

/**
* @returns A list of all cross-field keys contained in the change.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { assert } from "@fluidframework/core-utils/internal";
import type { CrossFieldManager } from "./crossFieldQueries.js";
import type {
FieldChangeHandler,
NestedChangesIndices,
NodeChangeComposer,
NodeChangePruner,
NodeChangeRebaser,
Expand Down Expand Up @@ -82,8 +83,9 @@ function compose(
return composed;
}

function getNestedChanges(change: GenericChangeset): [NodeId, number | undefined][] {
return change.toArray().map(([index, nodeChange]) => [nodeChange, index]);
function getNestedChanges(change: GenericChangeset): NestedChangesIndices {
// For generic changeset, the indices in the input and output contexts are the same.
return change.toArray().map(([index, nodeChange]) => [nodeChange, index, index]);
}

function rebaseGenericChange(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export {
type ToDelta,
NodeAttachState,
type FieldChangeEncodingContext,
type NestedChangesIndices,
} from "./fieldChangeHandler.js";
export type {
CrossFieldKeyRange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,18 @@ function makeModularChangeCodec(
context: FieldChangeEncodingContext,
): EncodedNodeChangeset {
const encodedChange: EncodedNodeChangeset = {};
const { fieldChanges, nodeExistsConstraint } = change;
const { fieldChanges, inputNodeExistsConstraint, outputNodeExistsConstraint } = change;

if (fieldChanges !== undefined) {
encodedChange.fieldChanges = encodeFieldChangesForJsonI(fieldChanges, context);
}

if (nodeExistsConstraint !== undefined) {
encodedChange.nodeExistsConstraint = nodeExistsConstraint;
if (inputNodeExistsConstraint !== undefined) {
encodedChange.inputNodeExistsConstraint = inputNodeExistsConstraint;
}

if (outputNodeExistsConstraint !== undefined) {
encodedChange.outputNodeExistsConstraint = outputNodeExistsConstraint;
}

return encodedChange;
Expand Down Expand Up @@ -299,7 +303,8 @@ function makeModularChangeCodec(
idAllocator: IdAllocator,
): NodeChangeset {
const decodedChange: NodeChangeset = {};
const { fieldChanges, nodeExistsConstraint } = encodedChange;
const { fieldChanges, inputNodeExistsConstraint, outputNodeExistsConstraint } =
encodedChange;

if (fieldChanges !== undefined) {
decodedChange.fieldChanges = decodeFieldChangesFromJson(
Expand All @@ -311,8 +316,12 @@ function makeModularChangeCodec(
);
}

if (nodeExistsConstraint !== undefined) {
decodedChange.nodeExistsConstraint = nodeExistsConstraint;
if (inputNodeExistsConstraint !== undefined) {
decodedChange.inputNodeExistsConstraint = inputNodeExistsConstraint;
}

if (outputNodeExistsConstraint !== undefined) {
decodedChange.outputNodeExistsConstraint = outputNodeExistsConstraint;
}

return decodedChange;
Expand Down Expand Up @@ -476,7 +485,7 @@ function makeModularChangeCodec(
changes: encodeFieldChangesForJson(change.fieldChanges, context, change.nodeChanges),
builds: encodeDetachedNodes(change.builds, context),
refreshers: encodeDetachedNodes(change.refreshers, context),
violations: change.constraintViolationCount,
violations: change.inputConstraintViolationCount,
};
},

Expand Down Expand Up @@ -505,7 +514,7 @@ function makeModularChangeCodec(
}

if (encodedChange.violations !== undefined) {
decoded.constraintViolationCount = encodedChange.violations;
decoded.inputConstraintViolationCount = encodedChange.violations;
}

const decodedRevInfos = decodeRevisionInfos(encodedChange.revisions, context);
Expand Down
Loading

0 comments on commit 704e854

Please sign in to comment.