diff --git a/.travis.yml b/.travis.yml index 5ca377d6..64402657 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js node_js: - - "iojs" - - "0.12" - + - "4" + - "6" + - "8" diff --git a/lib/protocol/flow.js b/lib/protocol/flow.js index 4ec5649b..f61f63c9 100644 --- a/lib/protocol/flow.js +++ b/lib/protocol/flow.js @@ -199,10 +199,10 @@ Flow.prototype.read = function read(limit) { } // * Looking at the first frame in the queue without pulling it out if possible. - var frame = this._readableState.buffer[0]; + var frame = bufferHead(this._readableState.buffer); if (!frame && !this._readableState.ended) { this._read(); - frame = this._readableState.buffer[0]; + frame = bufferHead(this._readableState.buffer); } if (frame && (frame.type === 'DATA')) { @@ -296,8 +296,7 @@ Flow.prototype.push = function push(frame) { // `getLastQueuedFrame` returns the last frame in output buffers. This is primarily used by the // [Stream](stream.html) class to mark the last frame with END_STREAM flag. Flow.prototype.getLastQueuedFrame = function getLastQueuedFrame() { - var readableQueue = this._readableState.buffer; - return this._queue[this._queue.length - 1] || readableQueue[readableQueue.length - 1]; + return this._queue[this._queue.length - 1] || bufferTail(this._readableState.buffer); }; // Outgoing frames - managing the window size @@ -351,3 +350,14 @@ Flow.prototype.setInitialWindow = function setInitialWindow(initialWindow) { this._increaseWindow(initialWindow - this._initialWindow); this._initialWindow = initialWindow; }; + +// The node stream internal buffer was changed from an Array to a linked list in node v6.3.0 +function bufferHead (buffer) { + if ('head' in buffer) return buffer.head && buffer.head.data + return buffer[0] +} + +function bufferTail (buffer) { + if ('tail' in buffer) return buffer.tail && buffer.tail.data + return buffer[buffer.length - 1] +} diff --git a/package.json b/package.json index 5372f17f..95559ec8 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "version": "3.3.6", "description": "An HTTP/2 client and server implementation", "main": "lib/index.js", - "engines" : { - "node" : ">=0.12.0" + "engines": { + "node": ">=0.12.0" }, "devDependencies": { "istanbul": "*", @@ -14,7 +14,7 @@ "bunyan": "*" }, "scripts": { - "test": "istanbul test _mocha -- --reporter spec --slow 500 --timeout 15000", + "test": "istanbul test node_modules/mocha/bin/_mocha -- --reporter spec --slow 500 --timeout 15000", "doc": "docco lib/* --output doc --layout parallel --template root.jst --css doc/docco.css && docco lib/protocol/* --output doc/protocol --layout parallel --template protocol.jst --css doc/docco.css" }, "repository": { diff --git a/test/flow.js b/test/flow.js index a077c684..28a2b50a 100644 --- a/test/flow.js +++ b/test/flow.js @@ -71,7 +71,7 @@ describe('flow.js', function() { flow._increaseWindow(Infinity); var increase = util.random(1,100); - expect(flow._increaseWindow.bind(flow, increase)).to.throw('Uncaught, unspecified "error" event.'); + expect(flow._increaseWindow.bind(flow, increase)).to.throw(util.uncaughtErrorEventMessage); }); it('should emit error when `_window` grows over the window limit', function() { var WINDOW_SIZE_LIMIT = Math.pow(2, 31) - 1; @@ -79,7 +79,7 @@ describe('flow.js', function() { flow._window = 0; flow._increaseWindow(WINDOW_SIZE_LIMIT); - expect(flow._increaseWindow.bind(flow, 1)).to.throw('Uncaught, unspecified "error" event.'); + expect(flow._increaseWindow.bind(flow, 1)).to.throw(util.uncaughtErrorEventMessage); }); }); diff --git a/test/http.js b/test/http.js index 95a074e4..22b34205 100644 --- a/test/http.js +++ b/test/http.js @@ -601,6 +601,7 @@ describe('http.js', function() { host: 'localhost', port: 1259, path: '/', + method: 'POST', ca: serverOptions.cert }); request.write('Ping'); diff --git a/test/stream.js b/test/stream.js index 90e0ef64..1d989945 100644 --- a/test/stream.js +++ b/test/stream.js @@ -194,7 +194,7 @@ describe('stream.js', function() { stream.upstream.write({ type: 'HEADERS', headers:{}, flags: { END_STREAM: true }, count_change: util.noop }); example_frames.slice(2).forEach(function(invalid_frame) { invalid_frame.count_change = util.noop; - expect(stream._transition.bind(stream, false, invalid_frame)).to.throw('Uncaught, unspecified "error" event.'); + expect(stream._transition.bind(stream, false, invalid_frame)).to.throw(util.uncaughtErrorEventMessage); }); // CLOSED state as a result of outgoing END_STREAM @@ -204,7 +204,7 @@ describe('stream.js', function() { stream.end(); example_frames.slice(3).forEach(function(invalid_frame) { invalid_frame.count_change = util.noop; - expect(stream._transition.bind(stream, false, invalid_frame)).to.throw('Uncaught, unspecified "error" event.'); + expect(stream._transition.bind(stream, false, invalid_frame)).to.throw(util.uncaughtErrorEventMessage); }); }); it('should throw exception for invalid outgoing frames', function() { diff --git a/test/util.js b/test/util.js index 52c6a1be..c7651762 100644 --- a/test/util.js +++ b/test/util.js @@ -10,7 +10,7 @@ if (process.env.HTTP2_LOG) { if (process.stderr.isTTY) { var bin = path.resolve(path.dirname(require.resolve('bunyan')), '..', 'bin', 'bunyan'); if(bin && fs.existsSync(bin)) { - logOutput = spawn(bin, ['-o', 'short'], { + logOutput = spawn(process.execPath, [bin, '-o', 'short'], { stdio: [null, process.stderr, process.stderr] }).stdin; } @@ -87,3 +87,9 @@ exports.shuffleBuffers = function shuffleBuffers(buffers) { return output; }; + +// Error message were changed in https://github.com/nodejs/node/commit/2141d374527337f7e1c74c9efad217b017d945cf +exports.uncaughtErrorEventMessage = + +(process.versions.node.split('.')[0]) >= 8 + ? 'Unhandled "error" event.' + : 'Uncaught, unspecified "error" event.'