Skip to content

Commit aa27645

Browse files
JoshuaGrossfacebook-github-bot
authored andcommitted
Guard against UIManagerHelper.getUIManager returning null
Summary: Because the `mCatalystInstance` of the ReactContext can be null during teardown, there are technicaly cases where `UIManagerHelper.getUIManager` can return null. In those cases we check for a CatalystInstance and raise a SoftException, and return null. We must then guard in every case where we call `getUIManager` to prevent NullPointerExceptions. See T56103679. Currently crashes are coming from `PropsAnimatedNode.restoreDefaultValues` calling `UIManagerModule.synchronouslyUpdateViewOnUIThread` on teardown/at the end of an animation as RN is being torn down. This can happen in both Paper and Fabric. In dev this will still crash because the SoftException will trigger a crash. It will be a noop with logged warnings in production builds. Changelog: [Internal] Reviewed By: yungsters Differential Revision: D18165576 fbshipit-source-id: 7059e04ca339208dd64a0a08a375b565cb8cda02
1 parent bdaab3c commit aa27645

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java

+10
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,32 @@
1010
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
1111
import static com.facebook.react.uimanager.common.ViewUtil.getUIManagerType;
1212

13+
import androidx.annotation.Nullable;
1314
import com.facebook.react.bridge.CatalystInstance;
1415
import com.facebook.react.bridge.JSIModuleType;
1516
import com.facebook.react.bridge.ReactContext;
17+
import com.facebook.react.bridge.ReactSoftException;
1618
import com.facebook.react.bridge.UIManager;
1719
import com.facebook.react.uimanager.common.UIManagerType;
1820

1921
/** Helper class for {@link UIManager}. */
2022
public class UIManagerHelper {
2123

2224
/** @return a {@link UIManager} that can handle the react tag received by parameter. */
25+
@Nullable
2326
public static UIManager getUIManagerForReactTag(ReactContext context, int reactTag) {
2427
return getUIManager(context, getUIManagerType(reactTag));
2528
}
2629

2730
/** @return a {@link UIManager} that can handle the react tag received by parameter. */
31+
@Nullable
2832
public static UIManager getUIManager(ReactContext context, @UIManagerType int uiManagerType) {
33+
if (!context.hasActiveCatalystInstance()) {
34+
ReactSoftException.logSoftException(
35+
"UIManagerHelper",
36+
new RuntimeException("Cannot get UIManager: no active Catalyst instance"));
37+
return null;
38+
}
2939
CatalystInstance catalystInstance = context.getCatalystInstance();
3040
return uiManagerType == FABRIC
3141
? (UIManager) catalystInstance.getJSIModule(JSIModuleType.UIManager)

ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java

+21-9
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,9 @@ public void synchronouslyUpdateViewOnUIThread(int tag, ReadableMap props) {
393393
if (uiManagerType == FABRIC) {
394394
UIManager fabricUIManager =
395395
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
396-
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
396+
if (fabricUIManager != null) {
397+
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
398+
}
397399
} else {
398400
mUIImplementation.synchronouslyUpdateViewOnUIThread(tag, new ReactStylesDiffMap(props));
399401
}
@@ -478,7 +480,9 @@ public void updateView(int tag, String className, ReadableMap props) {
478480
if (uiManagerType == FABRIC) {
479481
UIManager fabricUIManager =
480482
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
481-
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
483+
if (fabricUIManager != null) {
484+
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
485+
}
482486
} else {
483487
mUIImplementation.updateView(tag, className, props);
484488
}
@@ -668,14 +672,20 @@ public void dispatchViewManagerCommand(
668672
// the dispatchViewManagerCommand() method is supported by Fabric JS API.
669673
if (commandId.getType() == ReadableType.Number) {
670674
final int commandIdNum = commandId.asInt();
671-
UIManagerHelper.getUIManager(
672-
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag))
673-
.dispatchCommand(reactTag, commandIdNum, commandArgs);
675+
UIManager uiManager =
676+
UIManagerHelper.getUIManager(
677+
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag));
678+
if (uiManager != null) {
679+
uiManager.dispatchCommand(reactTag, commandIdNum, commandArgs);
680+
}
674681
} else if (commandId.getType() == ReadableType.String) {
675682
final String commandIdStr = commandId.asString();
676-
UIManagerHelper.getUIManager(
677-
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag))
678-
.dispatchCommand(reactTag, commandIdStr, commandArgs);
683+
UIManager uiManager =
684+
UIManagerHelper.getUIManager(
685+
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag));
686+
if (uiManager != null) {
687+
uiManager.dispatchCommand(reactTag, commandIdStr, commandArgs);
688+
}
679689
}
680690
}
681691

@@ -801,7 +811,9 @@ public void sendAccessibilityEvent(int tag, int eventType) {
801811
if (uiManagerType == FABRIC) {
802812
UIManager fabricUIManager =
803813
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
804-
fabricUIManager.sendAccessibilityEvent(tag, eventType);
814+
if (fabricUIManager != null) {
815+
fabricUIManager.sendAccessibilityEvent(tag, eventType);
816+
}
805817
} else {
806818
mUIImplementation.sendAccessibilityEvent(tag, eventType);
807819
}

0 commit comments

Comments
 (0)