Skip to content

Commit a7d0c76

Browse files
benjamingrdanielleadams
authored andcommitted
events: support emit on nodeeventtarget
PR-URL: #35851 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com> Reviewed-By: Ricky Zhou <0x19951125@gmail.com>
1 parent 76332a0 commit a7d0c76

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

lib/internal/event_target.js

+20
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ ObjectDefineProperty(Event.prototype, SymbolToStringTag, {
172172
value: 'Event',
173173
});
174174

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

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

478497
once(type, listener) {
479498
this.addEventListener(type, listener,
@@ -502,6 +521,7 @@ ObjectDefineProperties(NodeEventTarget.prototype, {
502521
on: { enumerable: true },
503522
addListener: { enumerable: true },
504523
once: { enumerable: true },
524+
emit: { enumerable: true },
505525
removeAllListeners: { enumerable: true },
506526
});
507527

lib/internal/worker/io.js

+4
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,15 @@ ObjectDefineProperties(MessageEvent.prototype, {
127127
},
128128
});
129129

130+
const originalCreateEvent = EventTarget.prototype[kCreateEvent];
130131
ObjectDefineProperty(
131132
MessagePort.prototype,
132133
kCreateEvent,
133134
{
134135
value: function(data, type) {
136+
if (type !== 'message' && type !== 'messageerror') {
137+
return originalCreateEvent.call(this, data, type);
138+
}
135139
return new MessageEvent(type, { data });
136140
},
137141
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)