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
This commit is contained in:
Joshua Gross
2019-10-27 23:11:31 -07:00
committed by Facebook Github Bot
parent bdaab3c2e5
commit aa27645cf0
2 changed files with 31 additions and 9 deletions
@@ -393,7 +393,9 @@ public class UIManagerModule extends ReactContextBaseJavaModule
if (uiManagerType == FABRIC) {
UIManager fabricUIManager =
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
if (fabricUIManager != null) {
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
}
} else {
mUIImplementation.synchronouslyUpdateViewOnUIThread(tag, new ReactStylesDiffMap(props));
}
@@ -478,7 +480,9 @@ public class UIManagerModule extends ReactContextBaseJavaModule
if (uiManagerType == FABRIC) {
UIManager fabricUIManager =
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
if (fabricUIManager != null) {
fabricUIManager.synchronouslyUpdateViewOnUIThread(tag, props);
}
} else {
mUIImplementation.updateView(tag, className, props);
}
@@ -668,14 +672,20 @@ public class UIManagerModule extends ReactContextBaseJavaModule
// the dispatchViewManagerCommand() method is supported by Fabric JS API.
if (commandId.getType() == ReadableType.Number) {
final int commandIdNum = commandId.asInt();
UIManagerHelper.getUIManager(
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag))
.dispatchCommand(reactTag, commandIdNum, commandArgs);
UIManager uiManager =
UIManagerHelper.getUIManager(
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag));
if (uiManager != null) {
uiManager.dispatchCommand(reactTag, commandIdNum, commandArgs);
}
} else if (commandId.getType() == ReadableType.String) {
final String commandIdStr = commandId.asString();
UIManagerHelper.getUIManager(
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag))
.dispatchCommand(reactTag, commandIdStr, commandArgs);
UIManager uiManager =
UIManagerHelper.getUIManager(
getReactApplicationContext(), ViewUtil.getUIManagerType(reactTag));
if (uiManager != null) {
uiManager.dispatchCommand(reactTag, commandIdStr, commandArgs);
}
}
}
@@ -801,7 +811,9 @@ public class UIManagerModule extends ReactContextBaseJavaModule
if (uiManagerType == FABRIC) {
UIManager fabricUIManager =
UIManagerHelper.getUIManager(getReactApplicationContext(), uiManagerType);
fabricUIManager.sendAccessibilityEvent(tag, eventType);
if (fabricUIManager != null) {
fabricUIManager.sendAccessibilityEvent(tag, eventType);
}
} else {
mUIImplementation.sendAccessibilityEvent(tag, eventType);
}