Skip to content

Commit

Permalink
fix: store emitted events and re-emit them for late listeners (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
nlf authored May 19, 2022
1 parent 0deb78e commit c5421f1
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 2 deletions.
27 changes: 26 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const getOptString = options => !options || !options.length

const _onEnd = Symbol('_onEnd')
const _getOptions = Symbol('_getOptions')
const _emittedSize = Symbol('_emittedSize')
const _emittedIntegrity = Symbol('_emittedIntegrity')
const _emittedVerified = Symbol('_emittedVerified')

class IntegrityStream extends MiniPass {
constructor (opts) {
super()
Expand Down Expand Up @@ -63,6 +67,22 @@ class IntegrityStream extends MiniPass {
this.optString = getOptString(options)
}

on (ev, handler) {
if (ev === 'size' && this[_emittedSize]) {
return handler(this[_emittedSize])
}

if (ev === 'integrity' && this[_emittedIntegrity]) {
return handler(this[_emittedIntegrity])
}

if (ev === 'verified' && this[_emittedVerified]) {
return handler(this[_emittedVerified])
}

return super.on(ev, handler)
}

emit (ev, data) {
if (ev === 'end') {
this[_onEnd]()
Expand Down Expand Up @@ -103,9 +123,14 @@ class IntegrityStream extends MiniPass {
err.sri = this.sri
this.emit('error', err)
} else {
this[_emittedSize] = this.size
this.emit('size', this.size)
this[_emittedIntegrity] = newSri
this.emit('integrity', newSri)
match && this.emit('verified', match)
if (match) {
this[_emittedVerified] = match
this.emit('verified', match)
}
}
}
}
Expand Down
65 changes: 64 additions & 1 deletion test/integrity-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,28 @@ const test = require('tap').test

const ssri = require('..')

test('generates integrity', t => {
test('works with no options', t => {
const TARGET = ssri.fromData('foo')
const stream = ssri.integrityStream()
stream.write('foo')
let integrity
stream.on('integrity', i => {
integrity = i
})

stream.on('end', () => {
t.same(integrity, TARGET, 'matching integrity emitted')
t.end()
})

stream.resume()
stream.end()
})

test('generates integrity', t => {
const TARGET = ssri.fromData('foo')
const stream = ssri.integrityStream({ integrity: TARGET })
stream.write('foo')
let collected = ''
stream.on('data', d => {
collected += d.toString()
Expand All @@ -16,9 +34,54 @@ test('generates integrity', t => {
stream.on('integrity', i => {
integrity = i
})
let size
stream.on('size', s => {
size = s
})
let verified
stream.on('verified', v => {
verified = v
})
stream.on('end', () => {
t.equal(collected, 'foo', 'stream output is complete')
t.equal(size, 3, 'size emitted')
t.same(integrity, TARGET, 'matching integrity emitted')
t.same(verified, TARGET.sha512[0], 'verified emitted')
t.end()
})
stream.end()
})

test('re-emits for late listeners', t => {
const TARGET = ssri.fromData('foo')
const stream = ssri.integrityStream({ integrity: TARGET })
stream.write('foo')
let collected = ''
stream.on('data', d => {
collected += d.toString()
})

stream.on('end', () => {
// we add the listeners _after_ the end event this time to ensure that the events
// get emitted again for late listeners
let integrity
stream.on('integrity', i => {
integrity = i
})

let size
stream.on('size', s => {
size = s
})

let verified
stream.on('verified', v => {
verified = v
})
t.equal(collected, 'foo', 'stream output is complete')
t.equal(size, 3, 'size emitted')
t.same(integrity, TARGET, 'matching integrity emitted')
t.same(verified, TARGET.sha512[0], 'verified emitted')
t.end()
})
stream.end()
Expand Down

0 comments on commit c5421f1

Please sign in to comment.