UNPKG

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.

212 lines (171 loc) 8.2 kB
Object.defineProperty(exports, '__esModule', { value: true }); /* * 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. */ 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; }; })(); 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 _commonsAtomFormatEnoentNotification2; function _commonsAtomFormatEnoentNotification() { return _commonsAtomFormatEnoentNotification2 = _interopRequireDefault(require('../../../commons-atom/format-enoent-notification')); } var _commonsNodeStream2; function _commonsNodeStream() { return _commonsNodeStream2 = require('../../../commons-node/stream'); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../../nuclide-logging'); } var _executeRequests2; function _executeRequests() { return _executeRequests2 = require('./executeRequests'); } var _runApp2; function _runApp() { return _runApp2 = require('./runApp'); } var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _rxjsBundlesRxUmdMinJs2; function _rxjsBundlesRxUmdMinJs() { return _rxjsBundlesRxUmdMinJs2 = require('rxjs/bundles/Rx.umd.min.js'); } /** * Debugging React Native involves running two processes in parallel: the React Native app, which * runs in a simulator or device, and the executor, which executes JavaScript in a separate * processes (and which is ultimately the process we debug). On the React Native App site, * instructions are sent and results received via websocket. The executor, on the other hand, * receives the instructions, executes them in a worker process, and emits the results. The whole * thing, then, is one big loop. * * In our code, this is modeled as streams of messages, with two transformations: one for the the * React Native app and one for the executor. The input of each is the output of the other. * * rnMessages -> executorRequests * * +-----------------------------------------+ * | | * | v * +--------+----------+ +--------+----------+ * | | | | * | | | | * | React Native App | | Executor | * | | | | * | (runApp) | | (executeRequests) | * | | | | * | | | | * +--------+----------+ +----------+--------+ * ^ | * | | * +-------------------------------------------+ * * executorResults <- executorResponses * */ var DebuggerProxyClient = (function () { function DebuggerProxyClient() { var _this = this; _classCallCheck(this, DebuggerProxyClient); var executorResults = new (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Subject(); this._rnMessages = (0, (_runApp2 || _runApp()).runApp)(executorResults).catch(function (err) { atom.notifications.addError('There was an unexpected error with the React Native app', { stack: err.stack }); return (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.empty(); }).finally(function () { _this.disconnect(); }).publish(); // Messages with `$close` are special instructions and messages with `replyID` are cross-talk // from another executor (probably Chrome), so filter both out. Otherwise, the messages from RN // are forwarded as-is to the executor. var executorRequests = this._rnMessages.filter(function (message) { return message.$close == null && message.replyID == null; }); this._executorResponses = (0, (_executeRequests2 || _executeRequests()).executeRequests)(executorRequests).catch(function (err) { if (err.code === 'ENOENT') { var _ref = (0, (_commonsAtomFormatEnoentNotification2 || _commonsAtomFormatEnoentNotification()).default)({ feature: 'React Native debugging', toolName: 'node', pathSetting: 'nuclide-react-native.pathToNode' }); var message = _ref.message; var meta = _ref.meta; atom.notifications.addError(message, meta); return (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.empty(); } (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)().error(err); return (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Observable.empty(); }).finally(function () { _this.disconnect(); }).publish(); this._pids = this._executorResponses.filter(function (response) { return response.kind === 'pid'; }).map(function (response) { (0, (_assert2 || _assert()).default)(response.kind === 'pid'); return response.pid; }); // Send the executor results to the RN app. (Close the loop.) this._executorResponses.filter(function (response) { return response.kind === 'result'; }).subscribe(executorResults); // Disconnect when the RN app tells us to (via a specially-formatted message). this._rnMessages.filter(function (message) { return Boolean(message.$close); }).subscribe(function () { _this.disconnect(); }); // Log executor errors. this._executorResponses.filter(function (response) { return response.kind === 'error'; }).map(function (response) { (0, (_assert2 || _assert()).default)(response.kind === 'error'); return response.message; }).subscribe((0, (_nuclideLogging2 || _nuclideLogging()).getLogger)().error); } _createClass(DebuggerProxyClient, [{ key: 'connect', value: function connect() { var _this2 = this; if (this._subscription != null) { // We're already connecting. return; } var sub = new (_rxjsBundlesRxUmdMinJs2 || _rxjsBundlesRxUmdMinJs()).Subscription(); sub.add(this._rnMessages.connect()); sub.add(this._executorResponses.connect()); // Null our subscription reference when the observable completes/errors. We'll use this to know // if it's running. sub.add(function () { _this2._subscription = null; }); this._subscription = sub; } }, { key: 'disconnect', value: function disconnect() { if (this._subscription == null) { return; } this._subscription.unsubscribe(); } /** * An API for subscribing to the next worker process pid. */ }, { key: 'onDidEvalApplicationScript', value: function onDidEvalApplicationScript(callback) { return new (_commonsNodeStream2 || _commonsNodeStream()).DisposableSubscription(this._pids.subscribe(callback)); } }]); return DebuggerProxyClient; })(); exports.DebuggerProxyClient = DebuggerProxyClient;