mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
428a670121 | ||
|
|
f7bc7fb031 | ||
|
|
d3e6834297 | ||
|
|
a958ebfca0 | ||
|
|
78afb12663 | ||
|
|
ad4fb5319b | ||
|
|
1e932ea930 | ||
|
|
ddb06cb552 | ||
|
|
60b5bcac0c | ||
|
|
46eda290be | ||
|
|
c19897b76a | ||
|
|
8ec4870611 | ||
|
|
8fb9cd2575 | ||
|
|
006e283b78 | ||
|
|
bdd82b7c5f | ||
|
|
9f25dc1625 | ||
|
|
511f80b3c8 | ||
|
|
13dba0d1c1 | ||
|
|
97e3040202 | ||
|
|
78fac9b863 | ||
|
|
969ee3dd83 | ||
|
|
39a2a9d1b6 | ||
|
|
08f1bf42bb | ||
|
|
18ff6db648 | ||
|
|
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 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,3 +12,5 @@ test/fixtures/hello.txt
|
||||
tmp/
|
||||
node
|
||||
node_g
|
||||
*.swp
|
||||
.benchmark_reports
|
||||
|
||||
13
AUTHORS
13
AUTHORS
@@ -109,8 +109,21 @@ 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>
|
||||
Joshua Peek <josh@joshpeek.com>
|
||||
Nathan Rajlich <nathan@tootallnate.net>
|
||||
Tom Hughes <tom.hughes@palm.com>
|
||||
Vitali Lovich <vitali.lovich@palm.com>
|
||||
|
||||
83
ChangeLog
83
ChangeLog
@@ -1,4 +1,79 @@
|
||||
2010.08.20, Version 0.2.0
|
||||
2010.10.24, Version 0.2.4
|
||||
|
||||
* Add --eval to command line options (TJ Holowaychuk)
|
||||
|
||||
* net fixes
|
||||
- TCP clients buffer writes before connection
|
||||
- Don't flush net writeQueue on end() if its still connecting
|
||||
(Joshua Peek)
|
||||
- Do not spin on aceept() with EMFILE
|
||||
|
||||
* Add --max-stack-size flag. (Tom Hughes)
|
||||
|
||||
* Fixes to child_process.exec (timeouts and proper termination)
|
||||
Default to SIGTERM instead of SIGKILL.
|
||||
|
||||
* Add signal handlers so we clean up before exiting. (Tom Hughes)
|
||||
|
||||
* Fix parsing of linux memory (Vitali Lovich)
|
||||
|
||||
* http-parser: Allow whitespace in the 'Content-Length' header.
|
||||
(Nathan Rajlich)
|
||||
|
||||
* Add flag to disable colors in REPL
|
||||
|
||||
2010.10.02, Version 0.2.3, dc103ae020ecd6182aa2adb482ac72ea944130ee
|
||||
|
||||
* 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 +191,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 +297,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 +317,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
|
||||
|
||||
14
Makefile
14
Makefile
@@ -36,9 +36,6 @@ test-pummel: all
|
||||
test-internet: all
|
||||
python tools/test.py internet
|
||||
|
||||
benchmark: all
|
||||
build/default/node benchmark/run.js
|
||||
|
||||
# http://rtomayko.github.com/ronn
|
||||
# gem install ronn
|
||||
doc: doc/node.1 doc/api.html doc/index.html doc/changelog.html
|
||||
@@ -85,4 +82,13 @@ dist: doc/node.1 doc/api.html
|
||||
rm -rf $(TARNAME)
|
||||
gzip -f -9 $(TARNAME).tar
|
||||
|
||||
.PHONY: benchmark clean docclean dist distclean check uninstall install all test test-all website-upload
|
||||
bench:
|
||||
benchmark/http_simple_bench.sh
|
||||
|
||||
bench-idle:
|
||||
./node benchmark/idle_server.js &
|
||||
sleep 1
|
||||
./node benchmark/idle_clients.js &
|
||||
|
||||
|
||||
.PHONY: bench clean docclean dist distclean check uninstall install all test test-all website-upload
|
||||
|
||||
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'
|
||||
@@ -1,24 +1,40 @@
|
||||
path = require("path");
|
||||
Buffer = require("buffer").Buffer;
|
||||
exec = require("child_process").exec;
|
||||
http = require("http");
|
||||
|
||||
port = parseInt(process.env.PORT || 8000);
|
||||
|
||||
var old = (process.argv[2] == 'old');
|
||||
|
||||
console.log('pid ' + process.pid);
|
||||
|
||||
http = require(old ? "http_old" : 'http');
|
||||
if (old) console.log('old version');
|
||||
|
||||
fixed = ""
|
||||
for (var i = 0; i < 20*1024; i++) {
|
||||
fixed += "C";
|
||||
}
|
||||
|
||||
var uname, rev;
|
||||
|
||||
exec('git rev-list -1 HEAD', function (e, stdout) {
|
||||
if (e) {
|
||||
console.error("Problem executing: 'git rev-list -1 HEAD'");
|
||||
throw new Error(e);
|
||||
}
|
||||
rev = stdout.replace(/\s/g, '');
|
||||
});
|
||||
|
||||
exec('uname -a', function (e, stdout) {
|
||||
if (e) {
|
||||
console.error("Problem executing: 'uname -a'");
|
||||
throw new Error(e);
|
||||
}
|
||||
uname = stdout.replace(/[\r\n]/g, '');
|
||||
});
|
||||
|
||||
|
||||
|
||||
stored = {};
|
||||
storedBuffer = {};
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
var server = http.createServer(function (req, res) {
|
||||
var commands = req.url.split("/");
|
||||
var command = commands[1];
|
||||
var body = "";
|
||||
@@ -57,6 +73,9 @@ http.createServer(function (req, res) {
|
||||
} else if (command == "fixed") {
|
||||
body = fixed;
|
||||
|
||||
} else if (command == "info") {
|
||||
body = 'rev=' + rev + '\nuname="' + uname + '"\n';
|
||||
|
||||
} else {
|
||||
status = 404;
|
||||
body = "not found\n";
|
||||
@@ -64,17 +83,13 @@ http.createServer(function (req, res) {
|
||||
|
||||
var content_length = body.length.toString();
|
||||
|
||||
res.writeHead( status
|
||||
, { "Content-Type": "text/plain"
|
||||
, "Content-Length": content_length
|
||||
}
|
||||
);
|
||||
if (old) {
|
||||
res.write(body, 'ascii');
|
||||
res.close();
|
||||
} else {
|
||||
res.end(body, 'ascii');
|
||||
}
|
||||
}).listen(port);
|
||||
res.writeHead(status, { "Content-Type": "text/plain",
|
||||
"Content-Length": content_length });
|
||||
res.end(body);
|
||||
|
||||
});
|
||||
|
||||
server.listen(port, function () {
|
||||
console.log('Listening at http://127.0.0.1:'+port+'/');
|
||||
});
|
||||
|
||||
console.log('Listening at http://127.0.0.1:'+port+'/');
|
||||
|
||||
77
benchmark/http_simple_bench.sh
Executable file
77
benchmark/http_simple_bench.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
|
||||
SERVER=127.0.0.1
|
||||
PORT=8000
|
||||
|
||||
# You may want to configure your TCP settings to make many ports available
|
||||
# to node and ab. On macintosh use:
|
||||
# sudo sysctl -w net.inet.ip.portrange.first=32768
|
||||
# sudo sysctl -w net.inet.tcp.msl=1000
|
||||
|
||||
if [ ! -d benchmark/ ]; then
|
||||
echo "Run this script from the node root directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $SERVER == "127.0.0.1" ]; then
|
||||
./node benchmark/http_simple.js &
|
||||
node_pid=$!
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
info=`curl -s http://$SERVER:$PORT/info`
|
||||
eval $info
|
||||
|
||||
date=`date "+%Y%m%d%H%M%S"`
|
||||
|
||||
ab_hello_world() {
|
||||
local type="$1"
|
||||
local ressize="$2"
|
||||
if [ $type == "string" ]; then
|
||||
local uri="bytes/$ressize"
|
||||
else
|
||||
local uri="buffer/$ressize"
|
||||
fi
|
||||
|
||||
|
||||
name="ab-hello-world-$type-$ressize"
|
||||
|
||||
dir=".benchmark_reports/$name/$rev/"
|
||||
if [ ! -d $dir ]; then
|
||||
mkdir -p $dir
|
||||
fi
|
||||
|
||||
summary_fn="$dir/$date.summary"
|
||||
data_fn="$dir/$date.data"
|
||||
|
||||
echo "Bench $name starts in 3 seconds..."
|
||||
# let shit calm down
|
||||
sleep 3
|
||||
|
||||
# hammer that as hard as it can for 10 seconds.
|
||||
ab -g $data_fn -c 100 -t 10 http://$SERVER:$PORT/$uri > $summary_fn
|
||||
|
||||
# add our data about the server
|
||||
echo >> $summary_fn
|
||||
echo >> $summary_fn
|
||||
echo "webserver-rev: $rev" >> $summary_fn
|
||||
echo "webserver-uname: $uname" >> $summary_fn
|
||||
|
||||
grep Req $summary_fn
|
||||
|
||||
echo "Summary: $summary_fn"
|
||||
echo
|
||||
}
|
||||
|
||||
# 1k
|
||||
ab_hello_world 'string' '1024'
|
||||
ab_hello_world 'buffer' '1024'
|
||||
|
||||
# 100k
|
||||
ab_hello_world 'string' '102400'
|
||||
ab_hello_world 'buffer' '102400'
|
||||
|
||||
|
||||
if [ ! -z $node_pid ]; then
|
||||
kill -9 $node_pid
|
||||
fi
|
||||
50
benchmark/idle_clients.js
Normal file
50
benchmark/idle_clients.js
Normal file
@@ -0,0 +1,50 @@
|
||||
net = require('net');
|
||||
|
||||
var errors = 0, connections = 0;
|
||||
|
||||
function connect () {
|
||||
process.nextTick(function () {
|
||||
var s = net.Stream();
|
||||
var gotConnected = false;
|
||||
s.connect(9000);
|
||||
s.on('connect', function () {
|
||||
gotConnected = true;
|
||||
connections++;
|
||||
connect();
|
||||
});
|
||||
|
||||
var haderror = false;
|
||||
|
||||
s.on('close', function () {
|
||||
if (gotConnected) connections--;
|
||||
if (!haderror) connect();
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
s.end();
|
||||
});
|
||||
|
||||
s.on('error', function () {
|
||||
haderror = true;
|
||||
errors++;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
connect();
|
||||
|
||||
|
||||
var oldConnections, oldErrors;
|
||||
|
||||
setInterval(function () {
|
||||
if (oldConnections != connections) {
|
||||
oldConnections = connections;
|
||||
console.log("CLIENT %d connections: %d", process.pid, connections);
|
||||
}
|
||||
|
||||
if (oldErrors != errors) {
|
||||
oldErrors = errors;
|
||||
console.log("CLIENT %d errors: %d", process.pid, errors);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
33
benchmark/idle_server.js
Normal file
33
benchmark/idle_server.js
Normal file
@@ -0,0 +1,33 @@
|
||||
net = require('net');
|
||||
connections = 0;
|
||||
|
||||
var errors = 0;
|
||||
|
||||
server = net.Server(function (socket) {
|
||||
|
||||
socket.on('end', function () {
|
||||
socket.end();
|
||||
});
|
||||
|
||||
socket.on('error', function () {
|
||||
errors++;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
server.listen(9000);
|
||||
|
||||
var oldConnections, oldErrors;
|
||||
|
||||
setInterval(function () {
|
||||
if (oldConnections != server.connections) {
|
||||
oldConnections = server.connections;
|
||||
console.log("SERVER %d connections: %d", process.pid, server.connections);
|
||||
}
|
||||
|
||||
if (oldErrors != errors) {
|
||||
oldErrors = errors;
|
||||
console.log("SERVER %d errors: %d", process.pid, errors);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
1
deps/http_parser/http_parser.c
vendored
1
deps/http_parser/http_parser.c
vendored
@@ -1264,6 +1264,7 @@ size_t http_parser_execute (http_parser *parser,
|
||||
break;
|
||||
|
||||
case h_content_length:
|
||||
if (ch == ' ') break;
|
||||
if (ch < '0' || ch > '9') goto error;
|
||||
parser->content_length *= 10;
|
||||
parser->content_length += ch - '0';
|
||||
|
||||
@@ -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
|
||||
@@ -911,9 +912,6 @@ normally, `code` is the final exit code of the process, otherwise `null`. If
|
||||
the process terminated due to receipt of a signal, `signal` is the string name
|
||||
of the signal, otherwise `null`.
|
||||
|
||||
After this event is emitted, the `'output'` and `'error'` callbacks will no
|
||||
longer be made.
|
||||
|
||||
See `waitpid(2)`.
|
||||
|
||||
### child.stdin
|
||||
@@ -1057,14 +1055,14 @@ There is a second optional argument to specify several options. The default opti
|
||||
{ encoding: 'utf8'
|
||||
, timeout: 0
|
||||
, maxBuffer: 200*1024
|
||||
, killSignal: 'SIGKILL'
|
||||
, killSignal: 'SIGTERM'
|
||||
, cwd: null
|
||||
, env: null
|
||||
}
|
||||
|
||||
If `timeout` is greater than 0, then it will kill the child process
|
||||
if it runs longer than `timeout` milliseconds. The child process is killed with
|
||||
`killSignal` (default: `'SIGKILL'`). `maxBuffer` specifies the largest
|
||||
`killSignal` (default: `'SIGTERM'`). `maxBuffer` specifies the largest
|
||||
amount of data allowed on stdout or stderr - if this value is exceeded then
|
||||
the child process is killed.
|
||||
|
||||
@@ -1447,19 +1445,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 +1468,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 +1579,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 +2203,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 +2292,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 +3262,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.4</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,13 @@ 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>
|
||||
Stable: 2010.10.24
|
||||
<a href="http://nodejs.org/dist/node-v0.2.4.tar.gz">node-v0.2.4.tar.gz</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unstable: 2010.10.23
|
||||
<a href="http://nodejs.org/dist/node-v0.3.0.tar.gz">node-v0.3.0.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) {
|
||||
|
||||
@@ -27,7 +27,7 @@ exports.execFile = function (file /* args, options, callback */) {
|
||||
var options = { encoding: 'utf8'
|
||||
, timeout: 0
|
||||
, maxBuffer: 200*1024
|
||||
, killSignal: 'SIGKILL'
|
||||
, killSignal: 'SIGTERM'
|
||||
, cwd: null
|
||||
, env: null
|
||||
};
|
||||
@@ -60,15 +60,43 @@ exports.execFile = function (file /* args, options, callback */) {
|
||||
var stdout = "";
|
||||
var stderr = "";
|
||||
var killed = false;
|
||||
|
||||
var exited = false;
|
||||
var timeoutId;
|
||||
|
||||
function exithandler (code, signal) {
|
||||
if (exited) return;
|
||||
exited = true;
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
|
||||
if (!callback) return;
|
||||
|
||||
if (code === 0 && signal === null) {
|
||||
callback(null, stdout, stderr);
|
||||
} else {
|
||||
var e = new Error("Command failed: " + stderr);
|
||||
e.killed = child.killed || killed;
|
||||
e.code = code;
|
||||
e.signal = signal;
|
||||
callback(e, stdout, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
function kill () {
|
||||
killed = true;
|
||||
child.kill(options.killSignal);
|
||||
process.nextTick(function () {
|
||||
exithandler(null, options.killSignal)
|
||||
});
|
||||
}
|
||||
|
||||
if (options.timeout > 0) {
|
||||
timeoutId = setTimeout(function () {
|
||||
if (!killed) {
|
||||
child.kill(options.killSignal);
|
||||
killed = true;
|
||||
timeoutId = null;
|
||||
}
|
||||
kill();
|
||||
timeoutId = null;
|
||||
}, options.timeout);
|
||||
}
|
||||
|
||||
@@ -77,32 +105,19 @@ exports.execFile = function (file /* args, options, callback */) {
|
||||
|
||||
child.stdout.addListener("data", function (chunk) {
|
||||
stdout += chunk;
|
||||
if (!killed && stdout.length > options.maxBuffer) {
|
||||
child.kill(options.killSignal);
|
||||
killed = true;
|
||||
if (stdout.length > options.maxBuffer) {
|
||||
kill();
|
||||
}
|
||||
});
|
||||
|
||||
child.stderr.addListener("data", function (chunk) {
|
||||
stderr += chunk;
|
||||
if (!killed && stderr.length > options.maxBuffer) {
|
||||
child.kill(options.killSignal);
|
||||
killed = true
|
||||
if (stderr.length > options.maxBuffer) {
|
||||
kill();
|
||||
}
|
||||
});
|
||||
|
||||
child.addListener("exit", function (code, signal) {
|
||||
if (timeoutId) clearTimeout(timeoutId);
|
||||
if (code === 0 && signal === null) {
|
||||
if (callback) callback(null, stdout, stderr);
|
||||
} else {
|
||||
var e = new Error("Command failed: " + stderr);
|
||||
e.killed = killed;
|
||||
e.code = code;
|
||||
e.signal = signal;
|
||||
if (callback) callback(e, stdout, stderr);
|
||||
}
|
||||
});
|
||||
child.addListener("exit", exithandler);
|
||||
|
||||
return child;
|
||||
};
|
||||
@@ -113,6 +128,8 @@ function ChildProcess () {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.killed = false;
|
||||
|
||||
var gotCHLD = false;
|
||||
var exitCode;
|
||||
var termSignal;
|
||||
@@ -158,7 +175,11 @@ inherits(ChildProcess, EventEmitter);
|
||||
|
||||
|
||||
ChildProcess.prototype.kill = function (sig) {
|
||||
return this._internal.kill(sig);
|
||||
if (this._internal.pid) {
|
||||
this.killed = true;
|
||||
sig = sig || 'SIGTERM';
|
||||
return this._internal.kill(sig);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
74
lib/net.js
74
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;
|
||||
@@ -637,13 +638,20 @@ Object.defineProperty(Stream.prototype, 'readyState', {
|
||||
// something was queued. If data was queued, then the "drain" event will
|
||||
// signal when it has been finally flushed to socket.
|
||||
Stream.prototype.write = function (data, encoding, fd) {
|
||||
if (this._writeQueue && this._writeQueue.length) {
|
||||
if (this._connecting || (this._writeQueue && this._writeQueue.length)) {
|
||||
if (!this._writeQueue) {
|
||||
this._writeQueue = [];
|
||||
this._writeQueueEncoding = [];
|
||||
this._writeQueueFD = [];
|
||||
}
|
||||
|
||||
// Slow. There is already a write queue, so let's append to it.
|
||||
if (this._writeQueueLast() === END_OF_FILE) {
|
||||
throw new Error('Stream.end() called already; cannot write.');
|
||||
}
|
||||
|
||||
if (typeof data == 'string' &&
|
||||
this._writeQueueEncoding.length &&
|
||||
this._writeQueueEncoding[this._writeQueueEncoding.length-1] === encoding) {
|
||||
// optimization - concat onto last
|
||||
this._writeQueue[this._writeQueue.length-1] += data;
|
||||
@@ -849,13 +857,21 @@ function doConnect (socket, port, host) {
|
||||
socket.destroy(e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (socket._writeQueue && socket._writeQueue.length) {
|
||||
// Flush socket in case any writes are queued up while connecting.
|
||||
// ugly
|
||||
_doFlush.call(socket._writeWatcher);
|
||||
}
|
||||
|
||||
} else if (errno != EINPROGRESS) {
|
||||
socket.destroy(errnoException(errno, 'connect'));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function isPort (x) { return parseInt(x) >= 0; }
|
||||
function toPort (x) { return (x = Number(x)) >= 0 ? x : false }
|
||||
|
||||
|
||||
// var stream = new Stream();
|
||||
@@ -871,10 +887,18 @@ Stream.prototype.connect = function () {
|
||||
timeout.active(socket);
|
||||
|
||||
self._connecting = true; // set false in doConnect
|
||||
self.writable = true;
|
||||
|
||||
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 +908,6 @@ Stream.prototype.connect = function () {
|
||||
doConnect(self, port, ip);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// UNIX
|
||||
self.fd = socket('unix');
|
||||
self.type = 'unix';
|
||||
|
||||
setImplmentationMethods(this);
|
||||
doConnect(self, arguments[0]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1025,13 +1042,16 @@ Stream.prototype.end = function (data, encoding) {
|
||||
if (data) this.write(data, encoding);
|
||||
if (this._writeQueueLast() !== END_OF_FILE) {
|
||||
this._writeQueue.push(END_OF_FILE);
|
||||
this.flush();
|
||||
if (!this._connecting) {
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function Server (listener) {
|
||||
if (!(this instanceof Server)) return new Server(listener);
|
||||
events.EventEmitter.call(this);
|
||||
var self = this;
|
||||
|
||||
@@ -1041,6 +1061,25 @@ function Server (listener) {
|
||||
|
||||
self.connections = 0;
|
||||
|
||||
self.paused = false;
|
||||
self.pauseTimeout = 1000;
|
||||
|
||||
function pause () {
|
||||
// We've hit the maximum file limit. What to do?
|
||||
// Let's try again in 1 second.
|
||||
self.watcher.stop();
|
||||
|
||||
// If we're already paused, don't do another timeout.
|
||||
if (self.paused) return;
|
||||
|
||||
setTimeout(function () {
|
||||
self.paused = false;
|
||||
// Make sure we haven't closed in the interim
|
||||
if (typeof self.fd != 'number') return;
|
||||
self.watcher.start();
|
||||
}, self.pauseTimeout);
|
||||
}
|
||||
|
||||
self.watcher = new IOWatcher();
|
||||
self.watcher.host = self;
|
||||
self.watcher.callback = function () {
|
||||
@@ -1048,7 +1087,10 @@ function Server (listener) {
|
||||
try {
|
||||
var peerInfo = accept(self.fd);
|
||||
} catch (e) {
|
||||
if (e.errno == EMFILE) return;
|
||||
if (e.errno == EMFILE) {
|
||||
pause();
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
if (!peerInfo) return;
|
||||
@@ -1107,7 +1149,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 +1185,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;
|
||||
|
||||
|
||||
31
lib/repl.js
31
lib/repl.js
@@ -20,6 +20,8 @@ var fs = require("fs");
|
||||
var rl = require('readline');
|
||||
var context;
|
||||
|
||||
var disableColors = process.env.NODE_DISABLE_COLORS ? true : false;
|
||||
|
||||
function cwdRequire (id) {
|
||||
if (id.match(/^\.\.\//) || id.match(/^\.\//)) {
|
||||
id = path.join(process.cwd(), id);
|
||||
@@ -48,13 +50,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 && !disableColors) {
|
||||
// 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 +150,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 +320,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 +401,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 +416,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;
|
||||
|
||||
127
src/node.cc
127
src/node.cc
@@ -49,7 +49,12 @@
|
||||
|
||||
using namespace v8;
|
||||
|
||||
# ifdef __APPLE__
|
||||
# include <crt_externs.h>
|
||||
# define environ (*_NSGetEnviron())
|
||||
# else
|
||||
extern char **environ;
|
||||
# endif
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -68,12 +73,16 @@ static Persistent<String> listeners_symbol;
|
||||
static Persistent<String> uncaught_exception_symbol;
|
||||
static Persistent<String> emit_symbol;
|
||||
|
||||
|
||||
static char *eval_string = NULL;
|
||||
static int option_end_index = 0;
|
||||
static bool use_debug_agent = false;
|
||||
static bool debug_wait_connect = false;
|
||||
static int debug_port=5858;
|
||||
static int max_stack_size = 0;
|
||||
|
||||
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 +173,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 +189,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 +218,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);
|
||||
@@ -1495,6 +1520,7 @@ static Handle<Value> Binding(const Arguments& args) {
|
||||
exports->Set(String::New("tcp"), String::New(native_tcp));
|
||||
exports->Set(String::New("url"), String::New(native_url));
|
||||
exports->Set(String::New("utils"), String::New(native_utils));
|
||||
exports->Set(String::New("util"), String::New(native_sys));
|
||||
exports->Set(String::New("path"), String::New(native_path));
|
||||
exports->Set(String::New("string_decoder"), String::New(native_string_decoder));
|
||||
binding_cache->Set(module, exports);
|
||||
@@ -1595,6 +1621,11 @@ static void Load(int argc, char *argv[]) {
|
||||
|
||||
process->Set(String::NewSymbol("pid"), Integer::New(getpid()));
|
||||
|
||||
// -e, --eval
|
||||
if (eval_string) {
|
||||
process->Set(String::NewSymbol("_eval"), String::New(eval_string));
|
||||
}
|
||||
|
||||
size_t size = 2*PATH_MAX;
|
||||
char execPath[size];
|
||||
if (OS::GetExecutablePath(execPath, &size) != 0) {
|
||||
@@ -1707,21 +1738,23 @@ static void ParseDebugOpt(const char* arg) {
|
||||
static void PrintHelp() {
|
||||
printf("Usage: node [options] script.js [arguments] \n"
|
||||
"Options:\n"
|
||||
" -v, --version print node's version\n"
|
||||
" --debug[=port] enable remote debugging via given TCP port\n"
|
||||
" without stopping the execution\n"
|
||||
" --debug-brk[=port] as above, but break in script.js and\n"
|
||||
" wait for remote debugger to connect\n"
|
||||
" --v8-options print v8 command line options\n"
|
||||
" --vars print various compiled-in variables\n"
|
||||
" -v, --version print node's version\n"
|
||||
" --debug[=port] enable remote debugging via given TCP port\n"
|
||||
" without stopping the execution\n"
|
||||
" --debug-brk[=port] as above, but break in script.js and\n"
|
||||
" wait for remote debugger to connect\n"
|
||||
" --v8-options print v8 command line options\n"
|
||||
" --vars print various compiled-in variables\n"
|
||||
" --max-stack-size=val set max v8 stack size (bytes)\n"
|
||||
"\n"
|
||||
"Enviromental variables:\n"
|
||||
"NODE_PATH ':'-separated list of directories\n"
|
||||
" prefixed to the module search path,\n"
|
||||
" require.paths.\n"
|
||||
"NODE_DEBUG Print additional debugging output.\n"
|
||||
"NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
|
||||
" global contexts.\n"
|
||||
"NODE_PATH ':'-separated list of directories\n"
|
||||
" prefixed to the module search path,\n"
|
||||
" require.paths.\n"
|
||||
"NODE_DEBUG Print additional debugging output.\n"
|
||||
"NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n"
|
||||
" global contexts.\n"
|
||||
"NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n"
|
||||
"\n"
|
||||
"Documentation can be found at http://nodejs.org/api.html"
|
||||
" or with 'man node'\n");
|
||||
@@ -1744,9 +1777,21 @@ static void ParseArgs(int *argc, char **argv) {
|
||||
printf("NODE_PREFIX: %s\n", NODE_PREFIX);
|
||||
printf("NODE_CFLAGS: %s\n", NODE_CFLAGS);
|
||||
exit(0);
|
||||
} else if (strstr(arg, "--max-stack-size=") == arg) {
|
||||
const char *p = 0;
|
||||
p = 1 + strchr(arg, '=');
|
||||
max_stack_size = atoi(p);
|
||||
argv[i] = const_cast<char*>("");
|
||||
} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
|
||||
PrintHelp();
|
||||
exit(0);
|
||||
} else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0) {
|
||||
if (*argc <= i + 1) {
|
||||
fprintf(stderr, "Error: --eval requires an argument\n");
|
||||
exit(1);
|
||||
}
|
||||
argv[i] = const_cast<char*>("");
|
||||
eval_string = argv[++i];
|
||||
} else if (strcmp(arg, "--v8-options") == 0) {
|
||||
argv[i] = const_cast<char*>("--help");
|
||||
} else if (argv[i][0] != '-') {
|
||||
@@ -1758,6 +1803,21 @@ static void ParseArgs(int *argc, char **argv) {
|
||||
}
|
||||
|
||||
|
||||
static void SignalExit(int signal) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static int RegisterSignalHandler(int signal, void (*handler)(int)) {
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = handler;
|
||||
sigfillset(&sa.sa_mask);
|
||||
return sigaction(signal, &sa, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void AtExit() {
|
||||
node::Stdio::Flush();
|
||||
node::Stdio::DisableRawMode(STDIN_FILENO);
|
||||
@@ -1788,13 +1848,26 @@ int main(int argc, char *argv[]) {
|
||||
v8argv[node::option_end_index] = const_cast<char*>("--expose_debug_as");
|
||||
v8argv[node::option_end_index + 1] = const_cast<char*>("v8debug");
|
||||
}
|
||||
|
||||
// For the normal stack which moves from high to low addresses when frames
|
||||
// are pushed, we can compute the limit as stack_size bytes below the
|
||||
// the address of a stack variable (e.g. &stack_var) as an approximation
|
||||
// of the start of the stack (we're assuming that we haven't pushed a lot
|
||||
// of frames yet).
|
||||
if (node::max_stack_size != 0) {
|
||||
uint32_t stack_var;
|
||||
ResourceConstraints constraints;
|
||||
|
||||
uint32_t *stack_limit = &stack_var - (node::max_stack_size / sizeof(uint32_t));
|
||||
constraints.set_stack_limit(stack_limit);
|
||||
SetResourceConstraints(&constraints); // Must be done before V8::Initialize
|
||||
}
|
||||
V8::SetFlagsFromCommandLine(&v8argc, v8argv, false);
|
||||
|
||||
// Ignore SIGPIPE
|
||||
struct sigaction sa;
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
node::RegisterSignalHandler(SIGPIPE, SIG_IGN);
|
||||
node::RegisterSignalHandler(SIGINT, node::SignalExit);
|
||||
node::RegisterSignalHandler(SIGTERM, node::SignalExit);
|
||||
|
||||
|
||||
// Initialize the default ev loop.
|
||||
@@ -1802,14 +1875,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), \
|
||||
|
||||
50
src/node.js
50
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();
|
||||
}
|
||||
};
|
||||
@@ -744,16 +746,22 @@ if (process.argv[0].indexOf('/') > 0) {
|
||||
}
|
||||
|
||||
if (process.argv[1]) {
|
||||
// Load module
|
||||
if (process.argv[1].charAt(0) != "/" && !(/^http:\/\//).exec(process.argv[1])) {
|
||||
process.argv[1] = path.join(cwd, process.argv[1]);
|
||||
}
|
||||
// REMOVEME: nextTick should not be necessary. This hack to get
|
||||
// test/simple/test-exception-handler2.js working.
|
||||
process.nextTick(function() {
|
||||
module.runMain();
|
||||
});
|
||||
|
||||
module.runMain();
|
||||
} else if (process._eval) {
|
||||
// -e, --eval
|
||||
if (process._eval) console.log(eval(process._eval));
|
||||
} else {
|
||||
// No arguments, run the repl
|
||||
var repl = module.requireNative('repl');
|
||||
console.log("Type '.help' for options.");
|
||||
repl.start();
|
||||
// REPL
|
||||
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);
|
||||
|
||||
|
||||
@@ -13,7 +13,12 @@
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
# ifdef __APPLE__
|
||||
# include <crt_externs.h>
|
||||
# define environ (*_NSGetEnviron())
|
||||
# else
|
||||
extern char **environ;
|
||||
# endif
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -286,8 +291,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 +299,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 +307,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,38 +12,39 @@ class ObjectWrap {
|
||||
refs_ = 0;
|
||||
}
|
||||
|
||||
|
||||
virtual ~ObjectWrap ( ) {
|
||||
if (!handle_.IsEmpty()) {
|
||||
assert(handle_.IsNearDeath());
|
||||
handle_.ClearWeak();
|
||||
handle_->SetInternalField(0, v8::Undefined());
|
||||
handle_.Dispose();
|
||||
handle_.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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,15 +74,17 @@ 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_);
|
||||
if (value.IsNearDeath()) delete obj;
|
||||
assert(value.IsNearDeath());
|
||||
delete obj;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,18 @@ static Handle<Value> GetRows (const Arguments& args) {
|
||||
return scope.Close(Integer::NewFromUnsigned(ws.ws_row));
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> IsATTY (const Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
int fd = args[0]->IntegerValue();
|
||||
|
||||
int r = isatty(fd);
|
||||
|
||||
return scope.Close(r ? True() : False());
|
||||
}
|
||||
|
||||
|
||||
/* STDERR IS ALWAY SYNC ALWAYS UTF8 */
|
||||
static Handle<Value>
|
||||
WriteError (const Arguments& args)
|
||||
@@ -219,6 +231,7 @@ void Stdio::Initialize(v8::Handle<v8::Object> target) {
|
||||
NODE_SET_METHOD(target, "setRawMode", SetRawMode);
|
||||
NODE_SET_METHOD(target, "getColumns", GetColumns);
|
||||
NODE_SET_METHOD(target, "getRows", GetRows);
|
||||
NODE_SET_METHOD(target, "isatty", IsATTY);
|
||||
|
||||
struct sigaction sa = {0};
|
||||
sa.sa_handler = HandleSIGCONT;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define NODE_MAJOR_VERSION 0
|
||||
#define NODE_MINOR_VERSION 2
|
||||
#define NODE_PATCH_VERSION 0
|
||||
#define NODE_PATCH_VERSION 4
|
||||
|
||||
#ifndef NODE_STRINGIFY
|
||||
#define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)
|
||||
|
||||
@@ -47,11 +47,26 @@ int OS::GetMemory(size_t *rss, size_t *vsize) {
|
||||
int itmp;
|
||||
char ctmp;
|
||||
size_t page_size = getpagesize();
|
||||
char *cbuf;
|
||||
bool foundExeEnd;
|
||||
|
||||
/* PID */
|
||||
if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Exec file */
|
||||
if (fscanf (f, "%s ", buf) == 0) goto error; /* coverity[secure_coding] */
|
||||
cbuf = buf;
|
||||
foundExeEnd = false;
|
||||
if (fscanf (f, "%c", cbuf++) == 0) goto error; // (
|
||||
while (1) {
|
||||
if (fscanf(f, "%c", cbuf) == 0) goto error;
|
||||
if (*cbuf == ')') {
|
||||
foundExeEnd = true;
|
||||
} else if (foundExeEnd && *cbuf == ' ') {
|
||||
*cbuf = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cbuf++;
|
||||
}
|
||||
/* State */
|
||||
if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Parent process */
|
||||
|
||||
@@ -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 @@
|
||||
;
|
||||
@@ -35,10 +35,10 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
|
||||
FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
|
||||
|
||||
|
||||
class SimpleTestCase(test.TestCase):
|
||||
class InternetTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, file, mode, context, config):
|
||||
super(SimpleTestCase, self).__init__(context, path)
|
||||
super(InternetTestCase, self).__init__(context, path)
|
||||
self.file = file
|
||||
self.config = config
|
||||
self.mode = mode
|
||||
@@ -68,10 +68,10 @@ class SimpleTestCase(test.TestCase):
|
||||
return open(self.file).read()
|
||||
|
||||
|
||||
class SimpleTestConfiguration(test.TestConfiguration):
|
||||
class InternetTestConfiguration(test.TestConfiguration):
|
||||
|
||||
def __init__(self, context, root):
|
||||
super(SimpleTestConfiguration, self).__init__(context, root)
|
||||
super(InternetTestConfiguration, self).__init__(context, root)
|
||||
|
||||
def Ls(self, path):
|
||||
def SelectTest(name):
|
||||
@@ -91,7 +91,7 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
||||
result.append(SimpleTestCase(test, file_path, mode, self.context, self))
|
||||
result.append(InternetTestCase(test, file_path, mode, self.context, self))
|
||||
return result
|
||||
|
||||
def GetBuildRequirements(self):
|
||||
@@ -105,4 +105,4 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
||||
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return SimpleTestConfiguration(context, root)
|
||||
return InternetTestConfiguration(context, root)
|
||||
|
||||
@@ -35,7 +35,7 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
|
||||
class MessageTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, file, expected, mode, context, config):
|
||||
super(MessageTestCase, self).__init__(context, path)
|
||||
super(MessageTestCase, self).__init__(context, path, mode)
|
||||
self.file = file
|
||||
self.expected = expected
|
||||
self.config = config
|
||||
@@ -105,10 +105,7 @@ class MessageTestConfiguration(test.TestConfiguration):
|
||||
return []
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
mjsunit = [current_path + [t] for t in self.Ls(self.root)]
|
||||
#regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
#bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
|
||||
all_tests = mjsunit #+ regress + bugs
|
||||
all_tests = [current_path + [t] for t in self.Ls(self.root)]
|
||||
result = []
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
import test
|
||||
import os
|
||||
import shutil
|
||||
from shutil import rmtree
|
||||
from os import mkdir
|
||||
from glob import glob
|
||||
from os.path import join, dirname, exists
|
||||
import re
|
||||
|
||||
@@ -35,14 +39,33 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
|
||||
FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
|
||||
|
||||
|
||||
class SimpleTestCase(test.TestCase):
|
||||
class PummelTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, file, mode, context, config):
|
||||
super(SimpleTestCase, self).__init__(context, path)
|
||||
super(PummelTestCase, self).__init__(context, path, mode)
|
||||
self.file = file
|
||||
self.config = config
|
||||
self.mode = mode
|
||||
self.tmpdir = join(dirname(self.config.root), 'tmp')
|
||||
|
||||
def AfterRun(self, result):
|
||||
# delete the whole tmp dir
|
||||
try:
|
||||
rmtree(self.tmpdir)
|
||||
except:
|
||||
pass
|
||||
# make it again.
|
||||
mkdir(self.tmpdir)
|
||||
|
||||
def BeforeRun(self):
|
||||
# delete the whole tmp dir
|
||||
try:
|
||||
rmtree(self.tmpdir)
|
||||
except:
|
||||
pass
|
||||
# make it again.
|
||||
mkdir(self.tmpdir)
|
||||
|
||||
def GetLabel(self):
|
||||
return "%s %s" % (self.mode, self.GetName())
|
||||
|
||||
@@ -68,10 +91,10 @@ class SimpleTestCase(test.TestCase):
|
||||
return open(self.file).read()
|
||||
|
||||
|
||||
class SimpleTestConfiguration(test.TestConfiguration):
|
||||
class PummelTestConfiguration(test.TestConfiguration):
|
||||
|
||||
def __init__(self, context, root):
|
||||
super(SimpleTestConfiguration, self).__init__(context, root)
|
||||
super(PummelTestConfiguration, self).__init__(context, root)
|
||||
|
||||
def Ls(self, path):
|
||||
def SelectTest(name):
|
||||
@@ -79,19 +102,12 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
||||
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
simple = [current_path + [t] for t in self.Ls(self.root)]
|
||||
#simple = [current_path + ['simple', t] for t in self.Ls(join(self.root, 'simple'))]
|
||||
#pummel = [current_path + ['pummel', t] for t in self.Ls(join(self.root, 'pummel'))]
|
||||
#internet = [current_path + ['internet', t] for t in self.Ls(join(self.root, 'internet'))]
|
||||
#regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
#bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
|
||||
#tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
|
||||
all_tests = simple # + regress + bugs + tools
|
||||
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
||||
result = []
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
||||
result.append(SimpleTestCase(test, file_path, mode, self.context, self))
|
||||
result.append(PummelTestCase(test, file_path, mode, self.context, self))
|
||||
return result
|
||||
|
||||
def GetBuildRequirements(self):
|
||||
@@ -105,4 +121,4 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
||||
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return SimpleTestConfiguration(context, root)
|
||||
return PummelTestConfiguration(context, root)
|
||||
|
||||
@@ -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.');
|
||||
|
||||
@@ -35,16 +35,53 @@ exec("ls /DOES_NOT_EXIST", function (err, stdout, stderr) {
|
||||
}
|
||||
});
|
||||
|
||||
exec("sleep 10", { timeout: 50 }, function (err, stdout, stderr) {
|
||||
|
||||
|
||||
var sleeperStart = new Date();
|
||||
exec("sleep 3", { timeout: 50 }, function (err, stdout, stderr) {
|
||||
var diff = (new Date()) - sleeperStart;
|
||||
console.log("sleep 3 with timeout 50 took %d ms", diff);
|
||||
assert.ok(diff < 500);
|
||||
assert.ok(err);
|
||||
assert.ok(err.killed);
|
||||
assert.equal(err.signal, 'SIGKILL');
|
||||
assert.equal(err.signal, 'SIGTERM');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
var startSleep3 = new Date();
|
||||
var killMeTwice = exec("sleep 3", { timeout: 1000 }, killMeTwiceCallback);
|
||||
|
||||
process.nextTick(function(){
|
||||
console.log("kill pid %d", killMeTwice.pid);
|
||||
// make sure there is no race condition in starting the process
|
||||
// the PID SHOULD exist directly following the exec() call.
|
||||
assert.equal('number', typeof killMeTwice._internal.pid);
|
||||
// Kill the process
|
||||
killMeTwice.kill();
|
||||
});
|
||||
|
||||
function killMeTwiceCallback(err, stdout, stderr) {
|
||||
var diff = (new Date()) - startSleep3;
|
||||
// We should have already killed this process. Assert that
|
||||
// the timeout still works and that we are getting the proper callback
|
||||
// parameters.
|
||||
assert.ok(err);
|
||||
assert.ok(err.killed);
|
||||
assert.equal(err.signal, 'SIGTERM');
|
||||
|
||||
// the timeout should still be in effect
|
||||
console.log("'sleep 3' was already killed. Took %d ms", diff);
|
||||
assert.ok(diff < 1500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
exec('python -c "print 200000*\'C\'"', { maxBuffer: 1000 }, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.ok(err.killed);
|
||||
assert.equal(err.signal, 'SIGKILL');
|
||||
assert.equal(err.signal, 'SIGTERM');
|
||||
});
|
||||
|
||||
process.addListener("exit", function () {
|
||||
|
||||
@@ -4,7 +4,7 @@ assert = common.assert
|
||||
var
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
fn = path.join(common.fixturesDir, "write.txt"),
|
||||
fn = path.join(common.tmpDir, "write.txt"),
|
||||
file = fs.createWriteStream(fn),
|
||||
|
||||
EXPECTED = '012345678910',
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ assert = common.assert
|
||||
var path = require('path'),
|
||||
Buffer = require('buffer').Buffer,
|
||||
fs = require('fs'),
|
||||
filename = path.join(common.fixturesDir, 'write.txt'),
|
||||
filename = path.join(common.tmpDir, 'write.txt'),
|
||||
expected = new Buffer('hello'),
|
||||
openCalled = 0,
|
||||
writeCalled = 0;
|
||||
|
||||
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.tmpDir, "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();
|
||||
})();
|
||||
|
||||
@@ -3,7 +3,7 @@ assert = common.assert
|
||||
path = require('path'),
|
||||
Buffer = require('buffer').Buffer
|
||||
fs = require('fs')
|
||||
fn = path.join(common.fixturesDir, 'write.txt');
|
||||
fn = path.join(common.tmpDir, 'write.txt');
|
||||
|
||||
|
||||
foo = 'foo'
|
||||
|
||||
@@ -3,7 +3,7 @@ assert = common.assert
|
||||
var path = require('path');
|
||||
var Buffer = require('buffer').Buffer;
|
||||
var fs = require('fs');
|
||||
var fn = path.join(common.fixturesDir, "write.txt");
|
||||
var fn = path.join(common.tmpDir, "write.txt");
|
||||
var expected = "ümlaut.";
|
||||
var found;
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
35
test/simple/test-http-client-parse-error.js
Normal file
35
test/simple/test-http-client-parse-error.js
Normal file
@@ -0,0 +1,35 @@
|
||||
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(); });
|
||||
});
|
||||
|
||||
var parseError = false;
|
||||
|
||||
srv.listen(common.PORT, '127.0.0.1', function () {
|
||||
var hc = http.createClient(common.PORT, '127.0.0.1');
|
||||
hc.request('GET', '/').end();
|
||||
|
||||
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,69 +8,49 @@ 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();
|
||||
});
|
||||
});
|
||||
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) {
|
||||
// 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');
|
||||
|
||||
socket.end();
|
||||
srv.close();
|
||||
srv.listen(common.PORT, '127.0.0.1', function () {
|
||||
|
||||
gotUpgrade = true;
|
||||
var hc = http.createClient(common.PORT, '127.0.0.1');
|
||||
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('GET', '/').end();
|
||||
});
|
||||
hc.request('/', {
|
||||
'Connection' : 'Upgrade',
|
||||
'Upgrade' : 'WebSocket'
|
||||
}).end();
|
||||
|
||||
process.addListener('exit', function() {
|
||||
assert.ok(gotUpgrade);
|
||||
|
||||
68
test/simple/test-http-upgrade-client2.js
Normal file
68
test/simple/test-http-upgrade-client2.js
Normal file
@@ -0,0 +1,68 @@
|
||||
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(common.PORT, function () {
|
||||
|
||||
var client = http.createClient(common.PORT);
|
||||
|
||||
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) {
|
||||
|
||||
47
test/simple/test-net-connect-buffer.js
Normal file
47
test/simple/test-net-connect-buffer.js
Normal file
@@ -0,0 +1,47 @@
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var net = require('net');
|
||||
|
||||
var tcpPort = common.PORT;
|
||||
|
||||
var tcp = net.Server(function (s) {
|
||||
tcp.close();
|
||||
|
||||
console.log("tcp server connection");
|
||||
|
||||
var buf = "";
|
||||
s.on('data', function (d) {
|
||||
buf += d;
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
assert.equal("foobar", buf);
|
||||
console.log("tcp socket disconnect");
|
||||
s.end();
|
||||
});
|
||||
|
||||
s.on('error', function (e) {
|
||||
console.log("tcp server-side error: " + e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
tcp.listen(tcpPort, startClient);
|
||||
|
||||
function startClient () {
|
||||
var socket = net.Stream();
|
||||
|
||||
console.log("Connecting to socket");
|
||||
|
||||
socket.connect(tcpPort);
|
||||
|
||||
socket.on('connect', function () {
|
||||
console.log('socket connected');
|
||||
});
|
||||
|
||||
assert.equal("opening", socket.readyState);
|
||||
|
||||
assert.equal(false, socket.write("foo"));
|
||||
socket.end("bar");
|
||||
|
||||
assert.equal("opening", socket.readyState);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
36
test/simple/test-sigint-infinite-loop.js
Normal file
36
test/simple/test-sigint-infinite-loop.js
Normal file
@@ -0,0 +1,36 @@
|
||||
// This test is to assert that we can SIGINT a script which loops forever.
|
||||
// ref: http://groups.google.com/group/nodejs-dev/browse_thread/thread/e20f2f8df0296d3f
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
console.log("start");
|
||||
|
||||
var c = spawn(process.execPath, ['-e', 'while(true) { console.log("hi"); }']);
|
||||
|
||||
var sentKill = false;
|
||||
var gotChildExit = true;
|
||||
|
||||
c.stdout.on('data', function (s) {
|
||||
// Prevent race condition:
|
||||
// Wait for the first bit of output from the child process
|
||||
// so that we're sure that it's in the V8 event loop and not
|
||||
// just in the startup phase of execution.
|
||||
if (!sentKill) {
|
||||
c.kill('SIGINT')
|
||||
console.log("SIGINT infinite-loop.js");
|
||||
sentKill = true;
|
||||
}
|
||||
});
|
||||
|
||||
c.on('exit', function (code) {
|
||||
assert.ok(code !== 0);
|
||||
console.log("killed infinite-loop.js");
|
||||
gotChildExit = true;
|
||||
});
|
||||
|
||||
process.on('exit', function () {
|
||||
assert.ok(sentKill);
|
||||
assert.ok(gotChildExit);
|
||||
});
|
||||
|
||||
@@ -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,10 @@
|
||||
|
||||
import test
|
||||
import os
|
||||
import shutil
|
||||
from shutil import rmtree
|
||||
from os import mkdir
|
||||
from glob import glob
|
||||
from os.path import join, dirname, exists
|
||||
import re
|
||||
|
||||
@@ -38,11 +42,30 @@ FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
|
||||
class SimpleTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, file, mode, context, config):
|
||||
super(SimpleTestCase, self).__init__(context, path)
|
||||
super(SimpleTestCase, self).__init__(context, path, mode)
|
||||
self.file = file
|
||||
self.config = config
|
||||
self.mode = mode
|
||||
self.tmpdir = join(dirname(self.config.root), 'tmp')
|
||||
|
||||
def AfterRun(self, result):
|
||||
# delete the whole tmp dir
|
||||
try:
|
||||
rmtree(self.tmpdir)
|
||||
except:
|
||||
pass
|
||||
# make it again.
|
||||
mkdir(self.tmpdir)
|
||||
|
||||
def BeforeRun(self):
|
||||
# delete the whole tmp dir
|
||||
try:
|
||||
rmtree(self.tmpdir)
|
||||
except:
|
||||
pass
|
||||
# make it again.
|
||||
mkdir(self.tmpdir)
|
||||
|
||||
def GetLabel(self):
|
||||
return "%s %s" % (self.mode, self.GetName())
|
||||
|
||||
@@ -79,14 +102,7 @@ class SimpleTestConfiguration(test.TestConfiguration):
|
||||
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
simple = [current_path + [t] for t in self.Ls(self.root)]
|
||||
#simple = [current_path + ['simple', t] for t in self.Ls(join(self.root, 'simple'))]
|
||||
#pummel = [current_path + ['pummel', t] for t in self.Ls(join(self.root, 'pummel'))]
|
||||
#internet = [current_path + ['internet', t] for t in self.Ls(join(self.root, 'internet'))]
|
||||
#regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
#bugs = [current_path + ['bugs', t] for t in self.Ls(join(self.root, 'bugs'))]
|
||||
#tools = [current_path + ['tools', t] for t in self.Ls(join(self.root, 'tools'))]
|
||||
all_tests = simple # + regress + bugs + tools
|
||||
all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
|
||||
result = []
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
|
||||
134
tools/test.py
134
tools/test.py
@@ -326,15 +326,16 @@ class CommandOutput(object):
|
||||
self.timed_out = timed_out
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.failed = None
|
||||
|
||||
|
||||
class TestCase(object):
|
||||
|
||||
def __init__(self, context, path):
|
||||
def __init__(self, context, path, mode):
|
||||
self.path = path
|
||||
self.context = context
|
||||
self.failed = None
|
||||
self.duration = None
|
||||
self.mode = mode
|
||||
|
||||
def IsNegative(self):
|
||||
return False
|
||||
@@ -343,9 +344,9 @@ class TestCase(object):
|
||||
return cmp(other.duration, self.duration)
|
||||
|
||||
def DidFail(self, output):
|
||||
if self.failed is None:
|
||||
self.failed = self.IsFailureOutput(output)
|
||||
return self.failed
|
||||
if output.failed is None:
|
||||
output.failed = self.IsFailureOutput(output)
|
||||
return output.failed
|
||||
|
||||
def IsFailureOutput(self, output):
|
||||
return output.exit_code != 0
|
||||
@@ -355,29 +356,55 @@ class TestCase(object):
|
||||
|
||||
def RunCommand(self, command):
|
||||
full_command = self.context.processor(command)
|
||||
output = Execute(full_command, self.context, self.context.timeout)
|
||||
return TestOutput(self, full_command, output)
|
||||
output = Execute(full_command,
|
||||
self.context,
|
||||
self.context.GetTimeout(self.mode))
|
||||
self.Cleanup()
|
||||
return TestOutput(self,
|
||||
full_command,
|
||||
output,
|
||||
self.context.store_unexpected_output)
|
||||
|
||||
def BeforeRun(self):
|
||||
pass
|
||||
|
||||
def AfterRun(self, result):
|
||||
pass
|
||||
|
||||
def Run(self):
|
||||
return self.RunCommand(self.GetCommand())
|
||||
self.BeforeRun()
|
||||
try:
|
||||
result = self.RunCommand(self.GetCommand())
|
||||
finally:
|
||||
self.AfterRun(result)
|
||||
return result
|
||||
|
||||
def Cleanup(self):
|
||||
return
|
||||
|
||||
|
||||
class TestOutput(object):
|
||||
|
||||
def __init__(self, test, command, output):
|
||||
def __init__(self, test, command, output, store_unexpected_output):
|
||||
self.test = test
|
||||
self.command = command
|
||||
self.output = output
|
||||
self.store_unexpected_output = store_unexpected_output
|
||||
|
||||
def UnexpectedOutput(self):
|
||||
if self.HasCrashed():
|
||||
outcome = CRASH
|
||||
elif self.HasTimedOut():
|
||||
outcome = TIMEOUT
|
||||
elif self.HasFailed():
|
||||
outcome = FAIL
|
||||
else:
|
||||
outcome = PASS
|
||||
return not outcome in self.test.outcomes
|
||||
|
||||
def HasPreciousOutput(self):
|
||||
return self.UnexpectedOutput() and self.store_unexpected_output
|
||||
|
||||
def HasCrashed(self):
|
||||
if utils.IsWindows():
|
||||
return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.output.exit_code)
|
||||
@@ -390,7 +417,7 @@ class TestOutput(object):
|
||||
|
||||
def HasTimedOut(self):
|
||||
return self.output.timed_out;
|
||||
|
||||
|
||||
def HasFailed(self):
|
||||
execution_failed = self.test.DidFail(self.output)
|
||||
if self.test.IsNegative():
|
||||
@@ -471,6 +498,13 @@ def PrintError(str):
|
||||
sys.stderr.write('\n')
|
||||
|
||||
|
||||
def CheckedUnlink(name):
|
||||
try:
|
||||
os.unlink(name)
|
||||
except OSError, e:
|
||||
PrintError("os.unlink() " + str(e))
|
||||
|
||||
|
||||
def Execute(args, context, timeout=None):
|
||||
(fd_out, outname) = tempfile.mkstemp()
|
||||
(fd_err, errname) = tempfile.mkstemp()
|
||||
@@ -485,11 +519,6 @@ def Execute(args, context, timeout=None):
|
||||
os.close(fd_err)
|
||||
output = file(outname).read()
|
||||
errors = file(errname).read()
|
||||
def CheckedUnlink(name):
|
||||
try:
|
||||
os.unlink(name)
|
||||
except OSError, e:
|
||||
PrintError("os.unlink() " + str(e))
|
||||
CheckedUnlink(outname)
|
||||
CheckedUnlink(errname)
|
||||
return CommandOutput(exit_code, timed_out, output, errors)
|
||||
@@ -538,6 +567,11 @@ class TestSuite(object):
|
||||
return self.name
|
||||
|
||||
|
||||
# Use this to run several variants of the tests, e.g.:
|
||||
# VARIANT_FLAGS = [[], ['--always_compact', '--noflush_code']]
|
||||
VARIANT_FLAGS = [[]]
|
||||
|
||||
|
||||
class TestRepository(TestSuite):
|
||||
|
||||
def __init__(self, path):
|
||||
@@ -564,8 +598,12 @@ class TestRepository(TestSuite):
|
||||
def GetBuildRequirements(self, path, context):
|
||||
return self.GetConfiguration(context).GetBuildRequirements()
|
||||
|
||||
def ListTests(self, current_path, path, context, mode):
|
||||
return self.GetConfiguration(context).ListTests(current_path, path, mode)
|
||||
def AddTestsToList(self, result, current_path, path, context, mode):
|
||||
for v in VARIANT_FLAGS:
|
||||
tests = self.GetConfiguration(context).ListTests(current_path, path, mode)
|
||||
for t in tests: t.variant_flags = v
|
||||
result += tests
|
||||
|
||||
|
||||
def GetTestStatus(self, context, sections, defs):
|
||||
self.GetConfiguration(context).GetTestStatus(sections, defs)
|
||||
@@ -592,7 +630,7 @@ class LiteralTestSuite(TestSuite):
|
||||
test_name = test.GetName()
|
||||
if not name or name.match(test_name):
|
||||
full_path = current_path + [test_name]
|
||||
result += test.ListTests(full_path, path, context, mode)
|
||||
test.AddTestsToList(result, full_path, path, context, mode)
|
||||
return result
|
||||
|
||||
def GetTestStatus(self, context, sections, defs):
|
||||
@@ -600,12 +638,20 @@ class LiteralTestSuite(TestSuite):
|
||||
test.GetTestStatus(context, sections, defs)
|
||||
|
||||
|
||||
SUFFIX = {'debug': '_g', 'release': ''}
|
||||
SUFFIX = {
|
||||
'debug' : '_g',
|
||||
'release' : '' }
|
||||
FLAGS = {
|
||||
'debug' : ['--enable-slow-asserts', '--debug-code', '--verify-heap'],
|
||||
'release' : []}
|
||||
TIMEOUT_SCALEFACTOR = {
|
||||
'debug' : 4,
|
||||
'release' : 1 }
|
||||
|
||||
|
||||
class Context(object):
|
||||
|
||||
def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, suppress_dialogs):
|
||||
def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, suppress_dialogs, store_unexpected_output):
|
||||
self.workspace = workspace
|
||||
self.buildspace = buildspace
|
||||
self.verbose = verbose
|
||||
@@ -613,20 +659,28 @@ class Context(object):
|
||||
self.timeout = timeout
|
||||
self.processor = processor
|
||||
self.suppress_dialogs = suppress_dialogs
|
||||
self.store_unexpected_output = store_unexpected_output
|
||||
|
||||
def GetVm(self, mode):
|
||||
if mode == 'debug':
|
||||
name = 'build/debug/node_g'
|
||||
else:
|
||||
name = 'build/default/node'
|
||||
|
||||
if utils.IsWindows() and not name.endswith('.exe'):
|
||||
name = name + '.exe'
|
||||
return name
|
||||
|
||||
def RunTestCases(all_cases, progress, tasks):
|
||||
def DoSkip(case):
|
||||
return SKIP in c.outcomes or SLOW in c.outcomes
|
||||
cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
|
||||
def GetVmCommand(self, testcase, mode):
|
||||
return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode)
|
||||
|
||||
def GetVmFlags(self, testcase, mode):
|
||||
return testcase.variant_flags + FLAGS[mode]
|
||||
|
||||
def GetTimeout(self, mode):
|
||||
return self.timeout * TIMEOUT_SCALEFACTOR[mode]
|
||||
|
||||
def RunTestCases(cases_to_run, progress, tasks):
|
||||
progress = PROGRESS_INDICATORS[progress](cases_to_run)
|
||||
return progress.Run(tasks)
|
||||
|
||||
@@ -1079,6 +1133,8 @@ def BuildOptions():
|
||||
choices=PROGRESS_INDICATORS.keys(), default="mono")
|
||||
result.add_option("--no-build", help="Don't build requirements",
|
||||
default=True, action="store_true")
|
||||
result.add_option("--build-only", help="Only build requirements, don't run the tests",
|
||||
default=False, action="store_true")
|
||||
result.add_option("--report", help="Print a summary of the tests to be run",
|
||||
default=False, action="store_true")
|
||||
result.add_option("-s", "--suite", help="A test suite",
|
||||
@@ -1087,6 +1143,8 @@ def BuildOptions():
|
||||
default=60, type="int")
|
||||
result.add_option("--arch", help='The architecture to run tests for',
|
||||
default='none')
|
||||
result.add_option("--snapshot", help="Run the tests with snapshot turned on",
|
||||
default=False, action="store_true")
|
||||
result.add_option("--simulator", help="Run tests with architecture simulator",
|
||||
default='none')
|
||||
result.add_option("--special-command", default=None)
|
||||
@@ -1104,7 +1162,13 @@ def BuildOptions():
|
||||
dest="suppress_dialogs", default=True, action="store_true")
|
||||
result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for crashing tests",
|
||||
dest="suppress_dialogs", action="store_false")
|
||||
result.add_option("--shell", help="Path to V8 shell", default="shell");
|
||||
result.add_option("--shell", help="Path to V8 shell", default="shell")
|
||||
result.add_option("--store-unexpected-output",
|
||||
help="Store the temporary JS files from tests that fails",
|
||||
dest="store_unexpected_output", default=True, action="store_true")
|
||||
result.add_option("--no-store-unexpected-output",
|
||||
help="Deletes the temporary JS files from tests that fails",
|
||||
dest="store_unexpected_output", action="store_false")
|
||||
return result
|
||||
|
||||
|
||||
@@ -1131,6 +1195,9 @@ def ProcessOptions(options):
|
||||
# was found, set the arch to the guess.
|
||||
if options.arch == 'none':
|
||||
options.arch = ARCH_GUESS
|
||||
options.scons_flags.append("arch=" + options.arch)
|
||||
if options.snapshot:
|
||||
options.scons_flags.append("snapshot=on")
|
||||
return True
|
||||
|
||||
|
||||
@@ -1238,11 +1305,13 @@ def Main():
|
||||
|
||||
shell = abspath(options.shell)
|
||||
buildspace = dirname(shell)
|
||||
|
||||
context = Context(workspace, buildspace, VERBOSE,
|
||||
shell,
|
||||
options.timeout,
|
||||
GetSpecialCommandProcessor(options.special_command),
|
||||
options.suppress_dialogs)
|
||||
options.suppress_dialogs,
|
||||
options.store_unexpected_output)
|
||||
# First build the required targets
|
||||
if not options.no_build:
|
||||
reqs = [ ]
|
||||
@@ -1255,6 +1324,10 @@ def Main():
|
||||
if not BuildRequirements(context, reqs, options.mode, options.scons_flags):
|
||||
return 1
|
||||
|
||||
# Just return if we are only building the targets for running the tests.
|
||||
if options.build_only:
|
||||
return 0
|
||||
|
||||
# Get status for tests
|
||||
sections = [ ]
|
||||
defs = { }
|
||||
@@ -1308,13 +1381,16 @@ def Main():
|
||||
PrintReport(all_cases)
|
||||
|
||||
result = None
|
||||
if len(all_cases) == 0:
|
||||
def DoSkip(case):
|
||||
return SKIP in case.outcomes or SLOW in case.outcomes
|
||||
cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
|
||||
if len(cases_to_run) == 0:
|
||||
print "No tests to run."
|
||||
return 0
|
||||
else:
|
||||
try:
|
||||
start = time.time()
|
||||
if RunTestCases(all_cases, options.progress, options.j):
|
||||
if RunTestCases(cases_to_run, options.progress, options.j):
|
||||
result = 0
|
||||
else:
|
||||
result = 1
|
||||
@@ -1328,7 +1404,7 @@ def Main():
|
||||
# test output.
|
||||
print
|
||||
sys.stderr.write("--- Total time: %s ---\n" % FormatTime(duration))
|
||||
timed_tests = [ t.case for t in all_cases if not t.case.duration is None ]
|
||||
timed_tests = [ t.case for t in cases_to_run if not t.case.duration is None ]
|
||||
timed_tests.sort(lambda a, b: a.CompareTime(b))
|
||||
index = 1
|
||||
for entry in timed_tests[:20]:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# git log --pretty='format:%ae %an' | tail -r | awk -f updateAuthors.awk
|
||||
# git log --pretty='format:%ae %an' | tac | awk -f tools/updateAuthors.awk
|
||||
{
|
||||
if (!x[$1]++) {
|
||||
#print $0
|
||||
|
||||
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