Compare commits

...

104 Commits

Author SHA1 Message Date
Ryan Dahl
dc103ae020 Bump version to v0.2.3 2010-10-02 06:05:56 -07:00
Ryan Dahl
fea3919d1b Fix zero length buffer bug for http res.end()
Reported by Kadir Pekel <kadirpekel@gmail.com>
2010-10-01 16:16:00 -07:00
Marco Rogers
b5dc54c6ed fix encoding option on ReadStream, updated test 2010-10-01 16:14:22 -07:00
Ryan Dahl
2fb393a768 Fix REPL crash on tabbing 'this.'
Thanks to Tim Becker for pointing this out.
2010-10-01 16:14:13 -07:00
Ryan Dahl
80974dc85b Drop reference to timer callback on clearTimeout
Reported here:
http://groups.google.com/group/nodejs-dev/browse_thread/thread/9e063d0938f99879

Would be good to test this somehow...
2010-10-01 16:13:59 -07:00
Evan Larkin
16f736200a fs.ReadStream: Passing null for file position on all reads except the first read of a range read. 2010-10-01 16:13:12 -07:00
Evan Larkin
d29e62d564 No longer using the global variable "stat" in unwatchFile 2010-10-01 16:11:42 -07:00
Ryan Dahl
41eca918e5 Add test for getting parse error from HTTP client
Made this test in response to this thread:
http://groups.google.com/group/nodejs/browse_thread/thread/f82835007a277de2/
But Node appears to be working correctly.
2010-10-01 16:11:17 -07:00
Ryan Dahl
45a01aff59 Move the http client's initParser() into prototype 2010-10-01 15:56:32 -07:00
Ryan Dahl
55aa7b17ab Put preprocessor defines into CPPFLAGS not compile flags... 2010-10-01 15:55:46 -07:00
Ryan Dahl
1165878e3c Fix timing on I/O benchmark 2010-10-01 15:54:49 -07:00
Ryan Dahl
b98958d7fe Add function_call benchmark 2010-10-01 15:54:44 -07:00
Fedor Indutny
448cbaf395 Fixed 'upgrade' event for httpclient
onend and ondata was cleaning on parser end
2010-10-01 15:54:27 -07:00
Tj Holowaychuk
b8eee9c6f0 Fixed fs.ReadStream() start: 0 bug 2010-10-01 15:53:53 -07:00
Mikeal Rogers
936a038bb7 HTTP: close connection on connection:close header.
rnewson found a good bug in keep-alive. we were only using the request
headers we send to enable/disable keep-alive but when the server sends
Connection: close we need to close down the connection regardless.

I wrote up a patch the Robert verified makes all his test client code work
now and I also added a new unittest for it.
2010-10-01 15:53:26 -07:00
Ryan Dahl
529cdad2dd Don't choose jobs based on processor
Leads to lots of builds with out-of-memory.
2010-10-01 15:53:02 -07:00
Ryan Dahl
7140933fcc More explicit openssl configure warning 2010-10-01 15:52:56 -07:00
Jorge Chamorro Bieling
27f6a20fdb sys.js: --needless Object.keys() --needless .map() in a single patch 2010-10-01 15:51:27 -07:00
Paul Querna
a30daa7b6c Fatal error out if OpenSSL was not explicitly disabled, we just couldn't autodetect it. 2010-10-01 15:50:32 -07:00
Jorge Chamorro Bieling
01035714a5 sys.js: sys.inspect: show function names 2010-10-01 15:50:18 -07:00
Ryan Dahl
f6f739b3a2 Pass correct message in HTTP client upgrade
Simplify and correct test.

