Guard against missing native module

Reviewed By: martinbigio

Differential Revision: D4579114

fbshipit-source-id: a2e9f634748e1c56eb9867bfb9e3e66e9cdc5e93
This commit is contained in:
Dan Abramov 2017-02-17 09:49:35 -08:00 committed by Facebook Github Bot
parent 3148cc09ae
commit 118e88393e
2 changed files with 49 additions and 2 deletions

View File

@ -11,6 +11,7 @@
*/
'use strict';
const EventEmitter = require('EventEmitter');
const NativeEventEmitter = require('NativeEventEmitter');
const NativeModules = require('NativeModules');
const RCTAppState = NativeModules.AppState;
@ -25,6 +26,9 @@ const invariant = require('fbjs/lib/invariant');
* AppState is frequently used to determine the intent and proper behavior when
* handling push notifications.
*
* This module depends on the native RCTAppState module. If you don't include it,
* `AppState.isAvailable` will return `false`, and any method calls will throw.
*
* ### App States
*
* - `active` - The app is running in the foreground
@ -86,6 +90,7 @@ class AppState extends NativeEventEmitter {
_eventHandlers: Object;
currentState: ?string;
isAvailable: boolean = true;
constructor() {
super(RCTAppState);
@ -173,6 +178,45 @@ class AppState extends NativeEventEmitter {
}
}
AppState = new AppState();
function throwMissingNativeModule() {
invariant(
false,
'Cannot use AppState module when native RCTAppState is not included in the build.\n' +
'Either include it, or check AppState.isAvailable before calling any methods.'
);
}
module.exports = AppState;
class MissingNativeAppStateShim extends EventEmitter {
// AppState
isAvailable: boolean = false;
currentState: ?string = null;
addEventListener() {
throwMissingNativeModule();
}
removeEventListener() {
throwMissingNativeModule();
}
// EventEmitter
addListener() {
throwMissingNativeModule();
}
removeAllListeners() {
throwMissingNativeModule();
}
removeSubscription() {
throwMissingNativeModule();
}
}
// Guard against missing native module by throwing on first method call.
// Keep the API the same so Flow doesn't complain.
const appState = RCTAppState
? new AppState()
: new MissingNativeAppStateShim();
module.exports = appState;

View File

@ -20,6 +20,9 @@ if (__DEV__) {
connectToDevTools({
isAppActive() {
// Don't steal the DevTools from currently active app.
// Note: if you add any AppState subscriptions to this file,
// you will also need to guard against `AppState.isAvailable`,
// or the code will throw for bundles that don't have it.
return AppState.currentState !== 'background';
},
// Special case: Genymotion is running on a different host.