Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Work in progress, major refactor

  • Loading branch information...
commit 668b1eb7a4849f963cce6b079bf72ea8a6b300c0 1 parent d223b4a
@c4milo authored
View
119 index.js
@@ -2,19 +2,28 @@ var agents = require('./lib');
var spawn = require('child_process').spawn;
var WebSocketServer = require('ws').Server;
-var DevToolsAgent = function() {
+/**
+ * DevToolsAgent
+ * @constructor
+ **/
+var DevToolsAgent = module.exports = function() {
+ this.loadedAgents = {};
this.proxy = null;
this.server = null;
this.socket = null;
- this.agents = {};
};
(function() {
- //Private variables
- var proxyPID = 0;
-
- //Private functions
- var spawnProxy = function() {
+ /**
+ * Spawns a new process with a websockets service proxy
+ * to serve devtools front-end requests.
+ *
+ * All the messages but debugging messages
+ * are sent to the main process. Debugger Agent lives in this proxy.
+ *
+ * @api private
+ **/
+ this.spawnProxy = function() {
var self = this;
//Parent PID for the proxy to know to whom to send the SIGUSR1 signal
@@ -24,7 +33,6 @@ var DevToolsAgent = function() {
env: process.env,
cwd: __dirname
});
- proxyPID = this.proxy.pid;
this.proxy.stderr.setEncoding('utf8');
this.proxy.stderr.on('data', function (data) {
@@ -35,20 +43,32 @@ var DevToolsAgent = function() {
this.proxy.stdout.on('data', function (data) {
console.log(data);
});
- }.bind(this);
+ };
- var onProxyConnection = function(socket) {
+ /**
+ * Proxy connection handler
+ *
+ * @param {net.Socket} socket The just opened network socket.
+ * @api private
+ **/
+ this.onProxyConnection = function(socket) {
console.log('webkit-devtools-agent: A proxy got connected.');
console.log('webkit-devtools-agent: Waiting for commands...');
this.socket = socket;
- this.socket.on('message', onProxyData);
+ this.socket.on('message', this.onProxyData.bind(this));
this.socket.on('error', function(error) {
console.error(error);
});
- }.bind(this);
+ };
- var onProxyData = function(message) {
+ /**
+ * Handler for data events coming from the proxy process.
+ *
+ * @param {String} message A message coming from the proxy process.
+ * @api private
+ **/
+ this.onProxyData = function(message) {
var self = this;
try {
@@ -60,7 +80,7 @@ var DevToolsAgent = function() {
var id = data.id;
var command = data.method.split('.');
- var domain = this.agents[command[0]];
+ var domain = this.loadedAgents[command[0]];
var method = command[1];
var params = data.params;
@@ -77,28 +97,42 @@ var DevToolsAgent = function() {
self.socket.send(JSON.stringify(response));
});
- }.bind(this);
+ };
- var sendEvent = function(data) {
+ /**
+ * Notification function in charge of sending events
+ * to the front-end following the protocol specified
+ * at https://developers.google.com/chrome-developer-tools/docs/protocol/1.0
+ *
+ * @param {Object} A notification object that follows devtools protocol 1.0
+ * @api private
+ **/
+ this.notify = function(notification) {
if (!this.socket) return;
- this.socket.send(JSON.stringify(data));
- }.bind(this);
+ this.socket.send(JSON.stringify(notification));
+ };
- var loadAgents = function() {
- var self = this;
+ /**
+ * Loads every agent required at the top of this file.
+ * @private
+ **/
- var runtimeAgent = new agents.Runtime(sendEvent);
- this.agents = {};
+ this.loadAgents = function() {
+ var runtimeAgent = new agents.Runtime(this.notify.bind(this));
for (var agent in agents) {
if (typeof agents[agent] == 'function' && agent != 'Runtime') {
- this.agents[agent] = new agents[agent](sendEvent, runtimeAgent);
+ this.loadedAgents[agent] = new agents[agent](this.notify.bind(this), runtimeAgent);
}
}
- this.agents.Runtime = runtimeAgent;
- }.bind(this);
+ this.loadedAgents.Runtime = runtimeAgent;
+ };
- // Public functions
+ /**
+ * Starts node-webkit-agent
+ *
+ * @api public
+ **/
this.start = function() {
var self = this;
@@ -114,24 +148,29 @@ var DevToolsAgent = function() {
'service process...');
//Spawns webkit devtools proxy / websockets server
- spawnProxy();
+ self.spawnProxy();
- loadAgents();
+ self.loadAgents();
});
- this.server.on('connection', onProxyConnection);
+ this.server.on('connection', this.onProxyConnection.bind(this));
};
+ /**
+ * Stops node-webkit-agent
+ *
+ * @api public
+ **/
this.stop = function() {
console.log('webkit-devtools-agent: Terminating websockets service' +
- ' with PID: ' + proxyPID + '...');
+ ' with PID: ' + this.proxy.pid + '...');
if (this.socket) {
- this.socket.end();
+ this.socket.close();
+ this.socket = null;
}
- if (proxyPID) {
- process.kill(proxyPID, 'SIGTERM');
- proxyPID = 0;
+ if (this.proxy && this.proxy.pid) {
+ process.kill(this.proxy.pid, 'SIGTERM');
}
if (this.server) {
@@ -141,9 +180,16 @@ var DevToolsAgent = function() {
};
}).call(DevToolsAgent.prototype);
+/**
+ * Creates an instance of the main function.
+ **/
var nodeAgent = new DevToolsAgent();
-//Prepares signal handler to activate the agent
+/**
+ * Prepares signal handler to activate the agent
+ * upon `SIGUSR2` signal which usually is triggered by `kill -SIGUSR2`
+ * in unix environments.
+ **/
if (!module.parent) {
nodeAgent.start();
} else {
@@ -156,6 +202,9 @@ if (!module.parent) {
});
}
+/**
+ * Avoids process termination due to uncaught exceptions
+ **/
['exit', 'uncaughtException'].forEach(function(e) {
process.on(e, function(e) {
if (e) {
View
8 lib/console.js
@@ -1,8 +1,8 @@
var util = require('util');
-function ConsoleAgent(sendEvent, runtimeAgent) {
+function ConsoleAgent(notify, runtimeAgent) {
var self = this;
- this.sendEvent = sendEvent;
+ this.notify = notify;
this.runtimeAgent = runtimeAgent;
this.enabled = false;
this.messages = [];
@@ -32,7 +32,7 @@ function ConsoleAgent(sendEvent, runtimeAgent) {
//TODO save messages when this agent is disabled.
//self.messages.push(message);
- sendEvent(message);
+ notify(message);
};
});
}
@@ -40,7 +40,7 @@ function ConsoleAgent(sendEvent, runtimeAgent) {
(function() {
this.enable = function(params, sendResult) {
for(var i = 0, len = this.messages.length; i < len; i++) {
- this.sendEvent(this.messages[i]);
+ this.notify(this.messages[i]);
}
sendResult({result: this.enabled});
};
View
237 lib/debugger/debugger-client.js
@@ -1,13 +1,242 @@
+/**
+ * Module dependencies.
+ */
+var net = require('net');
+var util = require('util');
var translator = require('./translator');
-function DebuggerClient() {
+/**
+ * DebuggerClient
+ * This file implements http://code.google.com/p/v8/wiki/DebuggerProtocol
+ * along with the `translator` object
+ *
+ * @param {Function} notify Notification function to send events
+ * straight to DevTools frontend.
+ * @constructor
+ */
-}
+var DebuggerClient = module.exports = function(notify) {
+ this.connection = null;
+ this.connected = false;
+ this.reqSequence = 0;
+ this.requests = {};
+ this.notify = notify;
+ this.queue = [];
+ this.port = 5858;
+};
(function() {
+ /**
+ * Callback function that gets invoked once
+ * a connection to the debuggee process is established.
+ *
+ * @api private
+ */
+ this.onConnect = function() {
+ this.connected = true;
+ this.flushQueue();
+ };
+
+ /**
+ * Callback function to received debug data coming out of
+ * the debugee process.
+ *
+ * @param {Buffer} data Data sent by v8 debug agent
+ * @api private
+ */
+ this.onData = function(data) {
+ data += '';
+ var message = data.split('Content-Length:')[1].split('\r\n\r\n');
+ var length = parseInt(message[0], 10) || 0;
+
+ if (!length) {
+ return;
+ }
+
+ /**
+ * TODO Buffering, I deferred until I find an explicit
+ * case where v8 chunks the response.
+ *
+ * If v8 is not chunking messages then
+ * it's really unlikely that those messages will be
+ * chunked at the application level and usually
+ * TCP proxies don't mess up with application data.
+ */
+
+ var payload = message[1];
+ try {
+ paylaod = JSON.parse(payload);
+ } catch(e) {
+ console.log(e.stack);
+ }
+
+ if (payload.type == 'event') {
+ if (!translate[payload.event]) {
+ console.warn('webkit-devtools-agent: Translator function ' +
+ ' not found for event: ' + payload.event);
+ return;
+ }
+
+ this.notify(translate[payload.event](payload));
+ } else if (payload.type == 'response') {
+ var callback = this.requests[payload.request_seq];
+ if (callback) {
+ callback(translate[payload.command](payload));
+
+ delete this.requests[payload.request_seq];
+ } else {
+ console.warn('webkit-devtools-agent: Unexpected '+
+ 'message was received, there is no callback function '+
+ ' to handle it :( :' + payload);
+ }
+ } else {
+ console.warn('webkit-devtools-agent: Unrecognized ' +
+ 'message type received by DebuggerAgent: ' + payload);
+ }
+
+ };
+
+ /**
+ * Callback function for `close` events in the
+ * connection to the debugee process.
+ *
+ * @api private
+ */
+ this.onClose = function() {
+ this.connected = false;
+ this.connection = null;
+ };
+
+ /**
+ * Callback function for `error` events in the
+ * connection to the debuggee process.
+ *
+ * @param {Buffer} error JSON containing the error.
+ * @api private
+ */
+ this.onError = function(error) {
+ console.error(error);
+ };
+
+ /**
+ * Flushes the internal queue, sending
+ * all the queued messages if
+ * there is a valid connection to the
+ * debugee process.
+ *
+ * @api private
+ */
+ this.flushQueue = function() {
+ if (!this.connected) {
+ return;
+ }
+
+ var queue = this.queue;
+
+ for (var i = 0, len = queue.length; i < len; i++) {
+ var message = queue[i];
+ this.connection.write('Content-Length: ' +
+ message.length + '\r\n\r\n' + message)
+ }
+
+ };
+
+ /**
+ * Sends out message to the debugee process
+ * through an internal queue.
+ *
+ * @param {Object} data Object to be sent
+ * @param {Function} callback Callback function
+ * to invoke once the debug agent, in the debugee process,
+ * get back to us with a response.
+ *
+ * @api public
+ */
+ this.send = function(data, callback) {
+ this.reqSequence++;
+ data.seq = this.reqSequence;
+
+ /**
+ * Once the response comes back, the
+ * `callback` function is going to be invoked and
+ * removed from the list of pending response handlers.
+ */
+ this.requests[data.seq] = callback;
+
+ /**
+ * This queue avoids some race conditions,
+ * especially in the devtools front-end
+ * initialization.
+ */
+ this.queue.push(data);
+
+ //Flushes only if this.connected is true
+ this.flushQueue();
+
+ if (this.queue.length > 50) {
+ console.warn('webkit-devtools-agent: Debugger client ' +
+ 'queue is too big. The client was unable ' +
+ 'to establish a connection with the v8 debug agent. ' +
+ 'Restart the agent and start your debugging session again.');
+ }
+ };
+
+ /**
+ * Establishes a connection to the
+ * Debug Agent of the debuggee process and
+ * sets up the callbacks to some events.
+ *
+ * @param {Function} callback Callback function
+ * @api public
+ */
this.connect = function(callback) {
- callback(translator.result({}));
+ this.connection = net.connect(this.port);
+ this.connection.setEncoding('utf8');
+
+ this.connection.on('connect', this.onConnect.bind(this));
+ this.connection.on('data', this.onData.bind(this));
+ this.connection.on('close', this.onClose.bind(this));
+ this.connection.on('error', this.onError.bind(this));
+
+ callback(translator.emptyResult());
+ };
+
+ /**
+ * Disconnects from the debuggee process
+ *
+ * @param {Function} callback Callback function
+ * @api public
+ */
+ this.disconnect = function(callback) {
+ this.connection.end();
+ callback();
+ };
+
+ /**
+ * Defines pause on exceptions state.
+ * Can be set to stop on `all` exceptions,
+ * `uncaught` exceptions or no exceptions.
+ * Initial pause on exceptions state is none.
+ *
+ * @param {String} exceptionBreak Type of exception break
+ * it can be `all` or `uncaught`.
+ * @param {Function} callback Callback function to send back
+ * the answer to this command. The response is returned
+ * in the DevTools Remote Protocol format specified in:
+ * https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/debugger#command-setPauseOnExceptions
+ * @api public
+ */
+ this.setExceptionBreak = function(exceptionBreak, callback) {
+ var request = {
+ type: 'request',
+ command: 'setexceptionbreak',
+ arguments: {
+ type: exceptionBreak,
+ enabled: true
+ }
+ };
+
+ this.send(request, callback);
};
}).call(DebuggerClient.prototype);
-module.exports = DebuggerClient;
View
65 lib/debugger/index.js
@@ -1,18 +1,40 @@
+/**
+ * Module dependencies.
+ */
var DebuggerClient = require('./debugger-client');
-function DebuggerAgent(debuggedProcess) {
+/**
+ * DebuggerAgent
+ *
+ * This file implements
+ * https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/debugger
+ *
+ * @param {Number} debuggee Process ID of the debuggee nodejs process.
+ * @constructor
+ */
+var DebuggerAgent = module.exports = function(debuggee) {
this.enabled = false;
- this.debuggedProcess = debuggedProcess;
- this.client = new DebuggerClient();
-}
+ this.debuggee = debuggee; //process being debugged
+ this.pauseOnExceptions = 'none'; //possible values are: none, all, uncaught
+};
(function(){
+ /**
+ * Initializes agent.
+ * @api public
+ */
this.initialize = function(notify) {
this.notify = notify;
+ this.client = new DebuggerClient(this.notify);
};
this.setPauseOnExceptions = function(params, sendResult) {
- sendResult({result: false});
+ var self = this;
+ this.pauseOnExceptions = params.state;
+
+ self.client.setExceptionBreak(this.pauseOnExceptions, function(data) {
+ sendResult(data);
+ });
};
this.causesRecompilation = function(params, sendResult) {
@@ -28,15 +50,19 @@ function DebuggerAgent(debuggedProcess) {
};
this.enable = function(params, sendResult) {
+ var self = this;
if (this.enabled) {
return;
}
- process.kill(this.debuggedProcess, 'SIGUSR1');
+ process.kill(this.debuggee, 'SIGUSR1');
- this.client.connect(function(data) {
- sendResult(data);
- });
+ setTimeout(function() {
+ self.client.connect(function(data) {
+ sendResult(data);
+ self.enabled = true;
+ });
+ }, 1000);
};
this.disable = function(params, sendResult) {
@@ -52,29 +78,8 @@ function DebuggerAgent(debuggedProcess) {
this.client.setBreakpoint(params, function(breakId) {
sendResult();
});
- /*var breakId = this.Debug.setScriptBreakPointByName( params.url,
- params.lineNumber,
- params.columnNumber,
- params.condition,
- 1);
- */
- var locations = this.Debug.findBreakPointActualLocations(breakId);
- if (!locations.length) {
- console.log('Unable to set breakpoint by URL');
- return;
- }
-
- sendResult({
- breakpointId: breakId.toString(),
- locations: [{
- lineNumber: locations[0].line,
- columnNumber: locations[0].column,
- scriptId: locations[0].script_id.toString()
- }]
- });
};
}).call(DebuggerAgent.prototype);
-module.exports = DebuggerAgent;
View
47 lib/debugger/translator.js
@@ -1,6 +1,51 @@
+/**
+ * @fileoverview
+ * Transforms http://code.google.com/p/v8/wiki/DebuggerProtocol
+ * to https://developers.google.com/chrome-developer-tools/docs/protocol/1.0
+ **/
+
+var formatScript = function(script) {
+ var lineEnds = script.line_ends;
+ var lineCount = lineEnds.length;
+ var endLine = script.line_offset + lineCount - 1;
+ var endColumn;
+ // V8 will not count last line if script source ends with \n.
+ if (script.source[script.source.length - 1] === '\n') {
+ endLine += 1;
+ endColumn = 0;
+ } else {
+ if (lineCount === 1)
+ endColumn = script.source.length + script.column_offset;
+ else
+ endColumn = script.source.length - (lineEnds[lineCount - 2] + 1);
+ }
+
+ return {
+ id: script.id,
+ name: script.nameOrSourceURL(),
+ source: script.source,
+ startLine: script.line_offset,
+ startColumn: script.column_offset,
+ endLine: endLine,
+ endColumn: endColumn,
+ isContentScript: !!script.context_data && script.context_data.indexOf("injected") == 0
+ };
+};
+
module.exports = {
- result: function(v8data) {
+ emptyResult: function() {
var devtoolsFormat = {};
return devtoolsFormat;
+ },
+
+ afterCompile: function(eventData) {
+ return {
+ method: 'Debugger.afterCompile',
+ params:{}
+ };
+ },
+
+ setexceptionbreak: function(response) {
+ return {};
}
};
View
22 lib/profiler.js
@@ -4,9 +4,9 @@ var fs = require('fs');
var HeapProfileType = 'HEAP';
var CPUProfileType = 'CPU';
-function ProfilerAgent(sendEvent) {
- this.sendEvent = sendEvent;
- this.profiles = {
+function ProfilerAgent(notify) {
+ this.notify = notify;
+ this.profiles = {
HEAP: {},
CPU: {}
};
@@ -54,7 +54,7 @@ function ProfilerAgent(sendEvent) {
this.takeHeapSnapshot = function(params, sendResult) {
var self = this;
var snapshot = profiler.takeSnapshot(function(done, total) {
- self.sendEvent({
+ self.notify({
method: 'Profiler.reportHeapSnapshotProgress',
params:{
done: done,
@@ -65,7 +65,7 @@ function ProfilerAgent(sendEvent) {
this.profiles[HeapProfileType][snapshot.uid] = snapshot;
- this.sendEvent({
+ this.notify({
method: 'Profiler.addProfileHeader',
params: {
header: {
@@ -87,7 +87,7 @@ function ProfilerAgent(sendEvent) {
snapshot.serialize({
onData: function(chunk, size) {
chunk = chunk + '';
- self.sendEvent({
+ self.notify({
method: 'Profiler.addHeapSnapshotChunk',
params: {
uid: snapshot.uid,
@@ -97,7 +97,7 @@ function ProfilerAgent(sendEvent) {
},
onEnd: function() {
- self.sendEvent({
+ self.notify({
method: 'Profiler.finishHeapSnapshot',
params: {uid: snapshot.uid}
});
@@ -107,7 +107,7 @@ function ProfilerAgent(sendEvent) {
title: snapshot.title,
uid: snapshot.uid,
typeId: HeapProfileType
- }
+ }
});
}
});
@@ -142,7 +142,7 @@ function ProfilerAgent(sendEvent) {
profiler.startProfiling();
- this.sendEvent({
+ this.notify({
method: 'Profiler.setRecordingProfile',
params: {
isProfiling: true
@@ -157,7 +157,7 @@ function ProfilerAgent(sendEvent) {
this.profiles[CPUProfileType][profile.uid] = profile;
- this.sendEvent({
+ this.notify({
method: 'Profiler.addProfileHeader',
params: {
header: {
@@ -168,7 +168,7 @@ function ProfilerAgent(sendEvent) {
}
});
- this.sendEvent({
+ this.notify({
method: 'Profiler.setRecordingProfile',
params: {
isProfiling: false
View
172 webkit-devtools-agent.js
@@ -3,92 +3,144 @@ var Debugger = require('./lib/debugger');
var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server;
-var DevToolsAgentProxy = function() {
+var DevToolsAgentProxy = module.exports = function() {
this.wss = null;
+ this.backend = null;
+ this.frontend = null;
+ this.debuggerAgent = null;
this.port = process.env.DEBUG_PORT || 9999;
this.host = process.env.DEBUG_HOST || '127.0.0.1';
};
(function() {
- var self = this;
process.on('uncaughtException', function (err) {
console.error('webkit-devtools-agent: Websockets service uncaught exception: ');
console.error(err.stack);
});
- this.start = function() {
+ this.onFrontendMessage = function(message) {
var self = this;
+ var data;
+ try {
+ data = JSON.parse(message);
+ } catch(e) {
+ console.log(e.stack);
+ }
+ var command = data.method.split('.');
+ var domainName = command[0];
+
+ if (domainName !== 'Debugger') {
+ this.backend.send(message);
+ return;
+ }
+
+ var id = data.id;
+ var method = command[1];
+ var params = data.params;
+
+ if (!this.debuggerAgent[method]) {
+ console.warn('%s is not implemented', data.method);
+ return;
+ }
+
+ this.debuggerAgent[method](params, function(result) {
+ var response = {
+ id: id,
+ result: result
+ };
+ self.frontend.send(JSON.stringify(response));
+ });
+ };
+
+ this.onFrontendConnection = function(socket) {
+ var self = this;
+ this.frontend = socket;
+
+ this.frontend.on('message', this.onFrontendMessage.bind(this));
- var debuggerAgent = new Debugger(process.env.PARENT_PID);
-
- var backend = new WebSocket('ws://localhost:3333');
- backend.on('open', function() {
- //Starts websockets server for devtools front-end
- self.wss = new WebSocketServer({
- port: self.port,
- host: self.host
- });
-
- console.log('webkit-devtools-agent: Websockets ' +
- 'service started on %s:%s', self.host, self.port);
-
- self.wss.on('connection', function(socket) {
- backend.on('message', function(message) {
- socket.send(message);
- });
-
- socket.on('message', function(message) {
- var data;
- try {
- data = JSON.parse(message);
- } catch(e) {
- console.log(e.stack);
- }
- var command = data.method.split('.');
- var domainName = command[0];
-
- if (domainName !== 'Debugger') {
- backend.send(message);
- return;
- }
-
- debuggerAgent.initialize(function(notification) {
- socket.send(JSON.stringify(notification));
- });
-
- var id = data.id;
- var method = command[1];
- var params = data.params;
-
- if (!debuggerAgent[method]) {
- console.warn('%s is not implemented', data.method);
- return;
- }
-
- debuggerAgent[method](params, function(result) {
- var response = {
- id: id,
- result: result
- };
- socket.send(JSON.stringify(response));
- });
- });
- });
+ console.log('webkit-devtools-agent: new frontend connection!');
+
+ this.debuggerAgent = new Debugger(process.env.PARENT_PID);
+
+ this.debuggerAgent.initialize(function(notification) {
+ self.frontend.send(JSON.stringify(notification));
});
};
+ /**
+ * Callback function invoked once
+ * a connection has been established
+ * with the backend process. It also
+ * initializes the websocket service
+ * for DevTools frontend to connect with.
+ *
+ * @api private
+ */
+ this.onBackendOpen = function() {
+ //Starts websockets server for DevTools frontend
+ this.wss = new WebSocketServer({
+ port: this.port,
+ host: this.host
+ });
+
+ console.log('webkit-devtools-agent: Websockets ' +
+ 'service started on %s:%s', this.host, this.port);
+
+ this.wss.on('connection', this.onFrontendConnection.bind(this));
+ };
+
+ /**
+ * Callback function that forwards agent responses
+ * to DevTools frontend except for the Debugger
+ * agent which lives in the current process.
+ *
+ * @param {String} message JSON message as it comes from
+ * the main process.
+ * @api private
+ */
+ this.onBackendMessage = function(message) {
+ if (!this.frontend) return;
+
+ this.frontend.send(message);
+ };
+
+ /**
+ * Starts proxy process.
+ * This process is in charge of receiving
+ * messages from DevTools frontend and forward them
+ * to the main process.
+ *
+ * DebuggerAgent is an exception to the rule of having
+ * all the agents in the main process. Given
+ * that the main process is going to be in debug mode
+ * we need the DebuggerAgent to live in a different process
+ * so that it can continue working and be responsive
+ * with DevTools frontend.
+ *
+ * @api public
+ **/
+ this.start = function() {
+ this.backend = new WebSocket('ws://localhost:3333');
+ this.backend.on('open', this.onBackendOpen.bind(this));
+ this.backend.on('message', this.onBackendMessage.bind(this));
+ };
+
+ /**
+ * Stops proxy process
+ *
+ * @api public
+ **/
this.stop = function() {
if (this.wss) {
this.wss.close();
this.wss = null;
console.log('webkit-devtools-agent: Websockets service with PID ' +
- process.pid + ' stopped');
+ process.pid + ' has stopped');
}
};
}).call(DevToolsAgentProxy.prototype);
var proxy = new DevToolsAgentProxy();
-
proxy.start();
['exit', 'SIGTERM', 'SIGHUP'].forEach(function(s) {
Please sign in to comment.
Something went wrong with that request. Please try again.