Skip to content

Commit

Permalink
Guard against missing native module
Browse files Browse the repository at this point in the history
Reviewed By: martinbigio

Differential Revision: D4579114

fbshipit-source-id: a2e9f634748e1c56eb9867bfb9e3e66e9cdc5e93
  • Loading branch information
gaearon authored and facebook-github-bot committed Feb 17, 2017
1 parent 3148cc0 commit 118e883
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
48 changes: 46 additions & 2 deletions Libraries/AppState/AppState.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
'use strict';

const EventEmitter = require('EventEmitter');
const NativeEventEmitter = require('NativeEventEmitter');
const NativeModules = require('NativeModules');
const RCTAppState = NativeModules.AppState;
Expand All @@ -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
Expand Down Expand Up @@ -86,6 +90,7 @@ class AppState extends NativeEventEmitter {

_eventHandlers: Object;
currentState: ?string;
isAvailable: boolean = true;

constructor() {
super(RCTAppState);
Expand Down Expand Up @@ -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.'
);
}

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;
module.exports = appState;
3 changes: 3 additions & 0 deletions Libraries/Core/Devtools/setupDevtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 118e883

Please sign in to comment.