diff --git a/lib/domain.js b/lib/domain.js index b68e642c490cc3..9670a53629e16b 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -399,32 +399,35 @@ EventEmitter.init = function() { const eventEmit = EventEmitter.prototype.emit; EventEmitter.prototype.emit = function emit(...args) { const domain = this.domain; - if (domain === null || domain === undefined || this === process) { - return Reflect.apply(eventEmit, this, args); - } const type = args[0]; - // edge case: if there is a domain and an existing non error object is given, - // it should not be errorized - // see test/parallel/test-event-emitter-no-error-provided-to-error-event.js - if (type === 'error' && args.length > 1 && args[1] && - !(args[1] instanceof Error)) { - domain.emit('error', args[1]); - return false; - } + const shouldEmitError = type === 'error' && + this.listenerCount(type) > 0; - domain.enter(); - try { + // Just call original `emit` if current EE instance has `error` + // handler, there's no active domain or this is process + if (shouldEmitError || domain === null || domain === undefined || + this === process) { return Reflect.apply(eventEmit, this, args); - } catch (er) { - if (typeof er === 'object' && er !== null) { + } + + if (type === 'error') { + const er = args.length > 1 && args[1] ? + args[1] : new errors.Error('ERR_UNHANDLED_ERROR'); + + if (typeof er === 'object') { er.domainEmitter = this; er.domain = domain; er.domainThrown = false; } + domain.emit('error', er); return false; - } finally { - domain.exit(); } + + domain.enter(); + const ret = Reflect.apply(eventEmit, this, args); + domain.exit(); + + return ret; }; diff --git a/test/parallel/test-domain-ee-error-listener.js b/test/parallel/test-domain-ee-error-listener.js new file mode 100644 index 00000000000000..69041c7523b142 --- /dev/null +++ b/test/parallel/test-domain-ee-error-listener.js @@ -0,0 +1,20 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const domain = require('domain').create(); +const EventEmitter = require('events'); + +domain.on('error', common.mustNotCall()); + +const ee = new EventEmitter(); + +const plainObject = { justAn: 'object' }; +ee.once('error', common.mustCall((err) => { + assert.deepStrictEqual(err, plainObject); +})); +ee.emit('error', plainObject); + +const err = new Error('test error'); +ee.once('error', common.expectsError(err)); +ee.emit('error', err);