From 724ccf10df8c77010600e8e1a11066faef50eb28 Mon Sep 17 00:00:00 2001 From: arlolra Date: Fri, 26 Feb 2010 15:06:32 -0500 Subject: [PATCH 01/11] Tests on common port. --- test/common.js | 1 + test/disabled/test-cat.js | 1 - test/disabled/test-dns.js | 2 +- test/disabled/test-eio-race3.js | 2 +- test/disabled/test-fs-sendfile.js | 3 +-- test/disabled/test-http-stress.js | 1 - test/pummel/test-http-client-reconnect-bug.js | 2 -- test/pummel/test-keep-alive.js | 1 - test/pummel/test-multipart.js | 1 - test/pummel/test-tcp-many-clients.js | 7 +++---- test/pummel/test-tcp-pingpong-delay.js | 2 +- test/pummel/test-tcp-pingpong.js | 7 +++---- test/pummel/test-tcp-throttle-kernel-buffer.js | 1 - test/pummel/test-tcp-throttle.js | 1 - test/pummel/test-tcp-timeout.js | 7 +++---- test/pummel/test-tcp-tls.js | 4 ++-- test/simple/test-http-1.0.js | 6 ++---- test/simple/test-http-cat.js | 1 - test/simple/test-http-chunked.js | 1 - test/simple/test-http-client-race.js | 1 - test/simple/test-http-client-upload.js | 1 - test/simple/test-http-eof-on-connect.js | 5 ++--- test/simple/test-http-malformed-request.js | 5 ++--- test/simple/test-http-proxy.js | 4 ++-- test/simple/test-http-server.js | 6 ++---- test/simple/test-http-tls.js | 1 - test/simple/test-http-wget.js | 6 ++---- test/simple/test-http.js | 1 - test/simple/test-remote-module-loading.js | 1 - test/simple/test-tcp-binary.js | 1 - test/simple/test-tcp-reconnect.js | 7 +++---- 31 files changed, 31 insertions(+), 59 deletions(-) diff --git a/test/common.js b/test/common.js index 2b97a33d1e8..6f7a4e1c77d 100644 --- a/test/common.js +++ b/test/common.js @@ -3,6 +3,7 @@ var path = require("path"); exports.testDir = path.dirname(__filename); exports.fixturesDir = path.join(exports.testDir, "fixtures"); exports.libDir = path.join(exports.testDir, "../lib"); +exports.PORT = 12346; require.paths.unshift(exports.libDir); diff --git a/test/disabled/test-cat.js b/test/disabled/test-cat.js index 2ae15beaba8..f5110404dc1 100644 --- a/test/disabled/test-cat.js +++ b/test/disabled/test-cat.js @@ -1,6 +1,5 @@ process.mixin(require("../common.js")); http = require("/http.js"); -PORT = 8888; puts("hello world"); diff --git a/test/disabled/test-dns.js b/test/disabled/test-dns.js index 47fa6e144c3..0d2bc2c3950 100644 --- a/test/disabled/test-dns.js +++ b/test/disabled/test-dns.js @@ -1,4 +1,4 @@ -process.mixin(require("./common")); +process.mixin(require("../common")); var dns = require("dns"), sys = require("sys"); diff --git a/test/disabled/test-eio-race3.js b/test/disabled/test-eio-race3.js index bcfc6e095d0..c911c077d91 100644 --- a/test/disabled/test-eio-race3.js +++ b/test/disabled/test-eio-race3.js @@ -1,6 +1,6 @@ /* XXX Can this test be modified to not call the now-removed wait()? */ -process.mixin(require("./common")); +process.mixin(require("../common")); puts('first stat ...'); diff --git a/test/disabled/test-fs-sendfile.js b/test/disabled/test-fs-sendfile.js index 41e16dffcf5..225657205b3 100644 --- a/test/disabled/test-fs-sendfile.js +++ b/test/disabled/test-fs-sendfile.js @@ -1,8 +1,7 @@ -process.mixin(require("./common")); +process.mixin(require("../common")); tcp = require("tcp"); sys = require("sys"); -PORT = 23123; var x = path.join(fixturesDir, "x.txt"); var expected = "xyz"; diff --git a/test/disabled/test-http-stress.js b/test/disabled/test-http-stress.js index 003d19fdd2b..da07bb72dff 100644 --- a/test/disabled/test-http-stress.js +++ b/test/disabled/test-http-stress.js @@ -1,6 +1,5 @@ process.mixin(require('../common.js')); -var PORT = 8003; var request_count = 1000; var response_body = '{"ok": true}'; diff --git a/test/pummel/test-http-client-reconnect-bug.js b/test/pummel/test-http-client-reconnect-bug.js index 0440a52a1fc..67149e6a762 100644 --- a/test/pummel/test-http-client-reconnect-bug.js +++ b/test/pummel/test-http-client-reconnect-bug.js @@ -4,8 +4,6 @@ var tcp = require("tcp"), sys = require("sys"), http = require("http"); -var PORT = 2143; - var errorCount = 0; var eofCount = 0; diff --git a/test/pummel/test-keep-alive.js b/test/pummel/test-keep-alive.js index d9d444d21cc..b77d815aeb6 100644 --- a/test/pummel/test-keep-alive.js +++ b/test/pummel/test-keep-alive.js @@ -2,7 +2,6 @@ process.mixin(require("../common")); http = require("http"); sys = require("sys"); -PORT = 8891; body = "hello world\n"; server = http.createServer(function (req, res) { diff --git a/test/pummel/test-multipart.js b/test/pummel/test-multipart.js index 4ba19e2ebcd..c3fb9492eed 100644 --- a/test/pummel/test-multipart.js +++ b/test/pummel/test-multipart.js @@ -3,7 +3,6 @@ process.mixin(require("../common")); var http = require("http"), multipart = require("multipart"), sys = require("sys"), - PORT = 8222, fixture = require("../fixtures/multipart"), events = require("events"), testPart = function (expect, part) { diff --git a/test/pummel/test-tcp-many-clients.js b/test/pummel/test-tcp-many-clients.js index 4653733faad..517b66ea4aa 100644 --- a/test/pummel/test-tcp-many-clients.js +++ b/test/pummel/test-tcp-many-clients.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); tcp = require("tcp"); // settings -var port = 20743; var bytes = 1024*40; var concurrency = 100; var connections_per_client = 5; @@ -22,10 +21,10 @@ var server = tcp.createServer(function (c) { c.close(); }); }); -server.listen(port); +server.listen(PORT); function runClient (callback) { - var client = tcp.createConnection(port); + var client = tcp.createConnection(PORT); client.connections = 0; client.setEncoding("utf8"); @@ -48,7 +47,7 @@ function runClient (callback) { assert.equal(false, had_error); assert.equal(bytes, client.recved.length); if (this.connections < connections_per_client) { - this.connect(port); + this.connect(PORT); } else { callback(); } diff --git a/test/pummel/test-tcp-pingpong-delay.js b/test/pummel/test-tcp-pingpong-delay.js index ae6868a8a2d..5afe0eacddc 100644 --- a/test/pummel/test-tcp-pingpong-delay.js +++ b/test/pummel/test-tcp-pingpong-delay.js @@ -84,7 +84,7 @@ function pingPongTest (port, host, on_complete) { }); } -pingPongTest(21988); +pingPongTest(PORT); process.addListener("exit", function () { assert.equal(1, tests_run); diff --git a/test/pummel/test-tcp-pingpong.js b/test/pummel/test-tcp-pingpong.js index 75e302c5f92..9fa231ee28d 100644 --- a/test/pummel/test-tcp-pingpong.js +++ b/test/pummel/test-tcp-pingpong.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); tcp = require("tcp"); - var tests_run = 0; function pingPongTest (port, host, on_complete) { @@ -81,9 +80,9 @@ function pingPongTest (port, host, on_complete) { } /* All are run at once, so run on different ports */ -pingPongTest(20989, "localhost"); -pingPongTest(20988, null); -pingPongTest(20997, "::1"); +pingPongTest(PORT, "localhost"); +pingPongTest(PORT+1, null); +pingPongTest(PORT+2, "::1"); process.addListener("exit", function () { assert.equal(3, tests_run); diff --git a/test/pummel/test-tcp-throttle-kernel-buffer.js b/test/pummel/test-tcp-throttle-kernel-buffer.js index 6f966fbc881..8914e3556d6 100644 --- a/test/pummel/test-tcp-throttle-kernel-buffer.js +++ b/test/pummel/test-tcp-throttle-kernel-buffer.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); tcp = require("tcp"); -PORT = 20444; N = 30*1024; // 500kb puts("build big string"); diff --git a/test/pummel/test-tcp-throttle.js b/test/pummel/test-tcp-throttle.js index 57ccec190a4..0316e7797d5 100644 --- a/test/pummel/test-tcp-throttle.js +++ b/test/pummel/test-tcp-throttle.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); tcp = require("tcp"); -PORT = 20443; N = 200; server = tcp.createServer(function (connection) { diff --git a/test/pummel/test-tcp-timeout.js b/test/pummel/test-tcp-timeout.js index 1fd95540cbd..6c04768dcf7 100644 --- a/test/pummel/test-tcp-timeout.js +++ b/test/pummel/test-tcp-timeout.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); tcp = require("tcp"); -port = 9992; exchanges = 0; starttime = null; timeouttime = null; @@ -25,10 +24,10 @@ var echo_server = tcp.createServer(function (socket) { }); }); -echo_server.listen(port); -puts("server listening at " + port); +echo_server.listen(PORT); +puts("server listening at " + PORT); -var client = tcp.createConnection(port); +var client = tcp.createConnection(PORT); client.setEncoding("UTF8"); client.setTimeout(0); // disable the timeout for client client.addListener("connect", function () { diff --git a/test/pummel/test-tcp-tls.js b/test/pummel/test-tcp-tls.js index 0635ea58dc3..9cdad204dbf 100644 --- a/test/pummel/test-tcp-tls.js +++ b/test/pummel/test-tcp-tls.js @@ -110,8 +110,8 @@ if (have_tls) { var keyPem = fs.readFileSync(fixturesDir+"/test_key.pem"); /* All are run at once, so run on different ports */ - tlsTest(20443, "localhost", caPem, keyPem, certPem); - tlsTest(21443, null, caPem, keyPem, certPem); + tlsTest(PORT, "localhost", caPem, keyPem, certPem); + tlsTest(PORT+1, null, caPem, keyPem, certPem); process.addListener("exit", function () { assert.equal(2, tests_run); diff --git a/test/simple/test-http-1.0.js b/test/simple/test-http-1.0.js index 455b9e22544..8a54b903428 100644 --- a/test/simple/test-http-1.0.js +++ b/test/simple/test-http-1.0.js @@ -2,8 +2,6 @@ process.mixin(require("../common")); tcp = require("tcp"); http = require("http"); -var port = 7333; - var body = "hello world\n"; var server_response = ""; var client_got_eof = false; @@ -13,9 +11,9 @@ var server = http.createServer(function (req, res) { res.write(body); res.close(); }) -server.listen(port); +server.listen(PORT); -var c = tcp.createConnection(port); +var c = tcp.createConnection(PORT); c.setEncoding("utf8"); diff --git a/test/simple/test-http-cat.js b/test/simple/test-http-cat.js index c6c2de845ba..7e729b275e0 100644 --- a/test/simple/test-http-cat.js +++ b/test/simple/test-http-cat.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); http = require("http"); -PORT = 8888; var body = "exports.A = function() { return 'A';}"; var server = http.createServer(function (req, res) { diff --git a/test/simple/test-http-chunked.js b/test/simple/test-http-chunked.js index 2ff677c2f0f..4bcabcc942f 100644 --- a/test/simple/test-http-chunked.js +++ b/test/simple/test-http-chunked.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); var http = require("http"); -var PORT = 8888; var UTF8_STRING = "Il était tué"; diff --git a/test/simple/test-http-client-race.js b/test/simple/test-http-client-race.js index 2ae92bcaeb6..acea6993f3e 100644 --- a/test/simple/test-http-client-race.js +++ b/test/simple/test-http-client-race.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); http = require("http"); url = require("url"); -PORT = 8888; var body1_s = "1111111111111111"; var body2_s = "22222"; diff --git a/test/simple/test-http-client-upload.js b/test/simple/test-http-client-upload.js index 91fc6606512..8c05de4d37a 100644 --- a/test/simple/test-http-client-upload.js +++ b/test/simple/test-http-client-upload.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); http = require("http"); -var PORT = 18032; var sent_body = ""; var server_req_complete = false; diff --git a/test/simple/test-http-eof-on-connect.js b/test/simple/test-http-eof-on-connect.js index 6be2e71a66a..ffa07b1ebb5 100644 --- a/test/simple/test-http-eof-on-connect.js +++ b/test/simple/test-http-eof-on-connect.js @@ -5,12 +5,11 @@ http = require("http"); // This is a regression test for http://github.com/ry/node/issues/#issue/44 // It is separate from test-http-malformed-request.js because it is only // reproduceable on the first packet on the first connection to a server. -port = 9999; server = http.createServer(function (req, res) {}); -server.listen(port); +server.listen(PORT); -tcp.createConnection(port).addListener("connect", function () { +tcp.createConnection(PORT).addListener("connect", function () { this.close(); }).addListener("close", function () { server.close(); diff --git a/test/simple/test-http-malformed-request.js b/test/simple/test-http-malformed-request.js index 27b6e80fcef..5121df4d4ab 100644 --- a/test/simple/test-http-malformed-request.js +++ b/test/simple/test-http-malformed-request.js @@ -5,7 +5,6 @@ url = require("url"); // Make sure no exceptions are thrown when receiving malformed HTTP // requests. -port = 9999; nrequests_completed = 0; nrequests_expected = 1; @@ -19,9 +18,9 @@ var s = http.createServer(function (req, res) { if (++nrequests_completed == nrequests_expected) s.close(); }); -s.listen(port); +s.listen(PORT); -var c = tcp.createConnection(port); +var c = tcp.createConnection(PORT); c.addListener("connect", function () { c.write("GET /hello?foo=%99bar HTTP/1.1\r\n\r\n"); c.close(); diff --git a/test/simple/test-http-proxy.js b/test/simple/test-http-proxy.js index f3bd0a8e93d..6f3af1d4492 100644 --- a/test/simple/test-http-proxy.js +++ b/test/simple/test-http-proxy.js @@ -2,8 +2,8 @@ process.mixin(require("../common")); http = require("http"); url = require("url"); -var PROXY_PORT = 8869; -var BACKEND_PORT = 8870; +var PROXY_PORT = PORT; +var BACKEND_PORT = PORT+1; var backend = http.createServer(function (req, res) { // debug("backend"); diff --git a/test/simple/test-http-server.js b/test/simple/test-http-server.js index 307256b7485..fc5e6f1552b 100644 --- a/test/simple/test-http-server.js +++ b/test/simple/test-http-server.js @@ -4,8 +4,6 @@ http = require("http"); url = require("url"); qs = require("querystring"); -var port = 8222; - var request_number = 0; var requests_sent = 0; var server_response = ""; @@ -43,9 +41,9 @@ http.createServer(function (req, res) { res.close(); }, 1); -}).listen(port); +}).listen(PORT); -var c = tcp.createConnection(port); +var c = tcp.createConnection(PORT); c.setEncoding("utf8"); diff --git a/test/simple/test-http-tls.js b/test/simple/test-http-tls.js index c250adf8e63..1a6e33b6d82 100644 --- a/test/simple/test-http-tls.js +++ b/test/simple/test-http-tls.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); http = require("http"); url = require("url"); -PORT = 8888; HOST = "localhost"; diff --git a/test/simple/test-http-wget.js b/test/simple/test-http-wget.js index 1184c463605..dfe9701e61a 100644 --- a/test/simple/test-http-wget.js +++ b/test/simple/test-http-wget.js @@ -17,8 +17,6 @@ http = require("http"); // content-length is not provided, that the connection is in fact // closed. -var port = 7333; - var server_response = ""; var client_got_eof = false; var connection_was_closed = false; @@ -29,9 +27,9 @@ var server = http.createServer(function (req, res) { res.write("world\n"); res.close(); }) -server.listen(port); +server.listen(PORT); -var c = tcp.createConnection(port); +var c = tcp.createConnection(PORT); c.setEncoding("utf8"); diff --git a/test/simple/test-http.js b/test/simple/test-http.js index 815ebf925e6..cd91d499043 100644 --- a/test/simple/test-http.js +++ b/test/simple/test-http.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); http = require("http"); url = require("url"); -PORT = 8888; var responses_sent = 0; var responses_recvd = 0; diff --git a/test/simple/test-remote-module-loading.js b/test/simple/test-remote-module-loading.js index 3b99ea629bc..f2463a4ebd7 100644 --- a/test/simple/test-remote-module-loading.js +++ b/test/simple/test-remote-module-loading.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); -var PORT = 8889; var http = require('http'); var sys = require('sys'); var url = require("url"); diff --git a/test/simple/test-tcp-binary.js b/test/simple/test-tcp-binary.js index fb2b8b4f2bb..796061b0a0d 100644 --- a/test/simple/test-tcp-binary.js +++ b/test/simple/test-tcp-binary.js @@ -1,6 +1,5 @@ process.mixin(require("../common")); tcp = require("tcp"); -PORT = 23123; binaryString = ""; for (var i = 255; i >= 0; i--) { diff --git a/test/simple/test-tcp-reconnect.js b/test/simple/test-tcp-reconnect.js index 65563b644b8..090ec61be15 100644 --- a/test/simple/test-tcp-reconnect.js +++ b/test/simple/test-tcp-reconnect.js @@ -1,7 +1,6 @@ process.mixin(require("../common")); tcp = require("tcp"); var N = 50; -var port = 8921; var c = 0; var client_recv_count = 0; @@ -21,9 +20,9 @@ var server = tcp.createServer(function (socket) { assert.equal(false, had_error); }); }); -server.listen(port); +server.listen(PORT); -var client = tcp.createConnection(port); +var client = tcp.createConnection(PORT); client.setEncoding("UTF8"); @@ -42,7 +41,7 @@ client.addListener("close", function (had_error) { puts("disconnect"); assert.equal(false, had_error); if (disconnect_count++ < N) - client.connect(port); // reconnect + client.connect(PORT); // reconnect else server.close(); }); From 2b91f8d2659a7aa668a5073c054eb7176ad07b20 Mon Sep 17 00:00:00 2001 From: kriskowal Date: Sat, 27 Feb 2010 16:58:54 -0800 Subject: [PATCH 02/11] Fixed spurious suffixes on fs.readlink. --- src/node_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_file.cc b/src/node_file.cc index ee2c2d6e4f7..285ce4bb654 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -275,7 +275,7 @@ static Handle ReadLink(const Arguments& args) { char buf[PATH_MAX]; ssize_t bz = readlink(*path, buf, PATH_MAX); if (bz == -1) return ThrowException(errno_exception(errno)); - return scope.Close(String::New(buf)); + return scope.Close(String::New(buf, bz)); } } From faa0c6d4493d565439a06abb1cb5cb8b564b32d1 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 1 Mar 2010 09:11:04 -0800 Subject: [PATCH 03/11] Add note about testing patches with debug build --- doc/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/index.html b/doc/index.html index d5f3661f3b2..e28ae2e8d43 100644 --- a/doc/index.html +++ b/doc/index.html @@ -239,7 +239,9 @@ make install
 git clone git://github.com/ry/node.git
 cd node
-# edit/compile/test
+(make your changes)
+./configure --debug
+make test-all # Check your patch with both debug and release builds
 git commit -m "Good description of what your patch does"
 git format-patch HEAD^
 
From 810882c1ad15c6eb6bc0fbe6225f58a01989c290 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 1 Mar 2010 10:14:49 -0800 Subject: [PATCH 04/11] Move 'fs' module out of src/node.js into its own file --- lib/fs.js | 252 +++++++++++++++++++++++++++++++++++++ src/node.js | 353 ++++++++-------------------------------------------- 2 files changed, 303 insertions(+), 302 deletions(-) create mode 100644 lib/fs.js diff --git a/lib/fs.js b/lib/fs.js new file mode 100644 index 00000000000..afa6623d3ba --- /dev/null +++ b/lib/fs.js @@ -0,0 +1,252 @@ +exports.Stats = process.Stats; + +process.Stats.prototype._checkModeProperty = function (property) { + return ((this.mode & property) === property); +}; + +process.Stats.prototype.isDirectory = function () { + return this._checkModeProperty(process.S_IFDIR); +}; + +process.Stats.prototype.isFile = function () { + return this._checkModeProperty(process.S_IFREG); +}; + +process.Stats.prototype.isBlockDevice = function () { + return this._checkModeProperty(process.S_IFBLK); +}; + +process.Stats.prototype.isCharacterDevice = function () { + return this._checkModeProperty(process.S_IFCHR); +}; + +process.Stats.prototype.isSymbolicLink = function () { + return this._checkModeProperty(process.S_IFLNK); +}; + +process.Stats.prototype.isFIFO = function () { + return this._checkModeProperty(process.S_IFIFO); +}; + +process.Stats.prototype.isSocket = function () { + return this._checkModeProperty(process.S_IFSOCK); +}; + + + +exports.readFile = process.fs.readFile; +exports.readFileSync = process.fs.readFileSync; + +// Used by fs.open and friends +function stringToFlags(flag) { + // Only mess with strings + if (typeof flag !== 'string') { + return flag; + } + switch (flag) { + case "r": return process.O_RDONLY; + case "r+": return process.O_RDWR; + case "w": return process.O_CREAT | process.O_TRUNC | process.O_WRONLY; + case "w+": return process.O_CREAT | process.O_TRUNC | process.O_RDWR; + case "a": return process.O_APPEND | process.O_CREAT | process.O_WRONLY; + case "a+": return process.O_APPEND | process.O_CREAT | process.O_RDWR; + default: throw new Error("Unknown file open flag: " + flag); + } +} + +function noop () {} + +// Yes, the follow could be easily DRYed up but I provide the explicit +// list to make the arguments clear. + +exports.close = function (fd, callback) { + process.fs.close(fd, callback || noop); +}; + +exports.closeSync = function (fd) { + return process.fs.close(fd); +}; + +exports.open = function (path, flags, mode, callback) { + if (mode === undefined) { mode = 0666; } + process.fs.open(path, stringToFlags(flags), mode, callback || noop); +}; + +exports.openSync = function (path, flags, mode) { + if (mode === undefined) { mode = 0666; } + return process.fs.open(path, stringToFlags(flags), mode); +}; + +exports.read = function (fd, length, position, encoding, callback) { + encoding = encoding || "binary"; + process.fs.read(fd, length, position, encoding, callback || noop); +}; + +exports.readSync = function (fd, length, position, encoding) { + encoding = encoding || "binary"; + return process.fs.read(fd, length, position, encoding); +}; + +exports.write = function (fd, data, position, encoding, callback) { + encoding = encoding || "binary"; + process.fs.write(fd, data, position, encoding, callback || noop); +}; + +exports.writeSync = function (fd, data, position, encoding) { + encoding = encoding || "binary"; + return process.fs.write(fd, data, position, encoding); +}; + +exports.rename = function (oldPath, newPath, callback) { + process.fs.rename(oldPath, newPath, callback || noop); +}; + +exports.renameSync = function (oldPath, newPath) { + return process.fs.rename(oldPath, newPath); +}; + +exports.truncate = function (fd, len, callback) { + process.fs.truncate(fd, len, callback || noop); +}; + +exports.truncateSync = function (fd, len) { + return process.fs.truncate(fd, len); +}; + +exports.rmdir = function (path, callback) { + process.fs.rmdir(path, callback || noop); +}; + +exports.rmdirSync = function (path) { + return process.fs.rmdir(path); +}; + +exports.mkdir = function (path, mode, callback) { + process.fs.mkdir(path, mode, callback || noop); +}; + +exports.mkdirSync = function (path, mode) { + return process.fs.mkdir(path, mode); +}; + +exports.sendfile = function (outFd, inFd, inOffset, length, callback) { + process.fs.sendfile(outFd, inFd, inOffset, length, callback || noop); +}; + +exports.sendfileSync = function (outFd, inFd, inOffset, length) { + return process.fs.sendfile(outFd, inFd, inOffset, length); +}; + +exports.readdir = function (path, callback) { + process.fs.readdir(path, callback || noop); +}; + +exports.readdirSync = function (path) { + return process.fs.readdir(path); +}; + +exports.lstat = function (path, callback) { + process.fs.lstat(path, callback || noop); +}; + +exports.stat = function (path, callback) { + process.fs.stat(path, callback || noop); +}; + +exports.lstatSync = function (path) { + return process.fs.lstat(path); +}; + +exports.statSync = function (path) { + return process.fs.stat(path); +}; + +exports.readlink = function (path, callback) { + process.fs.readlink(path, callback || noop); +}; + +exports.readlinkSync = function (path) { + return process.fs.readlink(path); +}; + +exports.symlink = function (destination, path, callback) { + process.fs.symlink(destination, path, callback || noop); +}; + +exports.symlinkSync = function (destination, path) { + return process.fs.symlink(destination, path); +}; + +exports.link = function (srcpath, dstpath, callback) { + process.fs.link(srcpath, dstpath, callback || noop); +}; + +exports.linkSync = function (srcpath, dstpath) { + return process.fs.link(srcpath, dstpath); +}; + +exports.unlink = function (path, callback) { + process.fs.unlink(path, callback || noop); +}; + +exports.unlinkSync = function (path) { + return process.fs.unlink(path); +}; + +exports.chmod = function (path, mode, callback) { + process.fs.chmod(path, mode, callback || noop); +}; + +exports.chmodSync = function (path, mode) { + return process.fs.chmod(path, mode); +}; + +function writeAll (fd, data, encoding, callback) { + exports.write(fd, data, 0, encoding, function (writeErr, written) { + if (writeErr) { + exports.close(fd, function () { + if (callback) callback(writeErr); + }); + } else { + if (written === data.length) { + exports.close(fd, callback); + } else { + writeAll(fd, data.slice(written), encoding, callback); + } + } + }); +} + +exports.writeFile = function (path, data, encoding_, callback) { + var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8'); + var callback_ = arguments[arguments.length - 1]; + var callback = (typeof(callback_) == 'function' ? callback_ : null); + exports.open(path, 'w', 0666, function (openErr, fd) { + if (openErr) { + if (callback) callback(openErr); + } else { + writeAll(fd, data, encoding, callback); + } + }); +}; + +exports.writeFileSync = function (path, data, encoding) { + encoding = encoding || "utf8"; // default to utf8 + var fd = exports.openSync(path, "w"); + var written = 0; + while (written < data.length) { + written += exports.writeSync(fd, data, 0, encoding); + data = data.slice(written); + } + exports.closeSync(fd); +}; + +exports.cat = function () { + throw new Error("fs.cat is deprecated. Please use fs.readFile instead."); +}; + + +exports.catSync = function () { + throw new Error("fs.catSync is deprecated. Please use fs.readFileSync instead."); +}; + diff --git a/src/node.js b/src/node.js index e76afa3e5b3..a764d0285e5 100644 --- a/src/node.js +++ b/src/node.js @@ -285,39 +285,6 @@ process.unwatchFile = function (filename) { } }; -process.Stats.prototype._checkModeProperty = function (property) { - return ((this.mode & property) === property); -}; - -process.Stats.prototype.isDirectory = function () { - return this._checkModeProperty(process.S_IFDIR); -}; - -process.Stats.prototype.isFile = function () { - return this._checkModeProperty(process.S_IFREG); -}; - -process.Stats.prototype.isBlockDevice = function () { - return this._checkModeProperty(process.S_IFBLK); -}; - -process.Stats.prototype.isCharacterDevice = function () { - return this._checkModeProperty(process.S_IFCHR); -}; - -process.Stats.prototype.isSymbolicLink = function () { - return this._checkModeProperty(process.S_IFLNK); -}; - -process.Stats.prototype.isFIFO = function () { - return this._checkModeProperty(process.S_IFIFO); -}; - -process.Stats.prototype.isSocket = function () { - return this._checkModeProperty(process.S_IFSOCK); -}; - - // Timers function addTimerListener (callback) { @@ -371,278 +338,60 @@ function debug (x) { -var fsModule = createInternalModule("fs", function (exports) { - exports.Stats = process.Stats; - - // Used by fs.open and friends - function stringToFlags(flag) { - // Only mess with strings - if (typeof flag !== 'string') { - return flag; + +function readAll (fd, pos, content, encoding, callback) { + process.fs.read(fd, 4*1024, pos, encoding, function (err, chunk, bytesRead) { + if (err) { + if (callback) callback(err); + } else if (chunk) { + content += chunk; + pos += bytesRead; + readAll(fd, pos, content, encoding, callback); + } else { + process.fs.close(fd, function (err) { + if (callback) callback(err, content); + }); } - switch (flag) { - case "r": return process.O_RDONLY; - case "r+": return process.O_RDWR; - case "w": return process.O_CREAT | process.O_TRUNC | process.O_WRONLY; - case "w+": return process.O_CREAT | process.O_TRUNC | process.O_RDWR; - case "a": return process.O_APPEND | process.O_CREAT | process.O_WRONLY; - case "a+": return process.O_APPEND | process.O_CREAT | process.O_RDWR; - default: throw new Error("Unknown file open flag: " + flag); + }); +} + +process.fs.readFile = function (path, encoding_, callback) { + var encoding = typeof(encoding_) == 'string' ? encoding : 'utf8'; + var callback_ = arguments[arguments.length - 1]; + var callback = (typeof(callback_) == 'function' ? callback_ : null); + process.fs.open(path, process.O_RDONLY, 0666, function (err, fd) { + if (err) { + if (callback) callback(err); + } else { + readAll(fd, 0, "", encoding, callback); } + }); +}; + +process.fs.readFileSync = function (path, encoding) { + encoding = encoding || "utf8"; // default to utf8 + + debug('readFileSync open'); + + var fd = process.fs.open(path, process.O_RDONLY, 0666); + var content = ''; + var pos = 0; + var r; + + while ((r = process.fs.read(fd, 4*1024, pos, encoding)) && r[0]) { + debug('readFileSync read ' + r[1]); + content += r[0]; + pos += r[1] } - function noop () {} + debug('readFileSync close'); - // Yes, the follow could be easily DRYed up but I provide the explicit - // list to make the arguments clear. + process.fs.close(fd); - exports.close = function (fd, callback) { - process.fs.close(fd, callback || noop); - }; - - exports.closeSync = function (fd) { - return process.fs.close(fd); - }; - - exports.open = function (path, flags, mode, callback) { - if (mode === undefined) { mode = 0666; } - process.fs.open(path, stringToFlags(flags), mode, callback || noop); - }; - - exports.openSync = function (path, flags, mode) { - if (mode === undefined) { mode = 0666; } - return process.fs.open(path, stringToFlags(flags), mode); - }; - - exports.read = function (fd, length, position, encoding, callback) { - encoding = encoding || "binary"; - process.fs.read(fd, length, position, encoding, callback || noop); - }; - - exports.readSync = function (fd, length, position, encoding) { - encoding = encoding || "binary"; - return process.fs.read(fd, length, position, encoding); - }; - - exports.write = function (fd, data, position, encoding, callback) { - encoding = encoding || "binary"; - process.fs.write(fd, data, position, encoding, callback || noop); - }; - - exports.writeSync = function (fd, data, position, encoding) { - encoding = encoding || "binary"; - return process.fs.write(fd, data, position, encoding); - }; - - exports.rename = function (oldPath, newPath, callback) { - process.fs.rename(oldPath, newPath, callback || noop); - }; - - exports.renameSync = function (oldPath, newPath) { - return process.fs.rename(oldPath, newPath); - }; - - exports.truncate = function (fd, len, callback) { - process.fs.truncate(fd, len, callback || noop); - }; - - exports.truncateSync = function (fd, len) { - return process.fs.truncate(fd, len); - }; - - exports.rmdir = function (path, callback) { - process.fs.rmdir(path, callback || noop); - }; - - exports.rmdirSync = function (path) { - return process.fs.rmdir(path); - }; - - exports.mkdir = function (path, mode, callback) { - process.fs.mkdir(path, mode, callback || noop); - }; - - exports.mkdirSync = function (path, mode) { - return process.fs.mkdir(path, mode); - }; - - exports.sendfile = function (outFd, inFd, inOffset, length, callback) { - process.fs.sendfile(outFd, inFd, inOffset, length, callback || noop); - }; - - exports.sendfileSync = function (outFd, inFd, inOffset, length) { - return process.fs.sendfile(outFd, inFd, inOffset, length); - }; - - exports.readdir = function (path, callback) { - process.fs.readdir(path, callback || noop); - }; - - exports.readdirSync = function (path) { - return process.fs.readdir(path); - }; - - exports.lstat = function (path, callback) { - process.fs.lstat(path, callback || noop); - }; - - exports.stat = function (path, callback) { - process.fs.stat(path, callback || noop); - }; - - exports.lstatSync = function (path) { - return process.fs.lstat(path); - }; - - exports.statSync = function (path) { - return process.fs.stat(path); - }; - - exports.readlink = function (path, callback) { - process.fs.readlink(path, callback || noop); - }; - - exports.readlinkSync = function (path) { - return process.fs.readlink(path); - }; - - exports.symlink = function (destination, path, callback) { - process.fs.symlink(destination, path, callback || noop); - }; - - exports.symlinkSync = function (destination, path) { - return process.fs.symlink(destination, path); - }; - - exports.link = function (srcpath, dstpath, callback) { - process.fs.link(srcpath, dstpath, callback || noop); - }; - - exports.linkSync = function (srcpath, dstpath) { - return process.fs.link(srcpath, dstpath); - }; - - exports.unlink = function (path, callback) { - process.fs.unlink(path, callback || noop); - }; - - exports.unlinkSync = function (path) { - return process.fs.unlink(path); - }; - - exports.chmod = function (path, mode, callback) { - process.fs.chmod(path, mode, callback || noop); - }; - - exports.chmodSync = function (path, mode) { - return process.fs.chmod(path, mode); - }; - - function writeAll (fd, data, encoding, callback) { - exports.write(fd, data, 0, encoding, function (writeErr, written) { - if (writeErr) { - exports.close(fd, function () { - if (callback) callback(writeErr); - }); - } else { - if (written === data.length) { - exports.close(fd, callback); - } else { - writeAll(fd, data.slice(written), encoding, callback); - } - } - }); - } - - exports.writeFile = function (path, data, encoding_, callback) { - var encoding = (typeof(encoding_) == 'string' ? encoding_ : 'utf8'); - var callback_ = arguments[arguments.length - 1]; - var callback = (typeof(callback_) == 'function' ? callback_ : null); - exports.open(path, 'w', 0666, function (openErr, fd) { - if (openErr) { - if (callback) callback(openErr); - } else { - writeAll(fd, data, encoding, callback); - } - }); - }; - - exports.writeFileSync = function (path, data, encoding) { - encoding = encoding || "utf8"; // default to utf8 - var fd = exports.openSync(path, "w"); - var written = 0; - while (written < data.length) { - written += exports.writeSync(fd, data, 0, encoding); - data = data.slice(written); - } - exports.closeSync(fd); - }; - - exports.cat = function () { - throw new Error("fs.cat is deprecated. Please use fs.readFile instead."); - }; - - function readAll (fd, pos, content, encoding, callback) { - exports.read(fd, 4*1024, pos, encoding, function (err, chunk, bytesRead) { - if (err) { - if (callback) callback(err); - } else if (chunk) { - content += chunk; - pos += bytesRead; - readAll(fd, pos, content, encoding, callback); - } else { - process.fs.close(fd, function (err) { - if (callback) callback(err, content); - }); - } - }); - } - - exports.readFile = function (path, encoding_, callback) { - var encoding = typeof(encoding_) == 'string' ? encoding : 'utf8'; - var callback_ = arguments[arguments.length - 1]; - var callback = (typeof(callback_) == 'function' ? callback_ : null); - exports.open(path, 'r', 0666, function (err, fd) { - if (err) { - if (callback) callback(err); - } else { - readAll(fd, 0, "", encoding, callback); - } - }); - }; - - exports.catSync = function () { - throw new Error("fs.catSync is deprecated. Please use fs.readFileSync instead."); - }; - - exports.readFileSync = function (path, encoding) { - encoding = encoding || "utf8"; // default to utf8 - - debug('readFileSync open'); - - var fd = exports.openSync(path, "r"); - var content = ''; - var pos = 0; - var r; - - while ((r = exports.readSync(fd, 4*1024, pos, encoding)) && r[0]) { - debug('readFileSync read ' + r[1]); - content += r[0]; - pos += r[1] - } - - debug('readFileSync close'); - - exports.closeSync(fd); - - debug('readFileSync done'); - - return content; - }; -}); - -var fs = fsModule.exports; + debug('readFileSync done'); + return content; +}; var pathModule = createInternalModule("path", function (exports) { exports.join = function () { @@ -703,7 +452,7 @@ var pathModule = createInternalModule("path", function (exports) { }; exports.exists = function (path, callback) { - fs.stat(path, function (err, stats) { + process.fs.stat(path, function (err, stats) { if (callback) callback(err ? false : true); }); }; @@ -713,7 +462,7 @@ var path = pathModule.exports; function existsSync (path) { try { - fs.statSync(path); + process.fs.stat(path); return true; } catch (e) { return false; @@ -932,7 +681,7 @@ function cat (id, callback) { } }); } else { - fs.readFile(id, callback); + process.fs.readFile(id, callback); } } @@ -971,7 +720,7 @@ Module.prototype._loadContent = function (content, filename) { Module.prototype._loadScriptSync = function (filename) { - var content = fs.readFileSync(filename); + var content = process.fs.readFileSync(filename); // remove shebang content = content.replace(/^\#\!.*/, ''); From 30b700ee225d0c5527390a5be90016895ae51189 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 1 Mar 2010 10:42:37 -0800 Subject: [PATCH 05/11] Move watchFile into fs module --- doc/api.txt | 48 +++++++++++++++++----------------- lib/fs.js | 40 ++++++++++++++++++++++++++++ src/node.js | 42 ++--------------------------- test/pummel/test-watch-file.js | 7 +++-- 4 files changed, 69 insertions(+), 68 deletions(-) diff --git a/doc/api.txt b/doc/api.txt index 1b3b102db9c..071b88a9dc8 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -153,30 +153,6 @@ Send a signal to a process. +pid+ is the process id and +signal+ is the signal to send; for example, "SIGINT" or "SIGUSR1". See kill(2) for more information. -+process.watchFile(filename, [options,] listener)+:: -Watch for changes on +filename+. The callback +listener+ will be called each -time the file changes. -+ -The second argument is optional. The +options+ if provided should be an -object containing two members a boolean, +persistent+, and +interval+, a -polling value in milliseconds. The default is +{persistent: true, interval: -0}+. -+ -The +listener+ gets two arguments the current stat object and the previous -stat object: -+ -------------------------- -process.watchFile(f, function (curr, prev) { - sys.puts("the current mtime is: " + curr.mtime); - sys.puts("the previous mtime was: " + prev.mtime); -}); -------------------------- -+ -These stat objects are instances of +fs.Stat+. - -+process.unwatchFile(filename)+:: -Stop watching for changes on +filename+. - +process.compile(source, scriptOrigin)+:: Just like +eval()+ except that you can specify a +scriptOrigin+ for better error reporting. @@ -755,6 +731,30 @@ fs.writeFile("message.txt", "Hello Node", function (err) { +fs.writeFileSync(filename, data, encoding="utf8")+:: The synchronous version of +fs.writeFile+. ++fs.watchFile(filename, [options,] listener)+:: +Watch for changes on +filename+. The callback +listener+ will be called each +time the file changes. ++ +The second argument is optional. The +options+ if provided should be an +object containing two members a boolean, +persistent+, and +interval+, a +polling value in milliseconds. The default is +{persistent: true, interval: +0}+. ++ +The +listener+ gets two arguments the current stat object and the previous +stat object: ++ +------------------------- +fs.watchFile(f, function (curr, prev) { + sys.puts("the current mtime is: " + curr.mtime); + sys.puts("the previous mtime was: " + prev.mtime); +}); +------------------------- ++ +These stat objects are instances of +fs.Stat+. + ++fs.unwatchFile(filename)+:: +Stop watching for changes on +filename+. + === +fs.Stats+ diff --git a/lib/fs.js b/lib/fs.js index afa6623d3ba..0bc68a58bb0 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -250,3 +250,43 @@ exports.catSync = function () { throw new Error("fs.catSync is deprecated. Please use fs.readFileSync instead."); }; +// Stat Change Watchers + +var statWatchers = {}; + +exports.watchFile = function (filename) { + var stat; + var options; + var listener; + + if ("object" == typeof arguments[1]) { + options = arguments[1]; + listener = arguments[2]; + } else { + options = {}; + listener = arguments[1]; + } + + if (options.persistent === undefined) options.persistent = true; + if (options.interval === undefined) options.interval = 0; + + if (filename in statWatchers) { + stat = statWatchers[filename]; + } else { + statWatchers[filename] = new process.Stat(); + stat = statWatchers[filename]; + stat.start(filename, options.persistent, options.interval); + } + stat.addListener("change", listener); + return stat; +}; + +exports.unwatchFile = function (filename) { + if (filename in statWatchers) { + stat = statWatchers[filename]; + stat.stop(); + statWatchers[filename] = undefined; + } +}; + + diff --git a/src/node.js b/src/node.js index a764d0285e5..ceae6329837 100644 --- a/src/node.js +++ b/src/node.js @@ -19,6 +19,8 @@ GLOBAL.print = removed("print() has moved. Use require('sys') to bring it back." GLOBAL.p = removed("p() has moved. Use require('sys') to bring it back."); process.debug = removed("process.debug() has moved. Use require('sys') to bring it back."); process.error = removed("process.error() has moved. Use require('sys') to bring it back."); +process.watchFile = removed("process.watchFile() has moved to fs.watchFile()"); +process.unwatchFile = removed("process.unwatchFile() has moved to fs.unwatchFile()"); GLOBAL.node = {}; @@ -246,46 +248,6 @@ process.addListener("newListener", function (event) { }); -// Stat Change Watchers - -var statWatchers = {}; - -process.watchFile = function (filename) { - var stat; - var options; - var listener; - - if ("object" == typeof arguments[1]) { - options = arguments[1]; - listener = arguments[2]; - } else { - options = {}; - listener = arguments[1]; - } - - if (options.persistent === undefined) options.persistent = true; - if (options.interval === undefined) options.interval = 0; - - if (filename in statWatchers) { - stat = statWatchers[filename]; - } else { - statWatchers[filename] = new process.Stat(); - stat = statWatchers[filename]; - stat.start(filename, options.persistent, options.interval); - } - stat.addListener("change", listener); - return stat; -}; - -process.unwatchFile = function (filename) { - if (filename in statWatchers) { - stat = statWatchers[filename]; - stat.stop(); - statWatchers[filename] = undefined; - } -}; - - // Timers function addTimerListener (callback) { var timer = this; diff --git a/test/pummel/test-watch-file.js b/test/pummel/test-watch-file.js index 1c235d6d17b..3b9890037cd 100644 --- a/test/pummel/test-watch-file.js +++ b/test/pummel/test-watch-file.js @@ -1,5 +1,6 @@ process.mixin(require("../common")); +var fs = require("fs"); var path = require("path"); var f = path.join(fixturesDir, "x.txt"); @@ -8,16 +9,14 @@ var f2 = path.join(fixturesDir, "x2.txt"); puts("watching for changes of " + f); var changes = 0; -process.watchFile(f, function (curr, prev) { +fs.watchFile(f, function (curr, prev) { puts(f + " change"); changes++; assert.ok(curr.mtime != prev.mtime); - process.unwatchFile(f); + fs.unwatchFile(f); }); -var fs = require("fs"); - var fd = fs.openSync(f, "w+"); fs.writeSync(fd, 'xyz\n'); fs.closeSync(fd); From b021a845f7d3712c6b821a30ebfe69156c708a28 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 1 Mar 2010 11:39:35 -0800 Subject: [PATCH 06/11] Move process.inherits to sys --- lib/assert.js | 4 ++-- lib/http.js | 2 +- lib/sys.js | 9 ++++++++- src/node.js | 10 +--------- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 4f6c46c9a7c..0a8c19715e2 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -23,7 +23,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // UTILITY - +var inherits = require('./sys').inherits; var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw @@ -47,7 +47,7 @@ assert.AssertionError = function AssertionError (options) { Error.captureStackTrace(this, stackStartFunction); } }; -process.inherits(assert.AssertionError, Error); +inherits(assert.AssertionError, Error); assert.AssertionError.prototype.toString = function() { if (this.message) { diff --git a/lib/http.js b/lib/http.js index 5e514e4be7f..d9eab022ee7 100644 --- a/lib/http.js +++ b/lib/http.js @@ -1,4 +1,4 @@ -var sys = require('sys'); +var sys = require('./sys'); var events = require('events'); var CRLF = "\r\n"; diff --git a/lib/sys.js b/lib/sys.js index 9c05342e480..4066ab917bb 100644 --- a/lib/sys.js +++ b/lib/sys.js @@ -214,5 +214,12 @@ exports.exec = function (command, callback) { * prototype * @param {function} superCtor Constructor function to inherit prototype from */ -exports.inherits = process.inherits; +exports.inherits = function (ctor, superCtor) { + var tempCtor = function(){}; + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; +}; + diff --git a/src/node.js b/src/node.js index ceae6329837..a1054206c86 100644 --- a/src/node.js +++ b/src/node.js @@ -27,6 +27,7 @@ GLOBAL.node = {}; node.createProcess = removed("node.createProcess() has been changed to process.createChildProcess() update your code"); node.exec = removed("process.exec() has moved. Use require('sys') to bring it back."); node.inherits = removed("node.inherits() has moved. Use require('sys') to access it."); +process.inherits = removed("process.inherits() has moved to sys.inherits."); node.http = {}; node.http.createServer = removed("node.http.createServer() has moved. Use require('http') to access it."); @@ -72,15 +73,6 @@ function createInternalModule (id, constructor) { }; -process.inherits = function (ctor, superCtor) { - var tempCtor = function(){}; - tempCtor.prototype = superCtor.prototype; - ctor.super_ = superCtor; - ctor.prototype = new tempCtor(); - ctor.prototype.constructor = ctor; -}; - - process.createChildProcess = function (file, args, env) { var child = new process.ChildProcess(); args = args || []; From 6034701f57354d7e44d7378d9d6f9860e49619fc Mon Sep 17 00:00:00 2001 From: Benjamin Thomas Date: Sat, 27 Feb 2010 08:32:55 +0000 Subject: [PATCH 07/11] Stop sys.inspect from adding extra new lines for deep objects that are elements in an array. A couple other small fixes: If the keys of an object were all numeric they should be quoted. This way, you can now hypothetically copy and paste the output into your code (if the object doesn't contain any circular objects, deeply nested objects, Dates, RegExps or functions. I think). If a nested object isn't being recursed into, output "[Object]" as opposed to "[object Object]". If an object is longer than the max width but it is one line no matter what, then don't put the closing brace on a new line. Fix some formatting issues to try and match Node's style guidelines. --- lib/sys.js | 27 +++++++++++++++++++-------- test/simple/test-sys.js | 6 +++--- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/sys.js b/lib/sys.js index 4066ab917bb..5ad68e49268 100644 --- a/lib/sys.js +++ b/lib/sys.js @@ -95,11 +95,11 @@ exports.inspect = function (obj, showHidden, depth) { return braces[0] + base + braces[1]; } - if( recurseTimes < 0 ) { + if (recurseTimes < 0) { if (value instanceof RegExp) { return '' + value; } else { - return "[object Object]"; + return "[Object]"; } } @@ -129,10 +129,17 @@ exports.inspect = function (obj, showHidden, depth) { else { str = format(value[key], recurseTimes - 1); } - if( str.indexOf('\n') > -1 ) { - str = '\n' + str.split('\n').map(function(line) { + if (str.indexOf('\n') > -1) { + if (value instanceof Array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } + else { + str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); + } } } else { str = '[Circular]'; @@ -143,7 +150,7 @@ exports.inspect = function (obj, showHidden, depth) { return str; } name = JSON.stringify('' + key); - if( name.match(/^"([a-zA-Z_0-9]+)"$/) ) { + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length-2); } else { @@ -154,13 +161,17 @@ exports.inspect = function (obj, showHidden, depth) { return name + ": " + str; }); - + var numLinesEst = 0; var length = output.reduce(function(prev, cur) { + numLinesEst++; + if( cur.indexOf('\n') >= 0 ) { + numLinesEst++; + } return prev + cur.length + 1; },0); - if( length > 50 ) { - output = braces[0] + (base === '' ? '' : base + '\n,') + ' ' + output.join('\n, ') + '\n' +braces[1]; + if (length > 50) { + output = braces[0] + (base === '' ? '' : base + '\n,') + ' ' + output.join('\n, ') + (numLinesEst > 1 ? '\n' : ' ') + braces[1]; } else { output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; diff --git a/test/simple/test-sys.js b/test/simple/test-sys.js index 06fd6943e05..d2b50a3a1a8 100644 --- a/test/simple/test-sys.js +++ b/test/simple/test-sys.js @@ -26,11 +26,11 @@ assert.equal('{ a: [Function] }', inspect({a: function() {}})); assert.equal('{ a: 1, b: 2 }', inspect({a: 1, b: 2})); assert.equal('{ a: {} }', inspect({'a': {}})); assert.equal('{ a: { b: 2 } }', inspect({'a': {'b': 2}})); -assert.equal('{ a: { b: { c: [object Object] } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}})); +assert.equal('{ a: { b: { c: [Object] } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}})); assert.equal('{ a: { b: { c: { d: 2 } } } }', inspect({'a': {'b': { 'c': { 'd': 2 }}}}, false, null)); assert.equal('[ 1, 2, 3, [length]: 3 ]', inspect([1,2,3], true)); -assert.equal('{ a: [object Object] }', inspect({'a': {'b': { 'c': 2}}},false,0)); -assert.equal('{ a: { b: [object Object] } }', inspect({'a': {'b': { 'c': 2}}},false,1)); +assert.equal('{ a: [Object] }', inspect({'a': {'b': { 'c': 2}}},false,0)); +assert.equal('{ a: { b: [Object] } }', inspect({'a': {'b': { 'c': 2}}},false,1)); assert.equal("{ visible: 1 }", inspect(Object.create({}, {visible:{value:1,enumerable:true},hidden:{value:2}})) ); From 55ab9b4541b2507f4e5491dd07437fab10867425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisend=C3=B6rfer?= Date: Mon, 1 Mar 2010 16:05:28 +0100 Subject: [PATCH 08/11] Bug fix for deep process.mixin array handling process.mixin was throwing an exception when trying to do a deep copy of an object that included an array. This bug was introduced in: 3bb7ad6fea42545e9d84ba5cbef8b48e470790fc --- src/node.js | 2 +- test/simple/test-process-mixin.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/node.js b/src/node.js index a1054206c86..221a5a2657c 100644 --- a/src/node.js +++ b/src/node.js @@ -126,7 +126,7 @@ process.mixin = function() { if ( (source = arguments[i]) != null ) { // Extend the base object Object.getOwnPropertyNames(source).forEach(function(k){ - var d = Object.getOwnPropertyDescriptor(source, k); + var d = Object.getOwnPropertyDescriptor(source, k) || {value: source[k]}; if (d.get) { target.__defineGetter__(k, d.get); if (d.set) { diff --git a/test/simple/test-process-mixin.js b/test/simple/test-process-mixin.js index 18d21f53eff..ca7bf9545bd 100644 --- a/test/simple/test-process-mixin.js +++ b/test/simple/test-process-mixin.js @@ -28,10 +28,19 @@ var source = { get foo(){ return this._foo; }, set foo(value){ this._foo = "did set to "+value; } }; -var target = {}; +target = {}; process.mixin(target, source); target._foo = 'b'; assert.equal(source.foo, 'a'); assert.equal('b', target.foo, 'target.foo != "b" -- value/result was copied instead of getter function'); source.foo = 'c'; assert.equal('did set to c', source.foo, 'source.foo != "c" -- value was set instead of calling setter function'); + +// Test that nested arrays are handled properly +target = {}; +process.mixin(true, target, { + foo: ['bar'], +}); + +assert.notStrictEqual(['bar'], target.foo); +assert.deepEqual(['bar'], target.foo); \ No newline at end of file From 7a251f3bdf0feac24262a94f56a65c4b18640d26 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 1 Mar 2010 14:39:31 -0800 Subject: [PATCH 09/11] Fix shebang in wscript --- wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wscript b/wscript index db456b838a3..7fc6365feca 100644 --- a/wscript +++ b/wscript @@ -1,4 +1,4 @@ -# /usr/bin/env python +#!/usr/bin/env python import re import Options import sys, os, shutil From 20d5963fae3795e0106f3b03ccee86b3590d044c Mon Sep 17 00:00:00 2001 From: Rasmus Andersson Date: Tue, 2 Mar 2010 03:01:44 +0100 Subject: [PATCH 10/11] Added fs.realpath and fs.realpathSync (pure javascript versions) --- doc/api.txt | 8 ++++ lib/fs.js | 85 +++++++++++++++++++++++++++++++++ test/simple/test-fs-realpath.js | 56 ++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 test/simple/test-fs-realpath.js diff --git a/doc/api.txt b/doc/api.txt index 071b88a9dc8..73f4f54c2e8 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -622,6 +622,14 @@ The callback gets two arguments +(err, resolvedPath)+. Synchronous readlink(2). Returns the resolved path. ++fs.realpath(path, callback)+ :: +Asynchronous realpath(2). +The callback gets two arguments +(err, resolvedPath)+. + ++fs.realpathSync(path)+ :: +Synchronous realpath(2). Returns the resolved path. + + +fs.unlink(path, callback)+ :: Asynchronous unlink(2). No arguments other than a possible exception are given to the completion callback. diff --git a/lib/fs.js b/lib/fs.js index 0bc68a58bb0..5687424dc26 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -289,4 +289,89 @@ exports.unwatchFile = function (filename) { } }; +// Realpath +var path = require('path'); +var dirname = path.dirname, + basename = path.basename, + normalize = path.normalize; + +function readlinkDeepSync(path, stats) { + var seen_links = {}, resolved_link, stats, file_id; + while (true) { + stats = stats || exports.lstatSync(path); + file_id = stats.dev.toString(32)+":"+stats.ino.toString(32); + if (file_id in seen_links) { + throw new Error("cyclic symbolic link at "+path); + } else { + seen_links[file_id] = 1; + if (stats.isSymbolicLink()) { + var newpath = exports.readlinkSync(path); + if (newpath.charAt(0) === '/') { + path = newpath; + } else { + var dir = dirname(path); + path = (dir !== '') ? dir + '/' + newpath : newpath; + } + } else { + return normalize(path); + } + } + stats = null; + } +} + +function readlinkDeep(path, stats, callback) { + var seen_links = {}, resolved_link, file_id; + function next(stats) { + file_id = stats.dev.toString(32)+":"+stats.ino.toString(32); + if (file_id in seen_links) { + callback(new Error("cyclic symbolic link at "+path)); + } else { + seen_links[file_id] = 1; + if (stats.isSymbolicLink()) { + exports.readlink(path, function(err, newpath) { + if (err) callback(err); + if (newpath.charAt(0) === '/') { + path = newpath; + } else { + var dir = dirname(path); + path = (dir !== '') ? dir + '/' + newpath : newpath; + } + _next(); + }); + } else { + callback(null, normalize(path)); + } + } + } + function _next() { + exports.lstat(path, function(err, stats){ + if (err) callback(err); + else next(stats); + }); + } + if (stats) next(stats); + else _next(); +} + +exports.realpathSync = function(path) { + var stats = exports.lstatSync(path); + if (stats.isSymbolicLink()) + return readlinkDeepSync(path, stats); + else + return normalize(path); +} + +exports.realpath = function(path, callback) { + var resolved_path = path; + if (!callback) return; + exports.lstat(path, function(err, stats){ + if (err) + callback(err); + else if (stats.isSymbolicLink()) + readlinkDeep(path, stats, callback); + else + callback(null, normalize(path)); + }); +} diff --git a/test/simple/test-fs-realpath.js b/test/simple/test-fs-realpath.js new file mode 100644 index 00000000000..384faebf4f8 --- /dev/null +++ b/test/simple/test-fs-realpath.js @@ -0,0 +1,56 @@ +process.mixin(require("../common")); + +var async_completed = 0, async_expected = 0; + +// a. deep relative file symlink +var dstPath = path.join(fixturesDir, 'cycles', 'root.js'); +var linkData1 = "../../cycles/root.js"; +var linkPath1 = path.join(fixturesDir, "nested-index", 'one', 'symlink1.js'); +try {fs.unlinkSync(linkPath1);}catch(e){} +fs.symlinkSync(linkData1, linkPath1); + +var linkData2 = "../one/symlink1.js"; +var linkPath2 = path.join(fixturesDir, "nested-index", 'two', 'symlink1-b.js'); +try {fs.unlinkSync(linkPath2);}catch(e){} +fs.symlinkSync(linkData2, linkPath2); + +// b. deep relative directory symlink +var dstPath_b = path.join(fixturesDir, 'cycles', 'folder'); +var linkData1b = "../../cycles/folder"; +var linkPath1b = path.join(fixturesDir, "nested-index", 'one', 'symlink1-dir'); +try {fs.unlinkSync(linkPath1b);}catch(e){} +fs.symlinkSync(linkData1b, linkPath1b); + +var linkData2b = "../one/symlink1-dir"; +var linkPath2b = path.join(fixturesDir, "nested-index", 'two', 'symlink12-dir'); +try {fs.unlinkSync(linkPath2b);}catch(e){} +fs.symlinkSync(linkData2b, linkPath2b); + +assert.equal(fs.realpathSync(linkPath2), dstPath); +assert.equal(fs.realpathSync(linkPath2b), dstPath_b); + +async_expected++; +fs.realpath(linkPath2, function(err, rpath) { + if (err) throw err; + assert.equal(rpath, dstPath); + async_completed++; +}); + +async_expected++; +fs.realpath(linkPath2b, function(err, rpath) { + if (err) throw err; + assert.equal(rpath, dstPath_b); + async_completed++; +}); + +// todo: test shallow symlinks (file & dir) +// todo: test non-symlinks (file & dir) +// todo: test error on cyclic symlinks + +process.addListener("exit", function () { + try {fs.unlinkSync(linkPath1);}catch(e){} + try {fs.unlinkSync(linkPath2);}catch(e){} + try {fs.unlinkSync(linkPath1b);}catch(e){} + try {fs.unlinkSync(linkPath2b);}catch(e){} + assert.equal(async_completed, async_expected); +}); From fdbc9a82e44511e3b94babf3534e9feac0c3f0cf Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 2 Mar 2010 10:39:02 -0800 Subject: [PATCH 11/11] Use EVBACKEND_SELECT on Solaris Using EVBACKEND_PORT DTraceToolkit-0.99/Proc/syscallbypid.d reports after 5 seconds PID CMD SYSCALL COUNT . . . . . . . . . . . . 28551 mysqld fcntl 485 24793 httpd gtime 528 28551 mysqld read 707 28551 mysqld gtime 956 21050 rsync pollsys 965 21050 rsync read 965 24793 httpd read 982 28551 mysqld lwp_sigmask 1422 4675 dtrace ioctl 1579 15136 node portfs 15681 15136 node clock_gettime 31358 On a very simple node process. --- src/node.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/node.cc b/src/node.cc index 57c61b08053..d760c72976c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1240,7 +1240,13 @@ int main(int argc, char *argv[]) { evcom_ignore_sigpipe(); // Initialize the default ev loop. +#ifdef __sun + // TODO(Ryan) I'm experiencing abnormally high load using Solaris's + // EVBACKEND_PORT. Temporarally forcing select() until I debug. + ev_default_loop(EVBACKEND_SELECT); +#else ev_default_loop(EVFLAG_AUTO); +#endif ev_timer_init(&node::gc_timer, node::GCTimeout, GC_INTERVAL, GC_INTERVAL);