fix(runtime-tags): serialize sourceless spread bindings in stateful intersections - #3752
fix(runtime-tags): serialize sourceless spread bindings in stateful intersections#3752rturnq wants to merge 3 commits into
Conversation
…ntersections A binding spread onto a native tag is marked noSerialize since its value is normally baked into the HTML. When that binding intersects with stateful spread attrs, the intersection re-runs client side and reads the value from scope — but a sourceless binding (e.g. a static tag return) has no client signal to recompute it, so its attrs were dropped on update. Clear noSerialize for such bindings so their value resumes.
🦋 Changeset detectedLatest commit: ff30265 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3752 +/- ##
=======================================
Coverage 90.35% 90.35%
=======================================
Files 423 423
Lines 19785 19793 +8
Branches 3635 3638 +3
=======================================
+ Hits 17876 17884 +8
Misses 1367 1367
Partials 542 542 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe translator preserves sourceless intersection binding values by assigning a serialized-value reason and honoring that reason during binding serialization. New runtime-tag fixtures combine static and dynamic spreads on a native button, verify updates across three clicks, and record output sizes. A changeset documents the hydration fix and patch release. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…sources Instead of unconditionally clearing noSerialize for sourceless bindings in an intersection, key their value serialization to the partner's sources. State-backed partners still serialize unconditionally, while input-backed partners emit a runtime guard so the value only serializes when the caller actually passes stateful input.
Description
A binding spread onto a native tag is marked
noSerializesince its attribute values are normally baked into the server-rendered HTML. When that binding participates in an intersection with stateful spread attrs, the intersection re-runs client side and reads the value from scope — but a sourceless binding (e.g. the return value of a non-stateful child tag) has no client signal to recompute it, so on the first update its attributes were dropped:Clicking the button removed
class="foo", because the intersection pass inreferences.tsadded a serialize reason forstaticAttrsbutwriteSerializedBindingskipped the value due tonoSerialize. Referencing the binding elsewhere (e.g.<log=staticAttrs>) masked the bug by making it no longer a pure spread.The fix registers a separate value-serialize reason (
kSerializedValueReason) for sourcelessnoSerializebindings in an intersection, keyed to the partner's sources.writeSerializedBindingconsults it when it would otherwise skip the value:<const/extra={ id: "x" }/>+<div ...input ...extra />innative-tag-spread-content-multi) → the value serializes behind the existing runtime serialize guard (_serialize_if(...) && extra), so callers that pass only static input pay nothing. That fixture's snapshot change reflects this — it was a latent instance of the same bug, and its serialized HTML actually shrinks for its static caller.Checklist: