atom-nuclide
Version:
A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.
668 lines (621 loc) • 26.7 kB
JavaScript
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _assert2;
function _assert() {
return _assert2 = _interopRequireDefault(require('assert'));
}
var _electron2;
function _electron() {
return _electron2 = _interopRequireDefault(require('electron'));
}
var _Emitter2;
function _Emitter() {
return _Emitter2 = _interopRequireDefault(require('./Emitter'));
}
var _libMultimap2;
function _libMultimap() {
return _libMultimap2 = _interopRequireDefault(require('../../lib/Multimap'));
}
var _libAnalyticsHelper2;
function _libAnalyticsHelper() {
return _libAnalyticsHelper2 = require('../../lib/AnalyticsHelper');
}
var _libWebInspector2;
function _libWebInspector() {
return _libWebInspector2 = _interopRequireDefault(require('../../lib/WebInspector'));
}
var ipcRenderer = (_electron2 || _electron()).default.ipcRenderer;
(0, (_assert2 || _assert()).default)(ipcRenderer != null);
var NUCLIDE_DEBUGGER_CONSOLE_OBJECT_GROUP = 'console';
var DebuggerSettingsChangedEvent = 'debugger-settings-updated';
var NuclideBridge = (function () {
function NuclideBridge() {
_classCallCheck(this, NuclideBridge);
this._allBreakpoints = [];
this._unresolvedBreakpoints = new (_libMultimap2 || _libMultimap()).default();
this._emitter = new (_Emitter2 || _Emitter()).default();
this._debuggerPausedCount = 0;
this._suppressBreakpointNotification = false;
this._settings = {};
ipcRenderer.on('command', this._handleIpcCommand.bind(this));
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.CallFrameSelected, this._handleCallFrameSelected, this);
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.ClearInterface, this._handleClearInterface, this);
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.DebuggerResumed, this._handleDebuggerResumed, this);
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.DebuggerPaused, this._handleDebuggerPaused, this);
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.ThreadsUpdateIPC, this._handleThreadsUpdated, this);
(_libWebInspector2 || _libWebInspector()).default.targetManager.addModelListener((_libWebInspector2 || _libWebInspector()).default.DebuggerModel, (_libWebInspector2 || _libWebInspector()).default.DebuggerModel.Events.StopThreadSwitched, this._handleStopThreadSwitched, this);
(_libWebInspector2 || _libWebInspector()).default.workspace.addEventListener((_libWebInspector2 || _libWebInspector()).default.Workspace.Events.UISourceCodeAdded, this._handleUISourceCodeAdded, this);
(_libWebInspector2 || _libWebInspector()).default.notifications.addEventListener((_libWebInspector2 || _libWebInspector()).default.UserMetrics.UserAction, function (event) {
if (event.data.action === 'openSourceLink') {
this._handleOpenSourceLocation(event);
}
}, this);
(_libWebInspector2 || _libWebInspector()).default.breakpointManager.addEventListener((_libWebInspector2 || _libWebInspector()).default.BreakpointManager.Events.BreakpointAdded, this._handleBreakpointAdded, this);
(_libWebInspector2 || _libWebInspector()).default.breakpointManager.addEventListener((_libWebInspector2 || _libWebInspector()).default.BreakpointManager.Events.BreakpointRemoved, this._handleBreakpointRemoved, this);
this._handleSettingsUpdated = this._handleSettingsUpdated.bind(this);
this._customizeWebInspector();
window.runOnWindowLoad(this._handleWindowLoad.bind(this));
}
/**
* Override and customize some functionalities of WebInspector.
* Deliberately suppress any flow errors in this method.
*/
_createClass(NuclideBridge, [{
key: '_customizeWebInspector',
value: function _customizeWebInspector() {
// $FlowFixMe.
(_libWebInspector2 || _libWebInspector()).default.ObjectPropertyTreeElement._populate = function (treeElement, value, skipProto, emptyPlaceholder) {
/**
* @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
* @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties
*/
function callback(properties, internalProperties) {
treeElement.removeChildren();
if (!properties) {
return;
}
// $FlowFixMe.
(_libWebInspector2 || _libWebInspector()).default.ObjectPropertyTreeElement.populateWithProperties(treeElement, properties, internalProperties, skipProto, value, emptyPlaceholder);
}
// $FlowFixMe.
(_libWebInspector2 || _libWebInspector()).default.RemoteObject.loadFromObjectPerProto(value, callback);
};
// $FlowFixMe.
(_libWebInspector2 || _libWebInspector()).default.ObjectPropertiesSection.prototype.update = function () {
/**
* @param {?Array.<!WebInspector.RemoteObjectProperty>} properties
* @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties
* @this {WebInspector.ObjectPropertiesSection}
*/
function callback(properties, internalProperties) {
if (!properties) {
return;
}
this.updateProperties(properties, internalProperties);
var neededProperties = properties.map(function (_ref) {
var name = _ref.name;
var value = _ref.value;
var type = value.type;
var subtype = value.subtype;
var objectId = value.objectId;
var innerValue = value.value;
var description = value.description;
return {
name: name,
value: {
type: type,
subtype: subtype,
objectId: objectId,
value: innerValue,
description: description
}
};
});
ipcRenderer.sendToHost('notification', 'LocalsUpdate', neededProperties);
}
// $FlowFixMe.
(_libWebInspector2 || _libWebInspector()).default.RemoteObject.loadFromObject(this.object, Boolean(this.ignoreHasOwnProperty), callback.bind(this));
};
}
}, {
key: '_handleWindowLoad',
value: function _handleWindowLoad() {
ipcRenderer.sendToHost('notification', 'ready');
}
}, {
key: '_handleIpcCommand',
value: function _handleIpcCommand(event, command) {
switch (command) {
case 'UpdateSettings':
this._handleSettingsUpdated(arguments[2]);
break;
case 'SyncBreakpoints':
this._allBreakpoints = arguments[2];
this._syncBreakpoints();
break;
case 'AddBreakpoint':
this._addBreakpoint(arguments[2]);
break;
case 'DeleteBreakpoint':
this._deleteBreakpoint(arguments[2]);
break;
case 'Continue':
this._continue();
break;
case 'StepOver':
this._stepOver();
break;
case 'StepInto':
this._stepInto();
break;
case 'StepOut':
this._stepOut();
break;
case 'evaluateOnSelectedCallFrame':
this._evaluateOnSelectedCallFrame(arguments[2], arguments[3]);
break;
case 'runtimeEvaluate':
this._runtimeEvaluate(arguments[2]);
break;
case 'getProperties':
this._getProperties(arguments[2]);
break;
case 'triggerDebuggerAction':
this._triggerDebuggerAction(arguments[2]);
break;
case 'setPauseOnException':
this._setPauseOnException(arguments[2]);
break;
case 'setPauseOnCaughtException':
this._setPauseOnCaughtException(arguments[2]);
break;
case 'setSingleThreadStepping':
this._setSingleThreadStepping(arguments[2]);
break;
case 'selectThread':
this.selectThread(arguments[2]);
break;
}
}
}, {
key: 'getSettings',
value: function getSettings() {
return this._settings;
}
}, {
key: '_handleSettingsUpdated',
value: function _handleSettingsUpdated(settingsData) {
this._settings = JSON.parse(settingsData);
this._emitter.emit(DebuggerSettingsChangedEvent, null);
}
}, {
key: 'onDebuggerSettingsChanged',
value: function onDebuggerSettingsChanged(callback) {
return this._emitter.on(DebuggerSettingsChangedEvent, callback);
}
}, {
key: '_handleCallFrameSelected',
value: function _handleCallFrameSelected(event) {
// TODO(jonaldislarry): Extend chrome protocol as per t12187369.
if (this._debuggerPausedCount <= 1) {
return;
}
var frame = event.data;
var uiLocation = (_libWebInspector2 || _libWebInspector()).default.debuggerWorkspaceBinding.rawLocationToUILocation(frame.location());
ipcRenderer.sendToHost('notification', 'CallFrameSelected', {
sourceURL: uiLocation.uiSourceCode.uri(),
lineNumber: uiLocation.lineNumber
});
}
}, {
key: '_handleOpenSourceLocation',
value: function _handleOpenSourceLocation(event) {
// TODO(jonaldislarry): Extend chrome protocol as per t12187369.
if (this._debuggerPausedCount <= 1) {
return;
}
var eventData = event.data;
this.sendOpenSourceLocation(eventData.url, eventData.lineNumber);
}
}, {
key: 'sendOpenSourceLocation',
value: function sendOpenSourceLocation(sourceURL, line) {
ipcRenderer.sendToHost('notification', 'OpenSourceLocation', {
sourceURL: sourceURL,
lineNumber: line
});
}
}, {
key: 'selectThread',
value: function selectThread(threadId) {
var _this = this;
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target != null) {
target.debuggerModel.selectThread(threadId);
target.debuggerModel.threadStore.getActiveThreadStack(function (callFrames) {
var callstack = _this._convertFramesToIPCFrames(callFrames);
ipcRenderer.sendToHost('notification', 'CallstackUpdate', callstack);
});
}
}
}, {
key: '_sendCallstack',
value: function _sendCallstack() {
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target == null) {
return;
}
var model = target.debuggerModel;
if (model == null) {
return;
}
var callFrames = model.callFrames;
if (callFrames == null) {
return;
}
var callstack = this._convertFramesToIPCFrames(callFrames);
ipcRenderer.sendToHost('notification', 'CallstackUpdate', callstack);
}
}, {
key: '_convertFramesToIPCFrames',
value: function _convertFramesToIPCFrames(callFrames) {
return callFrames.map(function (callFrame) {
var location = callFrame.location();
/* names anonymous functions "(anonymous function)" */
var functionName = (_libWebInspector2 || _libWebInspector()).default.beautifyFunctionName(callFrame.functionName);
return {
name: functionName,
location: {
path: callFrame.script.sourceURL,
column: location.columnNumber,
line: location.lineNumber
}
};
});
}
}, {
key: '_getProperties',
value: function _getProperties(objectId) {
var mainTarget = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (mainTarget == null) {
return;
}
var runtimeAgent = mainTarget.runtimeAgent();
if (runtimeAgent == null) {
return;
}
runtimeAgent.getProperties(objectId, false, // ownProperties
false, // accessorPropertiesOnly
false, // generatePreview
function (error, properties, internalProperties) {
ipcRenderer.sendToHost('notification', 'GetPropertiesResponse', {
result: properties,
error: error,
objectId: objectId
});
});
}
}, {
key: '_evaluateOnSelectedCallFrame',
value: function _evaluateOnSelectedCallFrame(expression, objectGroup) {
var mainTarget = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (mainTarget == null) {
return;
}
mainTarget.debuggerModel.evaluateOnSelectedCallFrame(expression, objectGroup, false, /* includeCommandLineAPI */
true, /* doNotPauseOnExceptionsAndMuteConsole */
false, /* returnByValue */
false, /* generatePreview */
function (remoteObject, wasThrown, error) {
ipcRenderer.sendToHost('notification', 'ExpressionEvaluationResponse', {
result: wasThrown ? null : remoteObject,
error: wasThrown ? error : null,
expression: expression
});
});
}
}, {
key: '_runtimeEvaluate',
value: function _runtimeEvaluate(expression) {
var mainTarget = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (mainTarget == null) {
return;
}
var executionContexts = mainTarget.runtimeModel.executionContexts();
if (executionContexts.length === 0) {
return;
}
var firstContext = executionContexts[0];
firstContext.evaluate(expression, NUCLIDE_DEBUGGER_CONSOLE_OBJECT_GROUP, false, /* includeCommandLineAPI */
true, /* doNotPauseOnExceptionsAndMuteConsole */
false, /* returnByValue */
false, /* generatePreview */
function (remoteObject, wasThrown, error) {
ipcRenderer.sendToHost('notification', 'ExpressionEvaluationResponse', {
result: wasThrown ? null : remoteObject,
error: wasThrown ? error : null,
expression: expression
});
});
}
}, {
key: '_setPauseOnException',
value: function _setPauseOnException(pauseOnExceptionEnabled) {
(_libWebInspector2 || _libWebInspector()).default.settings.pauseOnExceptionEnabled.set(pauseOnExceptionEnabled);
}
}, {
key: '_setPauseOnCaughtException',
value: function _setPauseOnCaughtException(pauseOnCaughtExceptionEnabled) {
(_libWebInspector2 || _libWebInspector()).default.settings.pauseOnCaughtException.set(pauseOnCaughtExceptionEnabled);
}
}, {
key: '_setSingleThreadStepping',
value: function _setSingleThreadStepping(singleThreadStepping) {
(_libWebInspector2 || _libWebInspector()).default.settings.singleThreadStepping.set(singleThreadStepping);
}
}, {
key: '_triggerDebuggerAction',
value: function _triggerDebuggerAction(actionId) {
switch (actionId) {
case 'debugger.toggle-pause':
case 'debugger.step-over':
case 'debugger.step-into':
case 'debugger.step-out':
case 'debugger.run-snippet':
(_libWebInspector2 || _libWebInspector()).default.actionRegistry.execute(actionId);
break;
default:
// console.error because throwing can fatal the Chrome dev tools.
// eslint-disable-next-line no-console
console.error('_triggerDebuggerAction: unrecognized actionId', actionId);
break;
}
}
}, {
key: '_handleDebuggerPaused',
value: function _handleDebuggerPaused(event) {
(0, (_libAnalyticsHelper2 || _libAnalyticsHelper()).endTimerTracking)();
++this._debuggerPausedCount;
if (this._debuggerPausedCount === 1) {
ipcRenderer.sendToHost('notification', 'LoaderBreakpointHit', {});
this._handleLoaderBreakpoint();
} else {
ipcRenderer.sendToHost('notification', 'NonLoaderDebuggerPaused', {});
}
this._sendCallstack();
}
}, {
key: '_handleLoaderBreakpoint',
value: function _handleLoaderBreakpoint() {
var _this2 = this;
// Sync any initial breakpoints to engine during loader breakpoint
// and continue from it.
this._syncBreakpoints();
// If we were to continue synchronously here, the debugger would no longer be paused when the
// remaining subscribers' callbacks were invoked. That's a violation of a pretty basic
// assumption (that the debugger will be paused when your paused event callback is called) so
// instead we wait until the next tick. If the debugger is still paused then, we continue. Not
// doing this results in an "Runtime.getProperties failed" error in node-inspector since that
// call is only valid during a paused state.
process.nextTick(function () {
var targetManager = (_libWebInspector2 || _libWebInspector()).default != null ? (_libWebInspector2 || _libWebInspector()).default.targetManager : null;
var mainTarget = targetManager != null ? targetManager.mainTarget() : null;
var debuggerModel = mainTarget != null ? mainTarget.debuggerModel : null;
var stillPaused = debuggerModel != null && debuggerModel.isPaused();
if (stillPaused) {
_this2._continue();
}
});
ipcRenderer.sendToHost('notification', 'LoaderBreakpointResumed', {});
}
}, {
key: '_handleDebuggerResumed',
value: function _handleDebuggerResumed(event) {
ipcRenderer.sendToHost('notification', 'DebuggerResumed', {});
}
}, {
key: '_handleClearInterface',
value: function _handleClearInterface(event) {
ipcRenderer.sendToHost('notification', 'ClearInterface', {});
}
}, {
key: '_handleBreakpointAdded',
value: function _handleBreakpointAdded(event) {
var location = event.data.uiLocation;
this._sendBreakpointNotification(location, 'BreakpointAdded');
}
}, {
key: '_handleBreakpointRemoved',
value: function _handleBreakpointRemoved(event) {
var location = event.data.uiLocation;
this._sendBreakpointNotification(location, 'BreakpointRemoved');
}
}, {
key: '_sendBreakpointNotification',
value: function _sendBreakpointNotification(location, type) {
if (!this._suppressBreakpointNotification) {
ipcRenderer.sendToHost('notification', type, {
sourceURL: location.uiSourceCode.uri(),
lineNumber: location.lineNumber
});
}
}
// TODO[jeffreytan]: this is a hack to enable debugger
// setting breakpoints in non-parsed files.
// Open issues:
// Any breakpoints in this list will shown as bound/resolved;
// needs to revisit the unresolved breakpoints detection logic.
}, {
key: '_parseBreakpointSources',
value: function _parseBreakpointSources() {
var _this3 = this;
this._allBreakpoints.forEach(function (breakpoint) {
_this3._parseBreakpointSourceIfNeeded(breakpoint);
});
}
}, {
key: '_parseBreakpointSourceIfNeeded',
value: function _parseBreakpointSourceIfNeeded(breakpoint) {
var sourceUrl = breakpoint.sourceURL;
if (sourceUrl.endsWith('.php') || sourceUrl.endsWith('.hh') || sourceUrl.endsWith('.c') || sourceUrl.endsWith('.cpp') || sourceUrl.endsWith('.h') || sourceUrl.endsWith('.hpp') || sourceUrl.endsWith('.js') || sourceUrl.endsWith('.m') || sourceUrl.endsWith('.mm')) {
var source = (_libWebInspector2 || _libWebInspector()).default.workspace.uiSourceCodeForOriginURL(sourceUrl);
if (source != null) {
return;
}
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target == null) {
return;
}
target.debuggerModel._parsedScriptSource(sourceUrl, sourceUrl);
}
}
// Synchronizes nuclide BreakpointStore and BreakpointManager
}, {
key: '_syncBreakpoints',
value: function _syncBreakpoints() {
var _this4 = this;
try {
this._suppressBreakpointNotification = true;
this._parseBreakpointSources();
// Add the ones that don't.
this._unresolvedBreakpoints = new (_libMultimap2 || _libMultimap()).default();
this._allBreakpoints.forEach(function (breakpoint) {
if (!_this4._addBreakpoint(breakpoint)) {
// No API exists for adding breakpoints to source files that are not
// yet known, store it locally and try to add them later.
_this4._unresolvedBreakpoints.set(breakpoint.sourceURL, breakpoint.lineNumber);
}
});
this._emitter.emit('unresolved-breakpoints-changed', null);
} finally {
this._suppressBreakpointNotification = false;
}
}
}, {
key: '_addBreakpoint',
value: function _addBreakpoint(breakpoint) {
this._parseBreakpointSourceIfNeeded(breakpoint);
var source = (_libWebInspector2 || _libWebInspector()).default.workspace.uiSourceCodeForOriginURL(breakpoint.sourceURL);
if (source == null) {
return false;
}
(_libWebInspector2 || _libWebInspector()).default.breakpointManager.setBreakpoint(source, breakpoint.lineNumber, 0, // columnNumber
'', // Condition
true);
// enabled
return true;
}
}, {
key: '_deleteBreakpoint',
value: function _deleteBreakpoint(breakpoint) {
var source = (_libWebInspector2 || _libWebInspector()).default.workspace.uiSourceCodeForOriginURL(breakpoint.sourceURL);
if (source == null) {
return false;
}
var chromeBreakpoint = (_libWebInspector2 || _libWebInspector()).default.breakpointManager.findBreakpointOnLine(source, breakpoint.lineNumber);
if (chromeBreakpoint == null) {
return false;
}
chromeBreakpoint.remove(false);
return true;
}
}, {
key: '_continue',
value: function _continue() {
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target) {
(0, (_libAnalyticsHelper2 || _libAnalyticsHelper()).beginTimerTracking)('nuclide-debugger-atom:continue');
target.debuggerModel.resume();
}
}
}, {
key: '_stepOver',
value: function _stepOver() {
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target) {
(0, (_libAnalyticsHelper2 || _libAnalyticsHelper()).beginTimerTracking)('nuclide-debugger-atom:stepOver');
target.debuggerModel.stepOver();
}
}
}, {
key: '_stepInto',
value: function _stepInto() {
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target) {
(0, (_libAnalyticsHelper2 || _libAnalyticsHelper()).beginTimerTracking)('nuclide-debugger-atom:stepInto');
target.debuggerModel.stepInto();
}
}
}, {
key: '_stepOut',
value: function _stepOut() {
var target = (_libWebInspector2 || _libWebInspector()).default.targetManager.mainTarget();
if (target) {
(0, (_libAnalyticsHelper2 || _libAnalyticsHelper()).beginTimerTracking)('nuclide-debugger-atom:stepOut');
target.debuggerModel.stepOut();
}
}
}, {
key: '_handleUISourceCodeAdded',
value: function _handleUISourceCodeAdded(event) {
var source = event.data;
this._unresolvedBreakpoints.get(source.uri()).forEach(function (line) {
(_libWebInspector2 || _libWebInspector()).default.breakpointManager.setBreakpoint(source, line, 0, '', true);
});
if (this._unresolvedBreakpoints.deleteAll(source.uri())) {
this._emitter.emit('unresolved-breakpoints-changed', null);
}
}
}, {
key: 'onUnresolvedBreakpointsChanged',
value: function onUnresolvedBreakpointsChanged(callback) {
return this._emitter.on('unresolved-breakpoints-changed', callback);
}
}, {
key: 'getUnresolvedBreakpointsList',
value: function getUnresolvedBreakpointsList() {
var result = [];
this._unresolvedBreakpoints.forEach(function (line, url) {
result.push({ url: url, line: line });
});
result.sort(function (a, b) {
if (a.url < b.url) {
return -1;
} else if (a.url > b.url) {
return 1;
} else {
return a.line - b.line;
}
});
return result;
}
}, {
key: '_handleThreadsUpdated',
value: function _handleThreadsUpdated(event) {
ipcRenderer.sendToHost('notification', 'ThreadsUpdate', event.data);
}
}, {
key: '_handleStopThreadSwitched',
value: function _handleStopThreadSwitched(event) {
if (this._debuggerPausedCount <= 1) {
return;
}
var uiLocation = (_libWebInspector2 || _libWebInspector()).default.debuggerWorkspaceBinding.rawLocationToUILocation(event.data.location);
ipcRenderer.sendToHost('notification', 'StopThreadSwitch', {
sourceURL: uiLocation.uiSourceCode.uri(),
lineNumber: uiLocation.lineNumber,
message: event.data.message
});
}
}]);
return NuclideBridge;
})();
module.exports = new NuclideBridge();