Skip to content

Commit

Permalink
events: extract EventEmitterAsyncResource to a separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
rluvaton committed Apr 27, 2024
1 parent 40ef9d5 commit 40e3fe7
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 111 deletions.
112 changes: 1 addition & 111 deletions lib/events.js
Expand Up @@ -27,7 +27,6 @@ const {
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSplice,
ArrayPrototypeUnshift,
Boolean,
Error,
ErrorCaptureStackTrace,
Expand Down Expand Up @@ -68,7 +67,6 @@ const {
AbortError,
codes: {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_THIS,
ERR_UNHANDLED_ERROR,
},
genericNodeError,
Expand All @@ -82,7 +80,6 @@ const {
validateFunction,
validateNumber,
validateObject,
validateString,
} = require('internal/validators');
const { addAbortListener } = require('internal/events/abort_listener');

Expand All @@ -102,114 +99,7 @@ let EventEmitterAsyncResource;
// eventemitter-asyncresource MIT-licensed userland module.
// https://github.com/addaleax/eventemitter-asyncresource
function lazyEventEmitterAsyncResource() {
if (EventEmitterAsyncResource === undefined) {
const {
AsyncResource,
} = require('async_hooks');

const kEventEmitter = Symbol('kEventEmitter');
const kAsyncResource = Symbol('kAsyncResource');
class EventEmitterReferencingAsyncResource extends AsyncResource {
/**
* @param {EventEmitter} ee
* @param {string} [type]
* @param {{
* triggerAsyncId?: number,
* requireManualDestroy?: boolean,
* }} [options]
*/
constructor(ee, type, options) {
super(type, options);
this[kEventEmitter] = ee;
}

/**
* @type {EventEmitter}
*/
get eventEmitter() {
if (this[kEventEmitter] === undefined)
throw new ERR_INVALID_THIS('EventEmitterReferencingAsyncResource');
return this[kEventEmitter];
}
}

EventEmitterAsyncResource =
class EventEmitterAsyncResource extends EventEmitter {
/**
* @param {{
* name?: string,
* triggerAsyncId?: number,
* requireManualDestroy?: boolean,
* }} [options]
*/
constructor(options = undefined) {
let name;
if (typeof options === 'string') {
name = options;
options = undefined;
} else {
if (new.target === EventEmitterAsyncResource) {
validateString(options?.name, 'options.name');
}
name = options?.name || new.target.name;
}
super(options);

this[kAsyncResource] =
new EventEmitterReferencingAsyncResource(this, name, options);
}

/**
* @param {symbol,string} event
* @param {...any} args
* @returns {boolean}
*/
emit(event, ...args) {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
const { asyncResource } = this;
ArrayPrototypeUnshift(args, super.emit, this, event);
return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
args);
}

/**
* @returns {void}
*/
emitDestroy() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
this.asyncResource.emitDestroy();
}

/**
* @type {number}
*/
get asyncId() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this.asyncResource.asyncId();
}

/**
* @type {number}
*/
get triggerAsyncId() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this.asyncResource.triggerAsyncId();
}

/**
* @type {EventEmitterReferencingAsyncResource}
*/
get asyncResource() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this[kAsyncResource];
}
};
}
EventEmitterAsyncResource ??= require('internal/events/event_emitter_async_resource');
return EventEmitterAsyncResource;
}

Expand Down
123 changes: 123 additions & 0 deletions lib/internal/events/event_emitter_async_resource.js
@@ -0,0 +1,123 @@
'use strict';

const {
ArrayPrototypeUnshift,
ReflectApply,
Symbol,
} = primordials;
const {
codes: {
ERR_INVALID_THIS,
},
} = require('internal/errors');

const { validateString } = require('internal/validators');

const {
AsyncResource,
} = require('async_hooks');
const EventEmitter = require('events');

const kEventEmitter = Symbol('kEventEmitter');
const kAsyncResource = Symbol('kAsyncResource');
class EventEmitterReferencingAsyncResource extends AsyncResource {
/**
* @param {EventEmitter} ee
* @param {string} [type]
* @param {{
* triggerAsyncId?: number,
* requireManualDestroy?: boolean,
* }} [options]
*/
constructor(ee, type, options) {
super(type, options);
this[kEventEmitter] = ee;
}

/**
* @type {EventEmitter}
*/
get eventEmitter() {
if (this[kEventEmitter] === undefined)
throw new ERR_INVALID_THIS('EventEmitterReferencingAsyncResource');
return this[kEventEmitter];
}
}

class EventEmitterAsyncResource extends EventEmitter {
/**
* @param {{
* name?: string,
* triggerAsyncId?: number,
* requireManualDestroy?: boolean,
* }} [options]
*/
constructor(options = undefined) {
let name;
if (typeof options === 'string') {
name = options;
options = undefined;
} else {
if (new.target === EventEmitterAsyncResource) {
validateString(options?.name, 'options.name');
}
name = options?.name || new.target.name;
}
super(options);

this[kAsyncResource] =
new EventEmitterReferencingAsyncResource(this, name, options);
}

/**
* @param {symbol,string} event
* @param {...any} args
* @returns {boolean}
*/
emit(event, ...args) {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
const { asyncResource } = this;
ArrayPrototypeUnshift(args, super.emit, this, event);
return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
args);
}

/**
* @returns {void}
*/
emitDestroy() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
this.asyncResource.emitDestroy();
}

/**
* @type {number}
*/
get asyncId() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this.asyncResource.asyncId();
}

/**
* @type {number}
*/
get triggerAsyncId() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this.asyncResource.triggerAsyncId();
}

/**
* @type {EventEmitterReferencingAsyncResource}
*/
get asyncResource() {
if (this[kAsyncResource] === undefined)
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
return this[kAsyncResource];
}
}

module.exports = EventEmitterAsyncResource;

0 comments on commit 40e3fe7

Please sign in to comment.