Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/pointers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ itself are tracked in the root [`CHANGELOG.md`](../../CHANGELOG.md).

## Unreleased

### Fixed

- `dereference` composes the `yields` renames of nested template references.
A region now takes the rename of each enclosing reference, innermost first,
where only the innermost rename used to apply.

## 0.1.0-preview.0 — 2026-09-21

The version scheme changed: prerelease versions are now `preview.<n>`, and
Expand Down
15 changes: 9 additions & 6 deletions packages/pointers/src/dereference/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,15 @@ export async function* generateRegions(
while (!result.done) {
let region = result.value;

// Apply rename if in context and region has a name in mapping
const currentMapping = renameStack[renameStack.length - 1];
if (currentMapping && region.name) {
const newName = currentMapping[region.name];
if (newName && newName !== region.name) {
region = { ...region, name: newName };
// Apply every active rename, innermost template first, so that
// nested yields compose
if (region.name) {
const name = renameStack.reduceRight(
(name, mapping) => mapping[name] ?? name,
region.name,
);
if (name !== region.name) {
region = { ...region, name };
}
}

Expand Down
30 changes: 30 additions & 0 deletions packages/pointers/src/dereference/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,36 @@ describe("dereference", () => {
expect(regions.named("outer-data")).toHaveLength(2);
});

it("composes yields renames across nested template references", async () => {
const templates: Pointer.Templates = {
leaf: {
expect: ["slot"],
for: { name: "data", location: "storage", slot: "slot" },
},
middle: {
expect: ["slot"],
for: {
template: "leaf",
yields: { data: "name-data" },
},
},
};

const pointer: Pointer = {
define: { slot: 10 },
in: {
template: "middle",
yields: { "name-data": "value-name-data" },
},
};

const cursor = await dereference(pointer, { templates });
const { regions } = await cursor.view(state);

expect(regions).toHaveLength(1);
expect(regions[0].name).toEqual("value-name-data");
});

it("works for inline template definitions", async () => {
const pointer: Pointer = {
templates: {
Expand Down
Loading