react-native
Version:
A framework for building native apps using React
143 lines (125 loc) • 5.23 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
;
import type {Domain} from '../../src/private/fusebox/setUpFuseboxReactDevToolsDispatcher';
if (__DEV__) {
// Register dispatcher on global, which can be used later by Chrome DevTools frontend
require('../../src/private/fusebox/setUpFuseboxReactDevToolsDispatcher');
// Install hook before React is loaded.
const reactDevTools = require('react-devtools-core');
// This should be defined in DEV, otherwise error is expected.
const fuseboxReactDevToolsDispatcher =
global.__FUSEBOX_REACT_DEVTOOLS_DISPATCHER__;
const reactDevToolsFuseboxGlobalBindingName =
fuseboxReactDevToolsDispatcher.BINDING_NAME;
const ReactNativeStyleAttributes = require('../Components/View/ReactNativeStyleAttributes');
const devToolsSettingsManager = require('../DevToolsSettings/DevToolsSettingsManager');
const resolveRNStyle = require('../StyleSheet/flattenStyle');
let disconnect = null;
function disconnectBackendFromReactDevToolsInFuseboxIfNeeded() {
if (disconnect != null) {
disconnect();
disconnect = null;
}
}
function connectToReactDevToolsInFusebox(domain: Domain) {
disconnect = reactDevTools.connectWithCustomMessagingProtocol({
onSubscribe: listener => {
domain.onMessage.addEventListener(listener);
},
onUnsubscribe: listener => {
domain.onMessage.removeEventListener(listener);
},
onMessage: (event, payload) => {
domain.sendMessage({event, payload});
},
settingsManager: devToolsSettingsManager,
nativeStyleEditorValidAttributes: Object.keys(ReactNativeStyleAttributes),
resolveRNStyle,
});
}
let isWebSocketOpen = false;
let ws = null;
function connectToWSBasedReactDevToolsFrontend() {
if (ws !== null && isWebSocketOpen) {
// If the DevTools backend is already connected, don't recreate the WebSocket.
// This would break the connection.
// If there isn't an active connection, a backend may be waiting to connect,
// in which case it's okay to make a new one.
return;
}
// not when debugging in chrome
// TODO(t12832058) This check is broken
if (!window.document) {
const AppState = require('../AppState/AppState');
const getDevServer = require('./Devtools/getDevServer');
// 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.
const isAppActive = () => AppState.currentState !== 'background';
// Get hostname from development server (packager)
const devServer = getDevServer();
const host = devServer.bundleLoadedFromServer
? devServer.url
.replace(/https?:\/\//, '')
.replace(/\/$/, '')
.split(':')[0]
: 'localhost';
// Read the optional global variable for backward compatibility.
// It was added in https://github.com/facebook/react-native/commit/bf2b435322e89d0aeee8792b1c6e04656c2719a0.
const port =
window.__REACT_DEVTOOLS_PORT__ != null
? window.__REACT_DEVTOOLS_PORT__
: 8097;
const WebSocket = require('../WebSocket/WebSocket');
ws = new WebSocket('ws://' + host + ':' + port);
ws.addEventListener('close', event => {
isWebSocketOpen = false;
});
ws.addEventListener('open', event => {
isWebSocketOpen = true;
});
reactDevTools.connectToDevTools({
isAppActive,
resolveRNStyle,
nativeStyleEditorValidAttributes: Object.keys(
ReactNativeStyleAttributes,
),
websocket: ws,
devToolsSettingsManager,
});
}
}
// 1. If React DevTools has already been opened and initialized in Fusebox, bindings survive reloads
if (global[reactDevToolsFuseboxGlobalBindingName] != null) {
disconnectBackendFromReactDevToolsInFuseboxIfNeeded();
const domain =
fuseboxReactDevToolsDispatcher.initializeDomain('react-devtools');
connectToReactDevToolsInFusebox(domain);
}
// 2. If React DevTools panel in Fusebox was opened for the first time after the runtime has been created
// 2. OR if React DevTools frontend was re-initialized: Chrome DevTools was closed and then re-opened
global.__FUSEBOX_REACT_DEVTOOLS_DISPATCHER__.onDomainInitialization.addEventListener(
(domain: Domain) => {
if (domain.name === 'react-devtools') {
disconnectBackendFromReactDevToolsInFuseboxIfNeeded();
connectToReactDevToolsInFusebox(domain);
}
},
);
// 3. Fallback to attempting to connect WS-based RDT frontend
const RCTNativeAppEventEmitter = require('../EventEmitter/RCTNativeAppEventEmitter');
RCTNativeAppEventEmitter.addListener(
'RCTDevMenuShown',
connectToWSBasedReactDevToolsFrontend,
);
connectToWSBasedReactDevToolsFrontend(); // Try connecting once on load
}