Support captured CRDT changes in compound transaction contracts
This commit is contained in:
@@ -319,12 +319,12 @@ export class GenericSourceTypes {
|
||||
return { kind: "record", fields: Object.fromEntries(fields) };
|
||||
}
|
||||
const name = context.identifier()!.getText();
|
||||
if (name === "change" && context.typeArguments())
|
||||
throw new GenericTypeError(
|
||||
"unsupported-prepared-change",
|
||||
name,
|
||||
"Authored change<T> transport values require LF-19; native edit contracts are available separately",
|
||||
);
|
||||
if (name === "change" && context.typeArguments()) {
|
||||
const args = this.arguments(context.typeArguments());
|
||||
if (args.length !== 1 || args[0]!.kind !== "value")
|
||||
throw new GenericTypeError("invalid-change-type", name, "change<T> requires one materialized value type");
|
||||
return { kind: "change", value: args[0]!.type };
|
||||
}
|
||||
if (context.ATOM_REF()) return { kind: "object-ref", expectation: this.atom(name) };
|
||||
if (context.INTERFACE_REF())
|
||||
return {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { isStorableType } from "./generics.js";
|
||||
import { validateInitialization } from "./initialization.js";
|
||||
import { validateExecutionContracts } from "./execution.js";
|
||||
import { resolveForwardedBinding, type ConcreteBinding } from "./forwarding.js";
|
||||
@@ -244,6 +245,15 @@ const validateValueType = (
|
||||
requireText(issues, type.descriptorId, `${path}.descriptorId`, "Message descriptor identity");
|
||||
return;
|
||||
case "change":
|
||||
if (!isStorableType(type.value))
|
||||
issue(
|
||||
issues,
|
||||
"invalid-value-type",
|
||||
path,
|
||||
"change<T> requires a storable materialized type, not references or nested changes",
|
||||
);
|
||||
validateValueType(issues, type.value, path + ".value", indexes);
|
||||
return;
|
||||
case "optional":
|
||||
case "list":
|
||||
validateValueType(issues, type.value, `${path}.value`, indexes);
|
||||
|
||||
@@ -144,8 +144,8 @@ export function compileExecutionPlan(input: WorkspaceRevision): ExecutionPlan {
|
||||
for (const pkg of workspace.packageImports)
|
||||
for (const entry of pkg.exports)
|
||||
if (entry.execution && entry.execution.kind !== "remote") {
|
||||
checkValue(entry.inputType, `${pkg.revisionId}/${entry.id}/input`);
|
||||
checkValue(entry.outputType, `${pkg.revisionId}/${entry.id}/output`);
|
||||
checkValue(entry.inputType, `${pkg.revisionId}/${entry.id}/input`, true);
|
||||
checkValue(entry.outputType, `${pkg.revisionId}/${entry.id}/output`, true);
|
||||
}
|
||||
for (const attachment of attachments)
|
||||
if (attachment.kind === "state" && attachment.storagePolicy.kind === "crdt-document")
|
||||
@@ -208,8 +208,8 @@ export function compileExecutionPlan(input: WorkspaceRevision): ExecutionPlan {
|
||||
operationMap.set(key, planned);
|
||||
const portable = planned.execution.kind !== "remote";
|
||||
if (portable) {
|
||||
checkValue(planned.input, `${key}/input`, binding.kind === "state" && binding.primitive === "edit");
|
||||
checkValue(planned.output, `${key}/output`);
|
||||
checkValue(planned.input, `${key}/input`, true);
|
||||
checkValue(planned.output, `${key}/output`, true);
|
||||
}
|
||||
if (binding.kind === "state") planned.dependencies.push({ kind: "state", slot: binding.slotId });
|
||||
else if (binding.kind === "edge")
|
||||
|
||||
Reference in New Issue
Block a user