react-native/Libraries/Devtools/setupDevtools.js
Pieter De Baets b00c77af80 Increase RN devtools retry timeout
Summary:The 200ms timeout was causing resource issues and causing a lot of overhead when you're not running the devtools, since it will basically create a new socket every 200ms.

Also clean up the way we do logging so it's completely compiled out in prod, and standardize all the names we use for threading to lowercase react.

Reviewed By: frantic

Differential Revision: D3115975

fb-gh-sync-id: e6e51c0621d8e9fc4eadb864acd678b8b5d322a1
fbshipit-source-id: e6e51c0621d8e9fc4eadb864acd678b8b5d322a1
2016-04-01 07:02:25 -07:00

111 lines
3.0 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule setupDevtools
* @flow
*/
'use strict';
function setupDevtools() {
var messageListeners = [];
var closeListeners = [];
var ws = new window.WebSocket('ws://localhost:8097/devtools');
// this is accessed by the eval'd backend code
var FOR_BACKEND = { // eslint-disable-line no-unused-vars
resolveRNStyle: require('flattenStyle'),
wall: {
listen(fn) {
messageListeners.push(fn);
},
onClose(fn) {
closeListeners.push(fn);
},
send(data) {
ws.send(JSON.stringify(data));
},
},
};
ws.onclose = handleClose;
ws.onerror = handleClose;
ws.onopen = function () {
tryToConnect();
};
var hasClosed = false;
function handleClose() {
if (!hasClosed) {
hasClosed = true;
setTimeout(setupDevtools, 2000);
closeListeners.forEach(fn => fn());
}
}
function tryToConnect() {
ws.send('attach:agent');
var _interval = setInterval(() => ws.send('attach:agent'), 500);
ws.onmessage = evt => {
if (evt.data.indexOf('eval:') === 0) {
clearInterval(_interval);
initialize(evt.data.slice('eval:'.length));
}
};
}
function initialize(text) {
try {
// FOR_BACKEND is used by the eval'd code
eval(text); // eslint-disable-line no-eval
} catch (e) {
console.error('Failed to eval: ' + e.message);
return;
}
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
CurrentOwner: require('ReactCurrentOwner'),
InstanceHandles: require('ReactInstanceHandles'),
Mount: require('ReactNativeMount'),
Reconciler: require('ReactReconciler'),
TextComponent: require('ReactNativeTextComponent'),
});
ws.onmessage = handleMessage;
}
function handleMessage(evt) {
// It's hard to handle JSON in a safe manner without inspecting it at
// runtime, hence the any
var data: any;
try {
data = JSON.parse(evt.data);
} catch (e) {
return console.error('failed to parse json: ' + evt.data);
}
// the devtools closed
if (data.$close || data.$error) {
closeListeners.forEach(fn => fn());
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.emit('shutdown');
tryToConnect();
return;
}
if (data.$open) {
return; // ignore
}
messageListeners.forEach(fn => {
try {
fn(data);
} catch (e) {
// jsc doesn't play so well with tracebacks that go into eval'd code,
// so the stack trace here will stop at the `eval()` call. Getting the
// message that caused the error is the best we can do for now.
console.log(data);
throw e;
}
});
}
}
module.exports = setupDevtools;