From 0df804b9e7b509797e652a0e8657989023a01911 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Sat, 18 Dec 2010 11:17:29 -0800
Subject: [PATCH 01/46] start debug agent on SIGUSR1
---
src/node.cc | 86 ++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 58 insertions(+), 28 deletions(-)
diff --git a/src/node.cc b/src/node.cc
index 9d8405571f..04a96a4187 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -87,6 +87,7 @@ static ev_idle tick_spinner;
static bool need_tick_cb;
static Persistent tick_callback_sym;
+static ev_async enable_debug;
static ev_async eio_want_poll_notifier;
static ev_async eio_done_poll_notifier;
static ev_idle eio_poller;
@@ -1862,6 +1863,41 @@ static void SignalExit(int signal) {
}
+static void EnableDebugSignalHandler(int signal) {
+ // can't do much here, marshal this back into the main thread where we'll
+ // enable the debugger.
+ ev_async_send(EV_DEFAULT_UC_ &enable_debug);
+}
+
+
+static void EnableDebug(bool wait_connect) {
+ // Start the debug thread and it's associated TCP server on port 5858.
+ bool r = Debug::EnableAgent("node " NODE_VERSION, debug_port);
+
+ if (wait_connect) {
+ // Set up an empty handler so v8 will not continue until a debugger
+ // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
+ // except we don't break at the beginning of the script.
+ // see Debugger::StartAgent in debug.cc of v8/src
+ Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
+ }
+
+ // Crappy check that everything went well. FIXME
+ assert(r);
+
+ // Print out some information.
+ fprintf(stderr, "debugger listening on port %d\r\n", debug_port);
+}
+
+
+static void EnableDebug2(EV_P_ ev_async *watcher, int revents) {
+ assert(watcher == &enable_debug);
+ assert(revents == EV_ASYNC);
+ EnableDebug(false);
+}
+
+
+
static int RegisterSignalHandler(int signal, void (*handler)(int)) {
struct sigaction sa;
@@ -1967,37 +2003,31 @@ int Start(int argc, char *argv[]) {
V8::SetFatalErrorHandler(node::OnFatalError);
+
+ // Initialize the async watcher for receiving messages from the debug
+ // thread and marshal it into the main thread. DebugMessageCallback()
+ // is called from the main thread to execute a random bit of javascript
+ // - which will give V8 control so it can handle whatever new message
+ // had been received on the debug thread.
+ ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
+ ev_set_priority(&node::debug_watcher, EV_MAXPRI);
+ // Set the callback DebugMessageDispatch which is called from the debug
+ // thread.
+ Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
+ // Start the async watcher.
+ ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
+ // unref it so that we exit the event loop despite it being active.
+ ev_unref(EV_DEFAULT_UC);
+
+
// If the --debug flag was specified then initialize the debug thread.
if (node::use_debug_agent) {
- // Initialize the async watcher for receiving messages from the debug
- // thread and marshal it into the main thread. DebugMessageCallback()
- // is called from the main thread to execute a random bit of javascript
- // - which will give V8 control so it can handle whatever new message
- // had been received on the debug thread.
- ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
- ev_set_priority(&node::debug_watcher, EV_MAXPRI);
- // Set the callback DebugMessageDispatch which is called from the debug
- // thread.
- Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
- // Start the async watcher.
- ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
- // unref it so that we exit the event loop despite it being active.
+ EnableDebug(debug_wait_connect);
+ } else {
+ RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler);
+ ev_async_init(&enable_debug, EnableDebug2);
+ ev_async_start(EV_DEFAULT_UC_ &enable_debug);
ev_unref(EV_DEFAULT_UC);
-
- // Start the debug thread and it's associated TCP server on port 5858.
- bool r = Debug::EnableAgent("node " NODE_VERSION, node::debug_port);
- if (node::debug_wait_connect) {
- // Set up an empty handler so v8 will not continue until a debugger
- // attaches. This is the same behavior as Debug::EnableAgent(_,_,true)
- // except we don't break at the beginning of the script.
- // see Debugger::StartAgent in debug.cc of v8/src
- Debug::SetMessageHandler2(node::DebugBreakMessageHandler);
- }
-
- // Crappy check that everything went well. FIXME
- assert(r);
- // Print out some information.
- printf("debugger listening on port %d\n", node::debug_port);
}
// Create the one and only Context.
From 8d82ec21308812132a71afe45c5bc517b4a43354 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 21 Dec 2010 19:14:29 -0800
Subject: [PATCH 02/46] Add beginning of build-in debugger
+ test-debugger-client (which is currently broken)
---
lib/_debugger.js | 221 ++++++++++++++++++++++++++++
src/node.js | 23 ++-
test/simple/test-debugger-client.js | 63 ++++++++
3 files changed, 300 insertions(+), 7 deletions(-)
create mode 100644 lib/_debugger.js
create mode 100644 test/simple/test-debugger-client.js
diff --git a/lib/_debugger.js b/lib/_debugger.js
new file mode 100644
index 0000000000..9f95e896ce
--- /dev/null
+++ b/lib/_debugger.js
@@ -0,0 +1,221 @@
+var net = require('net');
+var readline = require('readline');
+var inherits = require('util').inherits;
+
+exports.port = 5858;
+
+exports.start = function (pid) {
+ if (pid) {
+ process.kill(pid, "SIGUSR1");
+ setTimeout(tryConnect, 100);
+ } else {
+ tryConnect();
+ }
+};
+
+var c;
+
+function tryConnect() {
+ c = new Client();
+
+ process.stdout.write("connecting...");
+ c.connect(exports.port, function () {
+ process.stdout.write("ok\r\n");
+ startInterface();
+ });
+
+}
+
+//
+// Parser/Serializer for V8 debugger protocol
+// http://code.google.com/p/v8/wiki/DebuggerProtocol
+//
+// Usage:
+// p = new Protocol();
+//
+// p.onResponse = function (res) {
+// // do stuff with response from V8
+// };
+//
+// socket.setEncoding('utf8');
+// socket.on('data', function (s) {
+// // Pass strings into the protocol
+// p.execute(s);
+// });
+//
+//
+function Protocol() {
+ this._newRes();
+}
+exports.Protocol = Protocol;
+
+
+Protocol.prototype._newRes = function(raw) {
+ this.res = { raw: raw || '', headers: {} };
+ this.state = 'headers';
+ this.reqSeq = 1;
+};
+
+
+Protocol.prototype.execute = function(d) {
+ var res = this.res;
+ res.raw += d;
+
+ switch (this.state) {
+ case 'headers':
+ var endHeaderIndex = res.raw.indexOf('\r\n\r\n');
+
+ if (endHeaderIndex < 0) break;
+
+ var lines = res.raw.slice(0, endHeaderIndex).split('\r\n');
+ for (var i = 0; i < lines.length; i++) {
+ var kv = lines[i].split(/: +/);
+ res.headers[kv[0]] = kv[1];
+ }
+
+ this.contentLength = +res.headers['Content-Length'];
+ this.bodyStartIndex = endHeaderIndex + 4;
+
+ this.state = 'body';
+ if (res.raw.length - this.bodyStartIndex < this.contentLength) break;
+ // pass thru
+
+ case 'body':
+ if (res.raw.length - this.bodyStartIndex >= this.contentLength) {
+ res.body =
+ res.raw.slice(this.bodyStartIndex,
+ this.bodyStartIndex + this.contentLength);
+ // JSON parse body?
+ res.body = res.body.length ? JSON.parse(res.body) : {};
+
+ // Done!
+ this.onResponse(res);
+
+ this._newRes(res.raw.slice(this.bodyStartIndex + this.contentLength));
+ }
+ break;
+
+ default:
+ throw new Error("Unknown state");
+ break;
+ }
+};
+
+
+Protocol.prototype.serialize = function(req) {
+ req.type = 'request';
+ req.seq = this.reqSeq++;
+ var json = JSON.stringify(req);
+ return 'Content-Length: ' + json.length + '\r\n\r\n' + json;
+};
+
+
+
+
+function Client() {
+ net.Stream.call(this);
+ var protocol = this.protocol = new Protocol(c);
+ this._reqCallbacks = [];
+ var socket = this;
+
+ // Note that 'Protocol' requires strings instead of Buffers.
+ socket.setEncoding('utf8');
+ socket.on('data', function(d) {
+ protocol.execute(d);
+ });
+
+ protocol.onResponse = this._onResponse.bind(this);
+};
+inherits(Client, net.Stream);
+exports.Client = Client;
+
+
+Client.prototype._onResponse = function(res) {
+ console.error(res);
+ for (var i = 0; i < this._reqCallbacks.length; i++) {
+ var cb = this._reqCallbacks[i];
+ if (this._reqCallbacks[i].request_seq == cb.request_seq) break;
+ }
+
+ if (cb) {
+ this._reqCallbacks.splice(i, 1);
+ cb(res.body);
+ } else if (res.headers.Type == 'connect') {
+ // do nothing
+ } else {
+ console.error("unhandled res: %j", res.body);
+ }
+};
+
+
+Client.prototype.req = function(req, cb) {
+ this.write(this.protocol.serialize(req));
+ cb.request_seq = req.seq;
+ this._reqCallbacks.push(cb);
+};
+
+
+Client.prototype.reqVersion = function(cb) {
+ this.req({ command: 'version' } , function (res) {
+ if (cb) cb(res.body.V8Version, res.running);
+ });
+};
+
+
+var helpMessage = "Commands: version, eval, help, quit";
+
+
+function startInterface() {
+
+ var i = readline.createInterface(process.stdout);
+ var stdin = process.openStdin();
+ stdin.addListener('data', function(chunk) {
+ i.write(chunk);
+ });
+
+ var prompt = '> ';
+
+ i.setPrompt(prompt);
+ i.prompt();
+
+ i.on('SIGINT', function() {
+ i.close();
+ });
+
+ i.on('line', function(cmd) {
+ if (cmd == 'quit') {
+ process.exit(0);
+ } else if (/^help/.test(cmd)) {
+ console.log(helpMessage);
+ i.prompt();
+
+ } else if ('version' == cmd) {
+ c.reqVersion(function (v) {
+ console.log(v);
+ i.prompt();
+ });
+
+ } else if (/^eval/.test(cmd)) {
+ var req = {
+ command: 'evaluate',
+ arguments: { 'expression': cmd.slice(5) }
+ };
+
+ c.req(req, function (res) {
+ console.log(res);
+ i.prompt();
+ });
+
+ } else {
+ if (!/^\s*$/.test(cmd)) {
+ // If it's not all white-space print this error message.
+ console.log('Unknown command "%s". Try "help"', cmd);
+ }
+ i.prompt();
+ }
+ });
+
+ i.on('close', function() {
+ stdin.destroy();
+ });
+}
diff --git a/src/node.js b/src/node.js
index 43ccdb0325..4717e65d47 100644
--- a/src/node.js
+++ b/src/node.js
@@ -535,14 +535,23 @@
}
if (process.argv[1]) {
- // Load module
- if (process.argv[1].charAt(0) != '/' &&
- !(/^http:\/\//).exec(process.argv[1])) {
- process.argv[1] = path.join(cwd, process.argv[1]);
+
+ if (process.argv[1] == 'debug') {
+ // Start the debugger agent
+ var d = requireNative('_debugger');
+ var pid = process.argv[2];
+ d.start(pid);
+
+ } else {
+ // Load module
+ if (process.argv[1].charAt(0) != '/' &&
+ !(/^http:\/\//).exec(process.argv[1])) {
+ process.argv[1] = path.join(cwd, process.argv[1]);
+ }
+ // REMOVEME: nextTick should not be necessary. This hack to get
+ // test/simple/test-exception-handler2.js working.
+ process.nextTick(module.runMain);
}
- // REMOVEME: nextTick should not be necessary. This hack to get
- // test/simple/test-exception-handler2.js working.
- process.nextTick(module.runMain);
} else if (process._eval) {
// -e, --eval
diff --git a/test/simple/test-debugger-client.js b/test/simple/test-debugger-client.js
new file mode 100644
index 0000000000..a070b7aa15
--- /dev/null
+++ b/test/simple/test-debugger-client.js
@@ -0,0 +1,63 @@
+var common = require('../common');
+var assert = require('assert');
+var d = require('_debugger');
+
+var spawn = require('child_process').spawn;
+
+
+var resCount = 0;
+var p = new d.Protocol();
+p.onResponse = function (res) {
+ resCount++;
+};
+
+p.execute("Type: connect\r\n" +
+ "V8-Version: 3.0.4.1\r\n" +
+ "Protocol-Version: 1\r\n" +
+ "Embedding-Host: node v0.3.3-pre\r\n" +
+ "Content-Length: 0\r\n\r\n");
+assert.equal(1, resCount);
+
+var n = spawn(process.execPath,
+ ['-e', 'setInterval(function () { console.log("blah"); }, 1000);']);
+
+
+var connected = false;
+
+n.stdout.once('data', function () {
+ console.log("new node process: %d", n.pid);
+ process.kill(n.pid, "SIGUSR1");
+ console.log("signaling it with SIGUSR1");
+
+});
+
+var didTryConnect = false;
+n.stderr.setEncoding('utf8');
+n.stderr.on('data', function (d) {
+ if (didTryConnect == false && /debugger/.test(d)) {
+ didTryConnect = true;
+ tryConnect();
+ }
+})
+
+
+function tryConnect() {
+ // Wait for some data before trying to connect
+ var c = new d.Client();
+ process.stdout.write("connecting...");
+ c.connect(d.port, function () {
+ connected = true;
+ console.log("connected!");
+ });
+
+ c.reqVersion(function (v) {
+ assert.equal(process.versions.v8, v);
+ n.kill();
+ });
+}
+
+
+process.on('exit', function() {
+ assert.ok(connected);
+});
+
From 797aa97e19bbb7b9536e2a7da03012e2db018d23 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 21 Dec 2010 22:31:30 -0800
Subject: [PATCH 03/46] Fix test-debugger-client
---
lib/_debugger.js | 7 ++-
test/simple/test-debugger-client.js | 66 +++++++++++++++--------------
2 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 9f95e896ce..5c0dd55501 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -131,17 +131,16 @@ exports.Client = Client;
Client.prototype._onResponse = function(res) {
- console.error(res);
for (var i = 0; i < this._reqCallbacks.length; i++) {
var cb = this._reqCallbacks[i];
if (this._reqCallbacks[i].request_seq == cb.request_seq) break;
}
- if (cb) {
+ if (res.headers.Type == 'connect') {
+ // do nothing
+ } else if (cb) {
this._reqCallbacks.splice(i, 1);
cb(res.body);
- } else if (res.headers.Type == 'connect') {
- // do nothing
} else {
console.error("unhandled res: %j", res.body);
}
diff --git a/test/simple/test-debugger-client.js b/test/simple/test-debugger-client.js
index a070b7aa15..5239430d40 100644
--- a/test/simple/test-debugger-client.js
+++ b/test/simple/test-debugger-client.js
@@ -1,12 +1,12 @@
var common = require('../common');
var assert = require('assert');
-var d = require('_debugger');
+var debug = require('_debugger');
var spawn = require('child_process').spawn;
var resCount = 0;
-var p = new d.Protocol();
+var p = new debug.Protocol();
p.onResponse = function (res) {
resCount++;
};
@@ -18,46 +18,48 @@ p.execute("Type: connect\r\n" +
"Content-Length: 0\r\n\r\n");
assert.equal(1, resCount);
-var n = spawn(process.execPath,
- ['-e', 'setInterval(function () { console.log("blah"); }, 1000);']);
+var connectCount = 0;
-var connected = false;
+function test(cb) {
+ var nodeProcess = spawn(process.execPath,
+ ['-e', 'setInterval(function () { console.log("blah"); }, 1000);']);
-n.stdout.once('data', function () {
- console.log("new node process: %d", n.pid);
- process.kill(n.pid, "SIGUSR1");
- console.log("signaling it with SIGUSR1");
-
-});
+ nodeProcess.stdout.once('data', function () {
+ console.log("new node process: %d", nodeProcess.pid);
+ process.kill(nodeProcess.pid, "SIGUSR1");
+ console.log("signaling it with SIGUSR1");
+ });
-var didTryConnect = false;
-n.stderr.setEncoding('utf8');
-n.stderr.on('data', function (d) {
- if (didTryConnect == false && /debugger/.test(d)) {
- didTryConnect = true;
- tryConnect();
- }
-})
-
-
-function tryConnect() {
- // Wait for some data before trying to connect
- var c = new d.Client();
- process.stdout.write("connecting...");
- c.connect(d.port, function () {
- connected = true;
- console.log("connected!");
+ var didTryConnect = false;
+ nodeProcess.stderr.setEncoding('utf8');
+ nodeProcess.stderr.on('data', function (data) {
+ if (didTryConnect == false && /debugger/.test(data)) {
+ didTryConnect = true;
+
+ // Wait for some data before trying to connect
+ var c = new debug.Client();
+ process.stdout.write("connecting...");
+ c.connect(debug.port, function () {
+ connectCount++;
+ console.log("connected!");
+ cb(c, nodeProcess);
+ });
+ }
});
+}
- c.reqVersion(function (v) {
+
+test(function (client, nodeProcess) {
+ client.reqVersion(function (v) {
+ console.log("version: %s", v);
assert.equal(process.versions.v8, v);
- n.kill();
+ nodeProcess.kill();
});
-}
+});
process.on('exit', function() {
- assert.ok(connected);
+ assert.equal(1, connectCount);
});
From 8e96b8ab9bd559914c18b0bdf3b291862c961f94 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Wed, 22 Dec 2010 00:48:22 -0800
Subject: [PATCH 04/46] keep track of current frame. eval works for global
scope
---
lib/_debugger.js | 51 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 5c0dd55501..0232f312ba 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -110,7 +110,7 @@ Protocol.prototype.serialize = function(req) {
};
-
+var NO_FRAME = -1;
function Client() {
net.Stream.call(this);
@@ -118,6 +118,9 @@ function Client() {
this._reqCallbacks = [];
var socket = this;
+ this.currentFrame = NO_FRAME;
+ this.currentSourceLine = -1;
+
// Note that 'Protocol' requires strings instead of Buffers.
socket.setEncoding('utf8');
socket.on('data', function(d) {
@@ -142,7 +145,7 @@ Client.prototype._onResponse = function(res) {
this._reqCallbacks.splice(i, 1);
cb(res.body);
} else {
- console.error("unhandled res: %j", res.body);
+ this.emit('unhandledResponse', res.body);
}
};
@@ -161,7 +164,30 @@ Client.prototype.reqVersion = function(cb) {
};
-var helpMessage = "Commands: version, eval, help, quit";
+Client.prototype.reqEval = function(expression, cb) {
+ var req = {
+ command: 'evaluate',
+ arguments: { expression: expression }
+ };
+
+ if (this.currentFrame == NO_FRAME) req.arguments.global = true;
+
+ this.req(req, function (res) {
+ if (cb) cb(res.body);
+ });
+};
+
+
+// reqBacktrace(cb)
+// TODO: from, to, bottom
+Client.prototype.reqBacktrace = function(cb) {
+ this.req({ command: 'backtrace' } , function (res) {
+ if (cb) cb(res.body);
+ });
+};
+
+
+var helpMessage = "Commands: backtrace, version, eval, help, quit";
function startInterface() {
@@ -194,13 +220,14 @@ function startInterface() {
i.prompt();
});
- } else if (/^eval/.test(cmd)) {
- var req = {
- command: 'evaluate',
- arguments: { 'expression': cmd.slice(5) }
- };
+ } else if ('backtrace' == cmd || 'bt' == cmd) {
+ c.reqBacktrace(function (bt) {
+ console.log(bt);
+ i.prompt();
+ });
- c.req(req, function (res) {
+ } else if (/^eval/.test(cmd)) {
+ c.reqEval(cmd.slice(5), function (res) {
console.log(res);
i.prompt();
});
@@ -214,6 +241,12 @@ function startInterface() {
}
});
+ c.on('unhandledResponse', function (res) {
+ console.log("\r\nunhandled res:");
+ console.log(res.body);
+ i.prompt();
+ });
+
i.on('close', function() {
stdin.destroy();
});
From a8417c128e0c871c6af03236fa42209dc1977caa Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Wed, 22 Dec 2010 14:31:57 -0800
Subject: [PATCH 05/46] Add more debugger tests
---
lib/_debugger.js | 32 ++++++++++++-
test/simple/test-debugger-client.js | 73 ++++++++++++++++++++++++-----
2 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 0232f312ba..72af3a5cbc 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -187,7 +187,30 @@ Client.prototype.reqBacktrace = function(cb) {
};
-var helpMessage = "Commands: backtrace, version, eval, help, quit";
+// Returns an array of objects like this:
+//
+// { handle: 11,
+// type: 'script',
+// name: 'node.js',
+// id: 14,
+// lineOffset: 0,
+// columnOffset: 0,
+// lineCount: 562,
+// sourceStart: '(function(process) {\n\n ',
+// sourceLength: 15939,
+// scriptType: 2,
+// compilationType: 0,
+// context: { ref: 10 },
+// text: 'node.js (lines: 562)' }
+//
+Client.prototype.reqScripts = function(cb) {
+ this.req({ command: 'scripts' } , function (res) {
+ if (cb) cb(res.body);
+ });
+};
+
+
+var helpMessage = "Commands: scripts, backtrace, version, eval, help, quit";
function startInterface() {
@@ -226,6 +249,13 @@ function startInterface() {
i.prompt();
});
+ } else if (/^scripts/.test(cmd)) {
+ c.reqScripts(function (res) {
+ var text = res.map(function (x) { return x.text; });
+ console.log(text.join('\n'));
+ i.prompt();
+ });
+
} else if (/^eval/.test(cmd)) {
c.reqEval(cmd.slice(5), function (res) {
console.log(res);
diff --git a/test/simple/test-debugger-client.js b/test/simple/test-debugger-client.js
index 5239430d40..434a05ae66 100644
--- a/test/simple/test-debugger-client.js
+++ b/test/simple/test-debugger-client.js
@@ -18,17 +18,59 @@ p.execute("Type: connect\r\n" +
"Content-Length: 0\r\n\r\n");
assert.equal(1, resCount);
+var expectedConnections = 0;
+var tests = [];
+function addTest (cb) {
+ expectedConnections++;
+ tests.push(cb);
+}
+
+addTest(function (client, done) {
+ console.error("requesting version");
+ client.reqVersion(function (v) {
+ console.log("version: %s", v);
+ assert.equal(process.versions.v8, v);
+ done();
+ });
+});
+
+addTest(function (client, done) {
+ console.error("requesting scripts");
+ client.reqScripts(function (s) {
+ console.error("got %d scripts", s.length);
+ var foundMainScript = false;
+ for (var i = 0; i < s.length; i++) {
+ if (s[i].name === 'node.js') {
+ foundMainScript = true;
+ break;
+ }
+ }
+ assert.ok(foundMainScript);
+ done();
+ });
+});
+
+addTest(function (client, done) {
+ console.error("eval 2+2");
+ client.reqEval("2+2", function (res) {
+ console.error(res);
+ assert.equal('4', res.text);
+ assert.equal(4, res.value);
+ done();
+ });
+});
+
var connectCount = 0;
-function test(cb) {
+function doTest(cb, done) {
var nodeProcess = spawn(process.execPath,
['-e', 'setInterval(function () { console.log("blah"); }, 1000);']);
nodeProcess.stdout.once('data', function () {
- console.log("new node process: %d", nodeProcess.pid);
+ console.log(">>> new node process: %d", nodeProcess.pid);
process.kill(nodeProcess.pid, "SIGUSR1");
- console.log("signaling it with SIGUSR1");
+ console.log(">>> signaling it with SIGUSR1");
});
var didTryConnect = false;
@@ -39,27 +81,34 @@ function test(cb) {
// Wait for some data before trying to connect
var c = new debug.Client();
- process.stdout.write("connecting...");
+ process.stdout.write(">>> connecting...");
c.connect(debug.port, function () {
connectCount++;
console.log("connected!");
- cb(c, nodeProcess);
+ cb(c, function () {
+ console.error(">>> killing node process %d\n\n", nodeProcess.pid);
+ nodeProcess.kill();
+ done();
+ });
});
}
});
}
-test(function (client, nodeProcess) {
- client.reqVersion(function (v) {
- console.log("version: %s", v);
- assert.equal(process.versions.v8, v);
- nodeProcess.kill();
+function run () {
+ var t = tests[0];
+ if (!t) return;
+
+ doTest(t, function () {
+ tests.shift();
+ run();
});
-});
+}
+run();
process.on('exit', function() {
- assert.equal(1, connectCount);
+ assert.equal(expectedConnections, connectCount);
});
From 4e81cf7def7c672b620086323c34010d2718e697 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Wed, 22 Dec 2010 14:40:28 -0800
Subject: [PATCH 06/46] Debugger client emits ready after recving initial res
---
lib/_debugger.js | 4 +++-
test/simple/test-debugger-client.js | 7 ++++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 72af3a5cbc..25f82e72e1 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -19,7 +19,8 @@ function tryConnect() {
c = new Client();
process.stdout.write("connecting...");
- c.connect(exports.port, function () {
+ c.connect(exports.port);
+ c.on('ready', function () {
process.stdout.write("ok\r\n");
startInterface();
});
@@ -141,6 +142,7 @@ Client.prototype._onResponse = function(res) {
if (res.headers.Type == 'connect') {
// do nothing
+ this.emit('ready');
} else if (cb) {
this._reqCallbacks.splice(i, 1);
cb(res.body);
diff --git a/test/simple/test-debugger-client.js b/test/simple/test-debugger-client.js
index 434a05ae66..c542f89c49 100644
--- a/test/simple/test-debugger-client.js
+++ b/test/simple/test-debugger-client.js
@@ -65,7 +65,7 @@ var connectCount = 0;
function doTest(cb, done) {
var nodeProcess = spawn(process.execPath,
- ['-e', 'setInterval(function () { console.log("blah"); }, 1000);']);
+ ['-e', 'setInterval(function () { console.log("blah"); }, 100);']);
nodeProcess.stdout.once('data', function () {
console.log(">>> new node process: %d", nodeProcess.pid);
@@ -82,9 +82,10 @@ function doTest(cb, done) {
// Wait for some data before trying to connect
var c = new debug.Client();
process.stdout.write(">>> connecting...");
- c.connect(debug.port, function () {
+ c.connect(debug.port)
+ c.on('ready', function () {
connectCount++;
- console.log("connected!");
+ console.log("ready!");
cb(c, function () {
console.error(">>> killing node process %d\n\n", nodeProcess.pid);
nodeProcess.kill();
From 0dcbe3f74a0d92a399c508c92110648e76917d9b Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Wed, 22 Dec 2010 17:17:34 -0800
Subject: [PATCH 07/46] Fork out to debugger on debugger statements
Also implement continue in Client.
---
lib/_debugger.js | 36 +++++++++++++++++++++++++----
lib/readline.js | 2 ++
src/node.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 92 insertions(+), 5 deletions(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 25f82e72e1..83bc6c8fba 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -212,6 +212,13 @@ Client.prototype.reqScripts = function(cb) {
};
+Client.prototype.reqContinue = function(cb) {
+ this.req({ command: 'continue' } , function (res) {
+ if (cb) cb(res.body);
+ });
+};
+
+
var helpMessage = "Commands: scripts, backtrace, version, eval, help, quit";
@@ -223,18 +230,33 @@ function startInterface() {
i.write(chunk);
});
- var prompt = '> ';
+ var prompt = 'debug> ';
i.setPrompt(prompt);
i.prompt();
- i.on('SIGINT', function() {
+ var quitTried = false;
+
+ function tryQuit() {
+ if (quitTried) return;
+ quitTried = true;
i.close();
- });
+ console.log("debug done\n");
+ if (c.writable) {
+ c.reqContinue(function (res) {
+ process.exit(0);
+ });
+ } else {
+ process.exit(0);
+ }
+ }
+
+ i.on('SIGINT', tryQuit);
+ i.on('close', tryQuit);
i.on('line', function(cmd) {
if (cmd == 'quit') {
- process.exit(0);
+ tryQuit();
} else if (/^help/.test(cmd)) {
console.log(helpMessage);
i.prompt();
@@ -251,6 +273,12 @@ function startInterface() {
i.prompt();
});
+ } else if ('continue' == cmd || 'c' == cmd) {
+ c.reqContinue(function (res) {
+ console.log(res);
+ i.prompt();
+ });
+
} else if (/^scripts/.test(cmd)) {
c.reqScripts(function (res) {
var text = res.map(function (x) { return x.text; });
diff --git a/lib/readline.js b/lib/readline.js
index 341b20b479..3ae43f4735 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -160,6 +160,8 @@ Interface.prototype._refreshLine = function() {
Interface.prototype.close = function(d) {
+ if (this._closing) return;
+ this._closing = true;
if (this.enabled) {
tty.setRawMode(false);
}
diff --git a/src/node.cc b/src/node.cc
index 04a96a4187..d81aab841a 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -17,6 +17,11 @@
#include /* getpwnam() */
#include /* getgrnam() */
+// waitpid
+#include
+#include
+
+
#include "platform.h"
#include
@@ -1908,6 +1913,57 @@ static int RegisterSignalHandler(int signal, void (*handler)(int)) {
}
+static bool debugger_slave_running = false;
+
+static void HandleDebugEvent(DebugEvent event,
+ Handle
- Unstable: 2010.12.16
- node-v0.3.2.tar.gz
- (Documentation)
+ Unstable: 2011.01.02
+ node-v0.3.3.tar.gz
+ (Documentation)
Historical: versions, docs
diff --git a/src/node_version.h b/src/node_version.h
index 51798bc6a5..e1a92461eb 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -7,7 +7,7 @@
#define NODE_MAJOR_VERSION 0
#define NODE_MINOR_VERSION 3
#define NODE_PATCH_VERSION 3
-#define NODE_VERSION_IS_RELEASE 0
+#define NODE_VERSION_IS_RELEASE 1
#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
From 2b5b128cbac3cee8535d3e4f54c94d6a7c962dac Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Sun, 2 Jan 2011 18:57:22 -0800
Subject: [PATCH 37/46] Now working on v0.3.4-pre
---
src/node_version.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/node_version.h b/src/node_version.h
index e1a92461eb..70bd4be74b 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -6,8 +6,8 @@
#define NODE_MAJOR_VERSION 0
#define NODE_MINOR_VERSION 3
-#define NODE_PATCH_VERSION 3
-#define NODE_VERSION_IS_RELEASE 1
+#define NODE_PATCH_VERSION 4
+#define NODE_VERSION_IS_RELEASE 0
#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
From 282cce1ea58b6a450c397af22b64fac8fd03d579 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Mon, 3 Jan 2011 12:58:19 -0800
Subject: [PATCH 38/46] debugger: don't display whole path of scripts
---
lib/_debugger.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index bc1d810056..8c7c2a7ff0 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -734,7 +734,8 @@ Interface.prototype.printScripts = function(displayNatives) {
if (typeof script == 'object' && script.name) {
if (displayNatives || script.name == client.currentScript || !script.isNative) {
text += script.name == client.currentScript ? '* ' : ' ';
- text += script.name + '\n';
+ var n = require('path').split(script.name);
+ text += n[n.length - 1] + '\n';
}
}
}
From d040f1d19d17e056223ab3de0e58ed470c8b9f52 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Mon, 3 Jan 2011 13:21:28 -0800
Subject: [PATCH 39/46] debugger: use correct handle handle
---
lib/_debugger.js | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/_debugger.js b/lib/_debugger.js
index 8c7c2a7ff0..b0a539e7ff 100644
--- a/lib/_debugger.js
+++ b/lib/_debugger.js
@@ -128,7 +128,7 @@ exports.Client = Client;
Client.prototype._addHandle = function(desc) {
if (typeof desc != 'object' || !desc.handle) throw new Error("bad type");
- this.handles[desc.id] = desc;
+ this.handles[desc.handle] = desc;
if (desc.type == 'script') {
this._addScript(desc);
@@ -208,11 +208,13 @@ Client.prototype.reqVersion = function(cb) {
Client.prototype.reqEval = function(expression, cb) {
+ var self = this;
var req = {
command: 'evaluate',
arguments: { expression: expression }
};
+
if (this.currentFrame == NO_FRAME) {
req.arguments.global = true;
} else {
@@ -220,6 +222,8 @@ Client.prototype.reqEval = function(expression, cb) {
}
this.req(req, function (res) {
+ console.error('reqEval res ', res.body);
+ self._addHandle(res.body);
if (cb) cb(res.body);
});
};
From e4dd5cd6fd7b44f4fc21a5cfd39615a7a5833957 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Mon, 3 Jan 2011 15:27:57 -0800
Subject: [PATCH 40/46] NODE_DEBUG uses strings instead of bitflags
---
lib/http.js | 3 +--
lib/net.js | 3 +--
lib/tls.js | 3 +--
src/node.js | 3 +--
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/lib/http.js b/lib/http.js
index 0b4a0e2212..5594a8ff1c 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -6,8 +6,7 @@ var HTTPParser = process.binding('http_parser').HTTPParser;
var debug;
-var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
-if (debugLevel & 0x4) {
+if (process.env.NODE_DEBUG && /http/.test(process.env.NODE_DEBUG)) {
debug = function(x) { console.error('HTTP: %s', x); };
} else {
debug = function() { };
diff --git a/lib/net.js b/lib/net.js
index d29984668a..f240f8a351 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -5,9 +5,8 @@ var stream = require('stream');
var kMinPoolSpace = 128;
var kPoolSize = 40 * 1024;
-var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
var debug;
-if (debugLevel & 0x2) {
+if (process.env.NODE_DEBUG && /net/.test(process.env.NODE_DEBUG)) {
debug = function(x) { util.error.apply(this, arguments); };
} else {
debug = function() { };
diff --git a/lib/tls.js b/lib/tls.js
index 433d33958c..bcb036edc8 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -6,9 +6,8 @@ var stream = require('stream');
var assert = process.assert;
-var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
var debug;
-if (debugLevel & 0x2) {
+if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) {
debug = function() { util.error.apply(this, arguments); };
} else {
debug = function() { };
diff --git a/src/node.js b/src/node.js
index ca4bead83e..1d1ca687d8 100644
--- a/src/node.js
+++ b/src/node.js
@@ -123,9 +123,8 @@
// Modules
- var debugLevel = parseInt(process.env['NODE_DEBUG'], 16);
var debug;
- if (debugLevel & 1) {
+ if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) {
debug = function(x) { console.error(x); };
} else {
debug = function() { };
From 94f8368cf9e5077050525e32a24188402f077074 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Sun, 2 Jan 2011 01:13:56 -0800
Subject: [PATCH 41/46] First pass at new https server
---
lib/http.js | 1 +
lib/https.js | 22 ++++++++++++++++
lib/tls.js | 14 ++++++++--
test/simple/test-https-simple.js | 44 ++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+), 2 deletions(-)
create mode 100644 lib/https.js
create mode 100644 test/simple/test-https-simple.js
diff --git a/lib/http.js b/lib/http.js
index 5594a8ff1c..786f373e74 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -871,6 +871,7 @@ function connectionListener(socket) {
return false; // Not a HEAD response. (Not even a response!)
};
}
+exports._connectionListener = connectionListener;
function Client() {
diff --git a/lib/https.js b/lib/https.js
new file mode 100644
index 0000000000..c3e17a3602
--- /dev/null
+++ b/lib/https.js
@@ -0,0 +1,22 @@
+var tls = require('tls');
+var http = require('http');
+var inherits = require('util').inherits;
+
+
+function Server(opts, requestListener) {
+ if (!(this instanceof Server)) return new Server(opts, requestListener);
+ tls.Server.call(this, opts, http._connectionListener);
+
+ if (requestListener) {
+ this.addListener('request', requestListener);
+ }
+}
+inherits(Server, tls.Server);
+
+
+exports.Server = Server;
+
+
+exports.createServer = function(opts, requestListener) {
+ return new Server(opts, requestListener);
+};
diff --git a/lib/tls.js b/lib/tls.js
index bcb036edc8..08fa742ac8 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -77,6 +77,11 @@ CryptoStream.prototype.resume = function() {
};
+CryptoStream.prototype.setTimeout = function(n) {
+ if (this.socket) this.socket.setTimeout(n);
+};
+
+
function parseCertString (s) {
// EG '/C=US/ST=CA/L=SF/O=Joyent/OU=Node.js/CN=ca1/emailAddress=ry@tinyclouds.org'
var out = {};
@@ -183,8 +188,13 @@ CryptoStream.prototype._blow = function() {
} while ((chunkBytes > 0) && (pool.used + bytesRead < pool.length));
if (bytesRead > 0) {
- chunk = pool.slice(0, bytesRead);
- this.emit('data', chunk);
+ if (this._events && this._events['data']) {
+ chunk = pool.slice(0, bytesRead);
+ this.emit('data', chunk);
+ }
+
+ // Optimization: emit the original buffer with end points
+ if (this.ondata) this.ondata(pool, 0, bytesRead);
}
} while (bytesRead > 0 && this._writeState === true);
};
diff --git a/test/simple/test-https-simple.js b/test/simple/test-https-simple.js
new file mode 100644
index 0000000000..a90c0269e6
--- /dev/null
+++ b/test/simple/test-https-simple.js
@@ -0,0 +1,44 @@
+if (!process.versions.openssl) {
+ console.error("Skipping because node compiled without OpenSSL.");
+ process.exit(0);
+}
+
+var common = require('../common');
+var assert = require('assert');
+
+var fs = require('fs');
+var exec = require('child_process').exec;
+
+var https = require('https');
+
+var options = {
+ key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
+ cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
+};
+
+var reqCount = 0;
+var body = 'hello world\n';
+
+var server = https.createServer(options, function (req, res) {
+ reqCount++;
+ console.log("got request");
+ res.writeHead(200, { 'content-type': 'text/plain' });
+ res.end(body);
+})
+
+function afterCurl (err, stdout, stderr) {
+ if (err) throw err;
+ server.close();
+ common.error(common.inspect(stdout));
+ assert.equal(body, stdout);
+};
+
+server.listen(common.PORT, function () {
+ var cmd = 'curl --insecure https://127.0.0.1:' + common.PORT + '/';
+ console.error("executing %j", cmd);
+ exec(cmd, afterCurl);
+});
+
+process.on('exit', function () {
+ assert.equal(1, reqCount);
+});
From 73f4ec51fde3bfb3e16d6d706aae42656d083c1a Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 4 Jan 2011 10:36:05 -0800
Subject: [PATCH 42/46] hack for ending https connections
---
lib/http.js | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/lib/http.js b/lib/http.js
index 786f373e74..f061effe33 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -833,11 +833,17 @@ function connectionListener(socket) {
if (message._last) {
// No more messages to be pushed out.
- // HACK: need way to do this with socket interface
- if (socket._writeQueue.length) {
- socket.__destroyOnDrain = true; //socket.end();
+ if (!socket._writeQueue) {
+ // Putting this here for https. Really need to add below hack to
+ // both socket and https interfaces.
+ socket.end();
} else {
- socket.destroy();
+ // HACK: need way to do this with socket interface
+ if (socket._writeQueue.length) {
+ socket.__destroyOnDrain = true; //socket.end();
+ } else {
+ socket.destroy();
+ }
}
} else if (socket._outgoing.length) {
From 2957382991c6559fa397d0f9a790ee82f5029b37 Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 4 Jan 2011 11:22:17 -0800
Subject: [PATCH 43/46] Implement new stream method, destroySoon
Still missing on fs.WriteStream
---
doc/api/streams.markdown | 5 +++++
lib/fs.js | 3 +++
lib/http.js | 15 +--------------
lib/net.js | 8 ++++++++
lib/tls.js | 14 ++++++++++++++
5 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/doc/api/streams.markdown b/doc/api/streams.markdown
index 51540cc1c0..354c2ce32a 100644
--- a/doc/api/streams.markdown
+++ b/doc/api/streams.markdown
@@ -65,6 +65,11 @@ Resumes the incoming `'data'` events after a `pause()`.
Closes the underlying file descriptor. Stream will not emit any more events.
+
+### stream.destroySoon()
+
+After the write queue is drained, close the file descriptor.
+
### stream.pipe(destination, [options])
This is a `Stream.prototype` method available on all `Stream`s.
diff --git a/lib/fs.js b/lib/fs.js
index b9e6b2d716..75b7cf98c6 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -981,3 +981,6 @@ WriteStream.prototype.destroy = function(cb) {
}
};
+
+// TODO: WriteStream.prototype.destroySoon()
+
diff --git a/lib/http.js b/lib/http.js
index f061effe33..960d28aaa3 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -733,13 +733,11 @@ function httpSocketSetup(socket) {
// An array of outgoing messages for the socket. In pipelined connections
// we need to keep track of the order they were sent.
socket._outgoing = [];
- socket.__destroyOnDrain = false;
// NOTE: be sure not to use ondrain elsewhere in this file!
socket.ondrain = function() {
var message = socket._outgoing[0];
if (message) message.emit('drain');
- if (socket.__destroyOnDrain) socket.destroy();
};
}
@@ -833,18 +831,7 @@ function connectionListener(socket) {
if (message._last) {
// No more messages to be pushed out.
- if (!socket._writeQueue) {
- // Putting this here for https. Really need to add below hack to
- // both socket and https interfaces.
- socket.end();
- } else {
- // HACK: need way to do this with socket interface
- if (socket._writeQueue.length) {
- socket.__destroyOnDrain = true; //socket.end();
- } else {
- socket.destroy();
- }
- }
+ socket.destroySoon();
} else if (socket._outgoing.length) {
// Push out the next message.
diff --git a/lib/net.js b/lib/net.js
index f240f8a351..24f2e4a5bb 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -554,6 +554,7 @@ Stream.prototype._onWritable = function() {
if (this.flush()) {
if (this._events && this._events['drain']) this.emit('drain');
if (this.ondrain) this.ondrain(); // Optimization
+ if (this.__destroyOnDrain) this.destroy();
}
};
@@ -705,6 +706,13 @@ Stream.prototype.resume = function() {
this._readWatcher.start();
};
+Stream.prototype.destroySoon = function() {
+ if (this.flush()) {
+ this.destroy();
+ } else {
+ this.__destroyOnDrain = true;
+ }
+};
Stream.prototype.destroy = function(exception) {
// pool is shared between sockets, so don't need to free it here.
diff --git a/lib/tls.js b/lib/tls.js
index 08fa742ac8..41197f385c 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -139,6 +139,19 @@ CryptoStream.prototype.end = function(d) {
};
+CryptoStream.prototype.destroySoon = function(err) {
+ if (this.pair._done) return;
+
+ this.pair._cycle();
+
+ if (this._pending.length) {
+ this.__destroyOnDrain = true;
+ } else {
+ this.end();
+ }
+};
+
+
CryptoStream.prototype.destroy = function(err) {
if (this.pair._done) return;
this.pair._destroy();
@@ -249,6 +262,7 @@ CryptoStream.prototype._suck = function() {
if (havePending && this._pending && this._pending.length === 0) {
debug('drain');
this.emit('drain');
+ if (this.__destroyOnDrain) this.end();
}
};
From bc1d758408ce67db8fbdb212d7677831eac55d9e Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 4 Jan 2011 11:25:36 -0800
Subject: [PATCH 44/46] net.js: Check that readWatcher exists before pause,
resume
---
lib/net.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/lib/net.js b/lib/net.js
index 24f2e4a5bb..832954aa3e 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -695,15 +695,17 @@ Stream.prototype.setTimeout = function(msecs) {
Stream.prototype.pause = function() {
- this._readWatcher.stop();
+ if (this._readWatcher) this._readWatcher.stop();
};
Stream.prototype.resume = function() {
if (this.fd === null) throw new Error('Cannot resume() closed Stream.');
- this._readWatcher.stop();
- this._readWatcher.set(this.fd, true, false);
- this._readWatcher.start();
+ if (this._readWatcher) {
+ this._readWatcher.stop();
+ this._readWatcher.set(this.fd, true, false);
+ this._readWatcher.start();
+ }
};
Stream.prototype.destroySoon = function() {
From cda4d56bcf235baf15c401276b281de5955edd5d Mon Sep 17 00:00:00 2001
From: Ryan Dahl
Date: Tue, 4 Jan 2011 11:39:12 -0800
Subject: [PATCH 45/46] Implement WriteStream.destroySoon
---
lib/fs.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/fs.js b/lib/fs.js
index 75b7cf98c6..af18877a8d 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -981,6 +981,6 @@ WriteStream.prototype.destroy = function(cb) {
}
};
-
-// TODO: WriteStream.prototype.destroySoon()
+// There is no shutdown() for files.
+WriteStream.prototype.destroySoon = WriteStream.prototype.end;
From 131546e7339d6960ea91629915468c6f04a33cf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mihai=20C=C4=83lin=20Bazon?=
Date: Tue, 4 Jan 2011 12:24:17 -0800
Subject: [PATCH 46/46] realpath files during module load
---
src/node.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/node.js b/src/node.js
index 1d1ca687d8..57ff87f062 100644
--- a/src/node.js
+++ b/src/node.js
@@ -169,7 +169,7 @@
try {
var stats = fs.statSync(requestPath);
if (stats && !stats.isDirectory()) {
- return requestPath;
+ return fs.realpathSync(requestPath);
}
} catch (e) {}
return false;
@@ -277,6 +277,7 @@
if (!filename) {
throw new Error("Cannot find module '" + request + "'");
}
+ id = filename;
return [id, filename];
}