diff --git a/AUTHORS b/AUTHORS index 7159091579f..cf29f0189e4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -167,4 +167,7 @@ Dean McNamee Trevor Burnham Zachary Scott Arnout Kazemier +George Stagas +Scott McWhirter +Jakub Lekstan diff --git a/ChangeLog b/ChangeLog index e4a09248bbc..bba5127ea3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2011.04.13, Version 0.4.6 (stable) + +* Don't error on ENOTCONN from shutdown() #670 + +* Auto completion of built-in debugger suggests prefix match rather than + partial match. (koichik) + +* circular reference in vm modules. #822 (Jakub Lekstan) + +* http response.readable should be false after 'end' #867 (Abe Fettig) + +* Implemenet os.cpus() and os.uptime() on Solaris (Scott McWhirter) + +* fs.ReadStream: Allow omission of end option for range reads #801 + (Felix Geisendörfer) + +* Buffer.write() with UCS-2 should not be write partial char + #916 (koichik) + +* Pass secureProtocol through on tls.Server creation (Theo Schlossnagle) + +* TLS use RC4-SHA by default + +* Don't strangely drop out of event loop on HTTPS client uploads #892 + +* Doc improvements + +* Upgrade v8 to 3.1.8.10 + + 2011.04.01, Version 0.4.5 (stable) * Fix listener leak in stream.pipe() (Mikeal Rogers) diff --git a/doc/api/_toc.markdown b/doc/api/_toc.markdown index 23df8790887..58419663ae5 100644 --- a/doc/api/_toc.markdown +++ b/doc/api/_toc.markdown @@ -2,6 +2,7 @@ * [Synopsis](synopsis.html) * [Globals](globals.html) +* [STDIO](stdio.html) * [Timers](timers.html) * [Modules](modules.html) * [C/C++ Addons](addons.html) diff --git a/doc/api/all.markdown b/doc/api/all.markdown index fe12ef7e532..5498d17ddae 100644 --- a/doc/api/all.markdown +++ b/doc/api/all.markdown @@ -1,6 +1,7 @@ @include synopsis @include globals +@include stdio @include timers @include modules @include addons diff --git a/doc/api/globals.markdown b/doc/api/globals.markdown index fb971cbb0ee..8aceceaed6a 100644 --- a/doc/api/globals.markdown +++ b/doc/api/globals.markdown @@ -16,6 +16,11 @@ scope; `var something` inside a Node module will be local to that module. The process object. See the [process object](process.html#process) section. +### console + +Used to print to stdout and stderr. See the [stdio](stdio.html) section. + + ### require() To require modules. See the [Modules](modules.html#modules) section. @@ -66,6 +71,7 @@ Example: running `node example.js` from `/Users/mjr` A reference to the current module. In particular `module.exports` is the same as the `exports` object. See `src/node.js` for more information. +`module` isn't actually a global but rather local to each module. ### setTimeout(cb, ms) ### clearTimeout(t) @@ -73,5 +79,3 @@ for more information. ### clearInterval(t) The timer functions are global variables. See the [timers](timers.html) section. - -`module` isn't actually a global but rather local to each module. diff --git a/doc/api/http.markdown b/doc/api/http.markdown index 500347dd7e2..09efedebf75 100644 --- a/doc/api/http.markdown +++ b/doc/api/http.markdown @@ -259,6 +259,11 @@ be called before `response.end()` is called. If you call `response.write()` or `response.end()` before calling this, the implicit/mutable headers will be calculated and call this function for you. +Note: that Content-Length is given in bytes not characters. The above example +works because the string `'hello world'` contains only single byte characters. +If the body contains higher coded characters then `Buffer.byteLength()` +should be used to determine the number of bytes in a given encoding. + ### response.statusCode When using implicit headers (not calling `response.writeHead()` explicitly), this property diff --git a/doc/api/stdio.markdown b/doc/api/stdio.markdown new file mode 100644 index 00000000000..a24d0572c63 --- /dev/null +++ b/doc/api/stdio.markdown @@ -0,0 +1,51 @@ +## console + +Browser-like object for printing to stdout and stderr. + +### console.log() + +Prints to stdout with newline. This function can take multiple arguments in a +`printf()`-like way. Example: + + console.log('count: %d', count); + +If formating elements are not found in the first string then `util.inspect` +is used on each argument. + +### console.info() + +Same as `console.log`. + +### console.warn() +### console.error() + +Same as `console.log` but prints to stderr. + +### console.dir(obj) + +Uses `util.inspect` on `obj` and prints resulting string to stderr. + +### console.time(label) + +Mark a time. + + +### console.timeEnd(label) + +Finish timer, record output. Example + + console.time('100-elements'); + while (var i = 0; i < 100; i++) { + ; + } + console.timeEnd('100-elements'); + + +### console.trace() + +Print a stack trace to stderr of the current position. + +### console.assert() + +Same as `assert.ok()`. + diff --git a/doc/index.html b/doc/index.html index 7f4db3f96bc..5770786a929 100644 --- a/doc/index.html +++ b/doc/index.html @@ -26,13 +26,12 @@
  • Download
  • ChangeLog
  • About
  • -
  • v0.4.5 docs
  • -
    -
  • Wiki
  • -
  • Blog
  • -
    -
  • Jobs
  • +
  • v0.4.6 docs

  • +
  • Wiki
  • +
  • Blog
  • +
  • Jobs
  • +
  • Community
  • Demo
  • @@ -108,9 +107,9 @@

    Download

    - 2011.04.01 - node-v0.4.5.tar.gz - (Documentation) + 2011.04.13 + node-v0.4.6.tar.gz + (Documentation)

    Historical: versions, docs

    diff --git a/lib/net.js b/lib/net.js index 52aaefa4d64..26acbb35588 100644 --- a/lib/net.js +++ b/lib/net.js @@ -636,7 +636,11 @@ Socket.prototype._onReadable = function() { pool.length - pool.used); DTRACE_NET_SOCKET_READ(this, bytesRead); } catch (e) { - self.destroy(e); + if (e.code == 'ECONNRESET') { + self.destroy(); + } else { + self.destroy(e); + } return; } diff --git a/lib/stream.js b/lib/stream.js index d31a9fe239a..632c87d2e26 100644 --- a/lib/stream.js +++ b/lib/stream.js @@ -28,9 +28,13 @@ 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(); @@ -52,10 +56,18 @@ Stream.prototype.pipe = function(dest, options) { if (!options || options.end !== false) { function onend() { + var index = pipes.indexOf(dest); + pipes.splice(index, 1); + + if (pipes.indexOf(dest) > -1) { + return; + } + dest.end(); } source.on('end', onend); + source.on('close', onend); } /* @@ -73,34 +85,35 @@ Stream.prototype.pipe = function(dest, options) { source.emit('resume'); }; } - + var onpause = function() { source.pause(); } dest.on('pause', onpause); - + var onresume = function() { if (source.readable) source.resume(); }; - + dest.on('resume', onresume); - + var cleanup = function () { source.removeListener('data', ondata); dest.removeListener('drain', ondrain); source.removeListener('end', onend); - + source.removeListener('close', onend); + dest.removeListener('pause', onpause); dest.removeListener('resume', onresume); - + source.removeListener('end', cleanup); source.removeListener('close', cleanup); - + dest.removeListener('end', cleanup); dest.removeListener('close', cleanup); } - + source.on('end', cleanup); source.on('close', cleanup); diff --git a/lib/tls.js b/lib/tls.js index d4599aba383..a8f1898f49c 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -54,13 +54,14 @@ function CryptoStream(pair) { this._writeState = true; this._pending = []; this._pendingCallbacks = []; + this._pendingBytes = 0; } util.inherits(CryptoStream, stream.Stream); CryptoStream.prototype.write = function(data /* , encoding, cb */) { if (this == this.pair.cleartext) { - debug('cleartext.write called with (((' + data.toString() + ')))'); + debug('cleartext.write called with ' + data.length + ' bytes'); } else { debug('encrypted.write called with ' + data.length + ' bytes'); } @@ -90,10 +91,12 @@ 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(); - return this._writeState; + return this._pendingBytes < 128 * 1024; }; @@ -263,7 +266,7 @@ CryptoStream.prototype._push = function() { // Bail out if we didn't read any data. if (bytesRead == 0) { - if (this._pendingBytes() == 0 && this._destroyAfterPush) { + if (this._internallyPendingBytes() == 0 && this._destroyAfterPush) { this._done(); } return; @@ -272,7 +275,7 @@ CryptoStream.prototype._push = function() { var chunk = pool.slice(0, bytesRead); if (this === this.pair.cleartext) { - debug('cleartext emit "data" called with (((' + chunk.toString() + ')))'); + debug('cleartext emit "data" with ' + bytesRead + ' bytes'); } else { debug('encrypted emit "data" with ' + bytesRead + ' bytes'); } @@ -307,6 +310,8 @@ CryptoStream.prototype._push = function() { CryptoStream.prototype._pull = function() { var havePending = this._pending.length > 0; + assert(havePending || this._pendingBytes == 0); + while (this._pending.length > 0) { if (!this.pair._ssl) break; @@ -355,6 +360,9 @@ CryptoStream.prototype._pull = function() { break; } + this._pendingBytes -= tmp.length; + assert(this._pendingBytes >= 0); + if (cb) cb(); assert(rv === tmp.length); @@ -375,7 +383,7 @@ function CleartextStream(pair) { util.inherits(CleartextStream, CryptoStream); -CleartextStream.prototype._pendingBytes = function() { +CleartextStream.prototype._internallyPendingBytes = function() { if (this.pair._ssl) { return this.pair._ssl.clearPending(); } else { @@ -403,7 +411,7 @@ function EncryptedStream(pair) { util.inherits(EncryptedStream, CryptoStream); -EncryptedStream.prototype._pendingBytes = function() { +EncryptedStream.prototype._internallyPendingBytes = function() { if (this.pair._ssl) { return this.pair._ssl.encPending(); } else { @@ -539,24 +547,28 @@ SecurePair.prototype._cycle = function(depth) { if (!this._cycleEncryptedPullLock) { this._cycleEncryptedPullLock = true; + debug("encrypted._pull"); this.encrypted._pull(); this._cycleEncryptedPullLock = false; } if (!this._cycleCleartextPullLock) { this._cycleCleartextPullLock = true; + debug("cleartext._pull"); this.cleartext._pull(); this._cycleCleartextPullLock = false; } if (!this._cycleCleartextPushLock) { this._cycleCleartextPushLock = true; + debug("cleartext._push"); this.cleartext._push(); this._cycleCleartextPushLock = false; } if (!this._cycleEncryptedPushLock) { this._cycleEncryptedPushLock = true; + debug("encrypted._push"); this.encrypted._push(); this._cycleEncryptedPushLock = false; } @@ -728,7 +740,7 @@ function Server(/* [options], listener */) { secureOptions: self.secureOptions, crl: self.crl }); - //creds.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA'); + creds.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA'); var pair = new SecurePair(creds, true, diff --git a/test/simple/test-stream-pipe-cleanup.js b/test/simple/test-stream-pipe-cleanup.js index fce4ac82a7d..32ecd153dc8 100644 --- a/test/simple/test-stream-pipe-cleanup.js +++ b/test/simple/test-stream-pipe-cleanup.js @@ -28,10 +28,13 @@ var util = require('util'); function Writable () { this.writable = true; + this.endCalls = 0; stream.Stream.call(this); } util.inherits(Writable, stream.Stream); -Writable.prototype.end = function () {} +Writable.prototype.end = function () { + this.endCalls++; +} function Readable () { this.readable = true; @@ -56,6 +59,9 @@ for (i = 0; i < limit; i++) { r.emit('end') } assert.equal(0, r.listeners('end').length); +assert.equal(limit, w.endCalls); + +w.endCalls = 0; for (i = 0; i < limit; i++) { r = new Readable() @@ -63,6 +69,19 @@ for (i = 0; i < limit; i++) { r.emit('close') } assert.equal(0, r.listeners('close').length); +assert.equal(limit, w.endCalls); + +w.endCalls = 0; + +var r2; +r = new Readable() +r2 = new Readable(); + +r.pipe(w) +r2.pipe(w) +r.emit('close') +r2.emit('close') +assert.equal(1, w.endCalls); r = new Readable(); diff --git a/wscript b/wscript index 16956b75f49..b582b5835af 100644 --- a/wscript +++ b/wscript @@ -889,7 +889,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.5' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version. + , 'VERSION' : '0.4.6' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version. } return x