From 3e7f69c3abe7d6c02f585111cadd99a91852e5bf Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sat, 29 Feb 2020 19:27:31 +0100 Subject: [PATCH] [fix] Do not swallow errors emitted while destroying (#1672) Refs: https://github.com/nodejs/node/pull/29197 --- lib/stream.js | 11 ++++++- test/create-websocket-stream.test.js | 46 ++++++++++++++++++++++++++++ test/permessage-deflate.test.js | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/lib/stream.js b/lib/stream.js index 3899a399a..c6811afb1 100644 --- a/lib/stream.js +++ b/lib/stream.js @@ -78,6 +78,8 @@ function createWebSocketStream(ws, options) { }); ws.once('error', function error(err) { + if (duplex.destroyed) return; + duplex.destroy(err); }); @@ -94,8 +96,15 @@ function createWebSocketStream(ws, options) { return; } - ws.once('close', function close() { + let called = false; + + ws.once('error', function error(err) { + called = true; callback(err); + }); + + ws.once('close', function close() { + if (!called) callback(err); process.nextTick(emitClose, duplex); }); ws.terminate(); diff --git a/test/create-websocket-stream.test.js b/test/create-websocket-stream.test.js index a16a5a2ce..d70e947d0 100644 --- a/test/create-websocket-stream.test.js +++ b/test/create-websocket-stream.test.js @@ -225,6 +225,52 @@ describe('createWebSocketStream', () => { }); }); + it('does not swallow errors that may occur while destroying', (done) => { + const frame = Buffer.concat( + Sender.frame(Buffer.from([0x22, 0xfa, 0xec, 0x78]), { + fin: true, + rsv1: true, + opcode: 0x02, + mask: false, + readOnly: false + }) + ); + + const wss = new WebSocket.Server( + { + perMessageDeflate: true, + port: 0 + }, + () => { + const ws = new WebSocket(`ws://localhost:${wss.address().port}`); + const duplex = createWebSocketStream(ws); + + duplex.on('error', (err) => { + assert.ok(err instanceof Error); + assert.strictEqual(err.code, 'Z_DATA_ERROR'); + assert.strictEqual(err.errno, -3); + + duplex.on('close', () => { + wss.close(done); + }); + }); + + let bytesRead = 0; + + ws.on('open', () => { + ws._socket.on('data', (chunk) => { + bytesRead += chunk.length; + if (bytesRead === frame.length) duplex.destroy(); + }); + }); + } + ); + + wss.on('connection', (ws) => { + ws._socket.write(frame); + }); + }); + it("does not suppress the throwing behavior of 'error' events", (done) => { const wss = new WebSocket.Server({ port: 0 }, () => { const ws = new WebSocket(`ws://localhost:${wss.address().port}`); diff --git a/test/permessage-deflate.test.js b/test/permessage-deflate.test.js index b50fd6eda..11f8555af 100644 --- a/test/permessage-deflate.test.js +++ b/test/permessage-deflate.test.js @@ -589,6 +589,7 @@ describe('PerMessageDeflate', () => { perMessageDeflate.accept([{}]); perMessageDeflate.decompress(data, true, (err) => { assert.ok(err instanceof Error); + assert.strictEqual(err.code, 'Z_DATA_ERROR'); assert.strictEqual(err.errno, -3); done(); });