Skip to content

Commit 641e300

Browse files
Racer Engineerfacebook-github-bot
authored andcommitted
Guard against measuring detached views in SurfaceMountingManager.updateLayout
Summary: ## Summary: Catch `IllegalStateException` from `viewToUpdate.measure()` in `SurfaceMountingManager.updateLayout()` instead of skipping the entire layout update. This fixes a crash where Jetpack Compose's `onMeasure` throws when a `ComposeView` is detached from the window hierarchy, while ensuring `layout()`, visibility, and parent `requestLayout()` still execute normally. **Root cause:** RN Fabric dispatches layout updates via Choreographer. If a `ComposeView` was detached, its `onMeasure` attempts to access `windowRecomposer`, throwing `IllegalStateException`. **Previous approach (D99770236v1):** Used `isAttachedToWindow` guard to skip the entire method. This caused an E2E test regression — views created during Fabric's batch mount could receive layout updates before being attached, leaving them with zero dimensions. **New approach:** Wrap only the `measure()` call in a try-catch for `IllegalStateException`, logging via `ReactSoftExceptionLogger`. The `layout()` call and all other state updates proceed normally, preserving correct view dimensions for all views. Related: T263517828 (original crash task), D97087668 (similar guard in `updateProps`) --- ## Instructions about RACER Diffs: **Commandeer this diff (recommended) or land with accept2ship tag.** **This diff was generated by Racer AI agent on behalf of [William Khoe](https://www.internalfb.com/profile/view/3409840) for T263534248. If the diff quality is poor, consider contacting the user to provide clearer instructions on the task.** - If you are happy with the changes, commandeer it if minor edits are needed. (**we encourage commandeer to get the diff credit**) - If you are not happy with the changes, please comment on the diff with clear actions and send it back to the author. Racer will pick it up and re-generate. - If you really feel the Racer is not helping with this change (alas, some complex changes are hard for AI) feel free to abandon this diff. - **For M10N reviewers:** as you review AI-generated diffs, we ask you to give them the same priority as human-generated diffs, and take action in a timely manner by either accepting, rejecting, or resigning as a reviewer. For diffs that don't meet the quality bar (e.g. code doesn't compile, not readable or introduces functionality regressions), we ask that you use the following hashtags to provide clear signals to improve our tools - `#monlowqualitydiff` `#monwrongreviewerdiff` --- > Generated by [RACER](https://www.internalfb.com/wiki/RACER_(Risk-Aware_Code_Editing_and_Refactoring)/), powered by [Confucius](https://www.internalfb.com/wiki/Confucius/Analect/Shared_Analects/Confucius_Code_Assist_(CCA)/) [Session](https://www.internalfb.com/confucius?session_id=634a2946-3236-11f1-9c44-99a80a63f54d&tab=Chat), [Trace](https://www.internalfb.com/confucius?session_id=634a2946-3236-11f1-9c44-99a80a63f54d&tab=Trace) Reviewed By: cortinico Differential Revision: D99770236
1 parent 7ee893d commit 641e300

1 file changed

Lines changed: 14 additions & 4 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -779,10 +779,20 @@ internal constructor(
779779
// because of caching and calculation that may occur in onMeasure and onLayout. Layout
780780
// operations should also follow the native view hierarchy and go top to bottom for
781781
// consistency with standard layout passes (some views may depend on this).
782-
viewToUpdate.measure(
783-
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
784-
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY),
785-
)
782+
try {
783+
viewToUpdate.measure(
784+
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
785+
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY),
786+
)
787+
} catch (e: IllegalStateException) {
788+
ReactSoftExceptionLogger.logSoftException(
789+
TAG,
790+
ReactNoCrashSoftException(
791+
"measure() threw IllegalStateException for tag $reactTag (view not attached to window)",
792+
e,
793+
),
794+
)
795+
}
786796

787797
// We update the layout of the RootView when there is a change in the layout of its child. This
788798
// is required to re-measure the size of the native View container (usually a FrameLayout) that

0 commit comments

Comments
 (0)