'use strict'; const common = require('../common'); const assert = require('assert'); const domain = require('domain'); const EventEmitter = require('events'); /* * Make sure that the domains stack and the active domain is setup properly when * a domain's error handler is called due to an error event being emitted. * More specifically, we want to test that: * - the active domain in the domain's error handler is *not* that domain, *but* * the active domain is a any direct parent domain at the time the error was * emitted. * - the domains stack in the domain's error handler does *not* include that * domain, *but* it includes all parents of that domain when the error was * emitted. */ const d1 = domain.create(); const d2 = domain.create(); const d3 = domain.create(); function checkExpectedDomains(err) { // First, check that domains stack and active domain is as expected when the // event handler is called synchronously via ee.emit('error'). if (domain._stack.length !== err.expectedStackLength) { console.error('expected domains stack length of %d, but instead is %d', err.expectedStackLength, domain._stack.length); process.exit(1); } if (process.domain !== err.expectedActiveDomain) { console.error('expected active domain to be %j, but instead is %j', err.expectedActiveDomain, process.domain); process.exit(1); } // Then make sure that the domains stack and active domain is setup as // expected when executing a callback scheduled via nextTick from the error // handler. process.nextTick(() => { const expectedStackLengthInNextTickCb = err.expectedStackLength > 0 ? 1 : 0; if (domain._stack.length !== expectedStackLengthInNextTickCb) { console.error('expected stack length in nextTick cb to be %d, ' + 'but instead is %d', expectedStackLengthInNextTickCb, domain._stack.length); process.exit(1); } const expectedActiveDomainInNextTickCb = expectedStackLengthInNextTickCb === 0 ? undefined : err.expectedActiveDomain; if (process.domain !== expectedActiveDomainInNextTickCb) { console.error('expected active domain in nextTick cb to be %j, ' + 'but instead is %j', expectedActiveDomainInNextTickCb, process.domain); process.exit(1); } }); } d1.on('error', common.mustCall((err) => { checkExpectedDomains(err); }, 2)); d2.on('error', common.mustCall((err) => { checkExpectedDomains(err); }, 2)); d3.on('error', common.mustCall((err) => { checkExpectedDomains(err); }, 1)); d1.run(() => { const ee = new EventEmitter(); assert.strictEqual(process.domain, d1); assert.strictEqual(domain._stack.length, 1); const err = new Error('oops'); err.expectedStackLength = 0; err.expectedActiveDomain = null; ee.emit('error', err); assert.strictEqual(process.domain, d1); assert.strictEqual(domain._stack.length, 1); }); d1.run(() => { d1.run(() => { const ee = new EventEmitter(); assert.strictEqual(process.domain, d1); assert.strictEqual(domain._stack.length, 2); const err = new Error('oops'); err.expectedStackLength = 0; err.expectedActiveDomain = null; ee.emit('error', err); assert.strictEqual(process.domain, d1); assert.strictEqual(domain._stack.length, 2); }); }); d1.run(() => { d2.run(() => { const ee = new EventEmitter(); assert.strictEqual(process.domain, d2); assert.strictEqual(domain._stack.length, 2); const err = new Error('oops'); err.expectedStackLength = 1; err.expectedActiveDomain = d1; ee.emit('error', err); assert.strictEqual(process.domain, d2); assert.strictEqual(domain._stack.length, 2); }); }); d1.run(() => { d2.run(() => { d2.run(() => { const ee = new EventEmitter(); assert.strictEqual(process.domain, d2); assert.strictEqual(domain._stack.length, 3); const err = new Error('oops'); err.expectedStackLength = 1; err.expectedActiveDomain = d1; ee.emit('error', err); assert.strictEqual(process.domain, d2); assert.strictEqual(domain._stack.length, 3); }); }); }); d3.run(() => { d1.run(() => { d3.run(() => { d3.run(() => { const ee = new EventEmitter(); assert.strictEqual(process.domain, d3); assert.strictEqual(domain._stack.length, 4); const err = new Error('oops'); err.expectedStackLength = 2; err.expectedActiveDomain = d1; ee.emit('error', err); assert.strictEqual(process.domain, d3); assert.strictEqual(domain._stack.length, 4); }); }); }); });