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.

268 lines (232 loc) 9 kB
Object.defineProperty(exports, '__esModule', { value: true }); 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 _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { var callNext = step.bind(null, 'next'); var callThrow = step.bind(null, 'throw'); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(callNext, callThrow); } } callNext(); }); }; } 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 }; } /* * 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 _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../nuclide-logging'); } var logger = (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)(); // All remotable objects have some set of named functions, // and they also have a dispose method. // Handles lifetimes of marshalling wrappers remote objects. // // Object passed by reference over RPC are assigned an ID. // Positive IDs represent objects which live on the server, // negative IDs represent objects which live on the client. var ObjectRegistry = (function () { function ObjectRegistry(kind, serviceRegistry, context) { _classCallCheck(this, ObjectRegistry); this._delta = kind === 'server' ? 1 : -1; this._nextObjectId = this._delta; this._registrationsById = new Map(); this._registrationsByObject = new Map(); this._subscriptions = new Map(); this._proxiesById = new Map(); this._idsByProxy = new Map(); this._serviceRegistry = serviceRegistry; this._services = new Map(); this._context = context; } _createClass(ObjectRegistry, [{ key: 'hasService', value: function hasService(serviceName) { return this._serviceRegistry.hasService(serviceName); } }, { key: 'getService', value: function getService(serviceName) { var service = this._services.get(serviceName); if (service == null) { service = this._serviceRegistry.getService(serviceName).factory(this._context); this._services.set(serviceName, service); } return service; } }, { key: 'unmarshal', value: function unmarshal(id, proxyClass) { if (this._isLocalId(id)) { return this._unmarshalLocalObject(id); } else { (0, (_assert2 || _assert()).default)(proxyClass != null); return this._unmarshalRemoteObject(id, proxyClass); } } }, { key: '_unmarshalLocalObject', value: function _unmarshalLocalObject(id) { return this._getRegistration(id).object; } }, { key: '_unmarshalRemoteObject', value: function _unmarshalRemoteObject(remoteId, proxyClass) { var existingProxy = this._proxiesById.get(remoteId); if (existingProxy != null) { return existingProxy; } (0, (_assert2 || _assert()).default)(proxyClass != null); // Generate the proxy by manually setting the prototype of the proxy to be the // prototype of the remote proxy constructor. var newProxy = Object.create(proxyClass.prototype); this.addProxy(newProxy, Promise.resolve(remoteId)); return newProxy; } }, { key: '_getRegistration', value: function _getRegistration(remoteId) { var result = this._registrationsById.get(remoteId); (0, (_assert2 || _assert()).default)(result != null); return result; } }, { key: 'getInterface', value: function getInterface(remoteId) { return this._getRegistration(remoteId).interface; } }, { key: 'disposeObject', value: _asyncToGenerator(function* (remoteId) { var registration = this._getRegistration(remoteId); var object = registration.object; this._registrationsById.delete(remoteId); this._registrationsByObject.delete(object); // Call the object's local dispose function. yield object.dispose(); }) }, { key: 'disposeSubscription', value: function disposeSubscription(id) { var subscription = this.removeSubscription(id); if (subscription != null) { subscription.unsubscribe(); } } // Put the object in the registry. }, { key: 'marshal', value: function marshal(interfaceName, object) { if (this._isRemoteObject(object)) { return this._marshalRemoteObject(object); } else { return this._marshalLocalObject(interfaceName, object); } } }, { key: '_marshalRemoteObject', value: function _marshalRemoteObject(proxy) { var result = this._idsByProxy.get(proxy); (0, (_assert2 || _assert()).default)(result != null); return result; } }, { key: '_marshalLocalObject', value: function _marshalLocalObject(interfaceName, object) { var existingRegistration = this._registrationsByObject.get(object); if (existingRegistration != null) { (0, (_assert2 || _assert()).default)(existingRegistration.interface === interfaceName); return existingRegistration.remoteId; } var objectId = this._nextObjectId; this._nextObjectId += this._delta; var registration = { 'interface': interfaceName, remoteId: objectId, object: object }; this._registrationsById.set(objectId, registration); this._registrationsByObject.set(object, registration); return objectId; } }, { key: 'addSubscription', value: function addSubscription(id, subscription) { this._subscriptions.set(id, subscription); } }, { key: 'removeSubscription', value: function removeSubscription(id) { var subscription = this._subscriptions.get(id); if (subscription != null) { this._subscriptions.delete(id); } return subscription; } // Disposes all object in the registry }, { key: 'dispose', value: _asyncToGenerator(function* () { var _this = this; var ids = Array.from(this._registrationsById.keys()); logger.info('Disposing ' + ids.length + ' registrations'); yield Promise.all(ids.map(_asyncToGenerator(function* (id) { try { yield _this.disposeObject(id); } catch (e) { logger.error('Error disposing marshalled object.', e); } }))); var subscriptions = Array.from(this._subscriptions.keys()); logger.info('Disposing ' + subscriptions.length + ' subscriptions'); for (var _id of subscriptions) { try { this.disposeSubscription(_id); } catch (e) { logger.error('Error disposing subscription', e); } } }) // Returns null if the object is already disposed. }, { key: 'disposeProxy', value: _asyncToGenerator(function* (proxy) { (0, (_assert2 || _assert()).default)(this._idsByProxy.has(proxy)); var objectId = this._idsByProxy.get(proxy); if (objectId != null) { this._idsByProxy.set(proxy, null); return yield objectId; } else { return null; } }) }, { key: 'addProxy', value: _asyncToGenerator(function* (proxy, idPromise) { (0, (_assert2 || _assert()).default)(!this._idsByProxy.has(proxy)); this._idsByProxy.set(proxy, idPromise); var id = yield idPromise; (0, (_assert2 || _assert()).default)(!this._proxiesById.has(id)); this._proxiesById.set(id, proxy); }) }, { key: '_isRemoteObject', value: function _isRemoteObject(object) { return this._idsByProxy.has(object); } }, { key: '_isLocalId', value: function _isLocalId(id) { return id * this._delta > 0; } }]); return ObjectRegistry; })(); exports.ObjectRegistry = ObjectRegistry; // These members handle local objects which have been marshalled remotely. // These members handle remote objects. // null means the proxy has been disposed. // Maps service name to proxy