node/test/parallel/test-eventemitter-asyncresource.js
James M Snell 895c3d937e
events: add EventEmitterAsyncResource to core
Signd-off-by: James M Snell <jasnell@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/41246
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2021-12-23 00:56:57 +00:00

133 lines
2.9 KiB
JavaScript

'use strict';
const common = require('../common');
const { EventEmitterAsyncResource } = require('events');
const {
createHook,
executionAsyncId,
} = require('async_hooks');
const {
deepStrictEqual,
strictEqual,
} = require('assert');
const {
setImmediate: tick,
} = require('timers/promises');
function makeHook(trackedTypes) {
const eventMap = new Map();
function log(asyncId, name) {
const entry = eventMap.get(asyncId);
if (entry !== undefined) entry.push({ name });
}
const hook = createHook({
init(asyncId, type, triggerAsyncId, resource) {
if (trackedTypes.includes(type)) {
eventMap.set(asyncId, [
{
name: 'init',
type,
triggerAsyncId,
resource,
},
]);
}
},
before(asyncId) { log(asyncId, 'before'); },
after(asyncId) { log(asyncId, 'after'); },
destroy(asyncId) { log(asyncId, 'destroy'); }
}).enable();
return {
done() {
hook.disable();
return new Set(eventMap.values());
},
ids() {
return new Set(eventMap.keys());
}
};
}
// Tracks emit() calls correctly using async_hooks
(async () => {
const tracer = makeHook(['Foo']);
class Foo extends EventEmitterAsyncResource {}
const origExecutionAsyncId = executionAsyncId();
const foo = new Foo();
foo.on('someEvent', common.mustCall());
foo.emit('someEvent');
deepStrictEqual([foo.asyncId], [...tracer.ids()]);
strictEqual(foo.triggerAsyncId, origExecutionAsyncId);
strictEqual(foo.asyncResource.eventEmitter, foo);
foo.emitDestroy();
await tick();
deepStrictEqual(tracer.done(), new Set([
[
{
name: 'init',
type: 'Foo',
triggerAsyncId: origExecutionAsyncId,
resource: foo.asyncResource,
},
{ name: 'before' },
{ name: 'after' },
{ name: 'destroy' },
],
]));
})().then(common.mustCall());
// Can explicitly specify name as positional arg
(async () => {
const tracer = makeHook(['ResourceName']);
const origExecutionAsyncId = executionAsyncId();
class Foo extends EventEmitterAsyncResource {}
const foo = new Foo('ResourceName');
deepStrictEqual(tracer.done(), new Set([
[
{
name: 'init',
type: 'ResourceName',
triggerAsyncId: origExecutionAsyncId,
resource: foo.asyncResource,
},
],
]));
})().then(common.mustCall());
// Can explicitly specify name as option
(async () => {
const tracer = makeHook(['ResourceName']);
const origExecutionAsyncId = executionAsyncId();
class Foo extends EventEmitterAsyncResource {}
const foo = new Foo({ name: 'ResourceName' });
deepStrictEqual(tracer.done(), new Set([
[
{
name: 'init',
type: 'ResourceName',
triggerAsyncId: origExecutionAsyncId,
resource: foo.asyncResource,
},
],
]));
})().then(common.mustCall());