Skip to content

Commit e51d7c5

Browse files
benjamingrtargos
authored andcommitted
events: support emit on nodeeventtarget
PR-URL: #35851 Backport-PR-URL: #38386 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Yongsheng Zhang <[email protected]> Reviewed-By: Ricky Zhou <[email protected]>
1 parent 6558ffa commit e51d7c5

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed

lib/internal/event_target.js

+20
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ Object.defineProperty(Event.prototype, SymbolToStringTag, {
171171
value: 'Event',
172172
});
173173

174+
class NodeCustomEvent extends Event {
175+
constructor(type, options) {
176+
super(type, options);
177+
if (options && options.detail) {
178+
this.detail = options.detail;
179+
}
180+
}
181+
}
174182
// The listeners for an EventTarget are maintained as a linked list.
175183
// Unfortunately, the way EventTarget is defined, listeners are accounted
176184
// using the tuple [handler,capture], and even if we don't actually make
@@ -376,6 +384,9 @@ class EventTarget {
376384
event[kTarget] = undefined;
377385
}
378386

387+
[kCreateEvent](nodeValue, type) {
388+
return new NodeCustomEvent(type, { detail: nodeValue });
389+
}
379390
[customInspectSymbol](depth, options) {
380391
const name = this.constructor.name;
381392
if (depth < 0)
@@ -473,6 +484,14 @@ class NodeEventTarget extends EventTarget {
473484
this.addEventListener(type, listener, { [kIsNodeStyleListener]: true });
474485
return this;
475486
}
487+
emit(type, arg) {
488+
if (typeof type !== 'string') {
489+
throw new ERR_INVALID_ARG_TYPE('type', 'string', type);
490+
}
491+
const hadListeners = this.listenerCount(type) > 0;
492+
this[kHybridDispatch](arg, type);
493+
return hadListeners;
494+
}
476495

477496
once(type, listener) {
478497
this.addEventListener(type, listener,
@@ -501,6 +520,7 @@ Object.defineProperties(NodeEventTarget.prototype, {
501520
on: { enumerable: true },
502521
addListener: { enumerable: true },
503522
once: { enumerable: true },
523+
emit: { enumerable: true },
504524
removeAllListeners: { enumerable: true },
505525
});
506526

lib/internal/worker/io.js

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const {
3030
const { Readable, Writable } = require('stream');
3131
const {
3232
Event,
33+
EventTarget,
3334
NodeEventTarget,
3435
defineEventHandler,
3536
initNodeEventTarget,
@@ -79,11 +80,15 @@ class MessageEvent extends Event {
7980
}
8081
}
8182

83+
const originalCreateEvent = EventTarget.prototype[kCreateEvent];
8284
ObjectDefineProperty(
8385
MessagePort.prototype,
8486
kCreateEvent,
8587
{
8688
value: function(data, type) {
89+
if (type !== 'message' && type !== 'messageerror') {
90+
return originalCreateEvent.call(this, data, type);
91+
}
8792
return new MessageEvent(data, this, type);
8893
},
8994
configurable: false,

test/parallel/test-nodeeventtarget.js

+22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
deepStrictEqual,
1212
ok,
1313
strictEqual,
14+
throws,
1415
} = require('assert');
1516

1617
const { on } = require('events');
@@ -145,6 +146,27 @@ const { on } = require('events');
145146
target.on('foo', () => {});
146147
target.on('foo', () => {});
147148
}
149+
{
150+
// Test NodeEventTarget emit
151+
const emitter = new NodeEventTarget();
152+
emitter.addEventListener('foo', common.mustCall((e) => {
153+
strictEqual(e.type, 'foo');
154+
strictEqual(e.detail, 'bar');
155+
ok(e instanceof Event);
156+
}), { once: true });
157+
emitter.once('foo', common.mustCall((e, droppedAdditionalArgument) => {
158+
strictEqual(e, 'bar');
159+
strictEqual(droppedAdditionalArgument, undefined);
160+
}));
161+
emitter.emit('foo', 'bar', 'baz');
162+
}
163+
{
164+
// Test NodeEventTarget emit unsupported usage
165+
const emitter = new NodeEventTarget();
166+
throws(() => {
167+
emitter.emit();
168+
}, /ERR_INVALID_ARG_TYPE/);
169+
}
148170

149171
(async () => {
150172
// test NodeEventTarget async-iterability

test/parallel/test-worker-message-port.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,18 @@ const { MessageChannel, MessagePort } = require('worker_threads');
1616
port2.close(common.mustCall());
1717
}));
1818
}
19-
19+
{
20+
// Test emitting non-message events on a port
21+
const { port2 } = new MessageChannel();
22+
port2.addEventListener('foo', common.mustCall((received) => {
23+
assert.strictEqual(received.type, 'foo');
24+
assert.strictEqual(received.detail, 'bar');
25+
}));
26+
port2.on('foo', common.mustCall((received) => {
27+
assert.strictEqual(received, 'bar');
28+
}));
29+
port2.emit('foo', 'bar');
30+
}
2031
{
2132
const { port1, port2 } = new MessageChannel();
2233

0 commit comments

Comments
 (0)