|
1 | 1 | 'use strict'; |
2 | 2 |
|
3 | 3 | const { |
| 4 | + ArrayIsArray, |
4 | 5 | ObjectSetPrototypeOf, |
5 | 6 | } = primordials; |
6 | 7 |
|
@@ -58,12 +59,12 @@ Stream.prototype.pipe = function(dest, options) { |
58 | 59 | function onerror(er) { |
59 | 60 | cleanup(); |
60 | 61 | if (EE.listenerCount(this, 'error') === 0) { |
61 | | - throw er; // Unhandled stream error in pipe. |
| 62 | + this.emit('error', er); |
62 | 63 | } |
63 | 64 | } |
64 | 65 |
|
65 | | - source.on('error', onerror); |
66 | | - dest.on('error', onerror); |
| 66 | + prependListener(source, 'error', onerror); |
| 67 | + prependListener(dest, 'error', onerror); |
67 | 68 |
|
68 | 69 | // Remove all the event listeners that were added. |
69 | 70 | function cleanup() { |
@@ -92,4 +93,22 @@ Stream.prototype.pipe = function(dest, options) { |
92 | 93 | return dest; |
93 | 94 | }; |
94 | 95 |
|
95 | | -module.exports = Stream; |
| 96 | +function prependListener(emitter, event, fn) { |
| 97 | + // Sadly this is not cacheable as some libraries bundle their own |
| 98 | + // event emitter implementation with them. |
| 99 | + if (typeof emitter.prependListener === 'function') |
| 100 | + return emitter.prependListener(event, fn); |
| 101 | + |
| 102 | + // This is a hack to make sure that our error handler is attached before any |
| 103 | + // userland ones. NEVER DO THIS. This is here only because this code needs |
| 104 | + // to continue to work with older versions of Node.js that do not include |
| 105 | + // the prependListener() method. The goal is to eventually remove this hack. |
| 106 | + if (!emitter._events || !emitter._events[event]) |
| 107 | + emitter.on(event, fn); |
| 108 | + else if (ArrayIsArray(emitter._events[event])) |
| 109 | + emitter._events[event].unshift(fn); |
| 110 | + else |
| 111 | + emitter._events[event] = [fn, emitter._events[event]]; |
| 112 | +} |
| 113 | + |
| 114 | +module.exports = { Stream, prependListener }; |
0 commit comments