UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

193 lines (175 loc) 4.9 kB
// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @interface */ function Service() { } Service.prototype = { /** * @return {!Promise} */ dispose() {}, /** * @return {function(string)} */ setNotify(notify) {} }; /** * @unrestricted */ ServiceDispatcher = class { /** * @param {!ServicePort} port */ constructor(port) { /** @type {!Map<string, !Object>} */ this._objects = new Map(); this._lastObjectId = 1; this._port = port; this._port.setHandlers(this._dispatchMessageWrapped.bind(this), this._connectionClosed.bind(this)); } /** * @param {string} data */ _dispatchMessageWrapped(data) { try { const message = JSON.parse(data); if (!(message instanceof Object)) { this._sendErrorResponse(message['id'], 'Malformed message'); return; } this._dispatchMessage(message); } catch (e) { this._sendErrorResponse(message['id'], e.toString() + ' ' + e.stack); } } /** * @param {!Object} message */ _dispatchMessage(message) { const domainAndMethod = message['method'].split('.'); const serviceName = domainAndMethod[0]; const method = domainAndMethod[1]; if (method === 'create') { const extensions = self.runtime.extensions(Service).filter(extension => extension.descriptor()['name'] === serviceName); if (!extensions.length) { this._sendErrorResponse(message['id'], 'Could not resolve service \'' + serviceName + '\''); return; } extensions[0].instance().then(object => { const id = String(this._lastObjectId++); object.setNotify(this._notify.bind(this, id, serviceName)); this._objects.set(id, object); this._sendResponse(message['id'], {id: id}); }); } else if (method === 'dispose') { const object = this._objects.get(message['params']['id']); if (!object) { console.error('Could not look up object with id for ' + JSON.stringify(message)); return; } this._objects.delete(message['params']['id']); object.dispose().then(() => this._sendResponse(message['id'], {})); } else { if (!message['params']) { console.error('No params in the message: ' + JSON.stringify(message)); return; } const object = this._objects.get(message['params']['id']); if (!object) { console.error('Could not look up object with id for ' + JSON.stringify(message)); return; } const handler = object[method]; if (!(handler instanceof Function)) { console.error('Handler for \'' + method + '\' is missing.'); return; } object[method](message['params']).then(result => this._sendResponse(message['id'], result)); } } _connectionClosed() { for (const object of this._objects.values()) object.dispose(); this._objects.clear(); } /** * @param {string} objectId * @param {string} serviceName * @param {string} method * @param {!Object} params */ _notify(objectId, serviceName, method, params) { params['id'] = objectId; const message = {method: serviceName + '.' + method, params: params}; this._port.send(JSON.stringify(message)); } /** * @param {string} messageId * @param {!Object} result */ _sendResponse(messageId, result) { const message = {id: messageId, result: result}; this._port.send(JSON.stringify(message)); } /** * @param {string} messageId * @param {string} error */ _sendErrorResponse(messageId, error) { const message = {id: messageId, error: error}; this._port.send(JSON.stringify(message)); } }; /** * @implements {ServicePort} * @unrestricted */ WorkerServicePort = class { /** * @param {!Port|!Worker} port */ constructor(port) { this._port = port; this._port.onmessage = this._onMessage.bind(this); this._port.onerror = console.error; } /** * @override * @param {function(string)} messageHandler * @param {function(string)} closeHandler */ setHandlers(messageHandler, closeHandler) { this._messageHandler = messageHandler; this._closeHandler = closeHandler; } /** * @override * @param {string} data * @return {!Promise} */ send(data) { this._port.postMessage(data); return Promise.resolve(); } /** * @override * @return {!Promise} */ close() { return Promise.resolve(); } /** * @param {!MessageEvent} event */ _onMessage(event) { this._messageHandler(event.data); } }; const dispatchers = []; const worker = /** @type {!Object} */ (self); const servicePort = new WorkerServicePort(/** @type {!Worker} */ (worker)); dispatchers.push(new ServiceDispatcher(servicePort));