mirror of
https://github.com/nodejs/node.git
synced 2025-05-06 12:54:43 +00:00

As much as I would like to do this everywhere and then modify the lint rule to enforce it, the churn would be too big. However if we're going to have relatively frequent nits for this sort of thing (as we do), I'd prefer we migrate a few files at a time to never actually getting around to doing it. Ref: https://github.com/nodejs/node/pull/45448#pullrequestreview-1179370442 PR-URL: https://github.com/nodejs/node/pull/45466 Reviewed-By: James M Snell <jasnell@gmail.com>
157 lines
3.4 KiB
JavaScript
157 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const { EventEmitterAsyncResource } = require('events');
|
|
const {
|
|
createHook,
|
|
executionAsyncId,
|
|
} = require('async_hooks');
|
|
|
|
const {
|
|
deepStrictEqual,
|
|
strictEqual,
|
|
throws,
|
|
} = 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());
|
|
|
|
// Member methods ERR_INVALID_THIS
|
|
throws(
|
|
() => EventEmitterAsyncResource.prototype.emit(),
|
|
{ code: 'ERR_INVALID_THIS' }
|
|
);
|
|
|
|
throws(
|
|
() => EventEmitterAsyncResource.prototype.emitDestroy(),
|
|
{ code: 'ERR_INVALID_THIS' }
|
|
);
|
|
|
|
['asyncId', 'triggerAsyncId', 'asyncResource'].forEach((getter) => {
|
|
throws(
|
|
() => Reflect.get(EventEmitterAsyncResource.prototype, getter, {}),
|
|
{
|
|
code: 'ERR_INVALID_THIS',
|
|
name: /TypeError/,
|
|
message: 'Value of "this" must be of type EventEmitterAsyncResource',
|
|
stack: new RegExp(`at get ${getter}`),
|
|
}
|
|
);
|
|
});
|