mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Compare commits
104 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc103ae020 | ||
|
|
fea3919d1b | ||
|
|
b5dc54c6ed | ||
|
|
2fb393a768 | ||
|
|
80974dc85b | ||
|
|
16f736200a | ||
|
|
d29e62d564 | ||
|
|
41eca918e5 | ||
|
|
45a01aff59 | ||
|
|
55aa7b17ab | ||
|
|
1165878e3c | ||
|
|
b98958d7fe | ||
|
|
448cbaf395 | ||
|
|
b8eee9c6f0 | ||
|
|
936a038bb7 | ||
|
|
529cdad2dd | ||
|
|
7140933fcc | ||
|
|
27f6a20fdb | ||
|
|
a30daa7b6c | ||
|
|
01035714a5 | ||
|
|
f6f739b3a2 | ||
|
|
d7c1690c74 | ||
|
|
7bf46bc980 | ||
|
|
bcbc52e257 | ||
|
|
c00a6a7169 | ||
|
|
1d8b154e14 | ||
|
|
84f4ce742f | ||
|
|
f9cc35fa57 | ||
|
|
d506a42765 | ||
|
|
09a41a7f9c | ||
|
|
8dcd6dccab | ||
|
|
1375b8ed39 | ||
|
|
a3333e7393 | ||
|
|
d965640662 | ||
|
|
ee253b374d | ||
|
|
b17b28531b | ||
|
|
10af67714b | ||
|
|
180a04805b | ||
|
|
ee21920571 | ||
|
|
66bce65d33 | ||
|
|
2005ef9e37 | ||
|
|
3816ebc85f | ||
|
|
4c5520a37e | ||
|
|
0ddad3fbc7 | ||
|
|
db6a1788b2 | ||
|
|
1d17874a7d | ||
|
|
3191802605 | ||
|
|
da235fa12c | ||
|
|
92fb664bfc | ||
|
|
7704fb9711 | ||
|
|
c099e274d2 | ||
|
|
c86f3c5d5c | ||
|
|
9b8577230f | ||
|
|
9f6f26028f | ||
|
|
44f8756aab | ||
|
|
ae2f566fec | ||
|
|
2f071ac7d1 | ||
|
|
bd8ea2bb85 | ||
|
|
35682ac88e | ||
|
|
5bbebf3593 | ||
|
|
0b9dab650e | ||
|
|
a6659e7612 | ||
|
|
727843eea1 | ||
|
|
7e9a0173d7 | ||
|
|
74b70c3cb1 | ||
|
|
d5deb4c4a3 | ||
|
|
cc0164bc12 | ||
|
|
ccd1304c5b | ||
|
|
3d3d00d524 | ||
|
|
dffa9e76a1 | ||
|
|
90374797f0 | ||
|
|
c1a4e10156 | ||
|
|
b655ce5c08 | ||
|
|
b30b60717d | ||
|
|
b2dfea0361 | ||
|
|
610743daee | ||
|
|
df891c36a4 | ||
|
|
f35a8298b1 | ||
|
|
294c455678 | ||
|
|
14f16ec592 | ||
|
|
cdee88051d | ||
|
|
b39b15d53f | ||
|
|
b895568800 | ||
|
|
ead58b9a93 | ||
|
|
c306fa241c | ||
|
|
22f67f8585 | ||
|
|
416aa73946 | ||
|
|
6a39a7ed83 | ||
|
|
ad960f4462 | ||
|
|
f78691e45c | ||
|
|
3d8137c582 | ||
|
|
c14c445cb6 | ||
|
|
b9ca8435f5 | ||
|
|
baa24bd40e | ||
|
|
7a836ef813 | ||
|
|
a2b9e02d83 | ||
|
|
3f7c791b13 | ||
|
|
53dac7c341 | ||
|
|
c43ddf7acd | ||
|
|
699fdfaa43 | ||
|
|
8d2e79451e | ||
|
|
760efc0758 | ||
|
|
1b1ad1d363 | ||
|
|
c3eafdd3a4 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,3 +12,4 @@ test/fixtures/hello.txt
|
||||
tmp/
|
||||
node
|
||||
node_g
|
||||
*.swp
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -109,8 +109,17 @@ Chandra Sekar S <chandru.in@gmail.com>
|
||||
Andrew Naylor <argon@mkbot.net>
|
||||
Benjamin Kramer <benny.kra@gmail.com>
|
||||
Danny Coates <dannycoates@gmail.com>
|
||||
Samuel Shull <brickysam26@gmail.com>
|
||||
Nick Stenning <nick@whiteink.com>
|
||||
Bert Belder <bertbelder@gmail.com>
|
||||
Trent Mick <trentm@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com>
|
||||
Illarionov Oleg <oleg@emby.ru>
|
||||
Aria Stewart <aredridel@nbtsc.org>
|
||||
Johan Euphrosine <proppy@aminche.com>
|
||||
Russell Haering <russellhaering@gmail.com>
|
||||
Bradley Meck <bradley.meck@gmail.com>
|
||||
Tobie Langel <tobie.langel@gmail.com>
|
||||
Tony Metzidis <tonym@tonym.us>
|
||||
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
|
||||
Evan Larkin <evan.larkin.il.com>
|
||||
|
||||
59
ChangeLog
59
ChangeLog
@@ -1,4 +1,55 @@
|
||||
2010.08.20, Version 0.2.0
|
||||
2010.10.02, Version 0.2.3
|
||||
|
||||
* Fix require in REPL (bug introduced in v0.2.2)
|
||||
|
||||
* Pass correct message in client HTTP upgrade event.
|
||||
(Fedor Indutny)
|
||||
|
||||
* Show function names in sys.inspect (Jorge Chamorro Bieling)
|
||||
|
||||
* In HTTP, close connection on the "connection:close" header.
|
||||
(Mikeal Rogers)
|
||||
|
||||
* fs.ReadStream bug fixes (Tj Holowaychuk, Evan Larkin, Marco Rogers)
|
||||
|
||||
* Fix zero length buffer bug for http res.end()
|
||||
|
||||
|
||||
2010.09.17, Version 0.2.2, 7bf46bc9808f4db98f1cf177d58a6ecf3a50b65d
|
||||
|
||||
* REPL improvements (Trent Mick)
|
||||
|
||||
* Fix bug in fs.realpath (Isaac Schlueter)
|
||||
|
||||
* sys.pump catches errors (Russell Haering)
|
||||
|
||||
|
||||
2010.09.10, Version 0.2.1, da235fa12c208fc8243600e128db2c9b55624c5c
|
||||
|
||||
* 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
|
||||
|
||||
@@ -116,7 +167,7 @@
|
||||
* Upgrade http-parser, V8 to 2.2.21
|
||||
|
||||
|
||||
2010.06.21, Version 0.1.99, a620b7298f68f68a855306437a3b60b650d61d78
|
||||
2010.06.21, Version 0.1.99, a620b7298f68f68a855306437a3b60b650d61d78
|
||||
|
||||
* Datagram sockets (Paul Querna)
|
||||
|
||||
@@ -222,7 +273,7 @@
|
||||
|
||||
2010.05.06, Version 0.1.94, f711d5343b29d1e72e87107315708e40951a7826
|
||||
|
||||
* Look in /usr/local/lib/node for modules, so that there's a way
|
||||
* Look in /usr/local/lib/node for modules, so that there's a way
|
||||
to install modules globally (Issac Schlueter)
|
||||
|
||||
* SSL improvements (Rhys Jones, Paulo Matias)
|
||||
@@ -242,7 +293,7 @@
|
||||
* Bugfix: destroy() instead of end() http connection at end of
|
||||
pipeline
|
||||
|
||||
* Bugfix: http.Client may be prematurely released back to the
|
||||
* Bugfix: http.Client may be prematurely released back to the
|
||||
free pool. (Thomas Lee)
|
||||
|
||||
* Upgrade V8 to 2.2.8
|
||||
|
||||
4
TODO
4
TODO
@@ -16,3 +16,7 @@
|
||||
the maximum is reached it stops accepting new connections.
|
||||
- compile under clang
|
||||
- Use C++ style casts everywhere.
|
||||
- fs.readFile[Sync] should not call stat() and use the length.
|
||||
Test on Linux's /proc/sys/kernel/hostname
|
||||
- Ruby-like Process#detach (is that possible?)
|
||||
- stderr isn't flushing on exit
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
35
benchmark/function_call/bench.js
Normal file
35
benchmark/function_call/bench.js
Normal file
@@ -0,0 +1,35 @@
|
||||
var binding = require('./build/default/binding');
|
||||
|
||||
c = 0
|
||||
|
||||
function js() {
|
||||
return c++; //(new Date()).getTime();
|
||||
}
|
||||
|
||||
var cxx = binding.hello;
|
||||
|
||||
var i, N = 100000000;
|
||||
|
||||
console.log(js());
|
||||
console.log(cxx());
|
||||
|
||||
|
||||
|
||||
var start = new Date();
|
||||
for (i = 0; i < N; i++) {
|
||||
js();
|
||||
}
|
||||
var jsDiff = new Date() - start;
|
||||
console.log(N +" JS function calls: " + jsDiff);
|
||||
|
||||
|
||||
var start = new Date();
|
||||
for (i = 0; i < N; i++) {
|
||||
cxx();
|
||||
}
|
||||
var cxxDiff = new Date() - start;
|
||||
console.log(N +" C++ function calls: " + cxxDiff);
|
||||
|
||||
console.log("\nJS speedup " + (cxxDiff / jsDiff));
|
||||
|
||||
|
||||
19
benchmark/function_call/binding.cc
Normal file
19
benchmark/function_call/binding.cc
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <time.h>
|
||||
|
||||
using namespace v8;
|
||||
|
||||
static int c = 0;
|
||||
|
||||
static Handle<Value> Hello(const Arguments& args) {
|
||||
HandleScope scope;
|
||||
//time_t tv = time(NULL);
|
||||
return scope.Close(Integer::New(c++));
|
||||
}
|
||||
|
||||
extern "C" void init (Handle<Object> target) {
|
||||
HandleScope scope;
|
||||
//target->Set(String::New("hello"), String::New("World"));
|
||||
NODE_SET_METHOD(target, "hello", Hello);
|
||||
}
|
||||
15
benchmark/function_call/wscript
Normal file
15
benchmark/function_call/wscript
Normal file
@@ -0,0 +1,15 @@
|
||||
srcdir = '.'
|
||||
blddir = 'build'
|
||||
VERSION = '0.0.1'
|
||||
|
||||
def set_options(opt):
|
||||
opt.tool_options('compiler_cxx')
|
||||
|
||||
def configure(conf):
|
||||
conf.check_tool('compiler_cxx')
|
||||
conf.check_tool('node_addon')
|
||||
|
||||
def build(bld):
|
||||
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
|
||||
obj.target = 'binding'
|
||||
obj.source = 'binding.cc'
|
||||
@@ -5,13 +5,15 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int tsize = 1000 * 1048576;
|
||||
const char *path = "/tmp/wt.dat";
|
||||
|
||||
int c = 0;
|
||||
|
||||
char* bufit(size_t l)
|
||||
{
|
||||
@@ -24,7 +26,7 @@ void writetest(int size, size_t bsize)
|
||||
{
|
||||
int i;
|
||||
char *buf = bufit(bsize);
|
||||
clock_t start, end;
|
||||
struct timeval start, end;
|
||||
double elapsed;
|
||||
double mbps;
|
||||
|
||||
@@ -34,9 +36,10 @@ void writetest(int size, size_t bsize)
|
||||
exit(254);
|
||||
}
|
||||
|
||||
start = clock();
|
||||
assert(0 == gettimeofday(&start, NULL));
|
||||
for (i = 0; i < size; i += bsize) {
|
||||
int rv = write(fd, buf, bsize);
|
||||
if (c++ % 2000 == 0) fprintf(stderr, ".");
|
||||
if (rv < 0) {
|
||||
perror("write failed");
|
||||
exit(254);
|
||||
@@ -48,10 +51,10 @@ void writetest(int size, size_t bsize)
|
||||
fsync(fd);
|
||||
#endif
|
||||
close(fd);
|
||||
end = clock();
|
||||
elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
|
||||
assert(0 == gettimeofday(&end, NULL));
|
||||
elapsed = (end.tv_sec - start.tv_sec) + ((double)(end.tv_usec - start.tv_usec))/100000.;
|
||||
mbps = ((tsize/elapsed)) / 1048576;
|
||||
fprintf(stderr, "Wrote %d bytes in %03fs using %d byte buffers: %03fmB/s\n", size, elapsed, bsize, mbps);
|
||||
fprintf(stderr, "\nWrote %d bytes in %03fs using %ld byte buffers: %03fmB/s\n", size, elapsed, bsize, mbps);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
@@ -60,7 +63,7 @@ void readtest(int size, size_t bsize)
|
||||
{
|
||||
int i;
|
||||
char *buf = bufit(bsize);
|
||||
clock_t start, end;
|
||||
struct timeval start, end;
|
||||
double elapsed;
|
||||
double mbps;
|
||||
|
||||
@@ -70,7 +73,7 @@ void readtest(int size, size_t bsize)
|
||||
exit(254);
|
||||
}
|
||||
|
||||
start = clock();
|
||||
assert(0 == gettimeofday(&start, NULL));
|
||||
for (i = 0; i < size; i += bsize) {
|
||||
int rv = read(fd, buf, bsize);
|
||||
if (rv < 0) {
|
||||
@@ -79,10 +82,10 @@ void readtest(int size, size_t bsize)
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
end = clock();
|
||||
elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
|
||||
assert(0 == gettimeofday(&end, NULL));
|
||||
elapsed = (end.tv_sec - start.tv_sec) + ((double)(end.tv_usec - start.tv_usec))/100000.;
|
||||
mbps = ((tsize/elapsed)) / 1048576;
|
||||
fprintf(stderr, "Read %d bytes in %03fs using %d byte buffers: %03fmB/s\n", size, elapsed, bsize, mbps);
|
||||
fprintf(stderr, "Read %d bytes in %03fs using %ld byte buffers: %03fmB/s\n", size, elapsed, bsize, mbps);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var fs = require('fs');
|
||||
var sys = require('sys');
|
||||
var Buffer = require('buffer').Buffer;
|
||||
|
||||
var path = "/tmp/wt.dat";
|
||||
@@ -21,6 +22,8 @@ function once(emitter, name, cb) {
|
||||
emitter.addListener(name, incb);
|
||||
}
|
||||
|
||||
c = 0
|
||||
|
||||
function writetest(size, bsize) {
|
||||
var s = fs.createWriteStream(path, {'flags': 'w', 'mode': 0644});
|
||||
var remaining = size;
|
||||
@@ -40,6 +43,7 @@ function writetest(size, bsize) {
|
||||
|
||||
s.on('drain', function () {
|
||||
dowrite();
|
||||
if (c++ % 2000 == 0) sys.print(".");
|
||||
});
|
||||
|
||||
dowrite();
|
||||
|
||||
26
benchmark/startup.js
Normal file
26
benchmark/startup.js
Normal 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();
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
for (var i = 0; i < 9000000; i++) {
|
||||
for (var i = 0; i < 9e7; i++) {
|
||||
s = '01234567890';
|
||||
s[1] = "a";
|
||||
}
|
||||
|
||||
@@ -860,8 +860,9 @@ Experimental
|
||||
|
||||
Read the data from `readableStream` and send it to the `writableStream`.
|
||||
When `writeableStream.write(data)` returns `false` `readableStream` will be
|
||||
paused until the `drain` event occurs on the `writableStream`. `callback` is
|
||||
called when `writableStream` is closed.
|
||||
paused until the `drain` event occurs on the `writableStream`. `callback` gets
|
||||
an error as its only argument and is called when `writableStream` is closed or
|
||||
when an error occurs.
|
||||
|
||||
|
||||
## Timers
|
||||
@@ -1447,19 +1448,6 @@ See pwrite(2).
|
||||
The callback will be given two arguments `(err, written)` where `written`
|
||||
specifies how many _bytes_ were written.
|
||||
|
||||
### fs.write(fd, str, position, encoding='utf8', [callback])
|
||||
|
||||
Write the entire string `str` using the given `encoding` to the file specified
|
||||
by `fd`.
|
||||
|
||||
`position` refers to the offset from the beginning of the file where this data
|
||||
should be written. If `position` is `null`, the data will be written at the
|
||||
current position.
|
||||
See pwrite(2).
|
||||
|
||||
The callback will be given two arguments `(err, written)` where `written`
|
||||
specifies how many _bytes_ were written.
|
||||
|
||||
### fs.writeSync(fd, buffer, offset, length, position)
|
||||
|
||||
Synchronous version of buffer-based `fs.write()`. Returns the number of bytes written.
|
||||
@@ -1483,19 +1471,6 @@ If `position` is `null`, data will be read from the current file position.
|
||||
|
||||
The callback is given the two arguments, `(err, bytesRead)`.
|
||||
|
||||
### fs.read(fd, length, position, encoding, [callback])
|
||||
|
||||
Read data from the file specified by `fd`.
|
||||
|
||||
`length` is an integer specifying the number of bytes to read.
|
||||
|
||||
`position` is an integer specifying where to begin reading from in the file.
|
||||
If `position` is `null`, data will be read from the current file position.
|
||||
|
||||
`encoding` is the desired encoding of the string of data read in from `fd`.
|
||||
|
||||
The callback is given the three arguments, `(err, str, bytesRead)`.
|
||||
|
||||
### fs.readSync(fd, buffer, offset, length, position)
|
||||
|
||||
Synchronous version of buffer-based `fs.read`. Returns the number of `bytesRead`.
|
||||
@@ -1607,6 +1582,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 +2206,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 +2295,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 +3265,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.
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
<body>
|
||||
|
||||
<div id="toc">
|
||||
<div id="toctitle">Node v0.2.0</div>
|
||||
<div id="toctitle">Node v0.2.3</div>
|
||||
<noscript>JavaScript must be enabled in your browser to display the table of contents.</noscript>
|
||||
</div>
|
||||
<div id='man'>
|
||||
|
||||
12
doc/doc.js
12
doc/doc.js
@@ -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();
|
||||
|
||||
@@ -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.10.02
|
||||
<a href="http://nodejs.org/dist/node-v0.2.3.tar.gz">node-v0.2.3.tar.gz</a>
|
||||
</p>
|
||||
|
||||
<p>Historical: <a href="http://nodejs.org/dist">versions</a>, <a href="http://nodejs.org/docs">docs</a></p>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
exports.EventEmitter = process.EventEmitter;
|
||||
var EventEmitter = exports.EventEmitter = process.EventEmitter;
|
||||
|
||||
var isArray = Array.isArray;
|
||||
|
||||
process.EventEmitter.prototype.emit = function (type) {
|
||||
EventEmitter.prototype.emit = function (type) {
|
||||
// If there is no 'error' event listener then throw.
|
||||
if (type === 'error') {
|
||||
if (!this._events || !this._events.error ||
|
||||
@@ -18,27 +18,25 @@ process.EventEmitter.prototype.emit = function (type) {
|
||||
}
|
||||
|
||||
if (!this._events) return false;
|
||||
if (!this._events[type]) return false;
|
||||
var handler = this._events[type];
|
||||
if (!handler) return false;
|
||||
|
||||
if (typeof this._events[type] == 'function') {
|
||||
if (arguments.length < 3) {
|
||||
if (typeof handler == 'function') {
|
||||
if (arguments.length <= 3) {
|
||||
// fast case
|
||||
this._events[type].call( this
|
||||
, arguments[1]
|
||||
, arguments[2]
|
||||
);
|
||||
handler.call(this, arguments[1], arguments[2]);
|
||||
} else {
|
||||
// slower
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
this._events[type].apply(this, args);
|
||||
handler.apply(this, args);
|
||||
}
|
||||
return true;
|
||||
|
||||
} else if (isArray(this._events[type])) {
|
||||
} else if (isArray(handler)) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
|
||||
var listeners = this._events[type].slice(0);
|
||||
var listeners = handler.slice();
|
||||
for (var i = 0, l = listeners.length; i < l; i++) {
|
||||
listeners[i].apply(this, args);
|
||||
}
|
||||
@@ -49,9 +47,9 @@ process.EventEmitter.prototype.emit = function (type) {
|
||||
}
|
||||
};
|
||||
|
||||
// process.EventEmitter is defined in src/node_events.cc
|
||||
// process.EventEmitter.prototype.emit() is also defined there.
|
||||
process.EventEmitter.prototype.addListener = function (type, listener) {
|
||||
// EventEmitter is defined in src/node_events.cc
|
||||
// EventEmitter.prototype.emit() is also defined there.
|
||||
EventEmitter.prototype.addListener = function (type, listener) {
|
||||
if ('function' !== typeof listener) {
|
||||
throw new Error('addListener only takes instances of Function');
|
||||
}
|
||||
@@ -76,9 +74,9 @@ process.EventEmitter.prototype.addListener = function (type, listener) {
|
||||
return this;
|
||||
};
|
||||
|
||||
process.EventEmitter.prototype.on = process.EventEmitter.prototype.addListener;
|
||||
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
||||
|
||||
process.EventEmitter.prototype.removeListener = function (type, listener) {
|
||||
EventEmitter.prototype.removeListener = function (type, listener) {
|
||||
if ('function' !== typeof listener) {
|
||||
throw new Error('removeListener only takes instances of Function');
|
||||
}
|
||||
@@ -101,13 +99,13 @@ process.EventEmitter.prototype.removeListener = function (type, listener) {
|
||||
return this;
|
||||
};
|
||||
|
||||
process.EventEmitter.prototype.removeAllListeners = function (type) {
|
||||
EventEmitter.prototype.removeAllListeners = function (type) {
|
||||
// does not use listeners(), so no side effect of creating _events[type]
|
||||
if (type && this._events && this._events[type]) this._events[type] = null;
|
||||
return this;
|
||||
};
|
||||
|
||||
process.EventEmitter.prototype.listeners = function (type) {
|
||||
EventEmitter.prototype.listeners = function (type) {
|
||||
if (!this._events) this._events = {};
|
||||
if (!this._events[type]) this._events[type] = [];
|
||||
if (!isArray(this._events[type])) {
|
||||
|
||||
317
lib/fs.js
317
lib/fs.js
@@ -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);
|
||||
};
|
||||
@@ -445,6 +456,7 @@ fs.watchFile = function (filename) {
|
||||
};
|
||||
|
||||
fs.unwatchFile = function (filename) {
|
||||
var stat;
|
||||
if (statWatchers[filename]) {
|
||||
stat = statWatchers[filename];
|
||||
stat.stop();
|
||||
@@ -458,132 +470,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('/').concat(p.slice(i + 1)));
|
||||
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('/').concat(p.slice(i + 1)));
|
||||
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 () {
|
||||
@@ -598,8 +599,12 @@ fs.createReadStream = function(path, options) {
|
||||
};
|
||||
|
||||
var ReadStream = fs.ReadStream = function(path, options) {
|
||||
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
|
||||
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
var self = this;
|
||||
|
||||
this.path = path;
|
||||
this.fd = null;
|
||||
this.readable = true;
|
||||
@@ -607,7 +612,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 +623,14 @@ 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.encoding) this.setEncoding(this.encoding);
|
||||
|
||||
if (this.start !== undefined || this.end !== undefined) {
|
||||
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 +640,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);
|
||||
@@ -666,9 +673,8 @@ ReadStream.prototype._read = function () {
|
||||
allocNewPool();
|
||||
}
|
||||
|
||||
if(this.start && this.firstRead) {
|
||||
this.pos = this.start;
|
||||
this.firstRead = false;
|
||||
if (self.start !== undefined && self.firstRead) {
|
||||
self.pos = self.start;
|
||||
}
|
||||
|
||||
// Grab another reference to the pool in the case that while we're in the
|
||||
@@ -678,7 +684,7 @@ ReadStream.prototype._read = function () {
|
||||
var toRead = Math.min(pool.length - pool.used, this.bufferSize);
|
||||
var start = pool.used;
|
||||
|
||||
if(this.pos) {
|
||||
if (this.pos !== undefined) {
|
||||
toRead = Math.min(this.end - this.pos + 1, toRead);
|
||||
}
|
||||
|
||||
@@ -714,9 +720,12 @@ ReadStream.prototype._read = function () {
|
||||
self._read();
|
||||
}
|
||||
|
||||
fs.read(self.fd, pool, pool.used, toRead, this.pos, afterRead);
|
||||
// pass null for position after we've seeked to the start of a range read
|
||||
// always pass null on a non-range read
|
||||
fs.read(self.fd, pool, pool.used, toRead, (self.firstRead ? self.pos : null), afterRead);
|
||||
self.firstRead = false;
|
||||
|
||||
if(self.pos) {
|
||||
if (self.pos !== undefined) {
|
||||
self.pos += toRead;
|
||||
}
|
||||
pool.used += toRead;
|
||||
@@ -792,6 +801,8 @@ fs.createWriteStream = function(path, options) {
|
||||
};
|
||||
|
||||
var WriteStream = fs.WriteStream = function(path, options) {
|
||||
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
|
||||
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this.path = path;
|
||||
@@ -829,7 +840,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 +899,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 +950,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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
108
lib/http.js
108
lib/http.js
@@ -519,7 +519,7 @@ OutgoingMessage.prototype.end = function (data, encoding) {
|
||||
if (!hot) {
|
||||
if (this.chunkedEncoding) {
|
||||
ret = this._send('0\r\n\r\n'); // Last chunk.
|
||||
} else if (!data) {
|
||||
} else {
|
||||
// Force a flush, HACK.
|
||||
ret = this._send('');
|
||||
}
|
||||
@@ -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,60 +835,25 @@ function connectionListener (socket) {
|
||||
|
||||
|
||||
function Client ( ) {
|
||||
if (!(this instanceof Client)) return new Client();
|
||||
net.Stream.call(this);
|
||||
var self = this;
|
||||
|
||||
httpSocketSetup(self);
|
||||
|
||||
var parser;
|
||||
|
||||
function initParser () {
|
||||
if (!parser) parser = parsers.alloc();
|
||||
parser.reinitialize('response');
|
||||
parser.socket = self;
|
||||
parser.onIncoming = function (res) {
|
||||
debug("incoming response!");
|
||||
|
||||
var req = self._outgoing[0];
|
||||
|
||||
// Responses to HEAD requests are AWFUL. Ask Ryan.
|
||||
// A major oversight in HTTP. Hence this nastiness.
|
||||
var isHeadResponse = req.method == "HEAD";
|
||||
debug('isHeadResponse ' + isHeadResponse);
|
||||
|
||||
res.addListener('end', function ( ) {
|
||||
debug("request complete disconnecting. readyState = " + self.readyState);
|
||||
// For the moment we reconnect for every request. FIXME!
|
||||
// All that should be required for keep-alive is to not reconnect,
|
||||
// but outgoingFlush instead.
|
||||
if (req.shouldKeepAlive) {
|
||||
outgoingFlush(self)
|
||||
self._outgoing.shift()
|
||||
outgoingFlush(self)
|
||||
} else {
|
||||
self.end();
|
||||
}
|
||||
});
|
||||
|
||||
req.emit("response", res);
|
||||
|
||||
return isHeadResponse;
|
||||
};
|
||||
};
|
||||
|
||||
self.ondata = function (d, start, end) {
|
||||
if (!parser) {
|
||||
function onData(d, start, end) {
|
||||
if (!self.parser) {
|
||||
throw new Error("parser not initialized prior to Client.ondata call");
|
||||
}
|
||||
var ret = parser.execute(d, start, end - start);
|
||||
var ret = self.parser.execute(d, start, end - start);
|
||||
if (ret instanceof Error) {
|
||||
self.destroy(ret);
|
||||
} else if (parser.incoming && parser.incoming.upgrade) {
|
||||
} else if (self.parser.incoming && self.parser.incoming.upgrade) {
|
||||
var bytesParsed = ret;
|
||||
self.ondata = null;
|
||||
self.onend = null
|
||||
|
||||
var req = self._outgoing[0];
|
||||
var req = self.parser.incoming;
|
||||
|
||||
var upgradeHead = d.slice(start + bytesParsed + 1, end);
|
||||
|
||||
@@ -901,23 +867,27 @@ function Client ( ) {
|
||||
|
||||
self.addListener("connect", function () {
|
||||
debug('client connected');
|
||||
|
||||
self.ondata = onData;
|
||||
self.onend = onEnd;
|
||||
|
||||
if (this.https) {
|
||||
this.setSecure(this.credentials);
|
||||
} else {
|
||||
initParser();
|
||||
self._initParser();
|
||||
debug('requests: ' + sys.inspect(self._outgoing));
|
||||
outgoingFlush(self);
|
||||
}
|
||||
});
|
||||
|
||||
self.addListener("secure", function () {
|
||||
initParser();
|
||||
self._initParser();
|
||||
debug('requests: ' + sys.inspect(self._outgoing));
|
||||
outgoingFlush(self);
|
||||
});
|
||||
|
||||
self.onend = function () {
|
||||
if (parser) parser.finish();
|
||||
function onEnd() {
|
||||
if (self.parser) self.parser.finish();
|
||||
debug("self got end closing. readyState = " + self.readyState);
|
||||
self.end();
|
||||
};
|
||||
@@ -933,9 +903,9 @@ function Client ( ) {
|
||||
// If there are more requests to handle, reconnect.
|
||||
if (self._outgoing.length) {
|
||||
self._reconnect();
|
||||
} else if (parser) {
|
||||
parsers.free(parser);
|
||||
parser = null;
|
||||
} else if (self.parser) {
|
||||
parsers.free(self.parser);
|
||||
self.parser = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -953,6 +923,46 @@ exports.createClient = function (port, host, https, credentials) {
|
||||
};
|
||||
|
||||
|
||||
Client.prototype._initParser = function () {
|
||||
var self = this;
|
||||
if (!self.parser) self.parser = parsers.alloc();
|
||||
self.parser.reinitialize('response');
|
||||
self.parser.socket = self;
|
||||
self.parser.onIncoming = function (res) {
|
||||
debug("incoming response!");
|
||||
|
||||
var req = self._outgoing[0];
|
||||
|
||||
// Responses to HEAD requests are AWFUL. Ask Ryan.
|
||||
// A major oversight in HTTP. Hence this nastiness.
|
||||
var isHeadResponse = req.method == "HEAD";
|
||||
debug('isHeadResponse ' + isHeadResponse);
|
||||
|
||||
if (req.shouldKeepAlive && res.headers.connection === 'close') {
|
||||
req.shouldKeepAlive = false;
|
||||
}
|
||||
|
||||
res.addListener('end', function ( ) {
|
||||
debug("request complete disconnecting. readyState = " + self.readyState);
|
||||
// For the moment we reconnect for every request. FIXME!
|
||||
// All that should be required for keep-alive is to not reconnect,
|
||||
// but outgoingFlush instead.
|
||||
if (req.shouldKeepAlive) {
|
||||
outgoingFlush(self)
|
||||
self._outgoing.shift()
|
||||
outgoingFlush(self)
|
||||
} else {
|
||||
self.end();
|
||||
}
|
||||
});
|
||||
|
||||
req.emit("response", res);
|
||||
|
||||
return isHeadResponse;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// This is called each time a request has been pushed completely to the
|
||||
// socket. The message that was sent is still sitting at client._outgoing[0]
|
||||
// it is our responsibility to shift it off.
|
||||
|
||||
28
lib/net.js
28
lib/net.js
@@ -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);
|
||||
|
||||
138
lib/readline.js
138
lib/readline.js
@@ -15,24 +15,26 @@ var EventEmitter = require('events').EventEmitter;
|
||||
var stdio = process.binding('stdio');
|
||||
|
||||
|
||||
|
||||
exports.createInterface = function (output, completer) {
|
||||
return new Interface(output, completer);
|
||||
};
|
||||
|
||||
function Interface (output, completer) {
|
||||
if (!(this instanceof Interface)) return new Interface(output, completer);
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.output = output;
|
||||
this.completer = completer;
|
||||
|
||||
this.setPrompt("node> ");
|
||||
this.setPrompt("> ");
|
||||
|
||||
this._tty = output.fd < 3;
|
||||
this.enabled = output.fd < 3; // Looks like a TTY.
|
||||
|
||||
if (parseInt(process.env['NODE_NO_READLINE'])) {
|
||||
this._tty = false;
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
if (this._tty) {
|
||||
if (this.enabled) {
|
||||
// input refers to stdin
|
||||
|
||||
// Current line
|
||||
@@ -40,22 +42,28 @@ function Interface (output, completer) {
|
||||
|
||||
// Check process.env.TERM ?
|
||||
stdio.setRawMode(true);
|
||||
this._tty = true;
|
||||
this.enabled = true;
|
||||
|
||||
// Cursor position on the line.
|
||||
this.cursor = 0;
|
||||
|
||||
this.history = [];
|
||||
this.historyIndex = -1;
|
||||
|
||||
exports.columns = process.binding('stdio').getColumns();
|
||||
|
||||
if (process.listeners("SIGWINCH").length === 0) {
|
||||
process.on("SIGWINCH", function () {
|
||||
exports.columns = process.binding('stdio').getColumns();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inherits(Interface, EventEmitter);
|
||||
|
||||
Interface.prototype.__defineGetter__("columns", function () {
|
||||
if (this._tty) {
|
||||
return stdio.getColumns();
|
||||
}
|
||||
return exports.columns;
|
||||
});
|
||||
|
||||
Interface.prototype.setPrompt = function (prompt, length) {
|
||||
@@ -65,7 +73,7 @@ Interface.prototype.setPrompt = function (prompt, length) {
|
||||
|
||||
|
||||
Interface.prototype.prompt = function () {
|
||||
if (this._tty) {
|
||||
if (this.enabled) {
|
||||
this.cursor = 0;
|
||||
this._refreshLine();
|
||||
} else {
|
||||
@@ -111,7 +119,7 @@ Interface.prototype._refreshLine = function () {
|
||||
|
||||
|
||||
Interface.prototype.close = function (d) {
|
||||
if (this._tty) {
|
||||
if (this.enabled) {
|
||||
stdio.setRawMode(false);
|
||||
}
|
||||
this.emit('close');
|
||||
@@ -121,7 +129,7 @@ Interface.prototype.close = function (d) {
|
||||
|
||||
Interface.prototype.write = function (d) {
|
||||
if (this._closed) return;
|
||||
return this._tty ? this._ttyWrite(d) : this._normalWrite(d);
|
||||
return this.enabled ? this._ttyWrite(d) : this._normalWrite(d);
|
||||
};
|
||||
|
||||
|
||||
@@ -261,7 +269,12 @@ Interface.prototype._ttyWrite = function (b) {
|
||||
/* ctrl+c */
|
||||
case 3:
|
||||
//process.kill(process.pid, "SIGINT");
|
||||
this.close();
|
||||
if (this.listeners('SIGINT').length) {
|
||||
this.emit('SIGINT');
|
||||
} else {
|
||||
// default behavior, end the readline
|
||||
this.close();
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // control-d, delete right or EOF
|
||||
@@ -332,6 +345,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,34 +371,104 @@ Interface.prototype._ttyWrite = function (b) {
|
||||
return;
|
||||
|
||||
case 27: /* escape sequence */
|
||||
if (b[1] === 98 && this.cursor > 0) { // meta-b - backward word
|
||||
var next_word, next_non_word, previous_word, previous_non_word;
|
||||
|
||||
} else if (b[1] === 102 && this.cursor < this.line.length) { // meta-f - forward 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] === 91 && b[2] === 68) { // left arrow
|
||||
} 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--;
|
||||
this.output.write('\x1b[0D');
|
||||
}
|
||||
} else if (b[1] === 91 && b[2] === 67) { // right arrow
|
||||
|
||||
} else if (b[1] === 91 && b[2] === 67) {
|
||||
// right arrow
|
||||
if (this.cursor != this.line.length) {
|
||||
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
|
||||
|
||||
} else if (b[1] === 91 && b[2] === 65) {
|
||||
// up arrow
|
||||
this._historyPrev();
|
||||
} else if (b[1] === 91 && b[2] === 66) { // down arrow
|
||||
|
||||
} else if (b[1] === 91 && b[2] === 66) {
|
||||
// down arrow
|
||||
this._historyNext();
|
||||
} else if (b[1] === 91 && b[2] === 51 && this.cursor < this.line.length) { // delete right
|
||||
|
||||
} else if (b[1] === 91 && b[2] === 51 && this.cursor < this.line.length) {
|
||||
// delete right
|
||||
this.line = this.line.slice(0, this.cursor) +
|
||||
this.line.slice(this.cursor+1, this.line.length);
|
||||
this._refreshLine();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
29
lib/repl.js
29
lib/repl.js
@@ -48,13 +48,31 @@ function REPLServer(prompt, stream) {
|
||||
self.buffered_cmd = '';
|
||||
|
||||
self.stream = stream || process.openStdin();
|
||||
self.prompt = prompt || "node> ";
|
||||
self.prompt = prompt || "> ";
|
||||
|
||||
var rli = self.rli = rl.createInterface(self.stream, function (text) {
|
||||
return self.complete(text);
|
||||
});
|
||||
|
||||
if (rli.enabled) {
|
||||
// Turn on ANSI coloring.
|
||||
exports.writer = function(obj, showHidden, depth) {
|
||||
return sys.inspect(obj, showHidden, depth, true);
|
||||
}
|
||||
}
|
||||
|
||||
rli.setPrompt(self.prompt);
|
||||
|
||||
rli.on("SIGINT", function () {
|
||||
if (self.buffered_cmd && self.buffered_cmd.length > 0) {
|
||||
rli.write("\n");
|
||||
self.buffered_cmd = '';
|
||||
self.displayPrompt();
|
||||
} else {
|
||||
rli.close();
|
||||
}
|
||||
});
|
||||
|
||||
self.stream.addListener("data", function (chunk) {
|
||||
rli.write(chunk);
|
||||
});
|
||||
@@ -130,7 +148,7 @@ exports.start = function (prompt, source) {
|
||||
};
|
||||
|
||||
REPLServer.prototype.displayPrompt = function () {
|
||||
this.rli.setPrompt(this.buffered_cmd.length ? '... ' : this.prompt);
|
||||
this.rli.setPrompt(this.buffered_cmd.length ? '... ' : this.prompt);
|
||||
this.rli.prompt();
|
||||
};
|
||||
|
||||
@@ -300,7 +318,8 @@ REPLServer.prototype.complete = function (line) {
|
||||
if (typeof obj === "object" || typeof obj === "function") {
|
||||
memberGroups.push(Object.getOwnPropertyNames(obj));
|
||||
}
|
||||
var p = obj.constructor.prototype; // works for non-objects
|
||||
// works for non-objects
|
||||
var p = obj.constructor ? obj.constructor.prototype : null;
|
||||
try {
|
||||
var sentinel = 5;
|
||||
while (p !== null) {
|
||||
@@ -380,7 +399,8 @@ REPLServer.prototype.parseREPLKeyword = function (cmd) {
|
||||
var self = this;
|
||||
|
||||
switch (cmd) {
|
||||
case ".break":
|
||||
case ".break":
|
||||
// TODO remove me after 0.3.x
|
||||
self.buffered_cmd = '';
|
||||
self.displayPrompt();
|
||||
return true;
|
||||
@@ -394,7 +414,6 @@ REPLServer.prototype.parseREPLKeyword = function (cmd) {
|
||||
self.stream.destroy();
|
||||
return true;
|
||||
case ".help":
|
||||
self.stream.write(".break\tSometimes you get stuck in a place you can't get out... This will get you out.\n");
|
||||
self.stream.write(".clear\tBreak, and also clear the local context.\n");
|
||||
self.stream.write(".exit\tExit the prompt\n");
|
||||
self.stream.write(".help\tShow repl options\n");
|
||||
|
||||
113
lib/sys.js
113
lib/sys.js
@@ -33,10 +33,51 @@ var error = exports.error = function (x) {
|
||||
*
|
||||
* @param {Object} value The object to print out
|
||||
* @param {Boolean} showHidden Flag that shows hidden (not enumerable)
|
||||
* properties of objects.
|
||||
* properties of objects.
|
||||
* @param {Number} depth Depth in which to descend in object. Default is 2.
|
||||
* @param {Boolean} colors Flag to turn on ANSI escape codes to color the
|
||||
* output. Default is false (no coloring).
|
||||
*/
|
||||
exports.inspect = function (obj, showHidden, depth) {
|
||||
exports.inspect = function (obj, showHidden, depth, colors) {
|
||||
var seen = [];
|
||||
|
||||
var stylize = function (str, styleType) {
|
||||
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||
var styles = { 'bold' : [1, 22]
|
||||
, 'italic' : [3, 23]
|
||||
, 'underline' : [4, 24]
|
||||
, 'inverse' : [7, 27]
|
||||
, 'white' : [37, 39]
|
||||
, 'grey' : [90, 39]
|
||||
, 'black' : [30, 39]
|
||||
, 'blue' : [34, 39]
|
||||
, 'cyan' : [36, 39]
|
||||
, 'green' : [32, 39]
|
||||
, 'magenta' : [35, 39]
|
||||
, 'red' : [31, 39]
|
||||
, 'yellow' : [33, 39]
|
||||
};
|
||||
var style = { "special": "grey"
|
||||
, "number": "blue"
|
||||
, "boolean": "blue"
|
||||
, "undefined": "red"
|
||||
, "null": "red"
|
||||
, "string": "green"
|
||||
, "date": "magenta"
|
||||
//, "name": intentionally not styling
|
||||
, "regexp": "cyan"
|
||||
}[styleType];
|
||||
if (style) {
|
||||
return '\033[' + styles[style][0] + 'm' + str +
|
||||
'\033[' + styles[style][1] + 'm';
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
if (! colors) {
|
||||
stylize = function(str, styleType) { return str; };
|
||||
}
|
||||
|
||||
function format(value, recurseTimes) {
|
||||
// Provide a hook for user-specified inspect functions.
|
||||
// Check that value is an object with an inspect function on it
|
||||
@@ -50,39 +91,36 @@ exports.inspect = function (obj, showHidden, depth) {
|
||||
|
||||
// Primitive types cannot have properties
|
||||
switch (typeof value) {
|
||||
case 'undefined': return 'undefined';
|
||||
case 'string': return JSON.stringify(value).replace(/'/g, "\\'")
|
||||
.replace(/\\"/g, '"')
|
||||
.replace(/(^"|"$)/g, "'");
|
||||
case 'number': return '' + value;
|
||||
case 'boolean': return '' + value;
|
||||
case 'undefined': return stylize('undefined', 'undefined');
|
||||
case 'string': return stylize(
|
||||
JSON.stringify(value).replace(/'/g, "\\'")
|
||||
.replace(/\\"/g, '"')
|
||||
.replace(/(^"|"$)/g, "'"),
|
||||
'string');
|
||||
case 'number': return stylize('' + value, 'number');
|
||||
case 'boolean': return stylize('' + value, 'boolean');
|
||||
}
|
||||
// For some reason typeof null is "object", so special case here.
|
||||
if (value === null) {
|
||||
return 'null';
|
||||
return stylize('null', 'null');
|
||||
}
|
||||
|
||||
// Look up the keys of the object.
|
||||
if (showHidden) {
|
||||
var keys = Object.getOwnPropertyNames(value).map(function (key) { return '' + key; });
|
||||
} else {
|
||||
var keys = Object.keys(value);
|
||||
}
|
||||
|
||||
var visible_keys = Object.keys(value);
|
||||
var keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys;
|
||||
|
||||
// Functions without properties can be shortcutted.
|
||||
if (typeof value === 'function' && keys.length === 0) {
|
||||
if (isRegExp(value)) {
|
||||
return '' + value;
|
||||
return stylize('' + value, 'regexp');
|
||||
} else {
|
||||
return '[Function]';
|
||||
return stylize('[Function'+ (value.name ? ': '+ value.name : '')+ ']', 'special');
|
||||
}
|
||||
}
|
||||
|
||||
// Dates without properties can be shortcutted
|
||||
if (isDate(value) && keys.length === 0) {
|
||||
return value.toUTCString();
|
||||
return stylize(value.toUTCString(), 'date');
|
||||
}
|
||||
|
||||
var base, type, braces;
|
||||
@@ -97,7 +135,7 @@ exports.inspect = function (obj, showHidden, depth) {
|
||||
|
||||
// Make functions say that they are functions
|
||||
if (typeof value === 'function') {
|
||||
base = (isRegExp(value)) ? ' ' + value : ' [Function]';
|
||||
base = (isRegExp(value)) ? ' ' + value : ' [Function'+ (value.name ? ': '+ value.name : '')+ ']';
|
||||
} else {
|
||||
base = "";
|
||||
}
|
||||
@@ -115,24 +153,24 @@ exports.inspect = function (obj, showHidden, depth) {
|
||||
|
||||
if (recurseTimes < 0) {
|
||||
if (isRegExp(value)) {
|
||||
return '' + value;
|
||||
return stylize('' + value, "regexp");
|
||||
} else {
|
||||
return "[Object]";
|
||||
return stylize("[Object]", "special");
|
||||
}
|
||||
}
|
||||
|
||||
output = keys.map(function (key) {
|
||||
var output = keys.map(function (key) {
|
||||
var name, str;
|
||||
if (value.__lookupGetter__) {
|
||||
if (value.__lookupGetter__(key)) {
|
||||
if (value.__lookupSetter__(key)) {
|
||||
str = "[Getter/Setter]";
|
||||
str = stylize("[Getter/Setter]", "special");
|
||||
} else {
|
||||
str = "[Getter]";
|
||||
str = stylize("[Getter]", "special");
|
||||
}
|
||||
} else {
|
||||
if (value.__lookupSetter__(key)) {
|
||||
str = "[Setter]";
|
||||
str = stylize("[Setter]", "special");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +198,7 @@ exports.inspect = function (obj, showHidden, depth) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
str = '[Circular]';
|
||||
str = stylize('[Circular]', 'special');
|
||||
}
|
||||
}
|
||||
if (typeof name === 'undefined') {
|
||||
@@ -170,11 +208,13 @@ exports.inspect = function (obj, showHidden, depth) {
|
||||
name = JSON.stringify('' + key);
|
||||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||||
name = name.substr(1, name.length-2);
|
||||
name = stylize(name, "name");
|
||||
}
|
||||
else {
|
||||
name = name.replace(/'/g, "\\'")
|
||||
.replace(/\\"/g, '"')
|
||||
.replace(/(^"|"$)/g, "'");
|
||||
name = stylize(name, "string");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +323,15 @@ exports.exec = function () {
|
||||
|
||||
|
||||
exports.pump = function (readStream, writeStream, callback) {
|
||||
var callbackCalled = false;
|
||||
|
||||
function call (a, b, c) {
|
||||
if (callback && !callbackCalled) {
|
||||
callback(a, b, c);
|
||||
callbackCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!readStream.pause) readStream.pause = function () {readStream.emit("pause")};
|
||||
if (!readStream.resume) readStream.resume = function () {readStream.emit("resume")};
|
||||
|
||||
@@ -307,7 +356,17 @@ exports.pump = function (readStream, writeStream, callback) {
|
||||
});
|
||||
|
||||
readStream.addListener("close", function () {
|
||||
if (callback) callback();
|
||||
call();
|
||||
});
|
||||
|
||||
readStream.addListener("error", function (err) {
|
||||
writeStream.end();
|
||||
call(err);
|
||||
});
|
||||
|
||||
writeStream.addListener("error", function (err) {
|
||||
readStream.destroy();
|
||||
call(err);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
19
lib/url.js
19
lib/url.js
@@ -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;
|
||||
|
||||
37
src/node.cc
37
src/node.cc
@@ -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);
|
||||
@@ -1802,14 +1819,18 @@ int main(int argc, char *argv[]) {
|
||||
// TODO(Ryan) I'm experiencing abnormally high load using Solaris's
|
||||
// EVBACKEND_PORT. Temporarally forcing select() until I debug.
|
||||
ev_default_loop(EVBACKEND_POLL);
|
||||
#elif defined(__APPLE_CC__) && __APPLE_CC__ >= 5659
|
||||
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
|
||||
ev_default_loop(EVBACKEND_KQUEUE);
|
||||
#else
|
||||
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);
|
||||
|
||||
@@ -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), \
|
||||
|
||||
44
src/node.js
44
src/node.js
@@ -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);
|
||||
@@ -533,8 +534,8 @@ var events = module.requireNative('events');
|
||||
// Signal Handlers
|
||||
(function() {
|
||||
var signalWatchers = {};
|
||||
addListener = process.addListener,
|
||||
removeListener = process.removeListener;
|
||||
var addListener = process.addListener;
|
||||
var removeListener = process.removeListener;
|
||||
|
||||
function isSignal (event) {
|
||||
return event.slice(0, 3) === 'SIG' && process.hasOwnProperty(event);
|
||||
@@ -596,12 +597,13 @@ 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;
|
||||
};
|
||||
|
||||
global.clearTimeout = function (timer) {
|
||||
if (timer instanceof process.Timer) {
|
||||
timer.callback = null;
|
||||
timer.stop();
|
||||
}
|
||||
};
|
||||
@@ -748,12 +750,14 @@ 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');
|
||||
console.log("Type '.help' for options.");
|
||||
repl.start();
|
||||
module.requireNative('repl').start();
|
||||
}
|
||||
|
||||
// All our arguments are loaded. We've evaluated all of the scripts. We
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class ObjectWrap {
|
||||
refs_ = 0;
|
||||
}
|
||||
|
||||
|
||||
virtual ~ObjectWrap ( ) {
|
||||
if (!handle_.IsEmpty()) {
|
||||
assert(handle_.IsNearDeath());
|
||||
@@ -21,29 +22,28 @@ class ObjectWrap {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static inline T* Unwrap (v8::Handle<v8::Object> handle)
|
||||
{
|
||||
static inline T* Unwrap (v8::Handle<v8::Object> handle) {
|
||||
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
|
||||
|
||||
protected:
|
||||
inline void Wrap (v8::Handle<v8::Object> handle)
|
||||
{
|
||||
inline void Wrap (v8::Handle<v8::Object> handle) {
|
||||
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();
|
||||
}
|
||||
|
||||
inline void MakeWeak (void)
|
||||
{
|
||||
|
||||
inline void MakeWeak (void) {
|
||||
handle_.MakeWeak(this, WeakCallback);
|
||||
}
|
||||
|
||||
@@ -73,11 +73,12 @@ class ObjectWrap {
|
||||
if (--refs_ == 0) { MakeWeak(); }
|
||||
}
|
||||
|
||||
|
||||
int refs_; // ro
|
||||
|
||||
|
||||
private:
|
||||
static void WeakCallback (v8::Persistent<v8::Value> value, void *data)
|
||||
{
|
||||
static void WeakCallback (v8::Persistent<v8::Value> value, void *data) {
|
||||
ObjectWrap *obj = static_cast<ObjectWrap*>(data);
|
||||
assert(value == obj->handle_);
|
||||
assert(!obj->refs_);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define NODE_MAJOR_VERSION 0
|
||||
#define NODE_MINOR_VERSION 2
|
||||
#define NODE_PATCH_VERSION 0
|
||||
#define NODE_PATCH_VERSION 3
|
||||
|
||||
#ifndef NODE_STRINGIFY
|
||||
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -12,7 +12,12 @@ var client = net.createConnection(443, "www.microsoft.com");
|
||||
var caPem = fs.readFileSync(common.fixturesDir+"/msca.pem");
|
||||
//var caPem = fs.readFileSync("ca.pem");
|
||||
|
||||
var credentials = crypto.createCredentials({ca:caPem});
|
||||
try{
|
||||
var credentials = crypto.createCredentials({ca:caPem});
|
||||
} catch (e) {
|
||||
console.log("Not compiled with OPENSSL support.");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
client.setEncoding("UTF8");
|
||||
client.addListener("connect", function () {
|
||||
|
||||
@@ -9,7 +9,12 @@ var crypto=require('crypto');
|
||||
var keyPem = fs.readFileSync(common.fixturesDir + "/cert.pem");
|
||||
var certPem = fs.readFileSync(common.fixturesDir + "/cert.pem");
|
||||
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem});
|
||||
try{
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem});
|
||||
} catch (e) {
|
||||
console.log("Not compiled with OPENSSL support.");
|
||||
process.exit();
|
||||
}
|
||||
var i = 0;
|
||||
var server = net.createServer(function (connection) {
|
||||
connection.setSecure(credentials);
|
||||
|
||||
4
test/fixtures/global/plain.js
vendored
4
test/fixtures/global/plain.js
vendored
@@ -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};
|
||||
13
test/fixtures/global/sub1.js
vendored
13
test/fixtures/global/sub1.js
vendored
@@ -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();
|
||||
};
|
||||
18
test/fixtures/global/sub2.js
vendored
18
test/fixtures/global/sub2.js
vendored
@@ -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
1
test/fixtures/semicolon.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
;
|
||||
@@ -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:*
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
17
test/simple/test-console.js
Normal file
17
test/simple/test-console.js
Normal 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());
|
||||
@@ -17,7 +17,12 @@ var caPem = fs.readFileSync(common.fixturesDir+"/test_ca.pem", 'ascii');
|
||||
var certPem = fs.readFileSync(common.fixturesDir+"/test_cert.pem", 'ascii');
|
||||
var keyPem = fs.readFileSync(common.fixturesDir+"/test_key.pem", 'ascii');
|
||||
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
try{
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
} catch (e) {
|
||||
console.log("Not compiled with OPENSSL support.");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
// Test HMAC
|
||||
//var h1 = (new crypto.Hmac).init("sha1", "Node").update("some data").update("to hmac").digest("hex");
|
||||
|
||||
@@ -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);
|
||||
|
||||
21
test/simple/test-exception-handler2.js
Normal file
21
test/simple/test-exception-handler2.js
Normal 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.');
|
||||
|
||||
@@ -15,7 +15,7 @@ callbacks = { open: 0, end: 0, close: 0, destroy: 0 };
|
||||
|
||||
paused = false;
|
||||
|
||||
file = fs.createReadStream(fn);
|
||||
file = fs.ReadStream(fn);
|
||||
|
||||
file.addListener('open', function(fd) {
|
||||
file.length = 0;
|
||||
@@ -60,9 +60,8 @@ file2.destroy(function(err) {
|
||||
callbacks.destroy++;
|
||||
});
|
||||
|
||||
var file3 = fs.createReadStream(fn);
|
||||
var file3 = fs.createReadStream(fn, {encoding: 'utf8'});
|
||||
file3.length = 0;
|
||||
file3.setEncoding('utf8');
|
||||
file3.addListener('data', function(data) {
|
||||
assert.equal("string", typeof(data));
|
||||
file3.length += data.length;
|
||||
@@ -96,3 +95,28 @@ 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.');
|
||||
}
|
||||
|
||||
var stream = fs.createReadStream(rangeFile, { start: 0, end: 0 });
|
||||
stream.data = '';
|
||||
|
||||
stream.on('data', function(chunk){
|
||||
stream.data += chunk;
|
||||
});
|
||||
|
||||
stream.on('end', function(){
|
||||
assert.equal('x', stream.data);
|
||||
});
|
||||
@@ -9,3 +9,7 @@ var
|
||||
fs.readFile(fn, function(err, data) {
|
||||
assert.ok(data);
|
||||
});
|
||||
|
||||
fs.readFile(fn, 'utf8', function(err, data) {
|
||||
assert.strictEqual('', data);
|
||||
});
|
||||
@@ -2,16 +2,16 @@ common = require("../common");
|
||||
assert = common.assert
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var exec = require('child_process').exec;
|
||||
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,11 +19,11 @@ function asynctest(testBlock, args, callback, assertBlock) {
|
||||
}
|
||||
async_completed++;
|
||||
callback(ignoreError ? null : err);
|
||||
}]));
|
||||
}));
|
||||
}
|
||||
|
||||
function bashRealpath(path, callback) {
|
||||
common.exec("cd '"+path.replace("'","\\'")+"' && pwd -P",function
|
||||
exec("cd '"+path.replace("'","\\'")+"' && pwd -P",function
|
||||
(err, o) {
|
||||
callback(err, o.trim());
|
||||
});
|
||||
@@ -227,6 +227,69 @@ 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);
|
||||
|
||||
// absolute symlinks with children.
|
||||
// .
|
||||
// `-- a/
|
||||
// |-- b/
|
||||
// | `-- c/
|
||||
// | `-- x.txt
|
||||
// `-- link -> /tmp/node-test-realpath-abs-kids/a/b/
|
||||
// realpath(root+'/a/link/c/x.txt') ==> root+'/a/b/c/x.txt'
|
||||
function test_abs_with_kids (cb) {
|
||||
bashRealpath(common.fixturesDir, function(err, fixturesAbsDir) {
|
||||
var root = fixturesAbsDir+'/node-test-realpath-abs-kids';
|
||||
function cleanup () {
|
||||
;['/a/b/c/x.txt'
|
||||
, '/a/link'
|
||||
].forEach(function (file) {
|
||||
try {fs.unlinkSync(root+file)} catch (ex) {}
|
||||
});
|
||||
;['/a/b/c'
|
||||
, '/a/b'
|
||||
, '/a'
|
||||
, ''
|
||||
].forEach(function (folder) {
|
||||
try {fs.rmdirSync(root+folder)} catch (ex) {}
|
||||
});
|
||||
}
|
||||
function setup () {
|
||||
cleanup()
|
||||
;[''
|
||||
, '/a'
|
||||
, '/a/b'
|
||||
, '/a/b/c'
|
||||
].forEach(function (folder) {
|
||||
console.log("mkdir "+root+folder)
|
||||
fs.mkdirSync(root+folder, 0700);
|
||||
});
|
||||
fs.writeFileSync(root+'/a/b/c/x.txt', 'foo');
|
||||
fs.symlinkSync(root+'/a/b', root+'/a/link');
|
||||
}
|
||||
setup();
|
||||
var linkPath = root+'/a/link/c/x.txt';
|
||||
var expectPath = root+'/a/b/c/x.txt';
|
||||
var actual = fs.realpathSync(linkPath);
|
||||
// console.log({link:linkPath,expect:expectPath,actual:actual},'sync');
|
||||
assert.equal(actual, expectPath);
|
||||
asynctest(fs.realpath, [linkPath], cb, function (er, actual) {
|
||||
// console.log({link:linkPath,expect:expectPath,actual:actual},'async');
|
||||
assert.equal(actual, expectPath);
|
||||
cleanup();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var tests = [
|
||||
@@ -238,6 +301,8 @@ var tests = [
|
||||
test_relative_input_cwd,
|
||||
test_deep_symlink_mix,
|
||||
test_non_symlinks,
|
||||
test_escape_cwd,
|
||||
test_abs_with_kids
|
||||
];
|
||||
var numtests = tests.length;
|
||||
function runNextTest(err) {
|
||||
@@ -248,6 +313,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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
28
test/simple/test-fs-write-stream.js
Normal file
28
test/simple/test-fs-write-stream.js
Normal 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.WriteStream(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();
|
||||
})();
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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.");
|
||||
32
test/simple/test-global-leak.js
Normal file
32
test/simple/test-global-leak.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var assert = require('assert');
|
||||
|
||||
var knownGlobals = [ setTimeout
|
||||
, setInterval
|
||||
, clearTimeout
|
||||
, clearInterval
|
||||
, console
|
||||
, Buffer
|
||||
, process
|
||||
, global
|
||||
, __module
|
||||
, include
|
||||
, puts
|
||||
, print
|
||||
, p
|
||||
];
|
||||
|
||||
for (var x in global) {
|
||||
var found = false;
|
||||
|
||||
for (var y in knownGlobals) {
|
||||
if (global[x] === knownGlobals[y]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
console.error("Unknown global: %s", x);
|
||||
assert.ok(false);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
|
||||
34
test/simple/test-http-client-parse-error.js
Normal file
34
test/simple/test-http-client-parse-error.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var common = require("../common");
|
||||
var assert = require('assert');
|
||||
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
// Create a TCP server
|
||||
var srv = net.createServer(function(c) {
|
||||
c.write('bad http - should trigger parse error\r\n');
|
||||
|
||||
console.log("connection");
|
||||
|
||||
c.addListener('end', function() { c.end(); });
|
||||
});
|
||||
srv.listen(common.PORT, '127.0.0.1');
|
||||
|
||||
var hc = http.createClient(common.PORT, '127.0.0.1');
|
||||
hc.request('GET', '/').end();
|
||||
|
||||
var parseError = false;
|
||||
|
||||
hc.on('error', function (e) {
|
||||
console.log("got error from client");
|
||||
srv.close();
|
||||
assert.ok(e.message.indexOf("Parse Error") >= 0);
|
||||
parseError = true;
|
||||
});
|
||||
|
||||
|
||||
process.addListener('exit', function() {
|
||||
assert.ok(parseError);
|
||||
});
|
||||
|
||||
|
||||
49
test/simple/test-http-keep-alive-close-on-header.js
Normal file
49
test/simple/test-http-keep-alive-close-on-header.js
Normal file
@@ -0,0 +1,49 @@
|
||||
common = require("../common");
|
||||
assert = common.assert
|
||||
|
||||
assert = require("assert");
|
||||
http = require("http");
|
||||
sys = require("sys");
|
||||
|
||||
body = "hello world\n";
|
||||
headers = {'connection':'keep-alive'}
|
||||
|
||||
server = http.createServer(function (req, res) {
|
||||
res.writeHead(200, {"Content-Length": body.length, "Connection":"close"});
|
||||
res.write(body);
|
||||
res.end();
|
||||
});
|
||||
|
||||
connectCount = 0;
|
||||
|
||||
server.listen(common.PORT, function () {
|
||||
var client = http.createClient(common.PORT);
|
||||
|
||||
client.addListener("connect", function () {
|
||||
common.error("CONNECTED")
|
||||
connectCount++;
|
||||
})
|
||||
|
||||
var request = client.request("GET", "/", headers);
|
||||
request.end();
|
||||
request.addListener('response', function (response) {
|
||||
common.error('response start');
|
||||
|
||||
|
||||
response.addListener("end", function () {
|
||||
common.error('response end');
|
||||
var req = client.request("GET", "/", headers);
|
||||
req.addListener('response', function (response) {
|
||||
response.addListener("end", function () {
|
||||
client.end();
|
||||
server.close();
|
||||
})
|
||||
})
|
||||
req.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
process.addListener('exit', function () {
|
||||
assert.equal(2, connectCount);
|
||||
});
|
||||
@@ -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++;
|
||||
|
||||
@@ -27,7 +27,13 @@ var caPem = fs.readFileSync(common.fixturesDir+"/test_ca.pem", 'ascii');
|
||||
var certPem = fs.readFileSync(common.fixturesDir+"/test_cert.pem", 'ascii');
|
||||
var keyPem = fs.readFileSync(common.fixturesDir+"/test_key.pem", 'ascii');
|
||||
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
try{
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
} catch (e) {
|
||||
console.log("Not compiled with OPENSSL support.");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
|
||||
var https_server = http.createServer(function (req, res) {
|
||||
res.id = request_number;
|
||||
@@ -41,7 +47,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 +99,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;
|
||||
});
|
||||
|
||||
@@ -8,48 +8,21 @@ assert = common.assert
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
// Parse a string of data, returning an object if headers are complete, and
|
||||
// undefined otherwise
|
||||
var parseHeaders = function(data) {
|
||||
var m = data.search(/\r\n\r\n/);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
var o = {};
|
||||
data.substring(0, m.index).split('\r\n').forEach(function(h) {
|
||||
var foo = h.split(':');
|
||||
if (foo.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
o[foo[0].trim().toLowerCase()] = foo[1].trim().toLowerCase();
|
||||
});
|
||||
|
||||
return o;
|
||||
};
|
||||
|
||||
// Create a TCP server
|
||||
var srv = net.createServer(function(c) {
|
||||
var data = '';
|
||||
c.addListener('data', function(d) {
|
||||
data += d.toString('utf8');
|
||||
|
||||
// We found the end of the headers; make sure that we have an 'upgrade'
|
||||
// header and send back a response
|
||||
var headers = parseHeaders(data);
|
||||
if (!headers) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert.ok('upgrade' in headers);
|
||||
|
||||
c.write('HTTP/1.1 101\r\n');
|
||||
c.write('hello: world\r\n');
|
||||
c.write('connection: upgrade\r\n');
|
||||
c.write('upgrade: ' + headers.upgrade + '\r\n');
|
||||
c.write('upgrade: websocket\r\n');
|
||||
c.write('\r\n');
|
||||
c.write('nurtzo');
|
||||
});
|
||||
|
||||
c.addListener('end', function() {
|
||||
c.end();
|
||||
});
|
||||
});
|
||||
@@ -57,20 +30,24 @@ srv.listen(common.PORT, '127.0.0.1');
|
||||
|
||||
var gotUpgrade = false;
|
||||
var hc = http.createClient(common.PORT, '127.0.0.1');
|
||||
hc.addListener('upgrade', function(req, socket, upgradeHead) {
|
||||
hc.addListener('upgrade', function(res, socket, upgradeHead) {
|
||||
// XXX: This test isn't fantastic, as it assumes that the entire response
|
||||
// from the server will arrive in a single data callback
|
||||
assert.equal(upgradeHead, 'nurtzo');
|
||||
|
||||
console.log(res.headers);
|
||||
var expectedHeaders = { "hello": "world"
|
||||
, "connection": "upgrade"
|
||||
, "upgrade": "websocket"
|
||||
};
|
||||
assert.deepEqual(expectedHeaders, res.headers);
|
||||
|
||||
socket.end();
|
||||
srv.close();
|
||||
|
||||
gotUpgrade = true;
|
||||
});
|
||||
hc.request('/', {
|
||||
'Connection' : 'Upgrade',
|
||||
'Upgrade' : 'WebSocket'
|
||||
}).end();
|
||||
hc.request('GET', '/').end();
|
||||
|
||||
process.addListener('exit', function() {
|
||||
assert.ok(gotUpgrade);
|
||||
|
||||
64
test/simple/test-http-upgrade-client2.js
Normal file
64
test/simple/test-http-upgrade-client2.js
Normal file
@@ -0,0 +1,64 @@
|
||||
var common = require("../common");
|
||||
var assert = common.assert
|
||||
var http = require('http'),
|
||||
CRLF = '\r\n';
|
||||
|
||||
var server = http.createServer();
|
||||
server.on('upgrade', function(req, socket, head) {
|
||||
socket.write('HTTP/1.1 101 Ok' + CRLF +
|
||||
'Connection: Upgrade' + CRLF +
|
||||
'Upgrade: Test' + CRLF + CRLF + 'head');
|
||||
socket.on('end', function () {
|
||||
socket.end();
|
||||
});
|
||||
});
|
||||
server.listen(8000);
|
||||
|
||||
var client = http.createClient(8000);
|
||||
|
||||
function upgradeRequest(fn) {
|
||||
var request = client.request('GET', '/', {
|
||||
'Connection': 'Upgrade',
|
||||
'Upgrade': 'Test'
|
||||
});
|
||||
|
||||
var wasUpgrade = false;
|
||||
|
||||
function onUpgrade(res, socket, head) {
|
||||
wasUpgrade = true;
|
||||
|
||||
client.removeListener('upgrade', onUpgrade);
|
||||
socket.end();
|
||||
}
|
||||
client.on('upgrade', onUpgrade);
|
||||
|
||||
function onEnd() {
|
||||
client.removeListener('end', onEnd);
|
||||
if (!wasUpgrade) {
|
||||
throw new Error('hasn\'t received upgrade event');
|
||||
} else {
|
||||
fn && process.nextTick(fn);
|
||||
}
|
||||
}
|
||||
client.on('end', onEnd);
|
||||
|
||||
request.write('head');
|
||||
|
||||
}
|
||||
|
||||
successCount = 0;
|
||||
upgradeRequest(function() {
|
||||
successCount++;
|
||||
upgradeRequest(function() {
|
||||
successCount++;
|
||||
// Test pass
|
||||
console.log('Pass!');
|
||||
client.end();
|
||||
client.destroy();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function () {
|
||||
assert.equal(2, successCount);
|
||||
});
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -18,7 +18,12 @@ var caPem = fs.readFileSync(common.fixturesDir+"/test_ca.pem", 'ascii');
|
||||
var certPem = fs.readFileSync(common.fixturesDir+"/test_cert.pem", 'ascii');
|
||||
var keyPem = fs.readFileSync(common.fixturesDir+"/test_key.pem", 'ascii');
|
||||
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
try{
|
||||
var credentials = crypto.createCredentials({key:keyPem, cert:certPem, ca:caPem});
|
||||
} catch (e) {
|
||||
console.log("Not compiled with OPENSSL support.");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
var testData = "TEST123";
|
||||
var serverData = '';
|
||||
@@ -41,7 +46,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 +82,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();
|
||||
@@ -94,4 +101,4 @@ secureServer.addListener("listening", function() {
|
||||
process.addListener("exit", function () {
|
||||
assert.ok(gotSecureServer, "Did not get secure event for server");
|
||||
assert.ok(gotSecureClient, "Did not get secure event for clientr");
|
||||
});
|
||||
});
|
||||
|
||||
36
test/simple/test-next-tick-errors.js
Normal file
36
test/simple/test-next-tick-errors.js
Normal 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);
|
||||
});
|
||||
|
||||
17
test/simple/test-next-tick-ordering2.js
Normal file
17
test/simple/test-next-tick-ordering2.js
Normal 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']);
|
||||
});
|
||||
52
test/simple/test-pump-file2tcp-noexist.js
Normal file
52
test/simple/test-pump-file2tcp-noexist.js
Normal file
@@ -0,0 +1,52 @@
|
||||
common = require("../common");
|
||||
assert = common.assert
|
||||
net = require("net");
|
||||
fs = require("fs");
|
||||
sys = require("sys");
|
||||
path = require("path");
|
||||
fn = path.join(common.fixturesDir, 'does_not_exist.txt');
|
||||
|
||||
var got_error = false;
|
||||
var conn_closed = false;
|
||||
|
||||
server = net.createServer(function (stream) {
|
||||
common.error('pump!');
|
||||
sys.pump(fs.createReadStream(fn), stream, function (err) {
|
||||
common.error("sys.pump's callback fired");
|
||||
if (err) {
|
||||
got_error = true;
|
||||
} else {
|
||||
common.debug("sys.pump's callback fired with no error");
|
||||
common.debug("this shouldn't happen as the file doesn't exist...");
|
||||
assert.equal(true, false);
|
||||
}
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(common.PORT, function () {
|
||||
conn = net.createConnection(common.PORT);
|
||||
conn.setEncoding('utf8');
|
||||
conn.addListener("data", function (chunk) {
|
||||
common.error('recv data! nchars = ' + chunk.length);
|
||||
buffer += chunk;
|
||||
});
|
||||
|
||||
conn.addListener("end", function () {
|
||||
conn.end();
|
||||
});
|
||||
|
||||
conn.addListener("close", function () {
|
||||
common.error('client connection close');
|
||||
conn_closed = true;
|
||||
});
|
||||
});
|
||||
|
||||
var buffer = '';
|
||||
count = 0;
|
||||
|
||||
process.addListener('exit', function () {
|
||||
assert.equal(true, got_error);
|
||||
assert.equal(true, conn_closed);
|
||||
console.log("exiting");
|
||||
});
|
||||
108
test/simple/test-readline.js
Normal file
108
test/simple/test-readline.js
Normal 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);
|
||||
@@ -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);
|
||||
|
||||
@@ -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:",
|
||||
|
||||
41
test/simple/test-zerolengthbufferbug.js
Normal file
41
test/simple/test-zerolengthbufferbug.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// Serving up a zero-length buffer should work.
|
||||
|
||||
var common = require("../common");
|
||||
var assert = common.assert;
|
||||
var http = require('http');
|
||||
|
||||
var server = http.createServer(function (req, res) {
|
||||
var buffer = new Buffer(0);
|
||||
res.writeHead(200, {'Content-Type': 'text/html',
|
||||
'Content-Length': buffer.length});
|
||||
res.end(buffer);
|
||||
});
|
||||
|
||||
var gotResponse = false;
|
||||
var resBodySize = 0;
|
||||
|
||||
server.listen(common.PORT, function () {
|
||||
var client = http.createClient(common.PORT);
|
||||
|
||||
var req = client.request('GET', '/');
|
||||
req.end();
|
||||
|
||||
req.on('response', function (res) {
|
||||
gotResponse = true;
|
||||
|
||||
res.on('data', function (d) {
|
||||
resBodySize += d.length;
|
||||
});
|
||||
|
||||
res.on('end', function (d) {
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function () {
|
||||
assert.ok(gotResponse);
|
||||
assert.equal(0, resBodySize);
|
||||
});
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
58
wscript
58
wscript
@@ -18,12 +18,7 @@ blddir = 'build'
|
||||
jobs=1
|
||||
if os.environ.has_key('JOBS'):
|
||||
jobs = int(os.environ['JOBS'])
|
||||
else:
|
||||
try:
|
||||
import multiprocessing
|
||||
jobs = multiprocessing.cpu_count()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def set_options(opt):
|
||||
# the gcc module provides a --debug-level option
|
||||
@@ -162,18 +157,19 @@ 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',
|
||||
args='--cflags --libs',
|
||||
uselib_store='OPENSSL'):
|
||||
Options.options.use_openssl = conf.env["USE_OPENSSL"] = True
|
||||
conf.env.append_value("CXXFLAGS", "-DHAVE_OPENSSL=1")
|
||||
conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
|
||||
else:
|
||||
libssl = conf.check_cc(lib='ssl',
|
||||
header_name='openssl/ssl.h',
|
||||
@@ -185,7 +181,13 @@ def configure(conf):
|
||||
uselib_store='OPENSSL')
|
||||
if libcrypto and libssl:
|
||||
conf.env["USE_OPENSSL"] = Options.options.use_openssl = True
|
||||
conf.env.append_value("CXXFLAGS", "-DHAVE_OPENSSL=1")
|
||||
conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
|
||||
else:
|
||||
conf.fatal("Could not autodetect OpenSSL support. " +
|
||||
"Make sure OpenSSL development packages are installed. " +
|
||||
"Use configure --without-ssl to disable this message.")
|
||||
else:
|
||||
Options.options.use_openssl = conf.env["USE_OPENSSL"] = False
|
||||
|
||||
conf.check(lib='rt', uselib_store='RT')
|
||||
|
||||
@@ -264,13 +266,11 @@ def configure(conf):
|
||||
# used by platform_darwin_*.cc
|
||||
conf.env.append_value('LINKFLAGS', ['-framework','Carbon'])
|
||||
|
||||
conf.env.append_value("CCFLAGS", "-DX_STACKSIZE=%d" % (1024*64))
|
||||
|
||||
# Needed for getaddrinfo in libeio
|
||||
conf.env.append_value("CPPFLAGS", "-DX_STACKSIZE=%d" % (1024*64))
|
||||
# LFS
|
||||
conf.env.append_value('CCFLAGS', '-D_LARGEFILE_SOURCE')
|
||||
conf.env.append_value('CXXFLAGS', '-D_LARGEFILE_SOURCE')
|
||||
conf.env.append_value('CCFLAGS', '-D_FILE_OFFSET_BITS=64')
|
||||
conf.env.append_value('CXXFLAGS', '-D_FILE_OFFSET_BITS=64')
|
||||
conf.env.append_value('CPPFLAGS', '-D_LARGEFILE_SOURCE')
|
||||
conf.env.append_value('CPPFLAGS', '-D_FILE_OFFSET_BITS=64')
|
||||
|
||||
## needed for node_file.cc fdatasync
|
||||
## Strangely on OSX 10.6 the g++ doesn't see fdatasync but gcc does?
|
||||
@@ -284,14 +284,12 @@ def configure(conf):
|
||||
}
|
||||
"""
|
||||
if conf.check_cxx(msg="Checking for fdatasync(2) with c++", fragment=code):
|
||||
conf.env.append_value('CXXFLAGS', '-DHAVE_FDATASYNC=1')
|
||||
conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=1')
|
||||
else:
|
||||
conf.env.append_value('CXXFLAGS', '-DHAVE_FDATASYNC=0')
|
||||
conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=0')
|
||||
|
||||
# platform
|
||||
platform_def = '-DPLATFORM="' + conf.env['DEST_OS'] + '"'
|
||||
conf.env.append_value('CCFLAGS', platform_def)
|
||||
conf.env.append_value('CXXFLAGS', platform_def)
|
||||
conf.env.append_value('CPPFLAGS', '-DPLATFORM="' + conf.env['DEST_OS'] + '"')
|
||||
|
||||
# Split off debug variant before adding variant specific defines
|
||||
debug_env = conf.env.copy()
|
||||
@@ -300,14 +298,18 @@ def configure(conf):
|
||||
# Configure debug variant
|
||||
conf.setenv('debug')
|
||||
debug_env.set_variant('debug')
|
||||
debug_env.append_value('CCFLAGS', ['-DDEBUG', '-g', '-O0', '-Wall', '-Wextra'])
|
||||
debug_env.append_value('CXXFLAGS', ['-DDEBUG', '-g', '-O0', '-Wall', '-Wextra'])
|
||||
debug_env.append_value('CPPFLAGS', '-DDEBUG')
|
||||
debug_compile_flags = ['-g', '-O0', '-Wall', '-Wextra']
|
||||
debug_env.append_value('CCFLAGS', debug_compile_flags)
|
||||
debug_env.append_value('CXXFLAGS', debug_compile_flags)
|
||||
conf.write_config_header("config.h")
|
||||
|
||||
# Configure default variant
|
||||
conf.setenv('default')
|
||||
conf.env.append_value('CCFLAGS', ['-DNDEBUG', '-g', '-O3'])
|
||||
conf.env.append_value('CXXFLAGS', ['-DNDEBUG', '-g', '-O3'])
|
||||
conf.env.append_value('CPPFLAGS', '-DNDEBUG')
|
||||
default_compile_flags = ['-g', '-O3']
|
||||
conf.env.append_value('CCFLAGS', default_compile_flags)
|
||||
conf.env.append_value('CXXFLAGS', default_compile_flags)
|
||||
conf.write_config_header("config.h")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user