UNPKG

guvnor

Version:

A node process manager that isn't spanners all the way down

199 lines (168 loc) 4.88 kB
// "Borrowed" from node-inspector var CallbackHandler = { /** * Create a callback container * @return {Object} that wraps callbacks and returns a one-time id. */ create: function () { var lastId = 1, callbacks = {} return Object.create({}, { wrap: { value: function (callback) { var callbackId = lastId++ callbacks[callbackId] = callback || function () { } return callbackId } }, processResponse: { value: function (callbackId, args) { var callback = callbacks[callbackId] if (callback) { callback.apply(null, args) } delete callbacks[callbackId] } }, removeResponseCallbackEntry: { value: function (callbackId) { delete callbacks[callbackId] } } }) } } var Net = require('net'), Protocol = require('_debugger').Protocol, inherits = require('util').inherits, EventEmitter = require('events').EventEmitter, debugProtocol = require('debug')('node-inspector:protocol:v8-debug'), callbackHandler = CallbackHandler.create() /** * @param {Number} port */ function Debugger(port) { this._port = port this._connected = false this._connection = null this._lastError = null this._setupConnection() } inherits(Debugger, EventEmitter) Object.defineProperties(Debugger.prototype, { /** @type {boolean} */ isRunning: {writable: true, value: true}, /** @type {boolean} */ connected: { get: function () { return this._connected } } }) Debugger.prototype._setupConnection = function () { var connection = Net.createConnection(this._port), protocol = new Protocol() protocol.onResponse = this._processResponse.bind(this) connection .on('connect', this._onConnectionOpen.bind(this)) .on('data', protocol.execute.bind(protocol)) .on('error', this._onConnectionError.bind(this)) .on('end', this.close.bind(this)) .on('close', this._onConnectionClose.bind(this)) .setEncoding('utf8') this._connection = connection } Debugger.prototype._onConnectionOpen = function () { this._connected = true this.emit('connect') } /** * @param {Error} err */ Debugger.prototype._onConnectionError = function (err) { if (err.code == 'ECONNREFUSED') { err.helpString = 'Is node running with --debug port ' + this._port + '?' } else if (err.code == 'ECONNRESET') { err.helpString = 'Check there is no other debugger client attached to port ' + this._port + '.' } this._lastError = err.toString() if (err.helpString) { this._lastError += '. ' + err.helpString } this.emit('error', err) } Debugger.prototype._onConnectionClose = function (hadError) { this.emit('close', hadError ? this._lastError : 'Debugged process exited.') this._port = null this._connected = false this._connection = null this._lastError = null } Debugger.prototype._processResponse = function (message) { var obj = message.body if (typeof obj.running === 'boolean') { this.isRunning = obj.running } if (obj.type === 'response' && obj.request_seq > 0) { debugProtocol('response: ' + JSON.stringify(message.body)) callbackHandler.processResponse(obj.request_seq, [obj]) } else if (obj.type === 'event') { debugProtocol('event: ' + JSON.stringify(message.body)) if (['break', 'exception'].indexOf(obj.event) > -1) { this.isRunning = false } this.emit(obj.event, obj) } else { debugProtocol('unknown: ' + JSON.stringify(message.body)) } } /** * @param {string} data */ Debugger.prototype.send = function (data) { debugProtocol('request: ' + data) if (this.connected) { this._connection.write('Content-Length: ' + Buffer.byteLength(data, 'utf8') + '\r\n\r\n' + data) } } /** * @param {string} command * @param {Object} params * @param {function} callback */ Debugger.prototype.request = function (command, params, callback) { var message = { seq: 0, type: 'request', command: command } if (typeof callback === 'function') { message.seq = callbackHandler.wrap(callback) } if (params) { Object.keys(params).forEach(function (key) { message[key] = params[key] }) } this.send(JSON.stringify(message)) } /** */ Debugger.prototype.close = function () { this._connection.end() } module.exports = function (debugPort, callback) { // give the process time to start up setTimeout(function () { var debuggerClient = new Debugger(debugPort) debuggerClient.on('error', callback) debuggerClient.on('connect', function () { debuggerClient.request('continue', undefined, function (response) { debuggerClient.close() if (!response.success) return callback(new Error('Could not continue process')) callback() }) }) }, 1000) }