Skip to content

Commit

Permalink
Only emit errors once, since we abort on the first one
Browse files Browse the repository at this point in the history
This is the reason for node-tar's test failure in Node v14
  • Loading branch information
isaacs committed Aug 14, 2020
1 parent 24398f2 commit aa94333
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ZlibBase extends Minipass {
throw new TypeError('invalid options for ZlibBase constructor')

super(opts)
this[_sawError] = false
this[_ended] = false
this[_opts] = opts

Expand All @@ -64,7 +65,12 @@ class ZlibBase extends Minipass {
}

this[_onError] = (err) => {
// no sense raising multiple errors, since we abort on the first one.
if (this[_sawError])
return

this[_sawError] = true

// there is no way to cleanly recover.
// continuing only obscures problems.
this.close()
Expand Down Expand Up @@ -157,6 +163,8 @@ class ZlibBase extends Minipass {
// `_processChunk()` adds an 'error' listener. If we don't remove it
// after each call, these handlers start piling up.
this[_handle].removeAllListeners('error')
// make sure OUR error listener is still attached tho
this[_handle].on('error', er => this[_onError](new ZlibError(er)))
}
}

Expand Down
54 changes: 54 additions & 0 deletions test/multiple-errors-handled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const t = require('tap')
const { Gzip } = require('../')

t.test('only raise once if emitted before writing', t => {
t.plan(1)

const gz = new Gzip()

// dirty hack to get at the internal handle
const kHandle = Object.getOwnPropertySymbols(gz)
.filter(sym => sym.toString() === 'Symbol(handle)')[0]

gz.once('error', er => t.match(er, { message: 'zlib: fart' }))
const handle = gz[kHandle]
handle.emit('error', new Error('fart'))
handle.emit('error', new Error('poop'))
})

t.test('only raise once if emitted after writing', t => {
t.plan(1)

const gz = new Gzip()

// dirty hack to get at the internal handle
const kHandle = Object.getOwnPropertySymbols(gz)
.filter(sym => sym.toString() === 'Symbol(handle)')[0]

gz.once('error', er => t.match(er, { message: 'zlib: fart' }))

gz.write('hello, ')

const handle = gz[kHandle]
handle.emit('error', new Error('fart'))
handle.emit('error', new Error('poop'))
})

t.test('only raise once if emitted after writing after emitting', t => {
t.plan(1)

const gz = new Gzip()

// dirty hack to get at the internal handle
const kHandle = Object.getOwnPropertySymbols(gz)
.filter(sym => sym.toString() === 'Symbol(handle)')[0]

gz.once('error', er => t.match(er, { message: 'zlib: fart' }))

gz.write('hello, ')

const handle = gz[kHandle]
handle.emit('error', new Error('fart'))
gz.write(' world')
handle.emit('error', new Error('poop'))
})

0 comments on commit aa94333

Please sign in to comment.