mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add more specific error messages for different lifecycle problems
Summary: Currently the error messages lead users to assume that all problems are because we're trying to use the ReactContext too early; it could be because we're using it too late, after it's been destroyed. Because of D17944723, it could be because we're accessing too late, after teardown. Changelog: [Internal] making some error messages more specific and helpful Reviewed By: mdvacca Differential Revision: D20251909 fbshipit-source-id: e236d57e4d7d9c778d41de95160c242bcd69b3c9
This commit is contained in:
committed by
Facebook Github Bot
parent
4f3e3f8cc1
commit
d892bb889b
@@ -33,10 +33,17 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
*/
|
||||
public class ReactContext extends ContextWrapper {
|
||||
|
||||
private static final String TAG = "ReactContext";
|
||||
private static final String EARLY_JS_ACCESS_EXCEPTION_MESSAGE =
|
||||
"Tried to access a JS module before the React instance was fully set up. Calls to "
|
||||
+ "ReactContext#getJSModule should only happen once initialize() has been called on your "
|
||||
+ "native module.";
|
||||
private static final String LATE_JS_ACCESS_EXCEPTION_MESSAGE =
|
||||
"Tried to access a JS module after the React instance was destroyed.";
|
||||
private static final String EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE =
|
||||
"Trying to call native module before CatalystInstance has been set!";
|
||||
private static final String LATE_NATIVE_MODULE_EXCEPTION_MESSAGE =
|
||||
"Trying to call native module after CatalystInstance has been destroyed!";
|
||||
|
||||
private final CopyOnWriteArraySet<LifecycleEventListener> mLifecycleEventListeners =
|
||||
new CopyOnWriteArraySet<>();
|
||||
@@ -47,6 +54,7 @@ public class ReactContext extends ContextWrapper {
|
||||
|
||||
private LifecycleState mLifecycleState = LifecycleState.BEFORE_CREATE;
|
||||
|
||||
private volatile boolean mDestroyed = false;
|
||||
private @Nullable CatalystInstance mCatalystInstance;
|
||||
private @Nullable LayoutInflater mInflater;
|
||||
private @Nullable MessageQueueThread mUiMessageQueueThread;
|
||||
@@ -68,6 +76,11 @@ public class ReactContext extends ContextWrapper {
|
||||
if (mCatalystInstance != null) {
|
||||
throw new IllegalStateException("ReactContext has been already initialized");
|
||||
}
|
||||
if (mDestroyed) {
|
||||
ReactSoftException.logSoftException(
|
||||
TAG,
|
||||
new IllegalStateException("Cannot initialize ReactContext after it has been destroyed."));
|
||||
}
|
||||
|
||||
mCatalystInstance = catalystInstance;
|
||||
|
||||
@@ -104,6 +117,11 @@ public class ReactContext extends ContextWrapper {
|
||||
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
|
||||
}
|
||||
|
||||
private void raiseCatalystInstanceMissingException() {
|
||||
throw new IllegalStateException(
|
||||
mDestroyed ? LATE_NATIVE_MODULE_EXCEPTION_MESSAGE : EARLY_NATIVE_MODULE_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
// We override the following method so that views inflated with the inflater obtained from this
|
||||
// context return the ReactContext in #getContext(). The default implementation uses the base
|
||||
// context instead, so it couldn't be cast to ReactContext.
|
||||
@@ -124,6 +142,9 @@ public class ReactContext extends ContextWrapper {
|
||||
*/
|
||||
public <T extends JavaScriptModule> T getJSModule(Class<T> jsInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
if (mDestroyed) {
|
||||
throw new IllegalStateException(LATE_JS_ACCESS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
throw new IllegalStateException(EARLY_JS_ACCESS_EXCEPTION_MESSAGE);
|
||||
}
|
||||
return mCatalystInstance.getJSModule(jsInterface);
|
||||
@@ -131,8 +152,7 @@ public class ReactContext extends ContextWrapper {
|
||||
|
||||
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to call native module before CatalystInstance has been set!");
|
||||
raiseCatalystInstanceMissingException();
|
||||
}
|
||||
return mCatalystInstance.hasNativeModule(nativeModuleInterface);
|
||||
}
|
||||
@@ -140,8 +160,7 @@ public class ReactContext extends ContextWrapper {
|
||||
/** @return the instance of the specified module interface associated with this ReactContext. */
|
||||
public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface) {
|
||||
if (mCatalystInstance == null) {
|
||||
throw new IllegalStateException(
|
||||
"Trying to call native module before CatalystInstance has been set!");
|
||||
raiseCatalystInstanceMissingException();
|
||||
}
|
||||
return mCatalystInstance.getNativeModule(nativeModuleInterface);
|
||||
}
|
||||
@@ -273,6 +292,7 @@ public class ReactContext extends ContextWrapper {
|
||||
public void destroy() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
mDestroyed = true;
|
||||
if (mCatalystInstance != null) {
|
||||
mCatalystInstance.destroy();
|
||||
if (ReactFeatureFlags.nullifyCatalystInstanceOnDestroy) {
|
||||
|
||||
Reference in New Issue
Block a user