Fix #5880: merge attributesThatAreSet delta on restore instead of replacing - #5881
Merged
Conversation
ComponentStateHelper.restoreState replaced the whole list-valued state with the saved delta. The delta is add-only, carrying only entries appended after markInitialState, so replacing dropped every entry the tag handlers re-registered during buildView. attributesThatAreSet lost those from the second postback on, so any pass-through attribute (styleClass, style, title, dir, lang, tabindex, on*) stopped rendering once a non-literal binding was set on the restored component, e.g. from a PostRestoreStateEvent listener. Merge the delta onto the rebuilt list instead, adding only entries not already present, matching the Map branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
|
Thanks for the fast fix! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5880.
ComponentStateHelper.restoreStatetreated a restoredListas a wholesale replacement: it discarded both the default and delta entries for the key, then re-added only the saved delta. But the delta list is add-only — it carries only entries appended aftermarkInitialState— so replacing dropped everything the tag handlers had just re-registered duringbuildView.For
attributesThatAreSetthis meant that once a non-literalsetValueExpression(name, ve)ran on a restored component (e.g. from aPostRestoreStateEventlistener), the poisoned delta wiped the pass-through attributes from the second postback onward. Any ofstyleClass,style,title,dir,lang,tabindexand theon*handlers stopped rendering and never recovered.styleClassbecame newly affected in 4.0.19/4.1.10 (#5753); the rest go back to #4269 (2021).Fix
Merge the restored delta onto the list
buildViewalready rebuilt this request, adding only entries not already present, matching theMapbranch directly above it — which already merges. TheListpath serves exactly two keys (attributesThatAreSetandUIViewRoot.phaseListeners), both add-only with no overlap between the rebuilt default and the saved delta, so merge-with-dedup is lossless.Test
UIComponentBaseTestCase#testAttributesThatAreSetMergeOnRestorereproduces the two-postback drop: a tag attribute registered pre-markInitialState, a non-literal binding added as the delta, saved, then restored onto a rebuilt list. Asserts the merged[styleClass, label]. Verified it fails against the old replace logic (expected <[styleClass, label]> but was <[label]>) and passes with the fix; fullUIComponentBaseTestCase(43 tests) green.🤖 Generated with Claude Code (Opus 4.8)