From 13f36b3f79a54bbf45b67a9e8f2a34b9659b9689 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Tue, 28 Apr 2015 15:47:26 +0200 Subject: [PATCH] Various code simplifications and fixes. --- src/connection.js | 31 ++++++++----------------------- src/index.js | 29 ++++++++++++++++------------- src/xo.js | 24 ++++++++++++------------ 3 files changed, 36 insertions(+), 48 deletions(-) diff --git a/src/connection.js b/src/connection.js index a604f16ca..ed128f48c 100644 --- a/src/connection.js +++ b/src/connection.js @@ -2,43 +2,28 @@ import {EventEmitter} from 'events' // =================================================================== -const has = (function () { - return (val, prop) => hasOwnProperty.call(val, prop) -})(Object.hasOwnProperty) - -const noop = () => {} +// const noop = () => {} // =================================================================== export default class Connection extends EventEmitter { - constructor ({close, notify}) { + constructor () { super() - this._close = close - this.data = Object.create(null) - this.notify = notify + this._data = Object.create(null) } // Close the connection. close () { // Prevent errors when the connection is closed more than once. - this.close = noop - - this._close() + // this.close = noop this.emit('close') - - // Releases values AMAP to ease the garbage collecting. - for (let key in this) { - if (key !== 'close' && has(this, key)) { - delete this[key] - } - } } // Gets the value for this key. get (key, defaultValue) { - const {data} = this + const {_data: data} = this if (key in data) { return data[key] @@ -53,15 +38,15 @@ export default class Connection extends EventEmitter { // Checks whether there is a value for this key. has (key) { - return key in this.data + return key in this._data } // Sets the value for this key. set (key, value) { - this.data[key] = value + this._data[key] = value } unset (key) { - delete this.data[key] + delete this._data[key] } } diff --git a/src/index.js b/src/index.js index c926a4003..03db2fb72 100644 --- a/src/index.js +++ b/src/index.js @@ -206,33 +206,32 @@ const setUpApi = (webServer, xo) => { path: '/api/' }) - webSocketServer.on('connection', connection => { + webSocketServer.on('connection', socket => { debug('+ WebSocket connection') - let xoConnection + // Create the abstract XO object for this connection. + const connection = xo.createUserConnection() + connection.once('close', () => { + socket.close() + }) // Create the JSON-RPC server for this connection. const jsonRpc = createJsonRpcServer(message => { if (message.type === 'request') { - return api.call(xoConnection, message.method, message.params) + return api.call(connection, message.method, message.params) } }) - - // Create the abstract XO object for this connection. - xoConnection = xo.createUserConnection({ - close: bind(connection.close, connection), - notify: bind(jsonRpc.notify, jsonRpc) - }) + connection.notify = bind(jsonRpc.notify, jsonRpc) // Close the XO connection with this WebSocket. - connection.once('close', () => { + socket.once('close', () => { debug('- WebSocket connection') - xoConnection.close() + connection.close() }) // Connect the WebSocket to the JSON-RPC server. - connection.on('message', message => { + socket.on('message', message => { jsonRpc.write(message) }) @@ -242,7 +241,11 @@ const setUpApi = (webServer, xo) => { } } jsonRpc.on('data', data => { - connection.send(JSON.stringify(data), onSend) + // The socket may have been closed during the API method + // execution. + if (socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify(data), onSend) + } }) }) } diff --git a/src/xo.js b/src/xo.js index 8b4f2b8e1..2232e85a7 100644 --- a/src/xo.js +++ b/src/xo.js @@ -123,7 +123,9 @@ export default class Xo extends EventEmitter { let exited = {} let dispatcherRegistered = false - const dispatcher = () => { + const dispatcher = Bluebird.method(() => { + dispatcherRegistered = false + const {connections} = this if (!isEmpty(entered)) { @@ -131,6 +133,7 @@ export default class Xo extends EventEmitter { type: 'enter', items: pluck(entered, 'val') } + entered = {} for (let id in connections) { const connection = connections[id] @@ -139,15 +142,14 @@ export default class Xo extends EventEmitter { connection.notify('all', enterParams) } } - - entered = {} } - if (!isEmpty(entered)) { + if (!isEmpty(exited)) { const exitParams = { type: 'exit', items: pluck(exited, 'val') } + exited = {} for (let id in connections) { const connection = connections[id] @@ -156,10 +158,8 @@ export default class Xo extends EventEmitter { connection.notify('all', exitParams) } } - - exited = {} } - } + }) this._xobjs.on('any', (event, items) => { if (!dispatcherRegistered) { @@ -326,16 +326,16 @@ export default class Xo extends EventEmitter { // ----------------------------------------------------------------- - createUserConnection (opts) { + createUserConnection () { const {connections} = this - const connection = new Connection(opts) + const connection = new Connection() const id = connection.id = this._nextConId++ - connection.on('close', () => { - connections[id] - }) connections[id] = connection + connection.on('close', () => { + delete connections[id] + }) return connection }