Fix by Fedor Indutny.
2010-10-01 15:49:50 -07:00
Ryan Dahl
d7c1690c74 Revert requireNative changes: 4e6b9b0, d429033, 6abbfa0, bcad540 2010-10-01 15:45:21 -07:00
Ryan Dahl
7bf46bc980 bump version to v0.2.2 2010-09-17 11:34:16 -07:00
Ryan Dahl
bcbc52e257 ^c to get out of '...' in REPL 2010-09-17 11:23:08 -07:00
Ryan Dahl
c00a6a7169 Simplify REPL 2010-09-17 11:23:04 -07:00
Ryan Dahl
1d8b154e14 Safe constructors for fs.ReadStream and fs.WriteStream 2010-09-17 11:22:58 -07:00
Ryan Dahl
84f4ce742f Remove old versions of fs.read and fs.write from docs 2010-09-17 11:22:50 -07:00
Paul Querna
f9cc35fa57 Use the Apple recommended way of detecting OSX Versions
to enable KQueue, rather than deciding based on the compiler version.
2010-09-17 11:22:42 -07:00
Ryan Dahl
d506a42765 Handle writeStream errors in sys.pump 2010-09-17 11:21:59 -07:00
Russell Haering
09a41a7f9c Pass an error to the sys.pump callback if one occurs
- Add test case for pumping from unreadable stream.
- Document the sys.pump error handling behavior
2010-09-17 11:21:50 -07:00
Herbert Vojčík
8dcd6dccab Common subexpression in emit. 2010-09-17 11:20:52 -07:00
Herbert Vojčík
1375b8ed39 No need to do if (internalModuleCache...), it's in requireNative. 2010-09-17 11:20:32 -07:00
Herbert Vojčík
a3333e7393 Module system moved to the bottom, where only is it needed.
(this also splits the file into upper "setup" and lower "startup" sections)
2010-09-17 11:20:24 -07:00
Herbert Vojčík
d965640662 m.id unneccessary, id is enough. 2010-09-17 11:20:17 -07:00
Herbert Vojčík
ee253b374d Natives having their own self-contained minimalistic module system.
The main system is built upon this, and is optional, if only natives
are used in application (eg. node-core).

Natives not loaded into own context if NODE_MODULE_CONTEXTS=1.
This have its inner logic, if natives are seen just as lazy-loaded
parts of the core.
2010-09-17 11:19:33 -07:00
Ryan Dahl
b17b28531b shorten some lines in events.js 2010-09-17 11:18:59 -07:00
Ryan Dahl
10af67714b Optimize emit for two arguments 2010-09-17 11:18:54 -07:00
Ryan Dahl
180a04805b Make a list of known globals
And fix missing var!

It would be good to get this script running at the end of every test, so we
know that modules aren't leaking either - but it will require a lot
modification of the tests so that they themselves aren't leaking globals.
2010-09-17 11:18:42 -07:00
Ryan Dahl
ee21920571 Use child_process.exec rather than sys.exec 2010-09-17 11:17:33 -07:00
isaacs
66bce65d33 Bug in realpath with symlinks to absolute folder paths which have children.
Found by Cliffano Subagio
http://groups.google.com/group/nodejs/browse_thread/thread/f46f093938265ac0/387e14da08c7dd7b?
2010-09-17 11:17:26 -07:00
Tony Metzidis
2005ef9e37 Catch Exceptions thrown when openssl is disabled 2010-09-17 11:17:08 -07:00
Tony Metzidis
3816ebc85f - fix AttributeError on "use_openssl" when doing ./configure --without-ssl - error was: AttributeError: Values instance has no attribute 'use_openssl' 2010-09-17 11:17:00 -07:00
Ryan Dahl
4c5520a37e Fix style in node_object_wrap.h 2010-09-17 11:16:45 -07:00
Ryan Dahl
0ddad3fbc7 Fix style in readline 2010-09-17 11:12:01 -07:00
Ryan Dahl
db6a1788b2 Add SIGWINCH handler for readline 2010-09-17 11:11:52 -07:00
Ryan Dahl
1d17874a7d add to todo 2010-09-17 11:11:47 -07:00
Trent Mick
3191802605 add ANSI coloring option to sys.inspect and, by default, to the repl 2010-09-17 11:11:32 -07:00
Ryan Dahl
da235fa12c bump version to v0.2.1 2010-09-10 13:52:33 -07:00
Paul Querna
92fb664bfc Expose fingerproint from getPeerCertificate
Expose the SHA1 digest of the certificate as the fingerprint attribute in
the object returned by getPeerCertificate()
2010-09-10 13:31:46 -07:00
Ryan Dahl
7704fb9711 Fix fs.realpathSync('/') 2010-09-10 13:31:39 -07:00
isaacs
c099e274d2 Better temporary directory handling for tests.
Add a setUp and tearDown function to the test case class, and use it to
create and remove the test/tmp directory for each test.

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

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

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

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

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ test/fixtures/hello.txt
tmp/
node
node_g
*.swp

