import {
assert,
assertEquals,
assertMatch,
assertStringIncludes,
} from "@std/assert";
import { CFC_TRANSFORMER_STAGE_NAMES } from "../src/cf-pipeline.ts";
import { transformSource, validateSource } from "./utils.ts";
import { COMMONFABRIC_TYPES } from "./commonfabric-test-types.ts";
function extractSchemas(output: string): string[] {
const schemas: string[] = [];
const marker = "as const satisfies __cfHelpers.JSONSchema";
let searchFrom = 0;
while (true) {
const markerIdx = output.indexOf(marker, searchFrom);
if (markerIdx === -1) break;
let start = markerIdx - 1;
while (start >= 0 && /\s/.test(output[start]!)) start--;
let schemaText: string | undefined;
if (output[start] === "}") {
let depth = 1;
start--;
while (start >= 0 && depth > 0) {
if (output[start] === "}") depth++;
else if (output[start] === "{") depth--;
start--;
}
start++;
schemaText = output.slice(start, markerIdx).trim();
} else {
let tokenStart = start;
while (tokenStart >= 0 && /[A-Za-z]/.test(output[tokenStart]!)) {
tokenStart--;
}
tokenStart++;
const token = output.slice(tokenStart, start + 1).trim();
if (token === "true" || token === "false") {
schemaText = token;
}
}
if (!schemaText) {
searchFrom = markerIdx + marker.length;
continue;
}
schemas.push(schemaText);
searchFrom = markerIdx + marker.length;
}
return schemas;
}
Deno.test(
"Pipeline regression: manual mapWithPattern preserves fixed plain-capture key evaluation",
async () => {
const source = `import { pattern, UI } from "commonfabric";
const key = "small" as const;
const p = pattern<{ items: string[] }>((state) => ({
[UI]: (
{state.items.mapWithPattern(
pattern(({ params: { style: { [key]: fontSize } } }) => (
{fontSize}
)),
{ style: { small: 12, large: 16 }, key },
)}
),
}));
`;
const { diagnostics } = await validateSource(source, {
types: COMMONFABRIC_TYPES,
});
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
const computationDiagnostics = diagnostics.filter((diagnostic) =>
diagnostic.type === "pattern-context:computation"
);
assertEquals(computationDiagnostics.length, 0);
assertStringIncludes(
output,
"const fontSize = __cf_pattern_input.params.style[key];",
);
assert(!output.includes("__cf_pattern_input.params.style.small"));
},
);
Deno.test(
"Pipeline regression: CFC transformer stages stay in the fixed order",
() => {
assertEquals(CFC_TRANSFORMER_STAGE_NAMES, [
"CastValidationTransformer",
"EmptyArrayOfValidationTransformer",
"OpaqueGetValidationTransformer",
"PatternContextValidationTransformer",
"JsxExpressionSiteRouterTransformer",
"LiftLoweringTransformer",
"ClosureTransformer",
"PatternOwnedExpressionSiteLoweringTransformer",
"HelperOwnedExpressionSiteLoweringTransformer",
"WriteAuthorizedByValidationTransformer",
"PatternCallbackLoweringTransformer",
"SchemaInjectionTransformer",
"BuilderCallHoistingTransformer",
"SchemaGeneratorTransformer",
"ReactiveVariableForTransformer",
"ModuleScopeShadowingTransformer",
"ModuleScopeCfDataTransformer",
"PatternCoverageTransformer",
"ModuleScopeFunctionHardeningTransformer",
]);
},
);
Deno.test(
"Pipeline regression: opaque key lowering preserves literal-typed key evaluation",
async () => {
const source = `///
import { pattern, UI } from "commonfabric";
declare function getKey(): "title";
const p = pattern<{ item: { title: string } }>((state) => {
const { [getKey()]: title } = state.item;
return {
[UI]: {title}
,
};
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(
output,
'const __cf_destructure_1 = state.key("item"), title = __cf_destructure_1.key(getKey());',
);
assert(!output.includes('title = __cf_destructure_1.key("title")'));
},
);
Deno.test(
"Pipeline regression: imported Common Fabric keys stay helper-backed in rewrites",
async () => {
const source = `///
import { NAME, UI, pattern } from "commonfabric";
type MentionablePiece = { [NAME]?: string };
const p = pattern<{ mentionable: MentionablePiece[] }, { [UI]: any }>((
{ mentionable },
) => ({
[UI]: {mentionable.map((c) => c[NAME]!)}
,
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// Test intent: imported well-known CF keys (NAME/UI/SELF/FS) must never
// appear as bare identifiers in the lowered output — they must always be
// helper-backed (__cfHelpers.NAME etc.). After CT-1586, well-known CF
// keys on tracked-opaque roots lower to `expr.key(__cfHelpers.NAME)`
// in-place rather than being wrapped in `derive(..., ({c}) =>
// c[__cfHelpers.NAME])`. The surface form must include the helper
// expression on the `c` root specifically — generic substring
// checks could pass even if `c` got renamed by an unrelated bug.
assertStringIncludes(output, "c.key(__cfHelpers.NAME)");
assert(
!output.includes("c.key(NAME)") && !output.includes("c[NAME]"),
"Bare NAME identifier must not appear in lowered output",
);
},
);
Deno.test(
"Pipeline regression: nested writable map callbacks keep direct key reads in shrunk schemas",
async () => {
const source = await Deno.readTextFile(
new URL(
"./fixtures/kitchensink/nested-writable-pattern-branches.input.tsx",
import.meta.url,
),
);
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
const schemas = extractSchemas(output);
const outerMapSchema =
schemas.find((schema) =>
schema.includes('required: ["element", "params"]') &&
schema.includes("globalAccent") &&
schema.includes("selectedTaskId") &&
schema.includes("hoveredSectionId")
) ?? "";
assert(outerMapSchema.length > 0, "expected outer sections map schema");
assertStringIncludes(outerMapSchema, "id");
assertStringIncludes(outerMapSchema, "title");
assertStringIncludes(outerMapSchema, "expanded");
assertStringIncludes(outerMapSchema, "accent");
assertStringIncludes(outerMapSchema, "tasks");
const innerMapSchema =
schemas.find((schema) =>
schema.includes('required: ["element", "params"]') &&
schema.includes("sectionIndex") &&
schema.includes("selectedTaskId") &&
schema.includes("hoveredSectionId") &&
!schema.includes("globalAccent")
) ?? "";
assert(innerMapSchema.length > 0, "expected inner tasks map schema");
assertStringIncludes(innerMapSchema, "id");
assertStringIncludes(innerMapSchema, "label");
assertStringIncludes(innerMapSchema, "done");
assertStringIncludes(innerMapSchema, "tags");
assertStringIncludes(innerMapSchema, "note");
},
);
Deno.test(
"Pipeline regression: nested authored ifElse predicate in helper-owned branch lowers to derive",
async () => {
const source =
`import { computed, ifElse, pattern, UI } from "commonfabric";
interface ValidationIssue {
message: string;
severity: "error" | "warning";
}
interface ExtractedField {
targetModule: string;
fieldName: string;
confidenceLevel?: "high" | "medium" | "low";
validationIssue?: ValidationIssue;
explanation?: string;
}
interface Preview {
fields?: ExtractedField[];
}
export default pattern<{
inputFields: ExtractedField[];
fieldCheckStates: Record;
showPreview: boolean;
}>((state) => {
const preview = computed((): Preview | null => ({ fields: state.inputFields }));
return {
[UI]: (
{ifElse(
state.showPreview,
{preview?.fields?.map((f: ExtractedField, idx: number) => {
const fieldKey = f.targetModule + "." + f.fieldName;
const isChecked = state.fieldCheckStates[fieldKey] === true;
const confidenceBg = f.confidenceLevel === "high"
? "#dcfce7"
: f.confidenceLevel === "medium"
? "#fef9c3"
: f.confidenceLevel === "low"
? "#fee2e2"
: "transparent";
const confidenceColor = f.confidenceLevel === "high"
? "#166534"
: f.confidenceLevel === "medium"
? "#854d0e"
: f.confidenceLevel === "low"
? "#991b1b"
: "#6b7280";
const confidenceIcon = f.confidenceLevel === "high"
? "✓"
: f.confidenceLevel === "medium"
? "~"
: f.confidenceLevel === "low"
? "!"
: "";
const confidenceLabel = f.confidenceLevel === "high"
? "High"
: f.confidenceLevel === "medium"
? "Med"
: f.confidenceLevel === "low"
? "Low"
: "";
const hasConfidence = f.confidenceLevel !== undefined;
return (
{ifElse(
hasConfidence,
{confidenceIcon} {confidenceLabel}
,
null,
)}
{ifElse(
f.validationIssue !== undefined,
{f.validationIssue?.message}
,
null,
)}
{ifElse(
f.explanation !== undefined && f.explanation !== "",
{f.explanation}
,
null,
)}
);
})}
,
null,
)}
),
};
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(
output,
"=> f.validationIssue !== undefined",
);
// After CT-1644 Phase 2, the synthesized predicate wrapper is hoisted to a
// module-scope const and applied at the call site:
// const __cfLift_N = __cfHelpers.lift(
// argSchema, resSchema, ({ f }) => f.validationIssue !== undefined);
// ...__cfLift_N({ f: { validationIssue: f.key("validationIssue") } })
// The callback lives on the hoisted lift decl; the input on the applied
// site. Anchor on the unique predicate callback text, walk back to the
// nearest `const __cfLift_N =` that owns it (decls don't nest, so the last
// such declaration before the callback is its owner), then assert that same
// id is applied with the `f` validationIssue capture.
const predicateIdx = output.indexOf(
"({ f }) => f.validationIssue !== undefined",
);
assert(
predicateIdx >= 0,
"expected the synthesized validationIssue predicate callback",
);
const declMatches = [
...output.slice(0, predicateIdx).matchAll(
/const (__cfLift_\d+) = __cfHelpers\.lift/g,
),
];
assert(
declMatches.length > 0,
"expected a hoisted lift decl owning the validationIssue predicate",
);
const validationLiftId = declMatches[declMatches.length - 1][1];
assertMatch(
output,
new RegExp(
validationLiftId +
'\\(\\{ f: \\{[\\s\\S]*?validationIssue: f(?:\\.validationIssue|\\.key\\("validationIssue"\\))[\\s\\S]*?\\} \\}\\)',
),
);
},
);
Deno.test(
"Pipeline regression: dynamic key access in helper-owned map callback initializer lowers without computation diagnostics",
async () => {
const source =
`import { computed, ifElse, pattern, UI } from "commonfabric";
interface Field {
targetModule: string;
fieldName: string;
}
export default pattern<{
inputFields: Field[];
showPreview: boolean;
}>((state) => {
const preview = computed(() => ({ fields: state.inputFields }));
const fieldCheckStates = computed((): Record => ({
"record-title.name": true,
}));
return {
[UI]: ifElse(
state.showPreview,
{preview?.fields?.map((f: Field) => {
const fieldKey = f.targetModule + "." + f.fieldName;
const isChecked = fieldCheckStates[fieldKey] === true;
return {isChecked} ;
})}
,
null,
),
};
});
`;
const { diagnostics } = await validateSource(source, {
mode: "error",
types: COMMONFABRIC_TYPES,
});
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
const computationDiagnostics = diagnostics.filter((diagnostic) =>
diagnostic.type === "pattern-context:computation"
);
assertEquals(computationDiagnostics.length, 0);
assertStringIncludes(output, ".mapWithPattern(");
assertStringIncludes(output, "=> fieldCheckStates[fieldKey] === true");
assert(
!output.includes(
"const isChecked = fieldCheckStates[fieldKey] === true;",
),
);
},
);
Deno.test(
"Pipeline regression: self-improving classifier examples map keeps examples capture",
async () => {
const source = await Deno.readTextFile(
new URL("../../patterns/self-improving-classifier.tsx", import.meta.url),
);
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assert(
output.includes("{examples.mapWithPattern("),
"expected transformed examples.mapWithPattern call site",
);
// CT-1655: the whole `pattern(...)` call for this map is hoisted to a
// module-scope `const __cfPattern_N = __cfHelpers.pattern(...)`, so the
// callback (and its `__cf_pattern_input.key("params", …)` prologue) now
// lives at module scope, ABOVE the `examples.mapWithPattern(__cfPattern_N,
// …)` call site rather than inline at it. The property this test guards is
// unchanged: the examples capture's params-keyed prologue survives the
// pipeline. Assert against the whole output (the prologue lines are unique
// to this map's callback).
assertStringIncludes(
output,
'const selectedExampleId = __cf_pattern_input.key("params", "selectedExampleId");',
);
assertStringIncludes(
output,
'const currentItem = __cf_pattern_input.key("params", "currentItem");',
);
assertStringIncludes(
output,
'const examples = __cf_pattern_input.key("params", "examples");',
);
},
);
Deno.test(
"Pipeline regression: shopping-list sorted ifElse branch does not wrap mapped results in derive",
async () => {
const source = await Deno.readTextFile(
new URL("../../patterns/shopping-list.tsx", import.meta.url),
);
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, "itemsWithAisles.mapWithPattern(");
assert(
!output.includes(
'required: ["itemsWithAisles", "items", "correctionIndex", "correctionTitle", "hasConnectedStore"]',
),
"expected shopping-list sorted branch to stay pattern-lowered instead of wrapping the whole branch in derive",
);
},
);
Deno.test(
"Pipeline regression: imported pattern factory calls with local cells stay structural",
async () => {
const source =
`import { Writable, pattern, type PatternFactory } from "commonfabric";
declare const Child: PatternFactory<{ value: number }, { value: number }>;
export default pattern(() => {
const value = Writable.of(1);
const child = Child({ value });
return {
childValue: child.key("value"),
};
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, "const child = Child({ value });");
assertStringIncludes(output, 'childValue: child.key("value")');
assert(
!/__cfHelpers\.derive\([\s\S]{0,240}Child\(\{ value \}\)\)/.test(output),
"expected pattern factory invocation to stay structural instead of being wrapped in derive",
);
},
);
Deno.test(
"Pipeline regression: mapped pattern factory calls with element fields stay structural",
async () => {
const source = `import { UI, pattern, type VNode } from "commonfabric";
type Entry = {
piece: any;
name: string;
backlinks: any[];
};
const EntryRow = pattern(({ piece, backlinks }) => ({
[UI]: {piece}{backlinks.length}
,
}));
export default pattern<{ entries: Entry[] }, { [UI]: VNode }>(({ entries }) => ({
[UI]: (
{entries.map((entry) => {
const row = EntryRow({
piece: entry.piece,
name: entry.name,
backlinks: entry.backlinks,
});
return row[UI];
})}
),
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, "const row = EntryRow({");
assertStringIncludes(output, 'piece: entry.key("piece")');
assertStringIncludes(output, 'name: entry.key("name")');
assertStringIncludes(output, 'backlinks: entry.key("backlinks")');
// CT-1586: row[UI] must lower to row.key(__cfHelpers.UI) in-place,
// never to a derive wrapper around the [UI] element access. This is
// the exact ticket repro — without the assertion below, the bug
// (derive(..., ({row}) => row[__cfHelpers.UI])) would have passed the
// outer "stays structural" check above unnoticed.
assertStringIncludes(output, "row.key(__cfHelpers.UI)");
assert(
!/__cfHelpers\.derive\([\s\S]{0,500}EntryRow: EntryRow[\s\S]{0,500}EntryRow\(\{/
.test(
output,
),
"expected mapped pattern factory invocation to stay structural instead of being wrapped in derive",
);
},
);
Deno.test(
"Pipeline regression: plain callables that lack pattern-factory shape are not classified as opaque-origin calls (CT-1586 boundary)",
async () => {
// CT-1586 extended `isOpaqueOriginCall` to recognize structural pattern
// factories via `isPatternFactoryCalleeExpression`, which requires the
// callee type to expose both `argumentSchema` and `resultSchema`
// properties (and NOT `with`). A plain user-authored helper that
// returns a regular value should NOT trip the new gate.
//
// The call itself must therefore be wrapped in derive(...) when used
// inside a reactive context — that's the pre-existing behavior for
// non-opaque-origin calls. If `isPatternFactoryCalleeExpression`
// started false-positively matching plain helpers (e.g. due to type
// widening), we'd see the plainHelper call land structurally instead
// of being derive-wrapped. This test locks in the boundary.
const source = `import { pattern, UI, type VNode } from "commonfabric";
interface Entry { piece: string }
function plainHelper(input: { piece: string }): { rendered: string; [UI]: string } {
return { rendered: input.piece, [UI]: input.piece };
}
export default pattern<{ entries: Entry[] }, { [UI]: VNode }>(({ entries }) => ({
[UI]: (
{entries.map((entry) => {
const row = plainHelper({ piece: entry.piece });
return row[UI];
})}
),
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// The plain helper call is preserved.
assertStringIncludes(output, "plainHelper(");
// Because plainHelper is NOT classified as opaque-origin, the call
// result must be derive-wrapped — the call should appear inside a
// synthetic compute callback's body. The arrow `({ entry }) =>
// plainHelper(...)` is the tell. If isPatternFactoryCalleeExpression
// matched it, the call would land structurally as `const row =
// plainHelper(...)` with no surrounding derive.
assertStringIncludes(output, "}) => plainHelper(");
assert(
!/const row = plainHelper\(/.test(output),
"expected plainHelper call to be wrapped in derive(...) — non-opaque-origin calls must NOT be treated as pattern factories",
);
},
);
Deno.test(
"Pipeline regression: dynamic key access on pattern-factory result still wraps in derive (CT-1586 boundary)",
async () => {
// After CT-1586, well-known CF computed keys (UI/NAME/SELF/FS) lower
// to `.key()` in-place even when the access lives inside a JSX slot.
// But genuinely-dynamic key access — where the argument resolves to a
// value that isn't a static path segment — must STILL go through the
// dynamic-wrap (derive) path. The reorder in pattern-body-reactive-
// root-lowering is gated on `info?.root && !info.dynamic`; this test
// exercises the `info.dynamic === true` branch to lock in that
// boundary.
const source = `import { pattern, UI, type VNode } from "commonfabric";
type Entry = { piece: string; fieldName: string };
type Row = Record & { [UI]: VNode };
const EntryRow = pattern(({ piece }) => ({
[UI]: {piece} ,
body: piece,
}));
export default pattern<{ entries: Entry[] }, { [UI]: VNode }>(({ entries }) => ({
[UI]: (
{entries.map((entry) => {
const row = EntryRow({ piece: entry.piece, fieldName: entry.fieldName });
// Dynamic key — entry.fieldName is a reactive string, not a known
// static path segment.
return row[entry.fieldName.toString()];
})}
),
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// The pattern-factory call itself still stays structural.
assertStringIncludes(output, "const row = EntryRow({");
// The dynamic access should NOT have lowered to `.key()` — `.key()` is
// only valid for known-static path segments. The dynamic-wrap path
// is responsible for this case.
assert(
!/row\.key\(entry\./.test(output),
"expected dynamic key access not to lower to row.key(...)",
);
},
);
Deno.test(
"Pipeline regression: module-scope sub-pattern calls in maps stay structural",
async () => {
const source = `import { pattern, UI, type VNode } from "commonfabric";
type Entry = { value: number };
const EntryRow = pattern(({ value }) => ({
[UI]: {value} ,
}));
export default pattern<{ entries: Entry[] }, { [UI]: VNode }>(({ entries }) => ({
[UI]: (
{entries.map((entry) => {
const row = EntryRow({ value: entry.value });
return row[UI];
})}
),
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, "const row = EntryRow({");
assert(
!output.includes("EntryRow: EntryRow"),
"expected module-scope pattern factory to stay in lexical scope instead of being captured as derive data",
);
},
);
Deno.test(
"Pipeline regression: opaque-returning factory helpers with local cells stay structural",
async () => {
const source = `import { pattern, Writable } from "commonfabric";
function createAuthManager(input: { accountType: string }) {
return pattern<{ accountType: string }, {
auth: { email: string };
fullUI: string;
}>(({ accountType }) => ({
auth: { email: accountType },
fullUI: accountType,
}))(input);
}
export default pattern(() => {
const selectedAccountType = Writable.of("default");
const authManager = createAuthManager({
accountType: selectedAccountType,
});
return {
auth: authManager.key("auth"),
ui: authManager.key("fullUI"),
};
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, "const authManager = createAuthManager({");
assertStringIncludes(output, "accountType: selectedAccountType,");
assert(
!/__ctHelpers\.derive\([\s\S]{0,280}createAuthManager\(\{[\s\S]{0,120}accountType: selectedAccountType[\s\S]{0,120}\}\)\)/
.test(
output,
),
"expected opaque-returning factory helper to stay structural instead of being wrapped in derive",
);
},
);
Deno.test(
"Pipeline regression: computed callbacks that rely on contextual typing still receive injected schemas",
async () => {
const source = `import { computed, pattern } from "commonfabric";
const summarize = (values: string[]) => values.length;
export default pattern<{ values: string[] }>(({ values }) => {
const result = computed(() => summarize(values.get()));
return { result };
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
const normalized = output.replace(/\s+/g, " ");
// computed(() => summarize(values.get())) closure-extracts `values` and
// lowers to a hoisted lift; after CT-1644 Phase 2 the call site applies
// the hoisted const: const result = __cfLift_N({ values: values }).for(...)
assertMatch(
normalized,
/const result = __cfLift_\d+\(\{ values: values \}\)\.for\("result", true\);/,
);
},
);
Deno.test(
"Pipeline regression: local concise ternary event handlers stay function-valued",
async () => {
const source =
`import { computed, handler, pattern, UI, Writable } from "commonfabric";
interface Item {
id: string;
}
interface Vote {
itemId: string;
vote: "yes" | "no";
}
const castVote = handler<{ itemId: string; vote: "yes" }, { votes: Writable }>(
(event, { votes }) => {
votes.push(event);
},
);
const clearVote = handler<{ itemId: string }, {}>(() => {});
export default pattern<{ items: Writable- ; votes: Writable
}>(
({ items, votes }) => {
const boundCastVote = castVote({ votes });
const boundClearVote = clearVote({});
return {
[UI]: (
{items.map((item) => {
const iid = item.id;
const myVote = computed(() =>
votes.get().find((vote) => vote.itemId === iid)?.vote
);
const onVoteYes = () =>
myVote === "yes"
? boundClearVote.send({ itemId: iid })
: boundCastVote.send({ itemId: iid, vote: "yes" });
return yes ;
})}
),
};
},
);
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assertStringIncludes(output, 'const onVoteYes = () => myVote === "yes"');
assertStringIncludes(output, "boundClearVote.send({ itemId: iid })");
assertStringIncludes(
output,
'boundCastVote.send({ itemId: iid, vote: "yes" })',
);
// After CT-1644 Phase 2 a genuinely reactive computed lowers to a hoisted
// lift whose call site is `const onVoteYes = __cfLift_N(...)`. The local
// event handler must stay a plain arrow, so no such hoisted application is
// assigned to onVoteYes.
assert(
!output.includes("const onVoteYes = __cfHelpers.lift(") &&
!/const onVoteYes = __cfLift_\d+\(/.test(output),
"local event handler variable must not become a reactive cell containing a function",
);
assert(
!output.includes("=> () => __cfHelpers.ifElse("),
"local event handler body must keep imperative ternary semantics",
);
},
);
Deno.test(
"Pipeline regression: helper-owned IIFE local cell reads lower before use",
async () => {
const source = `import { pattern, UI, Writable } from "commonfabric";
export default pattern<{ enabled: Writable }>(({ enabled }) => ({
[UI]: {(() => {
const raw = enabled.get();
return typeof raw === "boolean" ? raw : true;
})()}
,
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
assert(
!output.includes("const raw = enabled.get();"),
"expected the eager cell read to be lowered into a derive before the IIFE body uses it",
);
assertStringIncludes(output, "({ enabled }) => enabled.get()");
},
);
Deno.test(
"Pipeline regression: nullable computed capture keeps source array schema array-shaped",
async () => {
const source = `import { computed, pattern, UI } from "commonfabric";
interface Option {
title: string;
ignored: string;
}
export default pattern<{ options: Option[] }, { [UI]: any }>(({ options }) => {
const minimalNullable = computed(() =>
options.length > 0 ? options[0].title : null
);
return {
[UI]: (
{computed(() => {
const value = minimalNullable;
return {value ?? "null"} ;
})}
),
};
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// computed(() => options.length > 0 ? options[0].title : null) closure-
// extracts `options` and lowers to a hoisted lift. After CT-1644 Phase 2
// the schema-bearing decl lives at `const __cfLift_N = __cfHelpers.lift(`
// and the call site is `const minimalNullable = __cfLift_N({ options })`.
const minimalNullableSite = output.match(
/const minimalNullable = (__cfLift_\d+)\(/,
);
assert(
minimalNullableSite !== null,
"expected transformed minimalNullable lift-applied call",
);
const minimalNullableLiftId = minimalNullableSite[1];
const minimalNullableStart = output.indexOf(
`const ${minimalNullableLiftId} = __cfHelpers.lift`,
);
assert(
minimalNullableStart >= 0,
"expected hoisted minimalNullable lift declaration",
);
const minimalNullableWindow = output.slice(
minimalNullableStart,
minimalNullableStart + 1200,
);
assertStringIncludes(minimalNullableWindow, 'type: "array"');
assertStringIncludes(minimalNullableWindow, "items:");
assertStringIncludes(minimalNullableWindow, "title:");
assertStringIncludes(minimalNullableWindow, 'type: "null"');
assert(
!minimalNullableWindow.includes('properties: {\n "0"'),
"expected the derive input schema to stay array-shaped, not shrink to an object with numeric keys",
);
assert(
!minimalNullableWindow.includes('required: ["length", "0"]'),
"expected the derive input schema not to require object-style array members",
);
},
);
Deno.test(
"Pipeline regression: computed captures preserve destructured PerUser defaults",
async () => {
const source =
`import { computed, Default, NAME, pattern, type PerSpace, type PerUser, UI, type VNode } from "commonfabric";
const trimmedName = (name: string | undefined) => (name ?? "").trim();
interface Input {
question?: PerSpace>;
myName?: PerUser>;
}
export default pattern (({ question, ["myName"]: displayName }) => ({
[NAME]: "ct-1606",
[UI]: (
{question}
{computed(() => {
const value = trimmedName(displayName);
return
me is: "{value}"
;
})}
body renders
),
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// After CT-1644 Phase 2, computed() lowers to a hoisted lift:
// const __cfLift_N = __cfHelpers.lift({argSchema}, {resSchema}, cb);
// The hoisted decl carries the capture's input schema; it is the first
// __cfHelpers.lift( occurrence in the module.
// Hoisted lift may carry generic type args (`lift(`) or not
// (`lift(`); match the helper-call head either way.
const liftMatch = output.match(/__cfHelpers\.lift(?:<[\s\S]*?>)?\(/);
assert(
liftMatch && liftMatch.index !== undefined,
"expected computed() to lower to a hoisted lift; output had no __cfHelpers.lift(",
);
const liftWindow = output.slice(liftMatch.index, liftMatch.index + 1200);
// Capture-input properties appear in the hoisted lift's argument schema.
assertStringIncludes(liftWindow, "displayName: {");
assertStringIncludes(liftWindow, 'type: "string"');
assertStringIncludes(liftWindow, '"default": ""');
assertStringIncludes(liftWindow, 'scope: "user"');
},
);
Deno.test(
"Pipeline regression: computed captures preserve destructured Writable defaults",
async () => {
const source =
`import { computed, Default, NAME, pattern, UI, type VNode, type Writable } from "commonfabric";
interface Input {
draftTitle: Writable>;
}
export default pattern (({ draftTitle }) => ({
[NAME]: "writable-default-capture",
[UI]: {computed(() => {draftTitle} )}
,
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// After CT-1644 Phase 2, computed() lowers to a hoisted lift whose decl is
// the first __cfHelpers.lift( occurrence in the module.
// Hoisted lift may carry generic type args (`lift(`) or not
// (`lift(`); match the helper-call head either way.
const liftMatch = output.match(/__cfHelpers\.lift(?:<[\s\S]*?>)?\(/);
assert(
liftMatch && liftMatch.index !== undefined,
"expected computed() to lower to a hoisted lift; output had no __cfHelpers.lift(",
);
const liftWindow = output.slice(liftMatch.index, liftMatch.index + 1200);
assertStringIncludes(liftWindow, "draftTitle: {");
assertStringIncludes(liftWindow, 'type: "string"');
assertStringIncludes(liftWindow, '"default": ""');
assertStringIncludes(liftWindow, "asCell:");
},
);
Deno.test(
"Pipeline regression: computed captures preserve Writable Record defaults without orphan refs",
async () => {
const source =
`import { computed, Default, NAME, pattern, UI, type VNode, type Writable } from "commonfabric";
interface Input {
selections: Writable | Default>>;
}
export default pattern (({ selections }) => ({
[NAME]: "writable-record-default-capture",
[UI]: {computed(() => selections.foo ? "yes" : "no")}
,
}));
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// After CT-1644 Phase 2, computed() lowers to a hoisted lift whose decl is
// the first __cfHelpers.lift( occurrence in the module.
// Hoisted lift may carry generic type args (`lift(`) or not
// (`lift(`); match the helper-call head either way.
const liftMatch = output.match(/__cfHelpers\.lift(?:<[\s\S]*?>)?\(/);
assert(
liftMatch && liftMatch.index !== undefined,
"expected computed() to lower to a hoisted lift; output had no __cfHelpers.lift(",
);
const liftWindow = output.slice(liftMatch.index, liftMatch.index + 1400);
assertStringIncludes(liftWindow, "selections:");
assert(
!liftWindow.includes("AnonymousType_"),
"expected Writable> capture not to emit orphan anonymous refs",
);
},
);
Deno.test(
"Pipeline regression: side-writing computed marks writable inputs for materialization",
async () => {
const source =
`import { computed, pattern, type Writable } from "commonfabric";
interface Input {
departments: Writable;
}
export default pattern (({ departments }) => {
const init = computed(() => {
if (departments.get().length === 0) departments.set(["Bakery"]);
return true;
});
return { init };
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// After CT-1644 Phase 2 the materializer options live in the hoisted
// decl `const __cfLift_N = __cfHelpers.lift(...)`; the call site is
// `const init = __cfLift_N(...)`.
const initSite = output.match(/const init = (__cfLift_\d+)\(/);
assert(
initSite !== null,
"expected computed() to lower to a hoisted lift call site for init",
);
const initStart = output.indexOf(
`const ${initSite[1]} = __cfHelpers.lift`,
);
assert(initStart >= 0, "expected hoisted lift declaration for init");
const liftWindow = output.slice(initStart, initStart + 1400);
assertStringIncludes(liftWindow, "materializerWriteInputPaths");
assertStringIncludes(liftWindow, '["departments"]');
},
);
Deno.test(
"Pipeline regression: readonly computed does not mark writable-looking inputs for materialization",
async () => {
const source =
`import { computed, pattern, type Writable } from "commonfabric";
interface Input {
departments: Writable;
}
export default pattern (({ departments }) => {
const count = computed(() => departments.get().length);
return { count };
});
`;
const output = await transformSource(source, {
types: COMMONFABRIC_TYPES,
});
// After CT-1644 Phase 2 the schema/options live in the hoisted decl
// `const __cfLift_N = __cfHelpers.lift(...)`; the call site is
// `const count = __cfLift_N(...)`.
const countSite = output.match(/const count = (__cfLift_\d+)\(/);
assert(
countSite !== null,
"expected computed() to lower to a hoisted lift call site for count",
);
const countStart = output.indexOf(
`const ${countSite[1]} = __cfHelpers.lift`,
);
assert(countStart >= 0, "expected hoisted lift declaration for count");
const liftWindow = output.slice(countStart, countStart + 1200);
assert(
!liftWindow.includes("materializerWriteInputPaths"),
"readonly computed() should remain a normal pull computation",
);
},
);