Compare commits

...

57 Commits

Author SHA1 Message Date
Ryan Dahl
da235fa12c bump version to v0.2.1 2010-09-10 13:52:33 -07:00
Paul Querna
92fb664bfc Expose fingerproint from getPeerCertificate
Expose the SHA1 digest of the certificate as the fingerprint attribute in
the object returned by getPeerCertificate()
2010-09-10 13:31:46 -07:00
Ryan Dahl
7704fb9711 Fix fs.realpathSync('/') 2010-09-10 13:31:39 -07:00
isaacs
c099e274d2 Better temporary directory handling for tests.
Add a setUp and tearDown function to the test case class, and use it to
create and remove the test/tmp directory for each test.

TODO: amend other tests.
2010-09-10 13:31:34 -07:00
Ryan Dahl
c86f3c5d5c Don't use empty.js - breaks module test 2010-09-10 13:31:27 -07:00
Felix Geisendörfer
9b8577230f Simple benchmark for node's startup time 2010-09-10 13:31:21 -07:00
Ryan Dahl
9f6f26028f Use SetPointerInInternalField 2010-09-10 13:31:16 -07:00
Felix Geisendörfer
44f8756aab Fix: uncaughtException was broken for main module
See: 635986e433
2010-09-10 13:30:48 -07:00
Ryan Dahl
ae2f566fec Call Tick() after coming out of select()
Previously we would only call it before going into select(). This is needed
to fix test/simple/test-next-tick-ordering2.js.
2010-09-10 13:30:38 -07:00
isaacs
2f071ac7d1 Fix issue #262. Allow fs.realpath to traverse above the current working directory. 2010-09-08 17:56:34 -07:00
Tobie Langel
bd8ea2bb85 Test for ReadStream typo 2010-09-08 17:56:25 -07:00
Ryan Dahl
35682ac88e Fix style; undefined reference bug 2010-09-08 17:56:17 -07:00
Tobie Langel
5bbebf3593 Do not emit WriteStream's drain event before ws.write has been called. 2010-09-08 17:56:12 -07:00
Tobie Langel
0b9dab650e Avoid closing a WriteStream before it has been opened. 2010-09-08 17:55:58 -07:00
Tobie Langel
a6659e7612 Avoid missing ref error in WriteStream.prototype.destroy(). 2010-09-08 17:55:53 -07:00
Herbert Vojčík
727843eea1 Make test-global work with NODE_MODULE_CONTEXTS. 2010-09-08 17:55:44 -07:00
Herbert Vojčík
7e9a0173d7 Modifying test-global to accomodate v8 inter-context 'global' protection. 2010-09-08 17:55:38 -07:00
Herbert Vojčík
74b70c3cb1 Removing test-global-between-modules.
Using "global" to push data to require()d modules
not supported under NODE_MODULE_CONTEXTS=1.
2010-09-08 17:55:33 -07:00
Herbert Vojčík
d5deb4c4a3 Removed comment-out code. 2010-09-08 17:48:52 -07:00
Ryan Dahl
cc0164bc12 Increase ReadStream bufferSize to 64k 2010-09-08 17:48:45 -07:00
Trent Mick
ccd1304c5b Ctrl+W support for the REPL
FWIW, command-line style (delete back to whitespace) would be:
    leading = leading.replace(/\S+\s*$/, '');
2010-09-08 17:48:15 -07:00
Felix Geisendörfer
3d3d00d524 Test case showing a bug in nextTick ordering
nextTick should fire before setTimeout in this test, but it doesn't.
2010-09-08 17:48:02 -07:00
Ryan Dahl
dffa9e76a1 test-http-parser should not use private API 2010-09-08 17:47:36 -07:00
Ryan Dahl
90374797f0 Don't refer to private API in test-repl 2010-09-08 17:47:30 -07:00
Ryan Dahl
c1a4e10156 Special deepEquals for buffer 2010-09-08 17:47:23 -07:00
Ryan Dahl
b655ce5c08 typo: forceClose -> destroy for WriteStreams 2010-09-08 17:47:17 -07:00
Benjamin Thomas
b30b60717d Fix bug in process._tickCallback where callbacks can get abandoned.
Change process._tickCallback so that if a callback throws an error but
there are other callbacks after it, we indicate that
process._tickCallback needs to be ran again.

Currently, if a callback in process._tickCallback throws an error, and
that error is caught by an uncaughtException handler and
process.nextTick is never called again, then any other callbacks already
added to the nextTickQueue won't be called again.

Updated the next-tick-errors test to catch this scenario.
2010-09-08 17:46:58 -07:00
isaacs
b2dfea0361 Treat "//some_path" as pathname rather than hostname by default.
Note that "//" is still a special indicator for the hostname, and this does
not change the parsing of mailto: and other "slashless" url schemes.  It
does however remove some oddness in url.parse(req.url) which is the most
common use-case for the url.parse function.
2010-09-08 17:46:50 -07:00
Ryan Dahl
610743daee Make sure setInterval(cb, 0) loops infinitely 2010-09-08 17:46:43 -07:00
Ryan Dahl
df891c36a4 Fix style 2010-09-08 17:46:36 -07:00
Ryan Dahl
f35a8298b1 Fix style in test/simple/test-dgram-unix.js 2010-09-08 17:46:30 -07:00
Ryan Dahl
294c455678 Remove timer from test/simple/test-dgram-unix.js
Test running already has a timeout mechanism.
2010-09-08 17:46:24 -07:00
Marco Rogers
14f16ec592 fix for fs.readFile to return string when encoding specified on zero length read 2010-09-08 17:45:26 -07:00
Marco Rogers
cdee88051d Fixed async fs writes with length 0, it should fire the callback 2010-09-08 17:45:21 -07:00
Bradley Meck
b39b15d53f Allow Strings for ports on net.Server.listen 2010-09-08 17:45:07 -07:00
Fedor Indutny
b895568800 Constants should be readOnly and DontDelete 2010-09-08 17:44:40 -07:00
Ryan Dahl
ead58b9a93 Add failing uncaughtException test
FIXME
2010-09-08 17:44:30 -07:00
Johan Euphrosine
c306fa241c add readline support for meta-d 2010-09-08 17:44:13 -07:00
Benjamin Thomas
22f67f8585 Fix process.nextTick so thrown errors don't confuse it.
If the function for a process.nextTick throws an error, then the
splice() never removes that function from the nextTickQueue array.  This
makes sure the functions that have been run in _tickCallback get removed
regardless of errors.

Also add a test for this.
2010-09-08 17:43:47 -07:00
Ryan Dahl
416aa73946 Safe constructor: net.Server, net.Stream 2010-09-08 17:43:39 -07:00
Ryan Dahl
6a39a7ed83 Safe Constructor: Buffer 2010-09-08 17:43:32 -07:00
Ryan Dahl
ad960f4462 Safe constructors: http.Server and http.Client 2010-09-08 17:43:25 -07:00
Ryan Dahl
f78691e45c Only check for execinfo lib in freebsd
OpenEmbedded doesn't like it when you look in /usr/lib
2010-09-08 17:43:17 -07:00
Johan Euphrosine
3d8137c582 add test for readline putty support 2010-09-08 17:42:59 -07:00
Brian
c14c445cb6 Fix home/end keys in repl for putty/xterm. 2010-09-08 17:42:47 -07:00
Russell Haering
b9ca8435f5 Modify fs.open to use accept a callback without a mode 2010-09-08 17:42:36 -07:00
Johan Euphrosine
baa24bd40e add readline support for meta-f and meta-b 2010-09-08 17:42:23 -07:00
Johan Euphrosine
7a836ef813 add home/end support in rxvt and readline tests 2010-09-08 17:42:09 -07:00
Felix Geisendörfer
a2b9e02d83 Document WriteStream 'open' event 2010-09-08 17:41:59 -07:00
isaacs
3f7c791b13 Add testing items, and make npm lowercase 2010-09-08 17:40:59 -07:00
isaacs
53dac7c341 Missing 'var' in sys.inspect (Found by Oleg Slobodskoi) 2010-09-08 17:40:50 -07:00
Aria Stewart
c43ddf7acd Fix doc.js so that it doesn't misnest menu items in the TOC 2010-09-08 17:40:41 -07:00
Johan Euphrosine
699fdfaa43 fix home/end on GNU/Linux 2010-09-08 17:40:35 -07:00
Johan Euphrosine
8d2e79451e add tests for console.log arguments handling 2010-09-08 17:40:26 -07:00
Aria Stewart
760efc0758 s/HTTPS/SSL/ where appropriate 2010-09-08 17:39:55 -07:00
Ryan Dahl
1b1ad1d363 Improve appendix markdown 2010-09-08 17:39:38 -07:00
Ryan Dahl
c3eafdd3a4 Add appendix to docs 2010-09-08 17:39:28 -07:00
58 changed files with 853 additions and 339 deletions

