Skip to content

fix(solid_generator): qualify cross-file registry entries by origin library - #111

Merged
nank1ro merged 2 commits into
mainfrom
fix/library-qualified-registry
Aug 26, 2026
Merged

nank1ro merged 2 commits into
mainfrom
fix/library-qualified-registry

Conversation

@nank1ro

@nank1ro nank1ro commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Closes #110. Extends the unreleased 3.0.0-dev.5 (no version bump — tag after merge, per plan).

Problem

The cross-file registry is keyed by simple class name, so a local plain Foo and a foreign @SolidState-bearing Foo were mutually exclusive: registering the foreign one wrongly rewrote the local class (caught in #109's review), and blocking registration — the shipped trade-off — silently lost the genuinely reactive foreign read.

Fix

  • Entries under a shadowed or multi-origin name are recorded qualified by origin library (name → originUri → fields side-maps). The flat registry is stripped for flagged names, so every other consumer sees byte-identical behavior for the unflagged common case.
  • The value rewriter resolves a flagged name only when the receiver's tier-1 resolved staticType library matches a recorded origin (asset:<pkg>/source/... normalized to the registry's package:<pkg>/... — verified against package:build's AssetId internals, and it's the build convention build.yaml mandates for every consumer, not a repo-local accident).
  • Conservative invariant: AST-only receivers (tiers 2–4 carry no library) never rewrite an ambiguous name — the change can only add rewrites proven by real resolution, never introduce a wrong one. Pinned by a red/green-by-construction unit test.

Review guide

Artifact Proves
cross_file_qualified_registry_disambiguation (new) two distinct @SolidState Foos in different files, consumed in one file — each read lowers against its own class (reviewer-probed at N=3 too)
cross_file_super_param_one_hop_local_shadow (updated) the #109 trade-off resolved: thing.label (foreign, reactive) now lowers; f.label (local, plain) stays untouched
cross_file_local_shadowing_decoy (comment-only) output byte-identical — but the mechanism verifiably moved from registration-blocking to tier-1 URI mismatch
value_rewriter_test.dart addition AST-only receiver + matching origin still refuses (cannot pass for the wrong reason)

Deliberate side-effect (changelogged): dispose auto-injection no longer recognizes a 2+-origin name as @Solid-annotated (previously it fired non-deterministically for whichever origin registered first) — pass dispose: explicitly for such same-named classes.

Verification

352/352 solid_generator tests (goldens + idempotency ×2), 11/11 integration, repo-root dart analyze --fatal-infos zero, format clean, 5 example apps zero-delta. Pre-release validation against fairtile via path overrides: byte-identical app output, the #108 bare-super.x probe lowers, and a live local-shadow probe (plain local AuthRepository beside the real reactive one) disambiguates correctly in the real app — tree left clean.

…ibrary

Closes #110. The name-keyed registry could not distinguish a local plain
class from a foreign @SolidState class sharing its simple name: blocking
registration protected the local class but silently lost the genuinely
reactive foreign read. Entries under a shadowed or multi-origin name are
now recorded qualified by origin library (side-maps; the flat registry is
stripped for flagged names so every other consumer is byte-identical for
the unflagged common case), and the value rewriter resolves flagged names
only when the receiver's tier-1 resolved staticType library matches a
recorded origin — asset:<pkg>/source URIs normalized to the registry's
package:<pkg> form. AST-only receivers never rewrite an ambiguous name,
so the change can only add rewrites proven by real resolution, never
introduce a wrong one. Two same-named @SolidState classes consumed in one
file each resolve through their own receiver; the one-hop local-shadow
fixture's foreign read now lowers while the local plain read stays
untouched. Deliberate side-effect (changelogged): dispose auto-injection
no longer recognizes a 2+-origin name as @Solid-annotated — pass dispose:
explicitly for such classes. Validated pre-release against the downstream
app via path overrides (byte-identical output + live shadow probe).
@nank1ro
nank1ro merged commit a0bdfff into main Aug 26, 2026
1 check passed
@nank1ro
nank1ro deleted the fix/library-qualified-registry branch August 26, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Name-keyed registry cannot disambiguate a local plain class from a foreign reactive class with the same name

1 participant