Repository navigation
Fix Fabric reusing nodes with a stale font scale (#57246) - #57246
Closed
j-piasecki wants to merge 1 commit into
Closed
j-piasecki wants to merge 1 commit into
j-piasecki wants to merge 1 commit into
Conversation
|
@j-piasecki has imported this pull request. If you are a Meta employee, you can view this in D108877387. |
j-piasecki
force-pushed
the
@jpiasecki/dirty-yoga-cache-on-font-scale-change
branch
from
June 17, 2026 12:53
2454c01 to
bcabdf3
Compare
j-piasecki
added a commit
to j-piasecki/react-native
that referenced
this pull request
Jun 17, 2026
Summary: Fixes react#52895 The original solution to this issue approached this by comparing the font scale used to lay out respective root nodes and re-cloning measurable nodes in the entire tree when it was different. This didn't work when a node within the tree was cloned from a node with an obsolete font scale stored (with root having the correct one). The new node would use the obsolete value in that pass. This PR changes this approach - instead of comparing font scale in `SurfaceHandler::constraintLayout` (only when it changes), it moves the comparison to happen as part of `configureYogaTree`, similarly to `pointScaleFactor`. This way, nodes with an obsolete value stored get re-cloned using the correct one on each commit instead of only on the first one. ## Changelog: [GENERAL][FIXED] - Fixed Fabric reusing nodes with a stale font scale Test Plan: Issue reproducer ||Before|After| |-|-|-| |Android|<video src="https://github.com/user-attachments/assets/0b30ca95-76e9-4ce9-8d8f-418f9d827bea" />|<video src="https://github.com/user-attachments/assets/009be13c-c3b5-4af0-8be1-b44c94ac0496" />| |iOS|<video src="https://github.com/user-attachments/assets/b861b622-a2ea-4cc4-a8db-0e3ad4cae5e7" />|<video src="https://github.com/user-attachments/assets/ec4d6f6e-7558-4430-813b-61a6e911c3b0" />| Differential Revision: D108877387 Pulled By: j-piasecki
|
@j-piasecki has exported this pull request. If you are a Meta employee, you can view the originating Diff in D108877387. |
chrfalch
reviewed
Jun 17, 2026
Summary: Fixes react#52895 The original solution to this issue approached this by comparing the font scale used to lay out respective root nodes and re-cloning measurable nodes in the entire tree when it was different. This didn't work when a node within the tree was cloned from a node with an obsolete font scale stored (with root having the correct one). The new node would use the obsolete value in that pass. This PR changes this approach - instead of comparing font scale in `SurfaceHandler::constraintLayout` (only when it changes), it moves the comparison to happen as part of `configureYogaTree`, similarly to `pointScaleFactor`. This way, nodes with an obsolete value stored get re-cloned using the correct one on each commit instead of only on the first one. ## Changelog: [GENERAL][FIXED] - Fixed Fabric reusing nodes with a stale font scale Test Plan: Issue reproducer ||Before|After| |-|-|-| |Android|<video src="https://github.com/user-attachments/assets/0b30ca95-76e9-4ce9-8d8f-418f9d827bea" />|<video src="https://github.com/user-attachments/assets/009be13c-c3b5-4af0-8be1-b44c94ac0496" />| |iOS|<video src="https://github.com/user-attachments/assets/b861b622-a2ea-4cc4-a8db-0e3ad4cae5e7" />|<video src="https://github.com/user-attachments/assets/ec4d6f6e-7558-4430-813b-61a6e911c3b0" />| Reviewed By: javache Differential Revision: D108877387 Pulled By: j-piasecki
j-piasecki
force-pushed
the
@jpiasecki/dirty-yoga-cache-on-font-scale-change
branch
from
June 17, 2026 13:39
bcabdf3 to
c4d84b1
Compare
|
@j-piasecki merged this pull request in 45904c8. |
1 of 7 tasks
curiosity26
added a commit
to curiosity26/react-native-gtk4
that referenced
this pull request
Oct 11, 2026
…ive 0.83 0.83's SurfaceHandler dirties measurable nodes only in the commit where the font scale changes; later commits bring back React's nodes laid out at the old scale, and Yoga reuses their layout, so Text kept GNOME's 1.5x size after text scaling went back to 1.0. Upstream fixed it after 0.83 (react/react-native#57246: layouts record their font scale in LayoutMetrics::fontSizeMultiplier). FontScaleCommitHook does the same from a UIManager commit hook: once a surface's font scale has changed, each commit clones and dirties the measurable nodes that are laid out but weren't committed at the current scale (and the path to them). The host registers it on each instance's UIManager only where LayoutMetrics has no fontSizeMultiplier, so it's inert on 0.87. gallery-platform-self-test checks Text's height going back on 0.83 too, and docs/upgrading.md lists the fix instead of the limitation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
curiosity26
added a commit
to curiosity26/react-native-gtk4
that referenced
this pull request
Oct 11, 2026
…ive 0.83 0.83's SurfaceHandler dirties measurable nodes only in the commit where the font scale changes; later commits bring back React's nodes laid out at the old scale, and Yoga reuses their layout, so Text kept GNOME's 1.5x size after text scaling went back to 1.0. Upstream fixed it after 0.83 (react/react-native#57246: layouts record their font scale in LayoutMetrics::fontSizeMultiplier). FontScaleCommitHook does the same from a UIManager commit hook: once a surface's font scale has changed, each commit clones and dirties the measurable nodes that are laid out but weren't committed at the current scale (and the path to them). The host registers it on each instance's UIManager only where LayoutMetrics has no fontSizeMultiplier, so it's inert on 0.87. gallery-platform-self-test checks Text's height going back on 0.83 too, and docs/upgrading.md lists the fix instead of the limitation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit 77050bc)
rhoadsjustin
added a commit
to rhoadsjustin/meno
that referenced
this pull request
Oct 26, 2026
Changing the iOS text size while Meno was open left every label clipped until the next launch: the glyphs grew, but their frames kept the height measured at the old size. Root cause is in React Native 0.86's Fabric renderer, not in Meno. On a content-size change, SurfaceHandler re-measures text by cloning the text nodes on the native side. React never learns about those clones, so its next commit (a tab switch, any state update) puts back the nodes it holds. Those carry the old measurement, while state reconciliation hands them the new, larger attributed string. Measured on iPhone 17 (large to AX5, one tab switch later): 58 of 58 text frames across Today, Library, Stats and Settings were stale. Upstream fixed this in 0.87.0 (react/react-native#57246, issue #57512); the 0.86 backport is still an open pick request. The upstream fix is C++ and Meno uses the prebuilt React Native core, so a native backport would mean building React Native from source on every local and EAS build. Instead, a patch-package patch to Text.js counts font-scale changes (from Dimensions) and keys each root text element on the count. React then creates fresh native text nodes, measured at the current scale, once per change. Only the native text nodes are rebuilt: components and their state stay mounted, so a practice session carries on mid-round. After the patch the same run matches a cold launch at AX5 for all 58 text frames. TextInput and the SwiftUI hosts already re-measure on their own and are untouched. Drop the patch when Meno moves to React Native 0.87 or later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rhoadsjustin
added a commit
to rhoadsjustin/meno
that referenced
this pull request
Oct 26, 2026
Changing the iOS text size while Meno was open left every label clipped until the next launch: the glyphs grew, but their frames kept the height measured at the old size. Root cause is in React Native 0.86's Fabric renderer, not in Meno. On a content-size change, SurfaceHandler re-measures text by cloning the text nodes on the native side. React never learns about those clones, so its next commit (a tab switch, any state update) puts back the nodes it holds. Those carry the old measurement, while state reconciliation hands them the new, larger attributed string. Measured on iPhone 17 (large to AX5, one tab switch later): 58 of 58 text frames across Today, Library, Stats and Settings were stale. Upstream fixed this in 0.87.0 (react/react-native#57246, issue #57512); the 0.86 backport is still an open pick request. The upstream fix is C++ and Meno uses the prebuilt React Native core, so a native backport would mean building React Native from source on every local and EAS build. Instead, a patch-package patch to Text.js counts font-scale changes (from Dimensions) and keys each root text element on the count. React then creates fresh native text nodes, measured at the current scale, once per change. Only the native text nodes are rebuilt: components and their state stay mounted, so a practice session carries on mid-round. After the patch the same run matches a cold launch at AX5 for all 58 text frames. TextInput and the SwiftUI hosts already re-measure on their own and are untouched. Drop the patch when Meno moves to React Native 0.87 or later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary:
Fixes #52895
The original solution to this issue approached this by comparing the font scale used to lay out respective root nodes and re-cloning measurable nodes in the entire tree when it was different. This didn't work when a node within the tree was cloned from a node with an obsolete font scale stored (with root having the correct one). The new node would use the obsolete value in that pass.
This PR changes this approach - instead of comparing font scale in
SurfaceHandler::constraintLayout(only when it changes), it moves the comparison to happen as part ofconfigureYogaTree, similarly topointScaleFactor. This way, nodes with an obsolete value stored get re-cloned using the correct one on each commit instead of only on the first one.Changelog:
[GENERAL][FIXED] - Fixed Fabric reusing nodes with a stale font scale
Test Plan:
Issue reproducer
Screen.Recording.2026-06-10.at.11.18.28.mov
Screen.Recording.2026-06-10.at.11.15.46.mov
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-06-10.at.11.19.05.mov
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-06-10.at.11.16.37.mov
Reviewed By: javache
Differential Revision: D108877387
Pulled By: j-piasecki