Skip to content

Commit

Permalink
Fail if error is thrown while awaiting a Promise
Browse files Browse the repository at this point in the history
This was causing a test in make-fetch-happen to hang silently and time
out rather than failing appropriately.

Note that this can only happen if the error is thrown _outside_ of the
Promise flow of control.  Throws from withing .then()/.catch() methods
will reject the promise, which may be what you want.  If an EventEmitter
or something throws an error, tap will still track it, but the Promise
chain might not.  If it makes it to tap, then the Promise chain is
probably broken.
  • Loading branch information
isaacs committed Sep 15, 2019
1 parent 73e7496 commit a266e30
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,11 @@ class Test extends Base {
if (!proxy)
this.end(IMPLICIT)
}
// threw while waiting for a promise to resolve.
// probably it's not ever gonna.
if (this.occupied && this.occupied instanceof Waiter)
this.occupied.abort(new Error('error thrown while awaiting Promise'))

this.process()
}

Expand Down
48 changes: 48 additions & 0 deletions tap-snapshots/test-test.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3187,3 +3187,51 @@ not ok 1 - child test # {time}
# failed 1 test
`

exports[`test/test.js TAP throw while waiting on a resolving promise > result 1`] = `
TAP version 13
# Subtest
not ok 1 - expect resolving Promise
---
at:
line: #
column: #
file: test/test.js
found:
!error
name: Error
message: error thrown while awaiting Promise
stack: |
{STACK}
source: |2
setTimeout(() => t.threw(new Error('poop')))
return t.resolveMatch(() => new Promise(() => {}), 'never resolves')
--^
})
tt.end()
...
not ok 2 - poop
---
at:
line: #
column: #
file: test/test.js
source: |2
tt.test(t => {
setTimeout(() => t.threw(new Error('poop')))
--^
return t.resolveMatch(() => new Promise(() => {}), 'never resolves')
})
stack: |
{STACK}
...
1..2
# failed 2 of 2 tests
not ok 1 # {time}
1..1
# failed 1 test
`
17 changes: 17 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1153,3 +1153,20 @@ t.test('endAll with sub while waiting on a resolving promise', t => {
tt.test(t => t.resolveMatch(() => new Promise(() => {}), 'never resolves'))
setTimeout(() => tt.endAll())
})

t.test('throw while waiting on a resolving promise', t => {
t.plan(1)
const tt = new Test()
tt.setEncoding('utf8')
const buf = []
tt.on('data', c => buf.push(c))
tt.on('end', () => {
const result = buf.join('')
t.matchSnapshot(result, 'result')
})
tt.test(t => {
setTimeout(() => t.threw(new Error('poop')))
return t.resolveMatch(() => new Promise(() => {}), 'never resolves')
})
tt.end()
})

0 comments on commit a266e30

Please sign in to comment.