View File

@@ -109,8 +109,17 @@ Chandra Sekar S <chandru.in@gmail.com>
Andrew Naylor <argon@mkbot.net>
Benjamin Kramer <benny.kra@gmail.com>
Danny Coates <dannycoates@gmail.com>
Samuel Shull <brickysam26@gmail.com>
Nick Stenning <nick@whiteink.com>
Bert Belder <bertbelder@gmail.com>
Trent Mick <trentm@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com>
Illarionov Oleg <oleg@emby.ru>
Aria Stewart <aredridel@nbtsc.org>
Johan Euphrosine <proppy@aminche.com>
Russell Haering <russellhaering@gmail.com>
Bradley Meck <bradley.meck@gmail.com>
Tobie Langel <tobie.langel@gmail.com>
Tony Metzidis <tonym@tonym.us>
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
Evan Larkin <evan.larkin.il.com>

View File

@@ -1,4 +1,55 @@
2010.08.20, Version 0.2.0
2010.10.02, Version 0.2.3
* Fix require in REPL (bug introduced in v0.2.2)
* Pass correct message in client HTTP upgrade event.
(Fedor Indutny)
* Show function names in sys.inspect (Jorge Chamorro Bieling)
* In HTTP, close connection on the "connection:close" header.
(Mikeal Rogers)
* fs.ReadStream bug fixes (Tj Holowaychuk, Evan Larkin, Marco Rogers)
* Fix zero length buffer bug for http res.end()
2010.09.17, Version 0.2.2, 7bf46bc9808f4db98f1cf177d58a6ecf3a50b65d
* REPL improvements (Trent Mick)
* Fix bug in fs.realpath (Isaac Schlueter)
* sys.pump catches errors (Russell Haering)
2010.09.10, Version 0.2.1, da235fa12c208fc8243600e128db2c9b55624c5c
* REPL improvements (Johan Euphrosine, Brian White)
* nextTick bug fixes (Benjamin Thomas, Felix Geisendörfer,
Trent Mick)
* fs module bug fixes (Russell Haering, Marco Rogers, Tobie Langel,
Isaac Schlueter)
* Build script change for OpenEmbedded.
* Most constrctuors work without 'new' now.
* Allow Strings for ports on net.Server.listen (Bradley Meck)
* setInterval(cb, 0) loops infinitely
* Fixes for NODE_MODULE_CONTEXTS=1 (Herbert Vojčík)
* Expose fingerproint from getPeerCertificate (Paul Querna)
* API: forceClose -> destroy for WriteStreams
2010.08.20, Version 0.2.0, 9283e134e558900ba89d9a33c18a9bdedab07cb9
* process.title support for FreeBSD, Macintosh, Linux
@@ -116,7 +167,7 @@
* Upgrade http-parser, V8 to 2.2.21
2010.06.21, Version 0.1.99, a620b7298f68f68a855306437a3b60b650d61d78
2010.06.21, Version 0.1.99, a620b7298f68f68a855306437a3b60b650d61d78
* Datagram sockets (Paul Querna)
@@ -222,7 +273,7 @@
2010.05.06, Version 0.1.94, f711d5343b29d1e72e87107315708e40951a7826
* Look in /usr/local/lib/node for modules, so that there's a way
* Look in /usr/local/lib/node for modules, so that there's a way
to install modules globally (Issac Schlueter)
* SSL improvements (Rhys Jones, Paulo Matias)
@@ -242,7 +293,7 @@
* Bugfix: destroy() instead of end() http connection at end of
pipeline
* Bugfix: http.Client may be prematurely released back to the
* Bugfix: http.Client may be prematurely released back to the
free pool. (Thomas Lee)
* Upgrade V8 to 2.2.8

4
TODO
View File

@@ -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

View File

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

View 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));

View 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);
}

View 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'

View File

@@ -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);
}

View File

@@ -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
View File

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

View File

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

View File

@@ -860,8 +860,9 @@ Experimental
Read the data from `readableStream` and send it to the `writableStream`.
When `writeableStream.write(data)` returns `false` `readableStream` will be
paused until the `drain` event occurs on the `writableStream`. `callback` is
called when `writableStream` is closed.
paused until the `drain` event occurs on the `writableStream`. `callback` gets
an error as its only argument and is called when `writableStream` is closed or
when an error occurs.
## Timers
@@ -1447,19 +1448,6 @@ See pwrite(2).
The callback will be given two arguments `(err, written)` where `written`
specifies how many _bytes_ were written.
### fs.write(fd, str, position, encoding='utf8', [callback])
Write the entire string `str` using the given `encoding` to the file specified
by `fd`.
`position` refers to the offset from the beginning of the file where this data
should be written. If `position` is `null`, the data will be written at the
current position.
See pwrite(2).
The callback will be given two arguments `(err, written)` where `written`
specifies how many _bytes_ were written.
### fs.writeSync(fd, buffer, offset, length, position)
Synchronous version of buffer-based `fs.write()`. Returns the number of bytes written.
@@ -1483,19 +1471,6 @@ If `position` is `null`, data will be read from the current file position.
The callback is given the two arguments, `(err, bytesRead)`.
### fs.read(fd, length, position, encoding, [callback])
Read data from the file specified by `fd`.
`length` is an integer specifying the number of bytes to read.
`position` is an integer specifying where to begin reading from in the file.
If `position` is `null`, data will be read from the current file position.
`encoding` is the desired encoding of the string of data read in from `fd`.
The callback is given the three arguments, `(err, str, bytesRead)`.
### fs.readSync(fd, buffer, offset, length, position)
Synchronous version of buffer-based `fs.read`. Returns the number of `bytesRead`.
@@ -1607,6 +1582,12 @@ An example to read the last 10 bytes of a file which is 100 bytes long:
`WriteStream` is a `Writable Stream`.
### Event: 'open'
`function (fd) { }`
`fd` is the file descriptor used by the WriteStream.
### fs.createWriteStream(path, [options])
Returns a new WriteStream object (See `Writable Stream`).
@@ -2225,7 +2206,7 @@ See `connect()`.
`function () { }`
Emitted when a stream connection successfully establishes a HTTPS handshake with its peer.
Emitted when a stream connection successfully establishes an SSL handshake with its peer.
### Event: 'data'
@@ -2314,9 +2295,9 @@ received.
### stream.setSecure([credentials])
Enables HTTPS support for the stream, with the crypto module credentials specifying the private key and certificate of the stream, and optionally the CA certificates for use in peer authentication.
Enables SSL support for the stream, with the crypto module credentials specifying the private key and certificate of the stream, and optionally the CA certificates for use in peer authentication.
If the credentials hold one ore more CA certificates, then the stream will request for the peer to submit a client certificate as part of the HTTPS connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate().
If the credentials hold one ore more CA certificates, then the stream will request for the peer to submit a client certificate as part of the SSL connection handshake. The validity and content of this can be accessed via verifyPeer() and getPeerCertificate().
### stream.verifyPeer()
@@ -3284,3 +3265,49 @@ All Node addons must export a function called `init` with this signature:
For the moment, that is all the documentation on addons. Please see
<http://github.com/ry/node_postgres> for a real example.
## Appendix - Third Party Modules
There are many third party modules for Node. At the time of writing, August
2010, the master repository of modules is
http://github.com/ry/node/wiki/modules[the wiki page].
This appendix is intended as a SMALL guide to new-comers to help them
quickly find what are considered to be quality modules. It is not intended
to be a complete list. There may be better more complete modules found
elsewhere.
- Module Installer: [npm](http://github.com/isaacs/npm)
- HTTP Middleware: [Connect](http://github.com/senchalabs/connect)
- Web Framework: [Express](http://github.com/visionmedia/express)
- Web Sockets: [Socket.IO](http://github.com/LearnBoost/Socket.IO-node)
- HTML Parsing: [HTML5](http://github.com/aredridel/html5)
- [mDNS/Zeroconf/Bonjour](http://github.com/agnat/node_mdns)
- [RabbitMQ, AMQP](http://github.com/ry/node-amqp)
- [mysql](http://github.com/felixge/node-mysql)
- Serialization: [msgpack](http://github.com/pgriess/node-msgpack)
- Scraping: [Apricot](http://github.com/silentrob/Apricot)
- Debugger: [ndb](http://github.com/smtlaissezfaire/ndb) is a CLI debugger
[inspector](http://github.com/dannycoates/node-inspector) is a web based
tool.
- [pcap binding](http://github.com/mranney/node_pcap)
- [ncurses](http://github.com/mscdex/node-ncurses)
- Testing/TDD/BDD: [vows](http://vowsjs.org/),
[expresso](http://github.com/visionmedia/expresso),
[mjsunit.runner](http://github.com/tmpvar/mjsunit.runner)
Patches to this list are welcome.

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
View File

@@ -6,7 +6,7 @@ var binding = process.binding('fs');
var fs = exports;
var kMinPoolSpace = 128;
var kPoolSize = 40*1024;
var kPoolSize = 40 * 1024;
fs.Stats = binding.Stats;
@@ -56,7 +56,7 @@ fs.readFile = function (path, encoding_, callback) {
function doRead() {
if (size < 1) {
binding.close(fd);
callback(null, buffer);
callback(null, encoding ? '' : buffer);
return;
}
// position is offset or null so we can read files on unseekable mediums
@@ -140,8 +140,11 @@ fs.closeSync = function (fd) {
return binding.close(fd);
};
fs.open = function (path, flags, mode, callback) {
if (mode === undefined) { mode = 0666; }
fs.open = function (path, flags, mode_, callback) {
var mode = (typeof(mode_) == 'number' ? mode_ : 0666);
var callback_ = arguments[arguments.length - 1];
var callback = (typeof(callback_) == 'function' ? callback_ : null);
binding.open(path, stringToFlags(flags), mode, callback || noop);
};
@@ -208,7 +211,15 @@ fs.write = function (fd, buffer, offset, length, position, callback) {
offset = 0;
length = buffer.length;
}
if(!length) return;
if (!length) {
if (typeof callback == 'function') {
process.nextTick(function() {
callback(undefined, 0);
});
}
return;
}
binding.write(fd, buffer, offset, length, position, callback || noop);
};
@@ -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);
}
};

View File

@@ -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.

View File

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

View File

@@ -15,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;

View File

@@ -48,13 +48,31 @@ function REPLServer(prompt, stream) {
self.buffered_cmd = '';
self.stream = stream || process.openStdin();
self.prompt = prompt || "node> ";
self.prompt = prompt || "> ";
var rli = self.rli = rl.createInterface(self.stream, function (text) {
return self.complete(text);
});
if (rli.enabled) {
// Turn on ANSI coloring.
exports.writer = function(obj, showHidden, depth) {
return sys.inspect(obj, showHidden, depth, true);
}
}
rli.setPrompt(self.prompt);
rli.on("SIGINT", function () {
if (self.buffered_cmd && self.buffered_cmd.length > 0) {
rli.write("\n");
self.buffered_cmd = '';
self.displayPrompt();
} else {
rli.close();
}
});
self.stream.addListener("data", function (chunk) {
rli.write(chunk);
});
@@ -130,7 +148,7 @@ exports.start = function (prompt, source) {
};
REPLServer.prototype.displayPrompt = function () {
this.rli.setPrompt(this.buffered_cmd.length ? '... ' : this.prompt);
this.rli.setPrompt(this.buffered_cmd.length ? '... ' : this.prompt);
this.rli.prompt();
};
@@ -300,7 +318,8 @@ REPLServer.prototype.complete = function (line) {
if (typeof obj === "object" || typeof obj === "function") {
memberGroups.push(Object.getOwnPropertyNames(obj));
}
var p = obj.constructor.prototype; // works for non-objects
// works for non-objects
var p = obj.constructor ? obj.constructor.prototype : null;
try {
var sentinel = 5;
while (p !== null) {
@@ -380,7 +399,8 @@ REPLServer.prototype.parseREPLKeyword = function (cmd) {
var self = this;
switch (cmd) {
case ".break":
case ".break":
// TODO remove me after 0.3.x
self.buffered_cmd = '';
self.displayPrompt();
return true;
@@ -394,7 +414,6 @@ REPLServer.prototype.parseREPLKeyword = function (cmd) {
self.stream.destroy();
return true;
case ".help":
self.stream.write(".break\tSometimes you get stuck in a place you can't get out... This will get you out.\n");
self.stream.write(".clear\tBreak, and also clear the local context.\n");
self.stream.write(".exit\tExit the prompt\n");
self.stream.write(".help\tShow repl options\n");

View File

@@ -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);
});
};

View File

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

View File

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

View File

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

View File

@@ -49,9 +49,20 @@ var nextTickQueue = [];
process._tickCallback = function () {
var l = nextTickQueue.length;
if (l === 0) return;
for (var i = 0; i < l; i++) {
nextTickQueue[i]();
try {
for (var i = 0; i < l; i++) {
nextTickQueue[i]();
}
}
catch(e) {
nextTickQueue.splice(0, i+1);
if (i+1 < l) {
process._needTickCallback();
}
throw e;
}
nextTickQueue.splice(0, l);
};
@@ -187,17 +198,6 @@ var module = (function () {
return;
}
/* if (dirs.length == 0) {
if (callback) {
callback();
} else {
return; // sync returns null
}
} //no need for this, eventually move simpler if to traverser
// question: what with /absolute/id when dirs.length is 0?
// if "load it anyway", then this ^^^ code is wrong, but omitting it
// makes it right*/
var nextLoc = traverser(id, id.charAt(0) === '/' ? [''] : dirs);
var fs = requireNative('fs');
@@ -433,6 +433,7 @@ var module = (function () {
sandbox.__filename = filename;
sandbox.__dirname = dirname;
sandbox.module = self;
sandbox.global = sandbox;
sandbox.root = root;
Script.runInNewContext(content, sandbox, filename);
@@ -533,8 +534,8 @@ var events = module.requireNative('events');
// Signal Handlers
(function() {
var signalWatchers = {};
addListener = process.addListener,
removeListener = process.removeListener;
var addListener = process.addListener;
var removeListener = process.removeListener;
function isSignal (event) {
return event.slice(0, 3) === 'SIG' && process.hasOwnProperty(event);
@@ -596,12 +597,13 @@ global.setTimeout = function (callback, after) {
global.setInterval = function (callback, repeat) {
var timer = new process.Timer();
addTimerListener.apply(timer, arguments);
timer.start(repeat, repeat);
timer.start(repeat, repeat ? repeat : 1);
return timer;
};
global.clearTimeout = function (timer) {
if (timer instanceof process.Timer) {
timer.callback = null;
timer.stop();
}
};
@@ -748,12 +750,14 @@ if (process.argv[1]) {
process.argv[1] = path.join(cwd, process.argv[1]);
}
module.runMain();
// REMOVEME: nextTick should not be necessary. This hack to get
// test/simple/test-exception-handler2.js working.
process.nextTick(function() {
module.runMain();
});
} else {
// No arguments, run the repl
var repl = module.requireNative('repl');
console.log("Type '.help' for options.");
repl.start();
module.requireNative('repl').start();
}
// All our arguments are loaded. We've evaluated all of the scripts. We

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,6 +12,7 @@ class ObjectWrap {
refs_ = 0;
}
virtual ~ObjectWrap ( ) {
if (!handle_.IsEmpty()) {
assert(handle_.IsNearDeath());
@@ -21,29 +22,28 @@ class ObjectWrap {
}
}
template <class T>
static inline T* Unwrap (v8::Handle<v8::Object> handle)
{
static inline T* Unwrap (v8::Handle<v8::Object> handle) {
assert(!handle.IsEmpty());
assert(handle->InternalFieldCount() > 0);
return static_cast<T*>(v8::Handle<v8::External>::Cast(
handle->GetInternalField(0))->Value());
return static_cast<T*>(handle->GetPointerFromInternalField(0));
}
v8::Persistent<v8::Object> handle_; // ro
protected:
inline void Wrap (v8::Handle<v8::Object> handle)
{
inline void Wrap (v8::Handle<v8::Object> handle) {
assert(handle_.IsEmpty());
assert(handle->InternalFieldCount() > 0);
handle_ = v8::Persistent<v8::Object>::New(handle);
handle_->SetInternalField(0, v8::External::New(this));
handle_->SetPointerInInternalField(0, this);
MakeWeak();
}
inline void MakeWeak (void)
{
inline void MakeWeak (void) {
handle_.MakeWeak(this, WeakCallback);
}
@@ -73,11 +73,12 @@ class ObjectWrap {
if (--refs_ == 0) { MakeWeak(); }
}
int refs_; // ro
private:
static void WeakCallback (v8::Persistent<v8::Value> value, void *data)
{
static void WeakCallback (v8::Persistent<v8::Value> value, void *data) {
ObjectWrap *obj = static_cast<ObjectWrap*>(data);
assert(value == obj->handle_);
assert(!obj->refs_);

View File

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

View File

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

View File

@@ -3,6 +3,7 @@ var path = require("path");
exports.testDir = path.dirname(__filename);
exports.fixturesDir = path.join(exports.testDir, "fixtures");
exports.libDir = path.join(exports.testDir, "../lib");
exports.tmpDir = path.join(exports.testDir, "tmp");
exports.PORT = 12346;
exports.assert = require('assert');

View File

@@ -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 () {

View File

@@ -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);

View File

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

View File

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

View File

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

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

@@ -0,0 +1 @@
;

View File

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

View File

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

View File

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

View File

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

View File

@@ -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");

View File

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

View File

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

View File

@@ -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);
});

View File

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

View File

@@ -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);

View File

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

View File

@@ -0,0 +1,28 @@
common = require("../common");
assert = common.assert
var path = require('path'),
fs = require('fs');
var file = path.join(common.fixturesDir, "write.txt");
(function() {
var stream = fs.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();
})();

View File

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

View File

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

View File

@@ -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);
}
}

View File

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

View File

@@ -0,0 +1,34 @@
var common = require("../common");
var assert = require('assert');
var http = require('http');
var net = require('net');
// Create a TCP server
var srv = net.createServer(function(c) {
c.write('bad http - should trigger parse error\r\n');
console.log("connection");
c.addListener('end', function() { c.end(); });
});
srv.listen(common.PORT, '127.0.0.1');
var hc = http.createClient(common.PORT, '127.0.0.1');
hc.request('GET', '/').end();
var parseError = false;
hc.on('error', function (e) {
console.log("got error from client");
srv.close();
assert.ok(e.message.indexOf("Parse Error") >= 0);
parseError = true;
});
process.addListener('exit', function() {
assert.ok(parseError);
});

View 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);
});

View File

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

View File

@@ -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;
});

View File

@@ -8,48 +8,21 @@ assert = common.assert
var http = require('http');
var net = require('net');
// Parse a string of data, returning an object if headers are complete, and
// undefined otherwise
var parseHeaders = function(data) {
var m = data.search(/\r\n\r\n/);
if (!m) {
return;
}
var o = {};
data.substring(0, m.index).split('\r\n').forEach(function(h) {
var foo = h.split(':');
if (foo.length < 2) {
return;
}
o[foo[0].trim().toLowerCase()] = foo[1].trim().toLowerCase();
});
return o;
};
// Create a TCP server
var srv = net.createServer(function(c) {
var data = '';
c.addListener('data', function(d) {
data += d.toString('utf8');
// We found the end of the headers; make sure that we have an 'upgrade'
// header and send back a response
var headers = parseHeaders(data);
if (!headers) {
return;
}
assert.ok('upgrade' in headers);
c.write('HTTP/1.1 101\r\n');
c.write('hello: world\r\n');
c.write('connection: upgrade\r\n');
c.write('upgrade: ' + headers.upgrade + '\r\n');
c.write('upgrade: websocket\r\n');
c.write('\r\n');
c.write('nurtzo');
});
c.addListener('end', function() {
c.end();
});
});
@@ -57,20 +30,24 @@ srv.listen(common.PORT, '127.0.0.1');
var gotUpgrade = false;
var hc = http.createClient(common.PORT, '127.0.0.1');
hc.addListener('upgrade', function(req, socket, upgradeHead) {
hc.addListener('upgrade', function(res, socket, upgradeHead) {
// XXX: This test isn't fantastic, as it assumes that the entire response
// from the server will arrive in a single data callback
assert.equal(upgradeHead, 'nurtzo');
console.log(res.headers);
var expectedHeaders = { "hello": "world"
, "connection": "upgrade"
, "upgrade": "websocket"
};
assert.deepEqual(expectedHeaders, res.headers);
socket.end();
srv.close();
gotUpgrade = true;
});
hc.request('/', {
'Connection' : 'Upgrade',
'Upgrade' : 'WebSocket'
}).end();
hc.request('GET', '/').end();
process.addListener('exit', function() {
assert.ok(gotUpgrade);

View File

@@ -0,0 +1,64 @@
var common = require("../common");
var assert = common.assert
var http = require('http'),
CRLF = '\r\n';
var server = http.createServer();
server.on('upgrade', function(req, socket, head) {
socket.write('HTTP/1.1 101 Ok' + CRLF +
'Connection: Upgrade' + CRLF +
'Upgrade: Test' + CRLF + CRLF + 'head');
socket.on('end', function () {
socket.end();
});
});
server.listen(8000);
var client = http.createClient(8000);
function upgradeRequest(fn) {
var request = client.request('GET', '/', {
'Connection': 'Upgrade',
'Upgrade': 'Test'
});
var wasUpgrade = false;
function onUpgrade(res, socket, head) {
wasUpgrade = true;
client.removeListener('upgrade', onUpgrade);
socket.end();
}
client.on('upgrade', onUpgrade);
function onEnd() {
client.removeListener('end', onEnd);
if (!wasUpgrade) {
throw new Error('hasn\'t received upgrade event');
} else {
fn && process.nextTick(fn);
}
}
client.on('end', onEnd);
request.write('head');
}
successCount = 0;
upgradeRequest(function() {
successCount++;
upgradeRequest(function() {
successCount++;
// Test pass
console.log('Pass!');
client.end();
client.destroy();
server.close();
});
});
process.on('exit', function () {
assert.equal(2, successCount);
});

View File

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

View File

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

View File

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

View File

@@ -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");
});
});

View File

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

View File

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

View File

@@ -0,0 +1,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");
});

View File

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

View File

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

View File

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

View File

@@ -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);
});

View File

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

View File

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

58
wscript
View File

@@ -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")