View File

@@ -1,4 +1,29 @@
2010.08.20, Version 0.2.0
2010.09.10, Version 0.2.1
* REPL improvements (Johan Euphrosine, Brian White)
* nextTick bug fixes (Benjamin Thomas, Felix Geisendörfer,
Trent Mick)
* fs module bug fixes (Russell Haering, Marco Rogers, Tobie Langel,
Isaac Schlueter)
* Build script change for OpenEmbedded.
* Most constrctuors work without 'new' now.
* Allow Strings for ports on net.Server.listen (Bradley Meck)
* setInterval(cb, 0) loops infinitely
* Fixes for NODE_MODULE_CONTEXTS=1 (Herbert Vojčík)
* Expose fingerproint from getPeerCertificate (Paul Querna)
* API: forceClose -> destroy for WriteStreams
2010.08.20, Version 0.2.0, 9283e134e558900ba89d9a33c18a9bdedab07cb9
* process.title support for FreeBSD, Macintosh, Linux

View File

@@ -1,6 +1,6 @@
for (var i = 0; i < 9000000; i++) {
for (var i = 0; i < 9e7; i++) {
b = new Buffer(10);
b[1] = 2
}

26
benchmark/startup.js Normal file
View File

@@ -0,0 +1,26 @@
var spawn = require('child_process').spawn,
path = require('path'),
emptyJsFile = path.join(__dirname, '../test/fixtures/semicolon.js'),
starts = 100,
i = 0,
start;
function startNode() {
var node = spawn(process.execPath || process.argv[0], [emptyJsFile]);
node.on('exit', function(exitCode) {
if (exitCode !== 0) {
throw new Error('Error during node startup');
}
i++;
if (i < starts) {
startNode();
} else{
var duration = +new Date - start;
console.log('Started node %d times in %s ms. %d ms / start.', starts, duration, duration / starts);
}
});
}
start = +new Date;
startNode();

View File

@@ -1,6 +1,6 @@
for (var i = 0; i < 9000000; i++) {
for (var i = 0; i < 9e7; i++) {
s = '01234567890';
s[1] = "a";
}

View File

@@ -1607,6 +1607,12 @@ An example to read the last 10 bytes of a file which is 100 bytes long:
`WriteStream` is a `Writable Stream`.
### Event: 'open'
`function (fd) { }`
`fd` is the file descriptor used by the WriteStream.
### fs.createWriteStream(path, [options])
Returns a new WriteStream object (See `Writable Stream`).
@@ -2225,7 +2231,7 @@ See `connect()`.
`function () { }`
Emitted when a stream connection successfully establishes a HTTPS handshake with its peer.
Emitted when a stream connection successfully establishes an SSL handshake with its peer.
### Event: 'data'
@@ -2314,9 +2320,9 @@ received.
### stream.setSecure([credentials])
Enables HTTPS support for the stream, with the crypto module credentials specifying the private key and certificate of the stream, and optionally the CA certificates for use in peer authentication.
Enables SSL support for the stream, with the crypto module credentials specifying the private key and certificate of the stream, and optionally the CA certificates for use in peer authentication.
If the credentials hold one ore more CA certificates, then the stream will request for the peer to submit a client certificate as part of the HTTPS connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate().
If the credentials hold one ore more CA certificates, then the stream will request for the peer to submit a client certificate as part of the SSL connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate().
### stream.verifyPeer()
@@ -3284,3 +3290,49 @@ All Node addons must export a function called `init` with this signature:
For the moment, that is all the documentation on addons. Please see
<http://github.com/ry/node_postgres> for a real example.
## Appendix - Third Party Modules
There are many third party modules for Node. At the time of writing, August
2010, the master repository of modules is
http://github.com/ry/node/wiki/modules[the wiki page].
This appendix is intended as a SMALL guide to new-comers to help them
quickly find what are considered to be quality modules. It is not intended
to be a complete list. There may be better more complete modules found
elsewhere.
- Module Installer: [npm](http://github.com/isaacs/npm)
- HTTP Middleware: [Connect](http://github.com/senchalabs/connect)
- Web Framework: [Express](http://github.com/visionmedia/express)
- Web Sockets: [Socket.IO](http://github.com/LearnBoost/Socket.IO-node)
- HTML Parsing: [HTML5](http://github.com/aredridel/html5)
- [mDNS/Zeroconf/Bonjour](http://github.com/agnat/node_mdns)
- [RabbitMQ, AMQP](http://github.com/ry/node-amqp)
- [mysql](http://github.com/felixge/node-mysql)
- Serialization: [msgpack](http://github.com/pgriess/node-msgpack)
- Scraping: [Apricot](http://github.com/silentrob/Apricot)
- Debugger: [ndb](http://github.com/smtlaissezfaire/ndb) is a CLI debugger
[inspector](http://github.com/dannycoates/node-inspector) is a web based
tool.
- [pcap binding](http://github.com/mranney/node_pcap)
- [ncurses](http://github.com/mscdex/node-ncurses)
- Testing/TDD/BDD: [vows](http://vowsjs.org/),
[expresso](http://github.com/visionmedia/expresso),
[mjsunit.runner](http://github.com/tmpvar/mjsunit.runner)
Patches to this list are welcome.

View File

@@ -295,7 +295,7 @@
<body>
<div id="toc">
<div id="toctitle">Node v0.2.0</div>
<div id="toctitle">Node v0.2.1</div>
<noscript>JavaScript must be enabled in your browser to display the table of contents.</noscript>
</div>
<div id='man'>

View File

@@ -23,6 +23,10 @@ NodeDoc.generateToc = function()
cur_level = this.tagName.substr(1, 1);
if (last_level != 0 && cur_level <= last_level) {
html.push("</li>")
}
if (cur_level > last_level)
{
html.push('<ul><li>');
@@ -38,15 +42,11 @@ NodeDoc.generateToc = function()
}
html.push('<a href="#' + $this.attr('id') + '">' + $this.text().replace(/\(.*\)$/gi, '') + '</a>');
if (cur_level == last_level || cur_level > last_level)
{
html.push('</li>');
}
last_level = cur_level;
});
html.push('</ul>');
html.push('</li></ul>');
var $toc = $('#toc').append(html.join('')).find('ul li ul').each(function()
{
@@ -175,4 +175,4 @@ NodeDoc.setupSmoothScrolling = function()
}
});
};
NodeDoc.init();
NodeDoc.init();

View File

@@ -89,8 +89,8 @@ net.createServer(function (socket) {
<a href="http://github.com/ry/node/tree/master">git repo</a>
</p>
<p>
2010.08.20
<a href="http://nodejs.org/dist/node-v0.2.0.tar.gz">node-v0.2.0.tar.gz</a>
2010.09.10
<a href="http://nodejs.org/dist/node-v0.2.1.tar.gz">node-v0.2.1.tar.gz</a>
</p>
<p>Historical: <a href="http://nodejs.org/dist">versions</a>, <a href="http://nodejs.org/docs">docs</a></p>

View File

@@ -131,6 +131,15 @@ function _deepEqual(actual, expected) {
if (actual === expected) {
return true;
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (actual instanceof Date && expected instanceof Date) {

296
lib/fs.js
View File

@@ -6,7 +6,7 @@ var binding = process.binding('fs');
var fs = exports;
var kMinPoolSpace = 128;
var kPoolSize = 40*1024;
var kPoolSize = 40 * 1024;
fs.Stats = binding.Stats;
@@ -56,7 +56,7 @@ fs.readFile = function (path, encoding_, callback) {
function doRead() {
if (size < 1) {
binding.close(fd);
callback(null, buffer);
callback(null, encoding ? '' : buffer);
return;
}
// position is offset or null so we can read files on unseekable mediums
@@ -140,8 +140,11 @@ fs.closeSync = function (fd) {
return binding.close(fd);
};
fs.open = function (path, flags, mode, callback) {
if (mode === undefined) { mode = 0666; }
fs.open = function (path, flags, mode_, callback) {
var mode = (typeof(mode_) == 'number' ? mode_ : 0666);
var callback_ = arguments[arguments.length - 1];
var callback = (typeof(callback_) == 'function' ? callback_ : null);
binding.open(path, stringToFlags(flags), mode, callback || noop);
};
@@ -208,7 +211,15 @@ fs.write = function (fd, buffer, offset, length, position, callback) {
offset = 0;
length = buffer.length;
}
if(!length) return;
if (!length) {
if (typeof callback == 'function') {
process.nextTick(function() {
callback(undefined, 0);
});
}
return;
}
binding.write(fd, buffer, offset, length, position, callback || noop);
};
@@ -458,132 +469,121 @@ var path = require('path');
var normalize = path.normalize;
var normalizeArray = path.normalizeArray;
fs.realpathSync = function (path) {
var seen_links = {}, knownHards = {}, buf, i = 0, part, x, stats;
if (path.charAt(0) !== '/') {
var cwd = process.cwd().split('/');
path = cwd.concat(path.split('/'));
path = normalizeArray(path);
i = cwd.length;
buf = [].concat(cwd);
} else {
path = normalizeArray(path.split('/'));
// realpath
// Not using realpath(2) because it's bad.
// See: http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
fs.realpathSync = realpathSync;
fs.realpath = realpath;
function realpathSync (p) {
if (p.charAt(0) !== '/') {
p = path.join(process.cwd(), p);
}
p = p.split('/');
var buf = [ '' ];
var seenLinks = {};
var knownHard = {};
// walk down the path, swapping out linked pathparts for their real
// values, and pushing non-link path bits onto the buffer.
// then return the buffer.
// NB: path.length changes.
for (var i = 0; i < p.length; i ++) {
// skip over empty path parts.
if (p[i] === '') continue;
var part = buf.join('/')+'/'+p[i];
if (knownHard[part]) {
buf.push( p[i] );
continue;
}
var stat = fs.lstatSync(part);
if (!stat.isSymbolicLink()) {
// not a symlink. easy.
knownHard[ part ] = true;
buf.push(p[i]);
continue;
}
var id = stat.dev.toString(32)+':'+stat.ino.toString(32);
if (seenLinks[id]) throw new Error("cyclic link at "+part);
seenLinks[id] = true;
var target = fs.readlinkSync(part);
if (target.charAt(0) === '/') {
// absolute. Start over.
buf = [''];
p = path.normalizeArray(target.split('/'));
i = 0;
continue;
}
// not absolute. join and splice.
target = target.split('/');
Array.prototype.splice.apply(p, [i, 1].concat(target));
p = path.normalizeArray(p);
i = 0;
buf = [''];
}
for (; i<path.length; i++) {
part = path.slice(0, i+1).join('/');
if (part.length !== 0) {
if (part in knownHards) {
buf.push(path[i]);
} else {
stats = fs.lstatSync(part);
if (stats.isSymbolicLink()) {
x = stats.dev.toString(32)+":"+stats.ino.toString(32);
if (x in seen_links)
throw new Error("cyclic link at "+part);
seen_links[x] = true;
part = fs.readlinkSync(part);
if (part.charAt(0) === '/') {
// absolute
path = normalizeArray(part.split('/'));
buf = [''];
i = 0;
} else {
// relative
Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
part = normalizeArray(path);
var y = 0, L = Math.max(path.length, part.length), delta;
for (; y<L && path[y] === part[y]; y++);
if (y !== L) {
path = part;
delta = i-y;
i = y-1;
if (delta > 0) buf.splice(y, delta);
} else {
i--;
}
}
} else {
buf.push(path[i]);
knownHards[buf.join('/')] = true;
}
}
}
}
return buf.join('/');
return buf.join('/') || '/';
}
fs.realpath = function (path, callback) {
var seen_links = {}, knownHards = {}, buf = [''], i = 0, part, x;
if (path.charAt(0) !== '/') {
// assumes cwd is canonical
var cwd = process.cwd().split('/');
path = cwd.concat(path.split('/'));
path = normalizeArray(path);
i = cwd.length-1;
buf = [].concat(cwd);
} else {
path = normalizeArray(path.split('/'));
function realpath (p, cb) {
if (p.charAt(0) !== '/') {
p = path.join(process.cwd(), p);
}
function done(err) {
if (callback) {
if (!err) callback(err, buf.join('/'));
else callback(err);
p = p.split('/');
var buf = [ '' ];
var seenLinks = {};
var knownHard = {};
// walk down the path, swapping out linked pathparts for their real
// values, and pushing non-link path bits onto the buffer.
// then return the buffer.
// NB: path.length changes.
var i = 0;
var part;
LOOP();
function LOOP () {
i ++;
if (!(i < p.length)) return exit();
// skip over empty path parts.
if (p[i] === '') return process.nextTick(LOOP);
part = buf.join('/')+'/'+p[i];
if (knownHard[part]) {
buf.push( p[i] );
return process.nextTick(LOOP);
}
return fs.lstat(part, gotStat);
}
function next() {
if (++i === path.length) return done();
part = path.slice(0, i+1).join('/');
if (part.length === 0) return next();
if (part in knownHards) {
buf.push(path[i]);
next();
} else {
fs.lstat(part, function(err, stats){
if (err) return done(err);
if (stats.isSymbolicLink()) {
x = stats.dev.toString(32)+":"+stats.ino.toString(32);
if (x in seen_links)
return done(new Error("cyclic link at "+part));
seen_links[x] = true;
fs.readlink(part, function(err, npart){
if (err) return done(err);
part = npart;
if (part.charAt(0) === '/') {
// absolute
path = normalizeArray(part.split('/'));
buf = [''];
i = 0;
} else {
// relative
Array.prototype.splice.apply(path, [i, 1].concat(part.split('/')));
part = normalizeArray(path);
var y = 0, L = Math.max(path.length, part.length), delta;
for (; y<L && path[y] === part[y]; y++);
if (y !== L) {
path = part;
delta = i-y;
i = y-1; // resolve new node if needed
if (delta > 0) buf.splice(y, delta);
}
else {
i--; // resolve new node if needed
}
}
next();
}); // binding.readlink
}
else {
buf.push(path[i]);
knownHards[buf.join('/')] = true;
next();
}
}); // binding.lstat
function gotStat (er, stat) {
if (er) return cb(er);
if (!stat.isSymbolicLink()) {
// not a symlink. easy.
knownHard[ part ] = true;
buf.push(p[i]);
return process.nextTick(LOOP);
}
var id = stat.dev.toString(32)+':'+stat.ino.toString(32);
if (seenLinks[id]) return cb(new Error("cyclic link at "+part));
seenLinks[id] = true;
fs.readlink(part, gotTarget);
}
next();
};
function gotTarget (er, target) {
if (er) return cb(er);
if (target.charAt(0) === '/') {
// absolute. Start over.
buf = [''];
p = path.normalizeArray(target.split('/'));
i = 0;
return process.nextTick(LOOP);
}
// not absolute. join and splice.
target = target.split('/');
Array.prototype.splice.apply(p, [i, 1].concat(target));
p = path.normalizeArray(p);
i = 0;
buf = [''];
return process.nextTick(LOOP);
}
function exit () {
cb(null, buf.join('/') || '/');
}
}
var pool;
function allocNewPool () {
@@ -600,6 +600,8 @@ fs.createReadStream = function(path, options) {
var ReadStream = fs.ReadStream = function(path, options) {
events.EventEmitter.call(this);
var self = this;
this.path = path;
this.fd = null;
this.readable = true;
@@ -607,7 +609,7 @@ var ReadStream = fs.ReadStream = function(path, options) {
this.flags = 'r';
this.mode = 0666;
this.bufferSize = 4 * 1024;
this.bufferSize = 64 * 1024;
options = options || {};
@@ -618,11 +620,12 @@ var ReadStream = fs.ReadStream = function(path, options) {
this[key] = options[key];
}
if(this.start || this.end) {
if(this.start === undefined || this.end === undefined) {
self.emit('error', new Error('Both start and end are needed for range streaming.'));
} else if(this.start > this.end) {
self.emit('error', new Error('start must be <= end'));
if (this.start || this.end) {
if (this.start === undefined || this.end === undefined) {
this.emit('error',
new Error('Both start and end are needed for range streaming.'));
} else if (this.start > this.end) {
this.emit('error', new Error('start must be <= end'));
} else {
this.firstRead = true;
}
@@ -632,7 +635,6 @@ var ReadStream = fs.ReadStream = function(path, options) {
return;
}
var self = this;
fs.open(this.path, this.flags, this.mode, function(err, fd) {
if (err) {
self.emit('error', err);
@@ -829,7 +831,10 @@ WriteStream.prototype.flush = function () {
var self = this;
var args = this._queue.shift();
if (!args) return self.emit('drain');
if (!args) {
if (this.drainable) { self.emit('drain'); }
return;
}
this.busy = true;
@@ -885,6 +890,8 @@ WriteStream.prototype.write = function (data) {
throw new Error('stream not writeable');
}
this.drainable = true;
var cb;
if (typeof(arguments[arguments.length-1]) == 'function') {
cb = arguments[arguments.length-1];
@@ -934,22 +941,27 @@ WriteStream.prototype.forceClose = function (cb) {
};
WriteStream.prototype.forceClose = function (cb) {
WriteStream.prototype.destroy = function (cb) {
var self = this;
this.writeable = false;
fs.close(self.fd, function(err) {
if (err) {
if (cb) {
cb(err);
function close() {
fs.close(self.fd, function(err) {
if (err) {
if (cb) { cb(err); }
self.emit('error', err);
return;
}
self.emit('error', err);
return;
}
if (cb) { cb(null); }
self.emit('close');
});
}
if (cb) {
cb(null);
}
self.emit('close');
});
if (this.fd) {
close();
} else {
this.addListener('open', close);
}
};

View File

@@ -713,6 +713,7 @@ function httpSocketSetup (socket) {
function Server (requestListener) {
if (!(this instanceof Server)) return new Server(requestListener);
net.Server.call(this);
if(requestListener){
@@ -834,6 +835,7 @@ function connectionListener (socket) {
function Client ( ) {
if (!(this instanceof Client)) return new Client();
net.Stream.call(this);
var self = this;

View File

@@ -513,6 +513,7 @@ function initStream (self) {
}
function Stream (fd, type) {
if (!(this instanceof Stream)) return new Stream(fd, type);
events.EventEmitter.call(this);
this.fd = null;
@@ -855,7 +856,7 @@ function doConnect (socket, port, host) {
};
}
function isPort (x) { return parseInt(x) >= 0; }
function toPort (x) { return (x = Number(x)) >= 0 ? x : false }
// var stream = new Stream();
@@ -872,9 +873,16 @@ Stream.prototype.connect = function () {
self._connecting = true; // set false in doConnect
if (isPort(arguments[0])) {
var port = toPort(arguments[0])
if (port === false) {
// UNIX
self.fd = socket('unix');
self.type = 'unix';
setImplmentationMethods(this);
doConnect(self, arguments[0]);
} else {
// TCP
var port = arguments[0];
dns.lookup(arguments[1], function (err, ip, addressType) {
if (err) {
self.emit('error', err);
@@ -884,13 +892,6 @@ Stream.prototype.connect = function () {
doConnect(self, port, ip);
}
});
} else {
// UNIX
self.fd = socket('unix');
self.type = 'unix';
setImplmentationMethods(this);
doConnect(self, arguments[0]);
}
};
@@ -1032,6 +1033,7 @@ Stream.prototype.end = function (data, encoding) {
function Server (listener) {
if (!(this instanceof Server)) return new Server(listener);
events.EventEmitter.call(this);
var self = this;
@@ -1107,7 +1109,8 @@ Server.prototype.listen = function () {
self.addListener('listening', lastArg);
}
if (!isPort(arguments[0])) {
var port = toPort(arguments[0])
if (port === false) {
// the first argument specifies a path
self.fd = socket('unix');
self.type = 'unix';
@@ -1142,13 +1145,12 @@ Server.prototype.listen = function () {
// The port can be found with server.address()
self.type = 'tcp4';
self.fd = socket(self.type);
bind(self.fd, arguments[0]);
bind(self.fd, port);
process.nextTick(function () {
self._doListen();
});
} else {
// the first argument is the port, the second an IP
var port = arguments[0];
dns.lookup(arguments[1], function (err, ip, addressType) {
if (err) {
self.emit('error', err);

View File

@@ -15,7 +15,6 @@ var EventEmitter = require('events').EventEmitter;
var stdio = process.binding('stdio');
exports.createInterface = function (output, completer) {
return new Interface(output, completer);
};
@@ -332,6 +331,17 @@ Interface.prototype._ttyWrite = function (b) {
this._historyNext();
break;
case 23: // control-w, delete backwards to a word boundary
if (this.cursor !== 0) {
var leading = this.line.slice(0, this.cursor);
var match = leading.match(/\s?((\W+|\w+)\s*)$/);
leading = leading.slice(0, leading.length - match[1].length);
this.line = leading + this.line.slice(this.cursor, this.line.length);
this.cursor = leading.length;
this._refreshLine();
}
break;
case 9: // tab, completion
if (this.completer) {
this._tabComplete();
@@ -347,10 +357,53 @@ Interface.prototype._ttyWrite = function (b) {
return;
case 27: /* escape sequence */
var next_word, next_non_word, previous_word, previous_non_word;
if (b[1] === 98 && this.cursor > 0) { // meta-b - backward word
previous_word = this.line.slice(0, this.cursor)
.split('').reverse().join('')
.search(/\w/);
if (previous_word !== -1) {
previous_non_word = this.line.slice(0, this.cursor - previous_word)
.split('').reverse().join('')
.search(/\W/);
if (previous_non_word !== -1) {
this.cursor -= previous_word + previous_non_word;
this._refreshLine();
break;
}
}
this.cursor = 0;
this._refreshLine();
} else if (b[1] === 102 && this.cursor < this.line.length) { // meta-f - forward word
next_word = this.line.slice(this.cursor, this.line.length)
.search(/\w/);
if (next_word !== -1) {
next_non_word = this.line.slice(this.cursor + next_word, this.line.length)
.search(/\W/);
if (next_non_word !== -1) {
this.cursor += next_word + next_non_word;
this._refreshLine();
break;
}
}
this.cursor = this.line.length;
this._refreshLine();
} else if (b[1] === 100 && this.cursor < this.line.length) { // meta-d delete forward word
next_word = this.line.slice(this.cursor, this.line.length)
.search(/\w/);
if (next_word !== -1) {
next_non_word = this.line.slice(this.cursor + next_word, this.line.length)
.search(/\W/);
if (next_non_word !== -1) {
this.line = this.line.slice(this.cursor + next_word + next_non_word);
this.cursor = 0;
this._refreshLine();
break;
}
}
this.line = '';
this.cursor = 0;
this._refreshLine();
} else if (b[1] === 91 && b[2] === 68) { // left arrow
if (this.cursor > 0) {
this.cursor--;
@@ -361,10 +414,16 @@ Interface.prototype._ttyWrite = function (b) {
this.cursor++;
this.output.write('\x1b[0C');
}
} else if (b[1] === 91 && b[2] === 72) { // home
} else if ((b[1] === 91 && b[2] === 72) ||
(b[1] === 79 && b[2] === 72) ||
(b[1] === 91 && b[2] === 55) ||
(b[1] === 91 && b[2] === 49 && (b[3] && b[3] === 126))) { // home
this.cursor = 0;
this._refreshLine();
} else if (b[1] === 91 && b[2] === 70) { // end
} else if ((b[1] === 91 && b[2] === 70) ||
(b[1] === 79 && b[2] === 70) ||
(b[1] === 91 && b[2] === 56) ||
(b[1] === 91 && b[2] === 52 && (b[3] && b[3] === 126))) { // end
this.cursor = this.line.length;
this._refreshLine();
} else if (b[1] === 91 && b[2] === 65) { // up arrow

View File

@@ -121,7 +121,7 @@ exports.inspect = function (obj, showHidden, depth) {
}
}
output = keys.map(function (key) {
var output = keys.map(function (key) {
var name, str;
if (value.__lookupGetter__) {
if (value.__lookupGetter__(key)) {

View File

@@ -18,7 +18,7 @@ var protocolPattern = /^([a-z0-9]+:)/,
path = require("path"), // internal module, guaranteed to be loaded already.
querystring = require('querystring');
function urlParse (url, parseQueryString) {
function urlParse (url, parseQueryString, slashesDenoteHost) {
if (url && typeof(url) === "object" && url.href) return url;
var out = { href : url },
@@ -32,10 +32,15 @@ function urlParse (url, parseQueryString) {
}
// figure out if it's got a host
var slashes = rest.substr(0, 2) === "//";
if (slashes && !(proto && hostlessProtocol[proto])) {
rest = rest.substr(2);
out.slashes = true;
// user@server is *always* interpreted as a hostname, and url
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs.
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
var slashes = rest.substr(0, 2) === "//";
if (slashes && !(proto && hostlessProtocol[proto])) {
rest = rest.substr(2);
out.slashes = true;
}
}
if (!hostlessProtocol[proto] && (slashes || (proto && !slashedProtocol[proto]))) {
// there's a hostname.
@@ -133,8 +138,8 @@ function urlResolve (source, relative) {
function urlResolveObject (source, relative) {
if (!source) return relative;
source = urlParse(urlFormat(source));
relative = urlParse(urlFormat(relative));
source = urlParse(urlFormat(source), false, true);
relative = urlParse(urlFormat(relative), false, true);
// hash is always overridden, no matter what.
source.hash = relative.hash;

View File

@@ -73,7 +73,8 @@ static bool use_debug_agent = false;
static bool debug_wait_connect = false;
static int debug_port=5858;
static ev_prepare next_tick_watcher;
static ev_check check_tick_watcher;
static ev_prepare prepare_tick_watcher;
static ev_idle tick_spinner;
static bool need_tick_cb;
static Persistent<String> tick_callback_sym;
@@ -164,6 +165,11 @@ static void Check(EV_P_ ev_check *watcher, int revents) {
static Handle<Value> NeedTickCallback(const Arguments& args) {
HandleScope scope;
need_tick_cb = true;
// TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
// sufficent, the problem is only in the case of the very last "tick" -
// there is nothing left to do in the event loop and libev will exit. The
// ev_prepare callback isn't called before exiting. Thus we start this
// tick_spinner to keep the event loop alive long enough to handle it.
ev_idle_start(EV_DEFAULT_UC_ &tick_spinner);
return Undefined();
}
@@ -175,10 +181,7 @@ static void Spin(EV_P_ ev_idle *watcher, int revents) {
}
static void Tick(EV_P_ ev_prepare *watcher, int revents) {
assert(watcher == &next_tick_watcher);
assert(revents == EV_PREPARE);
static void Tick(void) {
// Avoid entering a V8 scope.
if (!need_tick_cb) return;
@@ -207,6 +210,20 @@ static void Tick(EV_P_ ev_prepare *watcher, int revents) {
}
static void PrepareTick(EV_P_ ev_prepare *watcher, int revents) {
assert(watcher == &prepare_tick_watcher);
assert(revents == EV_PREPARE);
Tick();
}
static void CheckTick(EV_P_ ev_check *watcher, int revents) {
assert(watcher == &check_tick_watcher);
assert(revents == EV_CHECK);
Tick();
}
static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
assert(watcher == &eio_poller);
assert(revents == EV_IDLE);
@@ -1808,8 +1825,12 @@ int main(int argc, char *argv[]) {
ev_default_loop(EVFLAG_AUTO);
#endif
ev_prepare_init(&node::next_tick_watcher, node::Tick);
ev_prepare_start(EV_DEFAULT_UC_ &node::next_tick_watcher);
ev_prepare_init(&node::prepare_tick_watcher, node::PrepareTick);
ev_prepare_start(EV_DEFAULT_UC_ &node::prepare_tick_watcher);
ev_unref(EV_DEFAULT_UC);
ev_check_init(&node::check_tick_watcher, node::CheckTick);
ev_check_start(EV_DEFAULT_UC_ &node::check_tick_watcher);
ev_unref(EV_DEFAULT_UC);
ev_idle_init(&node::tick_spinner, node::Spin);

View File

@@ -25,7 +25,8 @@ namespace node {
#define NODE_DEFINE_CONSTANT(target, constant) \
(target)->Set(v8::String::NewSymbol(#constant), \
v8::Integer::New(constant))
v8::Integer::New(constant), \
static_cast<v8::PropertyAttribute>(v8::ReadOnly|v8::DontDelete))
#define NODE_SET_METHOD(obj, name, callback) \
obj->Set(v8::String::NewSymbol(name), \

View File

@@ -49,9 +49,20 @@ var nextTickQueue = [];
process._tickCallback = function () {
var l = nextTickQueue.length;
if (l === 0) return;
for (var i = 0; i < l; i++) {
nextTickQueue[i]();
try {
for (var i = 0; i < l; i++) {
nextTickQueue[i]();
}
}
catch(e) {
nextTickQueue.splice(0, i+1);
if (i+1 < l) {
process._needTickCallback();
}
throw e;
}
nextTickQueue.splice(0, l);
};
@@ -187,17 +198,6 @@ var module = (function () {
return;
}
/* if (dirs.length == 0) {
if (callback) {
callback();
} else {
return; // sync returns null
}
} //no need for this, eventually move simpler if to traverser
// question: what with /absolute/id when dirs.length is 0?
// if "load it anyway", then this ^^^ code is wrong, but omitting it
// makes it right*/
var nextLoc = traverser(id, id.charAt(0) === '/' ? [''] : dirs);
var fs = requireNative('fs');
@@ -433,6 +433,7 @@ var module = (function () {
sandbox.__filename = filename;
sandbox.__dirname = dirname;
sandbox.module = self;
sandbox.global = sandbox;
sandbox.root = root;
Script.runInNewContext(content, sandbox, filename);
@@ -596,7 +597,7 @@ global.setTimeout = function (callback, after) {
global.setInterval = function (callback, repeat) {
var timer = new process.Timer();
addTimerListener.apply(timer, arguments);
timer.start(repeat, repeat);
timer.start(repeat, repeat ? repeat : 1);
return timer;
};
@@ -748,7 +749,11 @@ if (process.argv[1]) {
process.argv[1] = path.join(cwd, process.argv[1]);
}
module.runMain();
// REMOVEME: nextTick should not be necessary. This hack to get
// test/simple/test-exception-handler2.js working.
process.nextTick(function() {
module.runMain();
});
} else {
// No arguments, run the repl
var repl = module.requireNative('repl');

View File

@@ -156,6 +156,16 @@ Buffer* Buffer::New(size_t size) {
Handle<Value> Buffer::New(const Arguments &args) {
HandleScope scope;
if (!args.IsConstructCall()) {
Local<Value> argv[10];
for (int i = 0; i < MIN(args.Length(), 10); i++) {
argv[i] = args[i];
}
Local<Object> instance =
constructor_template->GetFunction()->NewInstance(args.Length(), argv);
return scope.Close(instance);
}
Buffer *buffer;
if (args[0]->IsInt32()) {
// var buffer = new Buffer(1024);
@@ -701,6 +711,22 @@ Handle<Value> Buffer::ByteLength(const Arguments &args) {
}
Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) {
HandleScope scope;
Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
Local<Object> fast_buffer = args[1]->ToObject();;
uint32_t offset = args[2]->Uint32Value();
uint32_t length = args[3]->Uint32Value();
fast_buffer->SetIndexedPropertiesToPixelData((uint8_t*)buffer->data() + offset,
length);
return Undefined();
}
void Buffer::Initialize(Handle<Object> target) {
HandleScope scope;
@@ -731,6 +757,9 @@ void Buffer::Initialize(Handle<Object> target) {
NODE_SET_METHOD(constructor_template->GetFunction(),
"byteLength",
Buffer::ByteLength);
NODE_SET_METHOD(constructor_template->GetFunction(),
"makeFastBuffer",
Buffer::MakeFastBuffer);
target->Set(String::NewSymbol("Buffer"), constructor_template->GetFunction());
}

View File

@@ -61,6 +61,7 @@ class Buffer : public ObjectWrap {
static v8::Handle<v8::Value> AsciiWrite(const v8::Arguments &args);
static v8::Handle<v8::Value> Utf8Write(const v8::Arguments &args);
static v8::Handle<v8::Value> ByteLength(const v8::Arguments &args);
static v8::Handle<v8::Value> MakeFastBuffer(const v8::Arguments &args);
static v8::Handle<v8::Value> Unpack(const v8::Arguments &args);
static v8::Handle<v8::Value> Copy(const v8::Arguments &args);

View File

@@ -286,8 +286,7 @@ int ChildProcess::Spawn(const char *file,
close(stdin_pipe[0]);
stdio_fds[0] = stdin_pipe[1];
SetNonBlocking(stdin_pipe[1]);
}
else {
} else {
stdio_fds[0] = custom_fds[0];
}
@@ -295,8 +294,7 @@ int ChildProcess::Spawn(const char *file,
close(stdout_pipe[1]);
stdio_fds[1] = stdout_pipe[0];
SetNonBlocking(stdout_pipe[0]);
}
else {
} else {
stdio_fds[1] = custom_fds[1];
}
@@ -304,8 +302,7 @@ int ChildProcess::Spawn(const char *file,
close(stderr_pipe[1]);
stdio_fds[2] = stderr_pipe[0];
SetNonBlocking(stderr_pipe[0]);
}
else {
} else {
stdio_fds[2] = custom_fds[2];
}

View File

@@ -25,6 +25,7 @@ static Persistent<String> subject_symbol;
static Persistent<String> issuer_symbol;
static Persistent<String> valid_from_symbol;
static Persistent<String> valid_to_symbol;
static Persistent<String> fingerprint_symbol;
static Persistent<String> name_symbol;
static Persistent<String> version_symbol;
@@ -540,6 +541,28 @@ Handle<Value> SecureStream::GetPeerCertificate(const Arguments& args) {
BIO_free(bio);
info->Set(valid_to_symbol, String::New(buf));
unsigned int md_size, i;
unsigned char md[EVP_MAX_MD_SIZE];
if (X509_digest(peer_cert, EVP_sha1(), md, &md_size)) {
const char hex[] = "0123456789ABCDEF";
char fingerprint[EVP_MAX_MD_SIZE * 3];
for (i=0; i<md_size; i++) {
fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
fingerprint[(3*i)+2] = ':';
}
if (md_size > 0) {
fingerprint[(3*(md_size-1))+2] = '\0';
}
else {
fingerprint[0] = '\0';
}
info->Set(fingerprint_symbol, String::New(fingerprint));
}
X509_free(peer_cert);
}
return scope.Close(info);
@@ -2296,6 +2319,7 @@ void InitCrypto(Handle<Object> target) {
issuer_symbol = NODE_PSYMBOL("issuer");
valid_from_symbol = NODE_PSYMBOL("valid_from");
valid_to_symbol = NODE_PSYMBOL("valid_to");
fingerprint_symbol = NODE_PSYMBOL("fingerprint");
name_symbol = NODE_PSYMBOL("name");
version_symbol = NODE_PSYMBOL("version");
}

View File

@@ -26,8 +26,7 @@ class ObjectWrap {
{
assert(!handle.IsEmpty());
assert(handle->InternalFieldCount() > 0);
return static_cast<T*>(v8::Handle<v8::External>::Cast(
handle->GetInternalField(0))->Value());
return static_cast<T*>(handle->GetPointerFromInternalField(0));
}
v8::Persistent<v8::Object> handle_; // ro
@@ -38,7 +37,7 @@ class ObjectWrap {
assert(handle_.IsEmpty());
assert(handle->InternalFieldCount() > 0);
handle_ = v8::Persistent<v8::Object>::New(handle);
handle_->SetInternalField(0, v8::External::New(this));
handle_->SetPointerInInternalField(0, this);
MakeWeak();
}

View File

@@ -212,6 +212,7 @@ template <node::Script::EvalInputFlags iFlag,
for (i = 0; i < keys->Length(); i++) {
Handle<String> key = keys->Get(Integer::New(i))->ToString();
Handle<Value> value = sandbox->Get(key);
if (value == sandbox) { value = context->Global(); }
context->Global()->Set(key, value);
}
}
@@ -264,6 +265,7 @@ template <node::Script::EvalInputFlags iFlag,
for (i = 0; i < keys->Length(); i++) {
Handle<String> key = keys->Get(Integer::New(i))->ToString();
Handle<Value> value = context->Global()->Get(key);
if (value == context->Global()) { value = sandbox; }
sandbox->Set(key, value);
}
}

View File

@@ -6,7 +6,7 @@
#define NODE_MAJOR_VERSION 0
#define NODE_MINOR_VERSION 2
#define NODE_PATCH_VERSION 0
#define NODE_PATCH_VERSION 1
#ifndef NODE_STRINGIFY
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)

View File

@@ -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.tmpDir = path.join(exports.testDir, "tmp");
exports.PORT = 12346;
exports.assert = require('assert');

View File

@@ -1,6 +1,4 @@
foo = "foo";
global.bar = "bar";
exports.fooBar = function () {
return {foo: global.foo, bar: bar};
};
exports.fooBar = {foo: global.foo, bar:bar};

View File

@@ -1,13 +0,0 @@
foo1 = "foo1";
global.bar1 = "bar1";
var sub2 = require('./sub2');
exports.subGlobalKeys = function () {
return sub2.globalKeys();
};
exports.subAllFooBars = function () {
return sub2.allFooBars();
};

View File

@@ -1,18 +0,0 @@
foo2 = "foo2";
global.bar2 = "bar2";
exports.globalKeys = function () {
return Object.getOwnPropertyNames(global);
};
exports.allFooBars = function () {
return {
foo0: global.foo0,
bar0: bar0,
foo1: global.foo1,
bar1: bar1,
foo2: global.foo2,
bar2: bar2
};
};

1
test/fixtures/semicolon.js vendored Normal file
View File

@@ -0,0 +1 @@
;

View File

@@ -1,9 +1,8 @@
before
*.js:*
*cript.runIn*Context(*);
*^
node.js:*
throw e;
^
ReferenceError: foo is not defined
at evalmachine.<anonymous>:*
at *test/message/undefined_reference_in_new_context.js:*
@@ -11,4 +10,6 @@ ReferenceError: foo is not defined
at Module._loadScriptSync (node.js:*)
at Module.loadSync (node.js:*)
at Object.runMain (node.js:*)
at Array.<anonymous> (node.js:*)
at EventEmitter._tickCallback (node.js:*)
at node.js:*

View File

@@ -74,7 +74,14 @@ setInterval(function(param1, param2){
clearInterval(this);
}, 1000, "param1", "param2");
// setInterval(cb, 0) should be called multiple times.
count4 = 0;
interval4 = setInterval(function () {
if (++count4 > 10) clearInterval(interval4);
}, 0);
process.addListener("exit", function () {
assert.equal(true, setTimeout_called);
assert.equal(3, interval_count);
assert.equal(11, count4);
});

View File

@@ -4,7 +4,7 @@ assert = require("assert");
var Buffer = require('buffer').Buffer;
var b = new Buffer(1024);
var b = Buffer(1024); // safe constructor
console.log("b.length == " + b.length);
assert.strictEqual(1024, b.length);

View File

@@ -0,0 +1,17 @@
common = require("../common");
assert = common.assert;
var stdout_write = global.process.stdout.write;
var strings = [];
global.process.stdout.write = function(string) {
strings.push(string);
};
console.log('foo');
console.log('foo', 'bar');
console.log('%s %s', 'foo', 'bar', 'hop');
global.process.stdout.write = stdout_write;
assert.equal('foo\n', strings.shift());
assert.equal('foo bar\n', strings.shift());
assert.equal('foo bar hop\n', strings.shift());

View File

@@ -1,56 +1,48 @@
common = require("../common");
assert = common.assert
var Buffer = require("buffer").Buffer,
fs = require("fs"),
dgram = require("dgram"), server, client,
server_path = "/tmp/dgram_server_sock",
client_path = "/tmp/dgram_client_sock",
message_to_send = new Buffer("A message to send"),
timer;
fs = require("fs");
dgram = require("dgram");
serverPath = "/tmp/dgram_server_sock";
clientPath = "/tmp/dgram_client_sock";
msgToSend = new Buffer("A message to send");
server = dgram.createSocket("unix_dgram");
server.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " + rinfo.address);
assert.strictEqual(rinfo.address, client_path);
assert.strictEqual(msg.toString(), message_to_send.toString());
assert.strictEqual(rinfo.address, clientPath);
assert.strictEqual(msg.toString(), msgToSend.toString());
server.send(msg, 0, msg.length, rinfo.address);
});
server.on("listening", function () {
console.log("server is listening");
client = dgram.createSocket("unix_dgram");
client.on("message", function (msg, rinfo) {
console.log("client got: " + msg + " from " + rinfo.address);
assert.strictEqual(rinfo.address, server_path);
assert.strictEqual(msg.toString(), message_to_send.toString());
assert.strictEqual(rinfo.address, serverPath);
assert.strictEqual(msg.toString(), msgToSend.toString());
client.close();
server.close();
});
client.on("listening", function () {
console.log("client is listening");
client.send(message_to_send, 0, message_to_send.length, server_path, function (err, bytes) {
client.send(msgToSend, 0, msgToSend.length, serverPath, function (err, bytes) {
if (err) {
console.log("Caught error in client send.");
throw err;
}
console.log("client wrote " + bytes + " bytes.");
assert.strictEqual(bytes, message_to_send.length);
assert.strictEqual(bytes, msgToSend.length);
});
});
client.on("close", function () {
if (server.fd === null) {
clearTimeout(timer);
}
});
client.bind(client_path);
});
server.on("close", function () {
if (client.fd === null) {
clearTimeout(timer);
}
});
server.bind(server_path);
timer = setTimeout(function () {
throw new Error("Timeout");
}, 200);
client.bind(clientPath);
});
server.bind(serverPath);

View File

@@ -0,0 +1,21 @@
common = require("../common");
assert = common.assert
process.on('uncaughtException', function (err) {
console.log('Caught exception: ' + err);
});
var timeoutFired = false;
setTimeout(function () {
console.log('This will still run.');
timeoutFired = true;
}, 500);
process.on('exit', function() {
assert.ok(timeoutFired);
});
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');

View File

@@ -96,3 +96,17 @@ file4.addListener('data', function(data) {
file4.addListener('end', function(data) {
assert.equal(contentRead, 'yz');
});
try {
fs.createReadStream(rangeFile, {start: 10, end: 2});
assert.fail('Creating a ReadStream with incorrect range limits must throw.');
} catch(e) {
assert.equal(e.message, 'start must be <= end');
}
try {
fs.createReadStream(rangeFile, {start: 2});
assert.fail('Creating a ReadStream with a only one range limits must throw.');
} catch(e) {
assert.equal(e.message, 'Both start and end are needed for range streaming.');
}

View File

@@ -9,3 +9,7 @@ var
fs.readFile(fn, function(err, data) {
assert.ok(data);
});
fs.readFile(fn, 'utf8', function(err, data) {
assert.strictEqual('', data);
});

View File

@@ -6,12 +6,11 @@ var async_completed = 0, async_expected = 0, unlink = [];
function asynctest(testBlock, args, callback, assertBlock) {
async_expected++;
testBlock.apply(testBlock, args.concat([function(err){
testBlock.apply(testBlock, args.concat(function(err){
var ignoreError = false;
if (assertBlock) {
try {
ignoreError = assertBlock.apply(assertBlock,
Array.prototype.slice.call(arguments));
ignoreError = assertBlock.apply(assertBlock, arguments);
}
catch (e) {
err = e;
@@ -19,7 +18,7 @@ function asynctest(testBlock, args, callback, assertBlock) {
}
async_completed++;
callback(ignoreError ? null : err);
}]));
}));
}
function bashRealpath(path, callback) {
@@ -227,6 +226,18 @@ function test_non_symlinks(callback) {
});
}
var upone = path.join(process.cwd(), "..");
function test_escape_cwd (cb) {
asynctest(fs.realpath, [".."], cb, function(er, uponeActual){
assert.equal(upone, uponeActual,
"realpath('..') expected: "+upone+" actual:"+uponeActual);
})
}
var uponeActual = fs.realpathSync("..");
assert.equal(upone, uponeActual,
"realpathSync('..') expected: "+upone+" actual:"+uponeActual);
// ----------------------------------------------------------------------------
var tests = [
@@ -238,6 +249,7 @@ var tests = [
test_relative_input_cwd,
test_deep_symlink_mix,
test_non_symlinks,
test_escape_cwd
];
var numtests = tests.length;
function runNextTest(err) {
@@ -248,6 +260,15 @@ function runNextTest(err) {
}
runNextTest();
assert.equal('/', fs.realpathSync('/'));
fs.realpath('/', function (err, result) {
assert.equal(null, err);
assert.equal('/', result);
});
process.addListener("exit", function () {
unlink.forEach(function(path){ try {fs.unlinkSync(path);}catch(e){} });
assert.equal(async_completed, async_expected);

View File

@@ -1,13 +1,12 @@
common = require("../common");
assert = common.assert
var assert = common.assert;
var path = require('path');
var fs = require('fs');
var completed = 0;
// test creating and reading symbolic link
var linkData = "../../cycles/root.js";
var linkPath = path.join(common.fixturesDir, "nested-index", 'one', 'symlink1.js');
try {fs.unlinkSync(linkPath);}catch(e){}
var linkData = path.join(common.fixturesDir, "/cycles/root.js");
var linkPath = path.join(common.tmpDir, 'symlink1.js');
fs.symlink(linkData, linkPath, function(err){
if (err) throw err;
console.log('symlink done');
@@ -21,8 +20,7 @@ fs.symlink(linkData, linkPath, function(err){
// test creating and reading hard link
var srcPath = path.join(common.fixturesDir, "cycles", 'root.js');
var dstPath = path.join(common.fixturesDir, "nested-index", 'one', 'link1.js');
try {fs.unlinkSync(dstPath);}catch(e){}
var dstPath = path.join(common.tmpDir, 'link1.js');
fs.link(srcPath, dstPath, function(err){
if (err) throw err;
console.log('hard link done');
@@ -33,8 +31,6 @@ fs.link(srcPath, dstPath, function(err){
});
process.addListener("exit", function () {
try {fs.unlinkSync(linkPath);}catch(e){}
try {fs.unlinkSync(dstPath);}catch(e){}
assert.equal(completed, 2);
});

View File

@@ -0,0 +1,28 @@
common = require("../common");
assert = common.assert
var path = require('path'),
fs = require('fs');
var file = path.join(common.fixturesDir, "write.txt");
(function() {
var stream = fs.createWriteStream(file),
_fs_close = fs.close;
fs.close = function(fd) {
assert.ok(fd, "fs.close must not be called without an undefined fd.")
fs.close = _fs_close;
}
stream.destroy();
})();
(function() {
var stream = fs.createWriteStream(file);
stream.addListener('drain', function () {
assert.fail('"drain" event must not be emitted before stream.write() has been called at least once.')
});
stream.destroy();
})();

View File

@@ -11,7 +11,7 @@ fs.open(fn, 'w', 0644, function (err, fd) {
if (err) throw err;
console.log('open done');
fs.write(fd, '', 0, 'utf8', function(err, written) {
assert.fail('zero length write should not go through to callback');
assert.equal(0, written);
});
fs.write(fd, expected, 0, "utf8", function (err, written) {
console.log('write done');

View File

@@ -1,21 +0,0 @@
common = require("../common");
assert = common.assert
foo0 = "foo0";
global.bar0 = "bar0";
var module = require("../fixtures/global/sub1"),
keys = module.subGlobalKeys();
var fooBarKeys = keys.filter(
function (x) { return x.match(/^foo/) || x.match(/^bar/); }
);
fooBarKeys.sort();
assert.equal("bar0,bar1,bar2,foo0,foo1,foo2", fooBarKeys.join(), "global keys not as expected: "+JSON.stringify(keys));
var fooBars = module.subAllFooBars();
assert.equal("foo0", fooBars.foo0, "x from base level not visible in deeper levels.");
assert.equal("bar0", fooBars.bar0, "global.x from base level not visible in deeper levels.");
assert.equal("foo1", fooBars.foo1, "x from medium level not visible in deeper levels.");
assert.equal("bar1", fooBars.bar1, "global.x from medium level not visible in deeper levels.");

View File

@@ -9,7 +9,7 @@ assert.equal("foo", global.baseFoo, "x -> global.x in base level not working");
assert.equal("bar", baseBar, "global.x -> x in base level not working");
var module = require("../fixtures/global/plain"),
fooBar = module.fooBar();
fooBar = module.fooBar;
assert.equal("foo", fooBar.foo, "x -> global.x in sub level not working");

View File

@@ -15,7 +15,7 @@ var buffer = new Buffer(1024);
var request = "GET /hello HTTP/1.1\r\n\r\n";
buffer.asciiWrite(request, 0, request.length);
buffer.write(request, 0, 'ascii');
var callbacks = 0;
@@ -39,7 +39,7 @@ parser.onURL = function (b, off, len) {
parser.onPath = function (b, off, length) {
console.log("path [" + off + ", " + length + "]");
var path = b.asciiSlice(off, off+length);
var path = b.toString('ascii', off, off+length);
console.log("path = '" + path + "'");
assert.equal('/hello', path);
callbacks++;

View File

@@ -41,7 +41,8 @@ var https_server = http.createServer(function (req, res) {
+ '"issuer":"/C=UK/ST=Acknack Ltd/L=Rhys Jones/O=node.js'
+ '/OU=Test TLS Certificate/CN=localhost","valid_from":'
+ '"Nov 11 09:52:22 2009 GMT","valid_to":'
+ '"Nov 6 09:52:22 2029 GMT"}');
+ '"Nov 6 09:52:22 2029 GMT",'
+ '"fingerprint":"2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF"}');
if (req.id == 0) {
assert.equal("GET", req.method);
@@ -92,7 +93,8 @@ https_server.addListener("listening", function() {
+ '"issuer":"/C=UK/ST=Acknack Ltd/L=Rhys Jones/O=node.js'
+ '/OU=Test TLS Certificate/CN=localhost","valid_from":'
+ '"Nov 11 09:52:22 2009 GMT","valid_to":'
+ '"Nov 6 09:52:22 2029 GMT"}');
+ '"Nov 6 09:52:22 2029 GMT",'
+ '"fingerprint":"2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF"}');
c.write( "GET /hello?hello=world&foo=b==ar HTTP/1.1\r\n\r\n" );
requests_sent += 1;
});

View File

@@ -12,7 +12,7 @@ var responses_recvd = 0;
var body0 = "";
var body1 = "";
var server = http.createServer(function (req, res) {
var server = http.Server(function (req, res) {
if (responses_sent == 0) {
assert.equal("GET", req.method);
assert.equal("/hello", url.parse(req.url).pathname);

View File

@@ -4,8 +4,7 @@ var path = require('path');
var fs = require('fs');
var dirname = path.dirname(__filename);
var fixtures = path.join(dirname, "../fixtures");
var d = path.join(fixtures, "dir");
var d = path.join(common.tmpDir, "dir");
var mkdir_error = false;
var rmdir_error = false;

View File

@@ -1,6 +1,6 @@
common = require("../common");
assert = common.assert
tcp = require("tcp");
net = require("net");
binaryString = "";
for (var i = 255; i >= 0; i--) {
@@ -19,7 +19,8 @@ for (var i = 255; i >= 0; i--) {
binaryString += S;
}
var echoServer = tcp.createServer(function (connection) {
// safe constructor
var echoServer = net.Server(function (connection) {
connection.setEncoding("binary");
connection.addListener("data", function (chunk) {
common.error("recved: " + JSON.stringify(chunk));
@@ -35,7 +36,7 @@ var recv = "";
echoServer.addListener("listening", function() {
var j = 0;
var c = tcp.createConnection(common.PORT);
var c = net.createConnection(common.PORT);
c.setEncoding("binary");
c.addListener("data", function (chunk) {

View File

@@ -41,7 +41,8 @@ var secureServer = net.createServer(function (connection) {
+ '"issuer":"/C=UK/ST=Acknack Ltd/L=Rhys Jones/O=node.js'
+ '/OU=Test TLS Certificate/CN=localhost","valid_from":'
+ '"Nov 11 09:52:22 2009 GMT","valid_to":'
+ '"Nov 6 09:52:22 2029 GMT"}');
+ '"Nov 6 09:52:22 2029 GMT",'
+ '"fingerprint":"2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF"}');
});
@@ -76,7 +77,8 @@ secureServer.addListener("listening", function() {
+ '"issuer":"/C=UK/ST=Acknack Ltd/L=Rhys Jones/O=node.js'
+ '/OU=Test TLS Certificate/CN=localhost","valid_from":'
+ '"Nov 11 09:52:22 2009 GMT","valid_to":'
+ '"Nov 6 09:52:22 2029 GMT"}');
+ '"Nov 6 09:52:22 2029 GMT",'
+ '"fingerprint":"2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF"}');
secureClient.write(testData);
secureClient.end();

View File

@@ -0,0 +1,36 @@
common = require("../common");
assert = common.assert
var order = [],
exceptionHandled = false;
// This nextTick function will throw an error. It should only be called once.
// When it throws an error, it should still get removed from the queue.
process.nextTick(function() {
order.push('A');
// cause an error
what();
});
// This nextTick function should remain in the queue when the first one
// is removed. It should be called if the error in the first one is
// caught (which we do in this test).
process.nextTick(function() {
order.push('C');
});
process.addListener('uncaughtException', function() {
if (!exceptionHandled) {
exceptionHandled = true;
order.push('B');
}
else {
// If we get here then the first process.nextTick got called twice
order.push('OOPS!');
}
});
process.addListener('exit', function() {
assert.deepEqual(['A','B','C'], order);
});

View File

@@ -0,0 +1,17 @@
common = require("../common");
assert = common.assert
var order = [];
process.nextTick(function () {
setTimeout(function() {
order.push('setTimeout');
}, 0);
process.nextTick(function() {
order.push('nextTick');
});
})
process.addListener('exit', function () {
assert.deepEqual(order, ['nextTick', 'setTimeout']);
});

View File

@@ -0,0 +1,108 @@
common = require("../common");
assert = common.assert;
var readline = require("readline");
var key = {
xterm: {
home: [27, 91, 72],
end: [27, 91, 70],
metab: [27, 98],
metaf: [27, 102],
metad: [27, 100]
},
gnome: {
home: [27, 79, 72],
end: [27, 79, 70]
},
rxvt: {
home: [27, 91, 55],
end: [27, 91, 56]
},
putty: {
home: [27, 91, 49, 126],
end: [27, 91, 52, 126]
}
};
var readlineFakeStream = function() {
var written_bytes = [];
var rl = readline.createInterface({
fd: 1,
write: function(b) {
written_bytes.push(b);
}}, function (text) {
return [[], ""];
});
rl.written_bytes = written_bytes;
return rl;
};
var rl = readlineFakeStream();
var written_bytes_length, refreshed;
rl.write('foo');
assert.equal(3, rl.cursor);
rl.write(key.xterm.home);
assert.equal(0, rl.cursor);
rl.write(key.xterm.end);
assert.equal(3, rl.cursor);
rl.write(key.rxvt.home);
assert.equal(0, rl.cursor);
rl.write(key.rxvt.end);
assert.equal(3, rl.cursor);
rl.write(key.gnome.home);
assert.equal(0, rl.cursor);
rl.write(key.gnome.end);
assert.equal(3, rl.cursor);
rl.write(key.putty.home);
assert.equal(0, rl.cursor);
rl.write(key.putty.end);
assert.equal(3, rl.cursor);
rl = readlineFakeStream();
rl.write('foo bar.hop/zoo');
rl.write(key.xterm.home);
written_bytes_length = rl.written_bytes.length;
rl.write(key.xterm.metaf);
assert.equal(3, rl.cursor);
refreshed = written_bytes_length !== rl.written_bytes.length;
assert.equal(true, refreshed);
rl.write(key.xterm.metaf);
assert.equal(7, rl.cursor);
rl.write(key.xterm.metaf);
assert.equal(11, rl.cursor);
written_bytes_length = rl.written_bytes.length;
rl.write(key.xterm.metaf);
assert.equal(15, rl.cursor);
refreshed = written_bytes_length !== rl.written_bytes.length;
assert.equal(true, refreshed);
written_bytes_length = rl.written_bytes.length;
rl.write(key.xterm.metab);
assert.equal(12, rl.cursor);
refreshed = written_bytes_length !== rl.written_bytes.length;
assert.equal(true, refreshed);
rl.write(key.xterm.metab);
assert.equal(8, rl.cursor);
rl.write(key.xterm.metab);
assert.equal(4, rl.cursor);
written_bytes_length = rl.written_bytes.length;
rl.write(key.xterm.metab);
assert.equal(0, rl.cursor);
refreshed = written_bytes_length !== rl.written_bytes.length;
assert.equal(true, refreshed);
rl = readlineFakeStream();
rl.write('foo bar.hop/zoo');
rl.write(key.xterm.home);
rl.write(key.xterm.metad);
assert.equal(0, rl.cursor);
assert.equal(' bar.hop/zoo', rl.line);
rl.write(key.xterm.metad);
assert.equal(0, rl.cursor);
assert.equal('.hop/zoo', rl.line);
rl.write(key.xterm.metad);
assert.equal(0, rl.cursor);
assert.equal('/zoo', rl.line);
rl.write(key.xterm.metad);
assert.equal(0, rl.cursor);
assert.equal('', rl.line);

View File

@@ -60,7 +60,7 @@ function tcp_test() {
});
client_tcp.addListener('data', function (data) {
read_buffer += data.asciiSlice(0, data.length);
read_buffer += data.toString('ascii', 0, data.length);
common.error("TCP data: " + JSON.stringify(read_buffer) + ", expecting " + JSON.stringify(client_tcp.expect));
if (read_buffer.indexOf(prompt_tcp) !== -1) {
assert.strictEqual(client_tcp.expect, read_buffer);
@@ -121,7 +121,7 @@ function unix_test() {
});
client_unix.addListener('data', function (data) {
read_buffer += data.asciiSlice(0, data.length);
read_buffer += data.toString('ascii', 0, data.length);
common.error("Unix data: " + JSON.stringify(read_buffer) + ", expecting " + JSON.stringify(client_unix.expect));
if (read_buffer.indexOf(prompt_unix) !== -1) {
assert.strictEqual(client_unix.expect, read_buffer);

View File

@@ -7,6 +7,10 @@ var url = require("url"),
// URLs to parse, and expected data
// { url : parsed }
var parseTests = {
"//some_path" : {
"href": "//some_path",
"pathname": "//some_path"
},
"http://www.narwhaljs.org/blog/categories?id=news" : {
"href": "http://www.narwhaljs.org/blog/categories?id=news",
"protocol": "http:",

View File

@@ -27,6 +27,9 @@
import test
import os
import shutil
from shutil import rmtree
from os import mkdir
from os.path import join, dirname, exists
import re
@@ -42,7 +45,19 @@ class SimpleTestCase(test.TestCase):
self.file = file
self.config = config
self.mode = mode
def tearDown(self):
try:
rmtree(join(dirname(self.config.root), 'tmp'))
except:
pass
def setUp(self):
try:
mkdir(join(dirname(self.config.root), 'tmp'))
except:
pass
def GetLabel(self):
return "%s %s" % (self.mode, self.GetName())

View File

@@ -359,7 +359,16 @@ class TestCase(object):
return TestOutput(self, full_command, output)
def Run(self):
return self.RunCommand(self.GetCommand())
self.setUp()
result = self.RunCommand(self.GetCommand())
self.tearDown()
return result
def setUp(self):
return
def tearDown(self):
return
class TestOutput(object):

11
wscript
View File

@@ -162,11 +162,12 @@ def configure(conf):
if Options.options.efence:
conf.check(lib='efence', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='EFENCE')
if not conf.check(lib="execinfo", includes=['/usr/include', '/usr/local/include'], libpath=['/usr/lib', '/usr/local/lib'], uselib_store="EXECINFO"):
# Note on Darwin/OS X: This will fail, but will still be used as the
# execinfo stuff are part of the standard library.
if sys.platform.startswith("freebsd"):
conf.fatal("Install the libexecinfo port from /usr/ports/devel/libexecinfo.")
if sys.platform.startswith("freebsd"):
if not conf.check(lib="execinfo",
includes=['/usr/include', '/usr/local/include'],
libpath=['/usr/lib', '/usr/local/lib'],
uselib_store="EXECINFO"):
conf.fatal("Install the libexecinfo port from /usr/ports/devel/libexecinfo.")
if not Options.options.without_ssl:
if conf.check_cfg(package='openssl',