Merge branch 'v0.4'
Conflicts: lib/tls.js lib/url.js src/node_version.h test/simple/test-buffer.js test/simple/test-url.js
This commit is contained in:
commit
205b9beb6b
2
AUTHORS
2
AUTHORS
@ -170,4 +170,6 @@ Arnout Kazemier <info@3rd-Eden.com>
|
||||
George Stagas <gstagas@gmail.com>
|
||||
Scott McWhirter <scott.mcwhirter@joyent.com>
|
||||
Jakub Lekstan <jakub.lekstan@dreamlab.pl>
|
||||
Tim Baumann <tim@timbaumann.info>
|
||||
Robert Mustacchi <rm@joyent.com>
|
||||
|
||||
|
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
2011.04.22, Version 0.4.7 (stable)
|
||||
|
||||
* Don't emit error on ECONNRESET from read() #670
|
||||
|
||||
* Fix: Multiple pipes to the same stream were broken #929
|
||||
(Felix Geisendörfer)
|
||||
|
||||
* URL parsing/formatting corrections #954 (isaacs)
|
||||
|
||||
* make it possible to do repl.start('', stream) (Wade Simmons)
|
||||
|
||||
* Add os.loadavg for SunOS (Robert Mustacchi)
|
||||
|
||||
* Fix timeouts with floating point numbers #897 (Jorge Chamorro Bieling)
|
||||
|
||||
* Improve docs.
|
||||
|
||||
|
||||
2011.04.13, Version 0.4.6 (stable)
|
||||
|
||||
* Don't error on ENOTCONN from shutdown() #670
|
||||
|
8
deps/v8/src/arm/code-stubs-arm.cc
vendored
8
deps/v8/src/arm/code-stubs-arm.cc
vendored
@ -3425,6 +3425,8 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||
// Save the left value on the stack.
|
||||
__ Push(r5, r4);
|
||||
|
||||
Label pop_and_call_runtime;
|
||||
|
||||
// Allocate a heap number to store the result.
|
||||
heap_number_result = r5;
|
||||
GenerateHeapResultAllocation(masm,
|
||||
@ -3432,7 +3434,7 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||
heap_number_map,
|
||||
scratch1,
|
||||
scratch2,
|
||||
&call_runtime);
|
||||
&pop_and_call_runtime);
|
||||
|
||||
// Load the left value from the value saved on the stack.
|
||||
__ Pop(r1, r0);
|
||||
@ -3440,6 +3442,10 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||
// Call the C function to handle the double operation.
|
||||
FloatingPointHelper::CallCCodeForDoubleOperation(
|
||||
masm, op_, heap_number_result, scratch1);
|
||||
|
||||
__ bind(&pop_and_call_runtime);
|
||||
__ Drop(2);
|
||||
__ b(&call_runtime);
|
||||
}
|
||||
|
||||
break;
|
||||
|
4
deps/v8/src/builtins.cc
vendored
4
deps/v8/src/builtins.cc
vendored
@ -818,8 +818,8 @@ BUILTIN(ArraySplice) {
|
||||
const int delta = actual_delete_count - item_count;
|
||||
|
||||
if (actual_start > 0) {
|
||||
Object** start = elms->data_start();
|
||||
memmove(start + delta, start, actual_start * kPointerSize);
|
||||
AssertNoAllocation no_gc;
|
||||
MoveElements(&no_gc, elms, delta, elms, 0, actual_start);
|
||||
}
|
||||
|
||||
elms = LeftTrimFixedArray(elms, delta);
|
||||
|
2
deps/v8/src/runtime.cc
vendored
2
deps/v8/src/runtime.cc
vendored
@ -2625,7 +2625,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
|
||||
end = RegExpImpl::GetCapture(match_info_array, 1);
|
||||
}
|
||||
|
||||
int length = subject->length();
|
||||
int length = subject_handle->length();
|
||||
int new_length = length - (end - start);
|
||||
if (new_length == 0) {
|
||||
return Heap::empty_string();
|
||||
|
2
deps/v8/src/version.cc
vendored
2
deps/v8/src/version.cc
vendored
@ -35,7 +35,7 @@
|
||||
#define MAJOR_VERSION 3
|
||||
#define MINOR_VERSION 1
|
||||
#define BUILD_NUMBER 8
|
||||
#define PATCH_LEVEL 10
|
||||
#define PATCH_LEVEL 14
|
||||
#define CANDIDATE_VERSION false
|
||||
|
||||
// Define SONAME to have the SCons build the put a specific SONAME into the
|
||||
|
@ -88,7 +88,7 @@ sent to the server on that socket.
|
||||
|
||||
If a client connection emits an 'error' event - it will forwarded here.
|
||||
|
||||
### http.createServer(requestListener)
|
||||
### http.createServer([requestListener])
|
||||
|
||||
Returns a new web server object.
|
||||
|
||||
@ -397,6 +397,10 @@ Example:
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', function(e) {
|
||||
console.log('problem with request: ' + e.message);
|
||||
});
|
||||
|
||||
// write data to request body
|
||||
req.write('data\n');
|
||||
req.write('data\n');
|
||||
|
@ -4,7 +4,15 @@ HTTPS is the HTTP protocol over TLS/SSL. In Node this is implemented as a
|
||||
separate module.
|
||||
|
||||
## https.Server
|
||||
## https.createServer
|
||||
|
||||
This class is a subclass of `tls.Server` and emits events same as
|
||||
`http.Server`. See `http.Server` for more information.
|
||||
|
||||
## https.createServer(options, [requestListener])
|
||||
|
||||
Returns a new HTTPS web server object. The `options` is similer to
|
||||
`tls.createServer()`. The `requestListener` is a function which is
|
||||
automatically added to the `'request'` event.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -33,7 +33,7 @@ Example of using `vm.runInThisContext` and `eval` to run the same code:
|
||||
`eval` does have access to the local scope, so `localVar` is changed.
|
||||
|
||||
In case of syntax error in `code`, `vm.runInThisContext` emits the syntax error to stderr
|
||||
and throws.an exception.
|
||||
and throws an exception.
|
||||
|
||||
|
||||
### vm.runInNewContext(code, [sandbox], [filename])
|
||||
@ -62,7 +62,7 @@ Note that running untrusted code is a tricky business requiring great care. To
|
||||
global variable leakage, `vm.runInNewContext` is quite useful, but safely running untrusted code
|
||||
requires a separate process.
|
||||
|
||||
In case of syntax error in `code`, `vm.runInThisContext` emits the syntax error to stderr
|
||||
In case of syntax error in `code`, `vm.runInNewContext` emits the syntax error to stderr
|
||||
and throws an exception.
|
||||
|
||||
|
||||
|
@ -24,9 +24,9 @@
|
||||
<div id="toc">
|
||||
<ol>
|
||||
<li><a href="#download">Download</a></li>
|
||||
<li><a href="https://github.com/joyent/node/raw/master/ChangeLog">ChangeLog</a></li>
|
||||
<li><a href="https://github.com/joyent/node/raw/v0.4/ChangeLog">ChangeLog</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="http://nodejs.org/docs/v0.4.6/api">v0.4.6 docs</a></li>
|
||||
<li><a href="http://nodejs.org/docs/v0.4.7/api">v0.4.7 docs</a></li>
|
||||
<br/>
|
||||
<li><a href="https://github.com/joyent/node/wiki">Wiki</a></li>
|
||||
<li><a href="http://blog.nodejs.org/">Blog</a></li>
|
||||
@ -55,8 +55,8 @@ var http = require('http');
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.end('Hello World\n');
|
||||
}).listen(8124, "127.0.0.1");
|
||||
console.log('Server running at http://127.0.0.1:8124/');
|
||||
}).listen(1337, "127.0.0.1");
|
||||
console.log('Server running at http://127.0.0.1:1337/');
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@ -66,10 +66,10 @@ console.log('Server running at http://127.0.0.1:8124/');
|
||||
</p>
|
||||
<pre class="sh_none">
|
||||
% node example.js
|
||||
Server running at http://127.0.0.1:8124/</pre>
|
||||
Server running at http://127.0.0.1:1337/</pre>
|
||||
|
||||
<p>
|
||||
Here is an example of a simple TCP server which listens on port 8124
|
||||
Here is an example of a simple TCP server which listens on port 1337
|
||||
and echoes whatever you send it:
|
||||
</p>
|
||||
|
||||
@ -79,9 +79,9 @@ var net = require('net');
|
||||
var server = net.createServer(function (socket) {
|
||||
socket.write("Echo server\r\n");
|
||||
socket.pipe(socket);
|
||||
})
|
||||
});
|
||||
|
||||
server.listen(8124, "127.0.0.1");
|
||||
server.listen(1337, "127.0.0.1");
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@ -107,9 +107,9 @@ server.listen(8124, "127.0.0.1");
|
||||
</p>
|
||||
|
||||
<p>
|
||||
2011.04.13
|
||||
<a href="http://nodejs.org/dist/node-v0.4.6.tar.gz">node-v0.4.6.tar.gz</a>
|
||||
(<a href="http://nodejs.org/docs/v0.4.6/api/index.html">Documentation</a>)
|
||||
2011.04.22
|
||||
<a href="http://nodejs.org/dist/node-v0.4.7.tar.gz">node-v0.4.7.tar.gz</a>
|
||||
(<a href="http://nodejs.org/docs/v0.4.7/api/index.html">Documentation</a>)
|
||||
</p>
|
||||
|
||||
<p>Historical: <a href="http://nodejs.org/dist">versions</a>, <a href="http://nodejs.org/docs">docs</a></p>
|
||||
|
@ -291,7 +291,10 @@ Client.prototype.reqEval = function(expression, cb) {
|
||||
var frame = bt.frames[self.currentFrame];
|
||||
|
||||
var evalFrames = frame.scopes.map(function(s) {
|
||||
return bt.frames[s.index].index;
|
||||
if (!s) return;
|
||||
var x = bt.frames[s.index];
|
||||
if (!x) return;
|
||||
return x.index;
|
||||
});
|
||||
|
||||
self._reqFramesEval(expression, evalFrames, cb);
|
||||
@ -1043,19 +1046,16 @@ Interface.prototype.trySpawn = function(cb) {
|
||||
|
||||
this.pause();
|
||||
|
||||
setTimeout(function() {
|
||||
process.stdout.write('connecting...');
|
||||
var client = self.client = new Client();
|
||||
client.connect(exports.port);
|
||||
var client = self.client = new Client();
|
||||
var connectionAttempts = 0;
|
||||
|
||||
client.once('ready', function() {
|
||||
process.stdout.write('ok\r\n');
|
||||
client.once('ready', function() {
|
||||
process.stdout.write(' ok\r\n');
|
||||
|
||||
// since we did debug-brk, we're hitting a break point immediately
|
||||
// continue before anything else.
|
||||
client.reqContinue(function() {
|
||||
if (cb) cb();
|
||||
});
|
||||
// since we did debug-brk, we're hitting a break point immediately
|
||||
// continue before anything else.
|
||||
client.reqContinue(function() {
|
||||
if (cb) cb();
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
@ -1064,17 +1064,37 @@ Interface.prototype.trySpawn = function(cb) {
|
||||
self.killChild();
|
||||
if (!self.quitting) self.term.prompt();
|
||||
});
|
||||
});
|
||||
|
||||
client.on('unhandledResponse', function(res) {
|
||||
console.log('\r\nunhandled res:');
|
||||
console.log(res);
|
||||
self.term.prompt();
|
||||
});
|
||||
client.on('unhandledResponse', function(res) {
|
||||
console.log('\r\nunhandled res:');
|
||||
console.log(res);
|
||||
self.term.prompt();
|
||||
});
|
||||
|
||||
client.on('break', function(res) {
|
||||
self.handleBreak(res.body);
|
||||
});
|
||||
}, 100);
|
||||
client.on('break', function(res) {
|
||||
self.handleBreak(res.body);
|
||||
});
|
||||
|
||||
client.on('error', connectError);
|
||||
function connectError() {
|
||||
// If it's failed to connect 4 times then don't catch the next error
|
||||
if (connectionAttempts >= 4) {
|
||||
client.removeListener('error', connectError);
|
||||
}
|
||||
setTimeout(attemptConnect, 50);
|
||||
}
|
||||
|
||||
function attemptConnect() {
|
||||
++connectionAttempts;
|
||||
process.stdout.write('.');
|
||||
client.connect(exports.port);
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
process.stdout.write('connecting..');
|
||||
attemptConnect();
|
||||
}, 50);
|
||||
};
|
||||
|
||||
|
||||
|
@ -139,7 +139,7 @@ SlowBuffer.prototype.write = function(string, offset, encoding) {
|
||||
|
||||
case 'ucs2':
|
||||
case 'ucs-2':
|
||||
return this.ucs2Write(start, end);
|
||||
return this.ucs2Write(string, offset);
|
||||
|
||||
default:
|
||||
throw new Error('Unknown encoding');
|
||||
|
@ -1196,13 +1196,12 @@ Agent.prototype._establishNewConnection = function() {
|
||||
req = self.queue.shift();
|
||||
assert(req._queue === self.queue);
|
||||
req._queue = null;
|
||||
} else {
|
||||
// No requests on queue? Where is the request
|
||||
assert(0);
|
||||
}
|
||||
|
||||
req.emit('error', err);
|
||||
req._hadError = true; // hacky
|
||||
if (req) {
|
||||
req.emit('error', err);
|
||||
req._hadError = true; // hacky
|
||||
}
|
||||
|
||||
// clean up so that agent can handle new requests
|
||||
parser.finish();
|
||||
|
@ -80,7 +80,7 @@ function REPLServer(prompt, stream) {
|
||||
process.stdin.resume();
|
||||
}
|
||||
|
||||
self.prompt = prompt || '> ';
|
||||
self.prompt = (prompt != undefined ? prompt : '> ');
|
||||
|
||||
function complete(text) {
|
||||
return self.complete(text);
|
||||
@ -92,7 +92,7 @@ function REPLServer(prompt, stream) {
|
||||
this.commands = {};
|
||||
defineDefaultCommands(this);
|
||||
|
||||
if (rli.enabled && !disableColors) {
|
||||
if (rli.enabled && !disableColors && exports.writer === util.inspect) {
|
||||
// Turn on ANSI coloring.
|
||||
exports.writer = function(obj, showHidden, depth) {
|
||||
return util.inspect(obj, showHidden, depth, true);
|
||||
@ -181,8 +181,8 @@ function REPLServer(prompt, stream) {
|
||||
// It could also be an error from JSON.parse
|
||||
} else if (e &&
|
||||
e.stack &&
|
||||
e.stack.match('Unexpected token ILLEGAL') &&
|
||||
e.stack.match(/Object.parse \(native\)/)) {
|
||||
e.stack.match(/^SyntaxError: Unexpected token .*\n/) &&
|
||||
e.stack.match(/\n at Object.parse \(native\)\n/)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,9 @@ function Stream() {
|
||||
util.inherits(Stream, events.EventEmitter);
|
||||
exports.Stream = Stream;
|
||||
|
||||
var pipes = [];
|
||||
|
||||
Stream.prototype.pipe = function(dest, options) {
|
||||
var source = this;
|
||||
|
||||
pipes.push(dest);
|
||||
|
||||
function ondata(chunk) {
|
||||
if (dest.writable) {
|
||||
if (false === dest.write(chunk)) source.pause();
|
||||
@ -49,31 +45,66 @@ Stream.prototype.pipe = function(dest, options) {
|
||||
|
||||
dest.on('drain', ondrain);
|
||||
|
||||
/*
|
||||
* If the 'end' option is not supplied, dest.end() will be called when
|
||||
* source gets the 'end' event.
|
||||
*/
|
||||
|
||||
// If the 'end' option is not supplied, dest.end() will be called when
|
||||
// source gets the 'end' or 'close' events. Only dest.end() once, and
|
||||
// only when all sources have ended.
|
||||
if (!options || options.end !== false) {
|
||||
function onend() {
|
||||
var index = pipes.indexOf(dest);
|
||||
pipes.splice(index, 1);
|
||||
|
||||
if (pipes.indexOf(dest) > -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
dest.end();
|
||||
}
|
||||
dest._pipeCount = dest._pipeCount || 0;
|
||||
dest._pipeCount++;
|
||||
|
||||
source.on('end', onend);
|
||||
source.on('close', onend);
|
||||
source.on('close', onclose);
|
||||
}
|
||||
|
||||
/*
|
||||
* Questionable:
|
||||
*/
|
||||
var didOnEnd = false;
|
||||
function onend() {
|
||||
if (didOnEnd) return;
|
||||
didOnEnd = true;
|
||||
|
||||
dest._pipeCount--;
|
||||
|
||||
// remove the listeners
|
||||
cleanup();
|
||||
|
||||
if (dest._pipeCount > 0) {
|
||||
// waiting for other incoming streams to end.
|
||||
return;
|
||||
}
|
||||
|
||||
dest.end();
|
||||
}
|
||||
|
||||
|
||||
function onclose() {
|
||||
if (didOnEnd) return;
|
||||
didOnEnd = true;
|
||||
|
||||
dest._pipeCount--;
|
||||
|
||||
// remove the listeners
|
||||
cleanup();
|
||||
|
||||
if (dest._pipeCount > 0) {
|
||||
// waiting for other incoming streams to end.
|
||||
return;
|
||||
}
|
||||
|
||||
dest.destroy();
|
||||
}
|
||||
|
||||
// don't leave dangling pipes when there are errors.
|
||||
function onerror(er) {
|
||||
cleanup();
|
||||
if (this.listeners('error').length === 1) {
|
||||
throw er; // Unhandled stream error in pipe.
|
||||
}
|
||||
}
|
||||
|
||||
source.on('error', onerror);
|
||||
dest.on('error', onerror);
|
||||
|
||||
// guarantee that source streams can be paused and resumed, even
|
||||
// if the only effect is to proxy the event back up the pipe chain.
|
||||
if (!source.pause) {
|
||||
source.pause = function() {
|
||||
source.emit('pause');
|
||||
@ -86,27 +117,32 @@ Stream.prototype.pipe = function(dest, options) {
|
||||
};
|
||||
}
|
||||
|
||||
var onpause = function() {
|
||||
function onpause() {
|
||||
source.pause();
|
||||
}
|
||||
|
||||
dest.on('pause', onpause);
|
||||
|
||||
var onresume = function() {
|
||||
function onresume() {
|
||||
if (source.readable) source.resume();
|
||||
};
|
||||
}
|
||||
|
||||
dest.on('resume', onresume);
|
||||
|
||||
var cleanup = function () {
|
||||
// remove all the event listeners that were added.
|
||||
function cleanup() {
|
||||
source.removeListener('data', ondata);
|
||||
dest.removeListener('drain', ondrain);
|
||||
|
||||
source.removeListener('end', onend);
|
||||
source.removeListener('close', onend);
|
||||
source.removeListener('close', onclose);
|
||||
|
||||
dest.removeListener('pause', onpause);
|
||||
dest.removeListener('resume', onresume);
|
||||
|
||||
source.removeListener('error', onerror);
|
||||
dest.removeListener('error', onerror);
|
||||
|
||||
source.removeListener('end', cleanup);
|
||||
source.removeListener('close', cleanup);
|
||||
|
||||
|
193
lib/tls.js
193
lib/tls.js
@ -79,7 +79,7 @@ function CryptoStream(pair) {
|
||||
|
||||
this.readable = this.writable = true;
|
||||
|
||||
this._writeState = true;
|
||||
this._paused = false;
|
||||
this._pending = [];
|
||||
this._pendingCallbacks = [];
|
||||
this._pendingBytes = 0;
|
||||
@ -118,11 +118,10 @@ CryptoStream.prototype.write = function(data /* , encoding, cb */) {
|
||||
|
||||
this._pending.push(data);
|
||||
this._pendingCallbacks.push(cb);
|
||||
|
||||
this._pendingBytes += data.length;
|
||||
|
||||
this.pair._writeCalled = true;
|
||||
this.pair._cycle();
|
||||
this.pair.cycle();
|
||||
|
||||
return this._pendingBytes < 128 * 1024;
|
||||
};
|
||||
@ -130,14 +129,14 @@ CryptoStream.prototype.write = function(data /* , encoding, cb */) {
|
||||
|
||||
CryptoStream.prototype.pause = function() {
|
||||
debug('paused ' + (this == this.pair.cleartext ? 'cleartext' : 'encrypted'));
|
||||
this._writeState = false;
|
||||
this._paused = true;
|
||||
};
|
||||
|
||||
|
||||
CryptoStream.prototype.resume = function() {
|
||||
debug('resume ' + (this == this.pair.cleartext ? 'cleartext' : 'encrypted'));
|
||||
this._writeState = true;
|
||||
this.pair._cycle();
|
||||
this._paused = false;
|
||||
this.pair.cycle();
|
||||
};
|
||||
|
||||
|
||||
@ -175,8 +174,8 @@ function parseCertString(s) {
|
||||
|
||||
|
||||
CryptoStream.prototype.getPeerCertificate = function() {
|
||||
if (this.pair._ssl) {
|
||||
var c = this.pair._ssl.getPeerCertificate();
|
||||
if (this.pair.ssl) {
|
||||
var c = this.pair.ssl.getPeerCertificate();
|
||||
|
||||
if (c) {
|
||||
if (c.issuer) c.issuer = parseCertString(c.issuer);
|
||||
@ -190,8 +189,8 @@ CryptoStream.prototype.getPeerCertificate = function() {
|
||||
|
||||
|
||||
CryptoStream.prototype.getCipher = function(err) {
|
||||
if (this.pair._ssl) {
|
||||
return this.pair._ssl.getCurrentCipher();
|
||||
if (this.pair.ssl) {
|
||||
return this.pair.ssl.getCurrentCipher();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -199,23 +198,22 @@ CryptoStream.prototype.getCipher = function(err) {
|
||||
|
||||
|
||||
CryptoStream.prototype.end = function(d) {
|
||||
if (this.writable) {
|
||||
if (this.pair._done) return;
|
||||
if (this.pair._doneFlag) return;
|
||||
if (!this.writable) return;
|
||||
|
||||
if (d) {
|
||||
this.write(d);
|
||||
}
|
||||
|
||||
this._pending.push(END_OF_FILE);
|
||||
this._pendingCallbacks.push(null);
|
||||
|
||||
// If this is an encrypted stream then we need to disable further 'data'
|
||||
// events.
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.pair._cycle();
|
||||
if (d) {
|
||||
this.write(d);
|
||||
}
|
||||
|
||||
this._pending.push(END_OF_FILE);
|
||||
this._pendingCallbacks.push(null);
|
||||
|
||||
// If this is an encrypted stream then we need to disable further 'data'
|
||||
// events.
|
||||
|
||||
this.writable = false;
|
||||
|
||||
this.pair.cycle();
|
||||
};
|
||||
|
||||
|
||||
@ -229,8 +227,8 @@ CryptoStream.prototype.destroySoon = function(err) {
|
||||
|
||||
|
||||
CryptoStream.prototype.destroy = function(err) {
|
||||
if (this.pair._done) return;
|
||||
this.pair._destroy();
|
||||
if (this.pair._doneFlag) return;
|
||||
this.pair.destroy();
|
||||
};
|
||||
|
||||
|
||||
@ -239,9 +237,9 @@ CryptoStream.prototype._done = function() {
|
||||
|
||||
if (this.pair.cleartext._doneFlag &&
|
||||
this.pair.encrypted._doneFlag &&
|
||||
!this.pair._done) {
|
||||
!this.pair._doneFlag) {
|
||||
// If both streams are done:
|
||||
this.pair._destroy();
|
||||
this.pair.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
@ -269,7 +267,7 @@ CryptoStream.prototype._push = function() {
|
||||
return;
|
||||
}
|
||||
|
||||
while (this._writeState == true) {
|
||||
while (!this._paused) {
|
||||
var bytesRead = 0;
|
||||
var chunkBytes = 0;
|
||||
var pool = new Buffer(16 * 4096); // alloc every time?
|
||||
@ -277,18 +275,18 @@ CryptoStream.prototype._push = function() {
|
||||
do {
|
||||
chunkBytes = this._pusher(pool, bytesRead, pool.length - bytesRead);
|
||||
|
||||
if (this.pair._ssl && this.pair._ssl.error) {
|
||||
this.pair._error();
|
||||
if (this.pair.ssl && this.pair.ssl.error) {
|
||||
this.pair.error();
|
||||
return;
|
||||
}
|
||||
|
||||
this.pair._maybeInitFinished();
|
||||
this.pair.maybeInitFinished();
|
||||
|
||||
if (chunkBytes >= 0) {
|
||||
bytesRead += chunkBytes;
|
||||
}
|
||||
|
||||
} while ((chunkBytes > 0) && (bytesRead < pool.length));
|
||||
} while (chunkBytes > 0 && bytesRead < pool.length);
|
||||
|
||||
assert(bytesRead >= 0);
|
||||
|
||||
@ -341,7 +339,7 @@ CryptoStream.prototype._pull = function() {
|
||||
assert(havePending || this._pendingBytes == 0);
|
||||
|
||||
while (this._pending.length > 0) {
|
||||
if (!this.pair._ssl) break;
|
||||
if (!this.pair.ssl) break;
|
||||
|
||||
var tmp = this._pending.shift();
|
||||
var cb = this._pendingCallbacks.shift();
|
||||
@ -358,7 +356,7 @@ CryptoStream.prototype._pull = function() {
|
||||
assert(this === this.pair.cleartext);
|
||||
debug('end cleartext');
|
||||
|
||||
this.pair._ssl.shutdown();
|
||||
this.pair.ssl.shutdown();
|
||||
|
||||
// TODO check if we get EAGAIN From shutdown, would have to do it
|
||||
// again. should unshift END_OF_FILE back onto pending and wait for
|
||||
@ -366,7 +364,7 @@ CryptoStream.prototype._pull = function() {
|
||||
|
||||
this.pair.encrypted._destroyAfterPush = true;
|
||||
}
|
||||
this.pair._cycle();
|
||||
this.pair.cycle();
|
||||
this._done()
|
||||
return;
|
||||
}
|
||||
@ -375,12 +373,12 @@ CryptoStream.prototype._pull = function() {
|
||||
|
||||
var rv = this._puller(tmp);
|
||||
|
||||
if (this.pair._ssl && this.pair._ssl.error) {
|
||||
this.pair._error();
|
||||
if (this.pair.ssl && this.pair.ssl.error) {
|
||||
this.pair.error();
|
||||
return;
|
||||
}
|
||||
|
||||
this.pair._maybeInitFinished();
|
||||
this.pair.maybeInitFinished();
|
||||
|
||||
if (rv === 0 || rv < 0) {
|
||||
this._pending.unshift(tmp);
|
||||
@ -412,8 +410,8 @@ util.inherits(CleartextStream, CryptoStream);
|
||||
|
||||
|
||||
CleartextStream.prototype._internallyPendingBytes = function() {
|
||||
if (this.pair._ssl) {
|
||||
return this.pair._ssl.clearPending();
|
||||
if (this.pair.ssl) {
|
||||
return this.pair.ssl.clearPending();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -422,14 +420,14 @@ CleartextStream.prototype._internallyPendingBytes = function() {
|
||||
|
||||
CleartextStream.prototype._puller = function(b) {
|
||||
debug('clearIn ' + b.length + ' bytes');
|
||||
return this.pair._ssl.clearIn(b, 0, b.length);
|
||||
return this.pair.ssl.clearIn(b, 0, b.length);
|
||||
};
|
||||
|
||||
|
||||
CleartextStream.prototype._pusher = function(pool, offset, length) {
|
||||
debug('reading from clearOut');
|
||||
if (!this.pair._ssl) return -1;
|
||||
return this.pair._ssl.clearOut(pool, offset, length);
|
||||
if (!this.pair.ssl) return -1;
|
||||
return this.pair.ssl.clearOut(pool, offset, length);
|
||||
};
|
||||
|
||||
|
||||
@ -440,8 +438,8 @@ util.inherits(EncryptedStream, CryptoStream);
|
||||
|
||||
|
||||
EncryptedStream.prototype._internallyPendingBytes = function() {
|
||||
if (this.pair._ssl) {
|
||||
return this.pair._ssl.encPending();
|
||||
if (this.pair.ssl) {
|
||||
return this.pair.ssl.encPending();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -450,14 +448,14 @@ EncryptedStream.prototype._internallyPendingBytes = function() {
|
||||
|
||||
EncryptedStream.prototype._puller = function(b) {
|
||||
debug('writing from encIn');
|
||||
return this.pair._ssl.encIn(b, 0, b.length);
|
||||
return this.pair.ssl.encIn(b, 0, b.length);
|
||||
};
|
||||
|
||||
|
||||
EncryptedStream.prototype._pusher = function(pool, offset, length) {
|
||||
debug('reading from encOut');
|
||||
if (!this.pair._ssl) return -1;
|
||||
return this.pair._ssl.encOut(pool, offset, length);
|
||||
if (!this.pair.ssl) return -1;
|
||||
return this.pair.ssl.encOut(pool, offset, length);
|
||||
};
|
||||
|
||||
|
||||
@ -483,9 +481,7 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
|
||||
this._isServer = isServer ? true : false;
|
||||
this._encWriteState = true;
|
||||
this._clearWriteState = true;
|
||||
this._done = false;
|
||||
|
||||
var crypto = require('crypto');
|
||||
this._doneFlag = false;
|
||||
|
||||
if (!credentials) {
|
||||
this.credentials = crypto.createCredentials();
|
||||
@ -503,13 +499,13 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
|
||||
this._rejectUnauthorized = rejectUnauthorized ? true : false;
|
||||
this._requestCert = requestCert ? true : false;
|
||||
|
||||
this._ssl = new Connection(this.credentials.context,
|
||||
this.ssl = new Connection(this.credentials.context,
|
||||
this._isServer ? true : false,
|
||||
this._requestCert,
|
||||
this._rejectUnauthorized);
|
||||
|
||||
if (NPN_ENABLED && NPNProtocols) {
|
||||
this._ssl.setNPNProtocols(NPNProtocols);
|
||||
this.ssl.setNPNProtocols(NPNProtocols);
|
||||
this.npnProtocol = null;
|
||||
}
|
||||
|
||||
@ -520,8 +516,8 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
|
||||
this.encrypted = new EncryptedStream(this);
|
||||
|
||||
process.nextTick(function() {
|
||||
self._ssl.start();
|
||||
self._cycle();
|
||||
self.ssl.start();
|
||||
self.cycle();
|
||||
});
|
||||
}
|
||||
|
||||
@ -569,63 +565,57 @@ exports.createSecurePair = function(credentials,
|
||||
* Because it is also called everywhere, we also check if the connection has
|
||||
* completed negotiation and emit 'secure' from here if it has.
|
||||
*/
|
||||
SecurePair.prototype._cycle = function(depth) {
|
||||
depth = depth ? depth : 0;
|
||||
if (this._done) {
|
||||
return;
|
||||
}
|
||||
SecurePair.prototype.cycle = function(depth) {
|
||||
if (this._doneFlag) return;
|
||||
|
||||
if(depth == 0) this._writeCalled = false;
|
||||
depth = depth ? depth : 0;
|
||||
|
||||
if (depth == 0) this._writeCalled = false;
|
||||
|
||||
var established = this._secureEstablished;
|
||||
|
||||
if (!this._cycleEncryptedPullLock) {
|
||||
this._cycleEncryptedPullLock = true;
|
||||
if (!this.cycleEncryptedPullLock) {
|
||||
this.cycleEncryptedPullLock = true;
|
||||
debug("encrypted._pull");
|
||||
this.encrypted._pull();
|
||||
this._cycleEncryptedPullLock = false;
|
||||
this.cycleEncryptedPullLock = false;
|
||||
}
|
||||
|
||||
if (!this._cycleCleartextPullLock) {
|
||||
this._cycleCleartextPullLock = true;
|
||||
if (!this.cycleCleartextPullLock) {
|
||||
this.cycleCleartextPullLock = true;
|
||||
debug("cleartext._pull");
|
||||
this.cleartext._pull();
|
||||
this._cycleCleartextPullLock = false;
|
||||
this.cycleCleartextPullLock = false;
|
||||
}
|
||||
|
||||
if (!this._cycleCleartextPushLock) {
|
||||
this._cycleCleartextPushLock = true;
|
||||
if (!this.cycleCleartextPushLock) {
|
||||
this.cycleCleartextPushLock = true;
|
||||
debug("cleartext._push");
|
||||
this.cleartext._push();
|
||||
this._cycleCleartextPushLock = false;
|
||||
this.cycleCleartextPushLock = false;
|
||||
}
|
||||
|
||||
if (!this._cycleEncryptedPushLock) {
|
||||
this._cycleEncryptedPushLock = true;
|
||||
if (!this.cycleEncryptedPushLock) {
|
||||
this.cycleEncryptedPushLock = true;
|
||||
debug("encrypted._push");
|
||||
this.encrypted._push();
|
||||
this._cycleEncryptedPushLock = false;
|
||||
}
|
||||
|
||||
if (this._done) {
|
||||
return;
|
||||
this.cycleEncryptedPushLock = false;
|
||||
}
|
||||
|
||||
if ((!established && this._secureEstablished) ||
|
||||
(depth == 0 && this._writeCalled)) {
|
||||
// If we were not established but now we are, let's cycle again.
|
||||
// Or if there is some data to write...
|
||||
this._cycle(depth + 1);
|
||||
this.cycle(depth + 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SecurePair.prototype._maybeInitFinished = function() {
|
||||
if (this._ssl && !this._secureEstablished && this._ssl.isInitFinished()) {
|
||||
SecurePair.prototype.maybeInitFinished = function() {
|
||||
if (this.ssl && !this._secureEstablished && this.ssl.isInitFinished()) {
|
||||
if (NPN_ENABLED) {
|
||||
this.npnProtocol = this._ssl.getNegotiatedProtocol();
|
||||
this.npnProtocol = this.ssl.getNegotiatedProtocol();
|
||||
}
|
||||
|
||||
this._secureEstablished = true;
|
||||
debug('secure established');
|
||||
this.emit('secure');
|
||||
@ -633,45 +623,38 @@ SecurePair.prototype._maybeInitFinished = function() {
|
||||
};
|
||||
|
||||
|
||||
SecurePair.prototype._destroy = function() {
|
||||
SecurePair.prototype.destroy = function() {
|
||||
var self = this;
|
||||
|
||||
if (!this._done) {
|
||||
this._done = true;
|
||||
this._ssl.error = null;
|
||||
this._ssl.close();
|
||||
this._ssl = null;
|
||||
if (!this._doneFlag) {
|
||||
this._doneFlag = true;
|
||||
this.ssl.error = null;
|
||||
this.ssl.close();
|
||||
this.ssl = null;
|
||||
|
||||
self.encrypted.writable = self.encrypted.readable = false;
|
||||
self.cleartext.writable = self.cleartext.readable = false;
|
||||
|
||||
process.nextTick(function() {
|
||||
self.encrypted.emit('end');
|
||||
if (self.encrypted.onend) self.encrypted.onend();
|
||||
self.encrypted.emit('close');
|
||||
|
||||
self.cleartext.emit('end');
|
||||
if (self.cleartext.onend) self.cleartext.onend();
|
||||
self.cleartext.emit('close');
|
||||
});
|
||||
}
|
||||
|
||||
this._cycle();
|
||||
};
|
||||
|
||||
|
||||
SecurePair.prototype._error = function() {
|
||||
SecurePair.prototype.error = function() {
|
||||
if (!this._secureEstablished) {
|
||||
this._destroy();
|
||||
this.destroy();
|
||||
} else {
|
||||
var err = this._ssl.error;
|
||||
this._ssl.error = null;
|
||||
var err = this.ssl.error;
|
||||
this.ssl.error = null;
|
||||
|
||||
if (this._isServer &&
|
||||
this._rejectUnauthorized &&
|
||||
/peer did not return a certificate/.test(err.message)) {
|
||||
// Not really an error.
|
||||
this._destroy();
|
||||
this.destroy();
|
||||
} else {
|
||||
this.cleartext.emit('error', err);
|
||||
}
|
||||
@ -796,13 +779,13 @@ function Server(/* [options], listener */) {
|
||||
cleartext._controlReleased = true;
|
||||
self.emit('secureConnection', pair.cleartext, pair.encrypted);
|
||||
} else {
|
||||
var verifyError = pair._ssl.verifyError();
|
||||
var verifyError = pair.ssl.verifyError();
|
||||
if (verifyError) {
|
||||
pair.cleartext.authorizationError = verifyError;
|
||||
|
||||
if (self.rejectUnauthorized) {
|
||||
socket.destroy();
|
||||
pair._destroy();
|
||||
pair.destroy();
|
||||
} else {
|
||||
cleartext._controlReleased = true;
|
||||
self.emit('secureConnection', pair.cleartext, pair.encrypted);
|
||||
@ -904,7 +887,7 @@ exports.connect = function(port /* host, options, cb */) {
|
||||
socket.connect(port, host);
|
||||
|
||||
pair.on('secure', function() {
|
||||
var verifyError = pair._ssl.verifyError();
|
||||
var verifyError = pair.ssl.verifyError();
|
||||
|
||||
cleartext.npnProtocol = pair.npnProtocol;
|
||||
|
||||
|
85
lib/url.js
85
lib/url.js
@ -24,25 +24,40 @@ exports.resolve = urlResolve;
|
||||
exports.resolveObject = urlResolveObject;
|
||||
exports.format = urlFormat;
|
||||
|
||||
// Reference: RFC 3986, RFC 1808, RFC 2396
|
||||
|
||||
// define these here so at least they only have to be
|
||||
// compiled once on the first module load.
|
||||
var protocolPattern = /^([a-z0-9]+:)/i,
|
||||
portPattern = /:[0-9]+$/,
|
||||
delims = ['<', '>', '"', '\'', '`', /\s/],
|
||||
// RFC 2396: characters reserved for delimiting URLs.
|
||||
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
|
||||
// RFC 2396: characters not allowed for various reasons.
|
||||
unwise = ['{', '}', '|', '\\', '^', '~', '[', ']', '`'].concat(delims),
|
||||
nonHostChars = ['/', '?', ';', '#'].concat(unwise),
|
||||
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
||||
autoEscape = ['\''],
|
||||
// Characters that are never ever allowed in a hostname.
|
||||
// Note that any invalid chars are also handled, but these
|
||||
// are the ones that are *expected* to be seen, so we fast-path
|
||||
// them.
|
||||
nonHostChars = ['%', '/', '?', ';', '#']
|
||||
.concat(unwise).concat(autoEscape),
|
||||
hostnameMaxLen = 255,
|
||||
hostnamePartPattern = /^[a-z0-9][a-z0-9A-Z-]{0,62}$/,
|
||||
hostnamePartPattern = /^[a-zA-Z0-9][a-z0-9A-Z-]{0,62}$/,
|
||||
hostnamePartStart = /^([a-zA-Z0-9][a-z0-9A-Z-]{0,62})(.*)$/,
|
||||
// protocols that can allow "unsafe" and "unwise" chars.
|
||||
unsafeProtocol = {
|
||||
'javascript': true,
|
||||
'javascript:': true
|
||||
},
|
||||
// protocols that never have a hostname.
|
||||
hostlessProtocol = {
|
||||
'javascript': true,
|
||||
'javascript:': true,
|
||||
'file': true,
|
||||
'file:': true
|
||||
},
|
||||
// protocols that always have a path component.
|
||||
pathedProtocol = {
|
||||
'http': true,
|
||||
'https': true,
|
||||
@ -54,6 +69,7 @@ var protocolPattern = /^([a-z0-9]+:)/i,
|
||||
'gopher:': true,
|
||||
'file:': true
|
||||
},
|
||||
// protocols that always contain a // bit.
|
||||
slashedProtocol = {
|
||||
'http': true,
|
||||
'https': true,
|
||||
@ -71,17 +87,23 @@ var protocolPattern = /^([a-z0-9]+:)/i,
|
||||
function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
if (url && typeof(url) === 'object' && url.href) return url;
|
||||
|
||||
var out = { href: '' },
|
||||
var out = {},
|
||||
rest = url;
|
||||
|
||||
var proto = protocolPattern.exec(rest),
|
||||
lowerProto = proto;
|
||||
// cut off any delimiters.
|
||||
// This is to support parse stuff like "<http://foo.com>"
|
||||
for (var i = 0, l = rest.length; i < l; i++) {
|
||||
if (delims.indexOf(rest.charAt(i)) === -1) break;
|
||||
}
|
||||
if (i !== 0) rest = rest.substr(i);
|
||||
|
||||
|
||||
var proto = protocolPattern.exec(rest);
|
||||
if (proto) {
|
||||
proto = proto[0];
|
||||
lowerProto = proto.toLowerCase();
|
||||
var lowerProto = proto.toLowerCase();
|
||||
out.protocol = lowerProto;
|
||||
rest = rest.substr(proto.length);
|
||||
out.href += lowerProto;
|
||||
}
|
||||
|
||||
// figure out if it's got a host
|
||||
@ -90,15 +112,14 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
// how the browser resolves relative URLs.
|
||||
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
|
||||
var slashes = rest.substr(0, 2) === '//';
|
||||
if (slashes && !(lowerProto && hostlessProtocol[lowerProto])) {
|
||||
if (slashes && !(proto && hostlessProtocol[proto])) {
|
||||
rest = rest.substr(2);
|
||||
out.slashes = true;
|
||||
out.href += '//';
|
||||
}
|
||||
}
|
||||
|
||||
if (!hostlessProtocol[lowerProto] &&
|
||||
(slashes || (lowerProto && !slashedProtocol[lowerProto]))) {
|
||||
if (!hostlessProtocol[proto] &&
|
||||
(slashes || (proto && !slashedProtocol[proto]))) {
|
||||
// there's a hostname.
|
||||
// the first instance of /, ?, ;, or # ends the host.
|
||||
// don't enforce full RFC correctness, just be unstupid about it.
|
||||
@ -123,9 +144,10 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
var key = keys[i];
|
||||
out[key] = p[key];
|
||||
}
|
||||
|
||||
// we've indicated that there is a hostname,
|
||||
// so even if it's empty, it has to be present.
|
||||
out.hostname = (out.hostname) ? out.hostname.toLowerCase() : '';
|
||||
out.hostname = out.hostname || '';
|
||||
|
||||
// validate a little.
|
||||
if (out.hostname.length > hostnameMaxLen) {
|
||||
@ -134,19 +156,49 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
var hostparts = out.hostname.split(/\./);
|
||||
for (var i = 0, l = hostparts.length; i < l; i++) {
|
||||
var part = hostparts[i];
|
||||
if (!part) continue;
|
||||
if (!part.match(hostnamePartPattern)) {
|
||||
out.hostname = '';
|
||||
var validParts = hostparts.slice(0, i);
|
||||
var notHost = hostparts.slice(i + 1);
|
||||
var bit = part.match(hostnamePartStart);
|
||||
if (bit) {
|
||||
validParts.push(bit[1]);
|
||||
notHost.unshift(bit[2]);
|
||||
}
|
||||
if (notHost.length) {
|
||||
rest = '/' + notHost.join('.') + rest
|
||||
}
|
||||
out.hostname = validParts.join('.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.host = ((out.auth)?out.auth +'@':'') + (out.hostname||'') + ((out.port)?':'+out.port:'');
|
||||
// hostnames are always lower case.
|
||||
out.hostname = out.hostname.toLowerCase();
|
||||
|
||||
out.host = ((out.auth) ? out.auth + '@' : '') +
|
||||
(out.hostname || '') +
|
||||
((out.port) ? ':' + out.port : '');
|
||||
out.href += out.host;
|
||||
}
|
||||
|
||||
// now rest is set to the post-host stuff.
|
||||
// chop off any delim chars.
|
||||
if (!unsafeProtocol[lowerProto]) {
|
||||
|
||||
// First, make 100% sure that any "autoEscape" chars get
|
||||
// escaped, even if encodeURIComponent doesn't think they
|
||||
// need to be.
|
||||
for (var i = 0, l = autoEscape.length; i < l; i++) {
|
||||
var ae = autoEscape[i];
|
||||
var esc = encodeURIComponent(ae);
|
||||
if (esc === ae) {
|
||||
esc = escape(ae);
|
||||
}
|
||||
rest = rest.split(ae).join(esc);
|
||||
}
|
||||
|
||||
// Now make sure that delims never appear in a url.
|
||||
var chop = rest.length;
|
||||
for (var i = 0, l = delims.length; i < l; i++) {
|
||||
var c = rest.indexOf(delims[i]);
|
||||
@ -155,7 +207,6 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
}
|
||||
}
|
||||
rest = rest.substr(0, chop);
|
||||
out.href += rest;
|
||||
}
|
||||
|
||||
|
||||
@ -180,7 +231,7 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
out.query = {};
|
||||
}
|
||||
if (rest) out.pathname = rest;
|
||||
if (slashedProtocol[lowerProto] &&
|
||||
if (slashedProtocol[proto] &&
|
||||
out.hostname && !out.pathname) {
|
||||
out.pathname = '/';
|
||||
}
|
||||
|
19
src/node.cc
19
src/node.cc
@ -1278,13 +1278,24 @@ static void ReportException(TryCatch &try_catch, bool show_line) {
|
||||
|
||||
String::Utf8Value trace(try_catch.StackTrace());
|
||||
|
||||
if (trace.length() > 0) {
|
||||
// range errors have a trace member set to undefined
|
||||
if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) {
|
||||
fprintf(stderr, "%s\n", *trace);
|
||||
} else {
|
||||
// this really only happens for RangeErrors, since they're the only
|
||||
// kind that won't have all this info in the trace.
|
||||
// kind that won't have all this info in the trace, or when non-Error
|
||||
// objects are thrown manually.
|
||||
Local<Value> er = try_catch.Exception();
|
||||
String::Utf8Value msg(!er->IsObject() ? er->ToString()
|
||||
bool isErrorObject = er->IsObject() &&
|
||||
!(er->ToObject()->Get(String::New("message"))->IsUndefined()) &&
|
||||
!(er->ToObject()->Get(String::New("name"))->IsUndefined());
|
||||
|
||||
if (isErrorObject) {
|
||||
String::Utf8Value name(er->ToObject()->Get(String::New("name")));
|
||||
fprintf(stderr, "%s: ", *name);
|
||||
}
|
||||
|
||||
String::Utf8Value msg(!isErrorObject ? er->ToString()
|
||||
: er->ToObject()->Get(String::New("message"))->ToString());
|
||||
fprintf(stderr, "%s\n", *msg);
|
||||
}
|
||||
@ -2251,7 +2262,7 @@ static void EnableDebug(bool wait_connect) {
|
||||
assert(r);
|
||||
|
||||
// Print out some information.
|
||||
fprintf(stderr, "debugger listening on port %d\r\n", debug_port);
|
||||
fprintf(stderr, "debugger listening on port %d", debug_port);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ void EmitExit(v8::Handle<v8::Object> process);
|
||||
|
||||
/* Converts a unixtime to V8 Date */
|
||||
#define NODE_UNIXTIME_V8(t) v8::Date::New(1000*static_cast<double>(t))
|
||||
#define NODE_V8_UNIXTIME(v) (static_cast<double>((v)->IntegerValue())/1000.0);
|
||||
#define NODE_V8_UNIXTIME(v) (static_cast<double>((v)->NumberValue())/1000.0);
|
||||
|
||||
#define NODE_DEFINE_CONSTANT(target, constant) \
|
||||
(target)->Set(v8::String::NewSymbol(#constant), \
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/loadavg.h>
|
||||
|
||||
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
|
||||
#define PROCFS_FILE_OFFSET_BITS_HACK 1
|
||||
@ -250,6 +251,14 @@ double Platform::GetUptimeImpl() {
|
||||
}
|
||||
|
||||
int Platform::GetLoadAvg(Local<Array> *loads) {
|
||||
HandleScope scope;
|
||||
double loadavg[3];
|
||||
|
||||
(void) getloadavg(loadavg, 3);
|
||||
(*loads)->Set(0, Number::New(loadavg[LOADAVG_1MIN]));
|
||||
(*loads)->Set(1, Number::New(loadavg[LOADAVG_5MIN]));
|
||||
(*loads)->Set(2, Number::New(loadavg[LOADAVG_15MIN]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
33
test/message/stack_overflow.js
Normal file
33
test/message/stack_overflow.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
common.error('before');
|
||||
|
||||
// stack overflow
|
||||
function stackOverflow() {
|
||||
stackOverflow();
|
||||
}
|
||||
stackOverflow();
|
||||
|
||||
common.error('after');
|
6
test/message/stack_overflow.out
Normal file
6
test/message/stack_overflow.out
Normal file
@ -0,0 +1,6 @@
|
||||
before
|
||||
|
||||
node.js:*
|
||||
throw e; // process.nextTick error, or 'error' event on first tick
|
||||
^
|
||||
RangeError: Maximum call stack size exceeded
|
30
test/message/throw_custom_error.js
Normal file
30
test/message/throw_custom_error.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
common.error('before');
|
||||
|
||||
// custom error throwing
|
||||
throw { name: 'MyCustomError', message: 'This is a custom message' };
|
||||
|
||||
common.error('after');
|
6
test/message/throw_custom_error.out
Normal file
6
test/message/throw_custom_error.out
Normal file
@ -0,0 +1,6 @@
|
||||
before
|
||||
|
||||
node.js:*
|
||||
throw e; // process.nextTick error, or 'error' event on first tick
|
||||
^
|
||||
MyCustomError: This is a custom message
|
30
test/message/throw_non_error.js
Normal file
30
test/message/throw_non_error.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
common.error('before');
|
||||
|
||||
// custom error throwing
|
||||
throw { foo : 'bar' };
|
||||
|
||||
common.error('after');
|
6
test/message/throw_non_error.out
Normal file
6
test/message/throw_non_error.out
Normal file
@ -0,0 +1,6 @@
|
||||
before
|
||||
|
||||
node.js:*
|
||||
throw e; // process.nextTick error, or 'error' event on first tick
|
||||
^
|
||||
[object Object]
|
@ -540,6 +540,7 @@ console.log(z.length)
|
||||
assert.equal(2, z.length);
|
||||
assert.equal(0x66, z[0]);
|
||||
assert.equal(0x6f, z[1]);
|
||||
|
||||
assert.equal(0, Buffer('hello').slice(0, 0).length)
|
||||
|
||||
b = new Buffer(50);
|
||||
@ -557,3 +558,7 @@ b.fill(1, 16, 32);
|
||||
for (var i = 0; i < 16; i++) assert.equal(0, b[i]);
|
||||
for (; i < 32; i++) assert.equal(1, b[i]);
|
||||
for (; i < b.length; i++) assert.equal(0, b[i]);
|
||||
|
||||
var b = new SlowBuffer(10);
|
||||
b.write('あいうえお', 'ucs2');
|
||||
assert.equal(b.toString('ucs2'), 'あいうえお');
|
||||
|
@ -83,7 +83,7 @@ server.listen(common.PORT, function() {
|
||||
bodyBuffer += s;
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
res.on('close', function() {
|
||||
console.log('5) Client got "end" event.');
|
||||
gotEnd = true;
|
||||
});
|
||||
|
14
test/simple/test-regress-GH-897.js
Normal file
14
test/simple/test-regress-GH-897.js
Normal file
@ -0,0 +1,14 @@
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var t = Date.now();
|
||||
var diff;
|
||||
setTimeout(function () {
|
||||
diff = Date.now() - t;
|
||||
console.error(diff);
|
||||
}, 0.1);
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(diff < 100);
|
||||
});
|
@ -36,6 +36,10 @@ Writable.prototype.end = function () {
|
||||
this.endCalls++;
|
||||
}
|
||||
|
||||
Writable.prototype.destroy = function () {
|
||||
this.endCalls++;
|
||||
}
|
||||
|
||||
function Readable () {
|
||||
this.readable = true;
|
||||
stream.Stream.call(this);
|
||||
|
100
test/simple/test-stream-pipe-multi.js
Normal file
100
test/simple/test-stream-pipe-multi.js
Normal file
@ -0,0 +1,100 @@
|
||||
// Test that having a bunch of streams piping in parallel
|
||||
// doesn't break anything.
|
||||
|
||||
var common = require("../common");
|
||||
var assert = require("assert");
|
||||
var Stream = require("stream").Stream;
|
||||
var rr = [];
|
||||
var ww = [];
|
||||
var cnt = 100;
|
||||
var chunks = 1000;
|
||||
var chunkSize = 250;
|
||||
var data = new Buffer(chunkSize);
|
||||
var wclosed = 0;
|
||||
var rclosed = 0;
|
||||
|
||||
function FakeStream() {
|
||||
Stream.apply(this);
|
||||
this.wait = false;
|
||||
this.writable = true;
|
||||
this.readable = true;
|
||||
}
|
||||
|
||||
FakeStream.prototype = Object.create(Stream.prototype);
|
||||
|
||||
FakeStream.prototype.write = function(chunk) {
|
||||
console.error(this.ID, "write", this.wait)
|
||||
if (this.wait) {
|
||||
process.nextTick(this.emit.bind(this, "drain"));
|
||||
}
|
||||
this.wait = !this.wait;
|
||||
return this.wait;
|
||||
};
|
||||
|
||||
FakeStream.prototype.end = function() {
|
||||
this.emit("end");
|
||||
process.nextTick(this.close.bind(this));
|
||||
};
|
||||
|
||||
// noop - closes happen automatically on end.
|
||||
FakeStream.prototype.close = function() {
|
||||
this.emit("close");
|
||||
};
|
||||
|
||||
|
||||
// expect all streams to close properly.
|
||||
process.on("exit", function() {
|
||||
assert.equal(cnt, wclosed, "writable streams closed");
|
||||
assert.equal(cnt, rclosed, "readable streams closed");
|
||||
});
|
||||
|
||||
for (var i = 0; i < chunkSize; i ++) {
|
||||
chunkSize[i] = i % 256;
|
||||
}
|
||||
|
||||
for (var i = 0; i < cnt; i++) {
|
||||
var r = new FakeStream();
|
||||
r.on("close", function() {
|
||||
console.error(this.ID, "read close");
|
||||
rclosed++;
|
||||
});
|
||||
rr.push(r);
|
||||
|
||||
var w = new FakeStream();
|
||||
w.on("close", function() {
|
||||
console.error(this.ID, "write close");
|
||||
wclosed++;
|
||||
});
|
||||
ww.push(w);
|
||||
|
||||
r.ID = w.ID = i;
|
||||
r.pipe(w);
|
||||
}
|
||||
|
||||
// now start passing through data
|
||||
// simulate a relatively fast async stream.
|
||||
rr.forEach(function (r) {
|
||||
var cnt = chunks;
|
||||
var paused = false;
|
||||
|
||||
r.on("pause", function() {
|
||||
paused = true;
|
||||
});
|
||||
|
||||
r.on("resume", function() {
|
||||
paused = false;
|
||||
step();
|
||||
});
|
||||
|
||||
function step() {
|
||||
r.emit("data", data);
|
||||
if (--cnt === 0) {
|
||||
r.end();
|
||||
return;
|
||||
}
|
||||
if (paused) return;
|
||||
process.nextTick(step);
|
||||
}
|
||||
|
||||
process.nextTick(step);
|
||||
});
|
@ -63,7 +63,67 @@ var parseTests = {
|
||||
'host': 'USER:PW@www.example.com',
|
||||
'hostname': 'www.example.com',
|
||||
'pathname': '/'
|
||||
|
||||
},
|
||||
'http://x.com/path?that\'s#all, folks' : {
|
||||
'href': 'http://x.com/path?that%27s#all,',
|
||||
'protocol': 'http:',
|
||||
'host': 'x.com',
|
||||
'hostname': 'x.com',
|
||||
'search': '?that%27s',
|
||||
'query': 'that%27s',
|
||||
'pathname': '/path',
|
||||
'hash': '#all,'
|
||||
},
|
||||
'HTTP://X.COM/Y' : {
|
||||
'href': 'http://x.com/Y',
|
||||
'protocol': 'http:',
|
||||
'host': 'x.com',
|
||||
'hostname': 'x.com',
|
||||
'pathname': '/Y',
|
||||
},
|
||||
// an unexpected invalid char in the hostname.
|
||||
'HtTp://x.y.cOm*a/b/c?d=e#f g<h>i' : {
|
||||
'href': 'http://x.y.com/*a/b/c?d=e#f',
|
||||
'protocol': 'http:',
|
||||
'host': 'x.y.com',
|
||||
'hostname': 'x.y.com',
|
||||
'pathname': '/*a/b/c',
|
||||
'search': '?d=e',
|
||||
'query': 'd=e',
|
||||
'hash': '#f'
|
||||
},
|
||||
// make sure that we don't accidentally lcast the path parts.
|
||||
'HtTp://x.y.cOm*A/b/c?d=e#f g<h>i' : {
|
||||
'href': 'http://x.y.com/*A/b/c?d=e#f',
|
||||
'protocol': 'http:',
|
||||
'host': 'x.y.com',
|
||||
'hostname': 'x.y.com',
|
||||
'pathname': '/*A/b/c',
|
||||
'search': '?d=e',
|
||||
'query': 'd=e',
|
||||
'hash': '#f'
|
||||
},
|
||||
'http://x...y...#p': {
|
||||
'href': 'http://x...y.../#p',
|
||||
'protocol': 'http:',
|
||||
'host': 'x...y...',
|
||||
'hostname': 'x...y...',
|
||||
'hash': '#p',
|
||||
'pathname': '/'
|
||||
},
|
||||
'http://x/p/"quoted"': {
|
||||
'href': 'http://x/p/',
|
||||
'protocol':'http:',
|
||||
'host': 'x',
|
||||
'hostname': 'x',
|
||||
'pathname': '/p/'
|
||||
},
|
||||
'<http://goo.corn/bread> Is a URL!': {
|
||||
'href': 'http://goo.corn/bread',
|
||||
'protocol': 'http:',
|
||||
'host': 'goo.corn',
|
||||
'hostname': 'goo.corn',
|
||||
'pathname': '/bread'
|
||||
},
|
||||
'http://www.narwhaljs.org/blog/categories?id=news' : {
|
||||
'href': 'http://www.narwhaljs.org/blog/categories?id=news',
|
||||
@ -91,17 +151,18 @@ var parseTests = {
|
||||
'query': '??&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'pathname': '/vt/lyrs=m@114'
|
||||
},
|
||||
'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' : {
|
||||
'href': 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' +
|
||||
'&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'protocol': 'http:',
|
||||
'host': 'user:pass@mt0.google.com',
|
||||
'auth': 'user:pass',
|
||||
'hostname': 'mt0.google.com',
|
||||
'search': '???&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'query': '??&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'pathname': '/vt/lyrs=m@114'
|
||||
},
|
||||
'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=':
|
||||
{
|
||||
'href': 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' +
|
||||
'&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'protocol': 'http:',
|
||||
'host': 'user:pass@mt0.google.com',
|
||||
'auth': 'user:pass',
|
||||
'hostname': 'mt0.google.com',
|
||||
'search': '???&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'query': '??&hl=en&src=api&x=2&y=2&z=3&s=',
|
||||
'pathname': '/vt/lyrs=m@114'
|
||||
},
|
||||
'file:///etc/passwd' : {
|
||||
'href': 'file:///etc/passwd',
|
||||
'protocol': 'file:',
|
||||
@ -191,7 +252,7 @@ for (var u in parseTests) {
|
||||
actual = url.format(parseTests[u]);
|
||||
|
||||
assert.equal(expected, actual,
|
||||
'format(' + u + ') == ' + expected + '\nactual:' + actual);
|
||||
'format(' + u + ') == ' + u + '\nactual:' + actual);
|
||||
}
|
||||
|
||||
var parseTestsWithQueryString = {
|
||||
@ -204,7 +265,7 @@ var parseTestsWithQueryString = {
|
||||
},
|
||||
'pathname': '/foo/bar'
|
||||
},
|
||||
'http://example.com/' : {
|
||||
'http://example.com' : {
|
||||
'href': 'http://example.com/',
|
||||
'protocol': 'http:',
|
||||
'slashes': true,
|
||||
|
26
wscript
26
wscript
@ -143,13 +143,6 @@ def set_options(opt):
|
||||
, dest='openssl_libpath'
|
||||
)
|
||||
|
||||
opt.add_option( '--oprofile'
|
||||
, action='store_true'
|
||||
, default=False
|
||||
, help="add oprofile support"
|
||||
, dest='use_oprofile'
|
||||
)
|
||||
|
||||
opt.add_option( '--gdb'
|
||||
, action='store_true'
|
||||
, default=False
|
||||
@ -252,12 +245,8 @@ def configure(conf):
|
||||
conf.env["USE_SHARED_CARES"] = o.shared_cares or o.shared_cares_includes or o.shared_cares_libpath
|
||||
conf.env["USE_SHARED_LIBEV"] = o.shared_libev or o.shared_libev_includes or o.shared_libev_libpath
|
||||
|
||||
conf.env["USE_OPROFILE"] = o.use_oprofile
|
||||
conf.env["USE_GDBJIT"] = o.use_gdbjit
|
||||
|
||||
if o.use_oprofile:
|
||||
conf.check(lib=['bfd', 'opagent'], uselib_store="OPROFILE")
|
||||
|
||||
conf.check(lib='dl', uselib_store='DL')
|
||||
if not sys.platform.startswith("sunos") and not sys.platform.startswith("cygwin") and not sys.platform.startswith("win32"):
|
||||
conf.env.append_value("CCFLAGS", "-rdynamic")
|
||||
@ -552,7 +541,6 @@ def configure(conf):
|
||||
|
||||
# Configure default variant
|
||||
conf.setenv('default')
|
||||
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)
|
||||
@ -587,12 +575,7 @@ def v8_cmd(bld, variant):
|
||||
else:
|
||||
snapshot = ""
|
||||
|
||||
if bld.env["USE_OPROFILE"]:
|
||||
profile = "prof=oprofile"
|
||||
else:
|
||||
profile = ""
|
||||
|
||||
cmd_R = sys.executable + ' "%s" -j %d -C "%s" -Y "%s" visibility=default mode=%s %s toolchain=%s library=static %s %s'
|
||||
cmd_R = sys.executable + ' "%s" -j %d -C "%s" -Y "%s" visibility=default mode=%s %s toolchain=%s library=static %s'
|
||||
|
||||
cmd = cmd_R % ( scons
|
||||
, Options.options.jobs
|
||||
@ -602,7 +585,6 @@ def v8_cmd(bld, variant):
|
||||
, arch
|
||||
, toolchain
|
||||
, snapshot
|
||||
, profile
|
||||
)
|
||||
|
||||
if bld.env["USE_GDBJIT"]:
|
||||
@ -753,8 +735,8 @@ def build(bld):
|
||||
native_cc_debug = native_cc.clone("debug")
|
||||
native_cc_debug.rule = javascript_in_c_debug
|
||||
|
||||
native_cc.rule = javascript_in_c
|
||||
|
||||
native_cc.rule = javascript_in_c_debug
|
||||
|
||||
if bld.env["USE_DTRACE"]:
|
||||
dtrace = bld.new_task_gen(
|
||||
name = "dtrace",
|
||||
@ -892,7 +874,7 @@ def build(bld):
|
||||
, 'CPPFLAGS' : " ".join(program.env["CPPFLAGS"]).replace('"', '\\"')
|
||||
, 'LIBFLAGS' : " ".join(program.env["LIBFLAGS"]).replace('"', '\\"')
|
||||
, 'PREFIX' : safe_path(program.env["PREFIX"])
|
||||
, 'VERSION' : '0.4.6' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
|
||||
, 'VERSION' : '0.4.7' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
|
||||
}
|
||||
return x
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user