Skip to content

Analysis: Never call a constant an identity once the map travels - #2290

Merged
marcoroth merged 1 commit into
mainfrom
analysis/constant-identity
Aug 19, 2026
Merged

Analysis: Never call a constant an identity once the map travels#2290
marcoroth merged 1 commit into
mainfrom
analysis/constant-identity

Conversation

@marcoroth

Copy link
Copy Markdown
Owner

This pull request fixes a slot dependency map that told a client it could write a value the client has never been given.

SlotDependencies classifies each slot by where its next value comes from. identity means the slot's expression is the state itself, so a client writes it by copying what it already holds. Everything computed is derived, and only the server can answer it.

A constant is a dependency and not something a page can set, so it can never be an identity. for had that right and across did not, and across is the one whose answer is delivered:

subject.for(path)      #=> { 0 => { state: ["Post.count"], mode: :derived } }
subject.across(path)   #=> { "Post.count" => [{ …, mode: :identity }] }
subject.payload(path)  #=> { "state" => { "Post.count" => [{ "mode" => "identity" }] } }

A partial's incoming locals are not among the names it declares, so #2281 treats the names the trace carries as settable, which is what lets a partial answer in its caller's terms. Constants arrive through the same door and are settable by nothing, so the exclusion for applies was lost on the way.

The map already leaves constants out of the request names it publishes, so payload["params"] is empty for a template whose only state is Post.count, and nothing resolves to it by the name a request would use. Reaching it takes calling state.set("Post.count", …) by the state's own name, through the escape hatch meant for state whose request name could not be derived.

`for` said a constant was derived and `across` said it was an identity, and
`across` is the one whose answer is delivered. A client reading that map is told
it can write `<%= Post.count %>` by copying a value it has never been given.

A partial's incoming locals are not among the names it declares, so the names
carried by the trace are treated as settable to make a partial answer in its
caller's terms. Constants arrive by the same door and are not settable by
anything, which is what `for` had right and `across` lost.

The map already left constants out of the request names, so nothing could reach
one by the name a request uses. That is what kept this from being reachable in
practice, and it is not the same as the map being right.
@marcoroth marcoroth added the reactivity Reactive ERB templates: diff and re-render only what changed label Aug 19, 2026
@github-actions github-actions Bot added ruby Ruby source for the gem and its libraries engine Herb engine and Rails template compilation rubygem The herb RubyGem and its packaging labels Aug 19, 2026
@nx-cloud

nx-cloud Bot commented Aug 19, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit faea43e

Command Status Duration Result
nx run-many -t test --all --parallel --exclude=... ✅ Succeeded 2m 55s View ↗
nx run-many -t build --all --exclude=herb-langu... ✅ Succeeded 33s View ↗
nx build @herb-tools/tailwind-class-sorter ✅ Succeeded 1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-19 00:58:11 UTC

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

🌿 Interactive Playground and Documentation Preview

A preview deployment has been built for this pull request. Try out the changes live in the interactive playground:


🌱 Grown from commit faea43e


✅ Preview deployment has been cleaned up.

@pkg-pr-new

pkg-pr-new Bot commented Aug 19, 2026

Copy link
Copy Markdown
npx https://pkg.pr.new/@herb-tools/formatter@2290
npx https://pkg.pr.new/@herb-tools/language-server@2290
npx https://pkg.pr.new/@herb-tools/linter@2290

commit: faea43e

@marcoroth
marcoroth merged commit 14eaf94 into main Aug 19, 2026
35 checks passed
@marcoroth
marcoroth deleted the analysis/constant-identity branch August 19, 2026 00:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engine Herb engine and Rails template compilation reactivity Reactive ERB templates: diff and re-render only what changed ruby Ruby source for the gem and its libraries rubygem The herb RubyGem and its packaging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant