Skip to content

Commit

Permalink
Guard against UIManagerHelper.getUIManager returning null
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JoshuaGross authored and facebook-github-bot committed Oct 28, 2019
1 parent bdaab3c commit aa27645
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,32 @@
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
import static com.facebook.react.uimanager.common.ViewUtil.getUIManagerType;

import androidx.annotation.Nullable;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JSIModuleType;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactSoftException;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.uimanager.common.UIManagerType;

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

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

/** @return a {@link UIManager} that can handle the react tag received by parameter. */
@Nullable
public static UIManager getUIManager(ReactContext context, @UIManagerType int uiManagerType) {
if (!context.hasActiveCatalystInstance()) {
ReactSoftException.logSoftException(
"UIManagerHelper",
new RuntimeException("Cannot get UIManager: no active Catalyst instance"));
return null;
}
CatalystInstance catalystInstance = context.getCatalystInstance();
return uiManagerType == FABRIC
? (UIManager) catalystInstance.getJSIModule(JSIModuleType.UIManager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ public void synchronouslyUpdateViewOnUIThread(int tag, ReadableMap props) {
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));
}
Expand Down Expand Up @@ -478,7 +480,9 @@ public void updateView(int tag, String className, ReadableMap props) {
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);
}
Expand Down Expand Up @@ -668,14 +672,20 @@ public void dispatchViewManagerCommand(
// 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);
}
}
}

Expand Down Expand Up @@ -801,7 +811,9 @@ public void sendAccessibilityEvent(int tag, int eventType) {
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);
}
Expand Down

0 comments on commit aa27645

Please sign in to comment.