• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals --no-warnings
2'use strict';
3
4const common = require('../common');
5const {
6  Event,
7  NodeEventTarget,
8} = require('internal/event_target');
9
10const {
11  deepStrictEqual,
12  ok,
13  strictEqual,
14  throws,
15} = require('assert');
16
17const { on } = require('events');
18
19{
20  const eventTarget = new NodeEventTarget();
21  strictEqual(eventTarget.listenerCount('foo'), 0);
22  deepStrictEqual(eventTarget.eventNames(), []);
23
24  const ev1 = common.mustCall(function(event) {
25    strictEqual(event.type, 'foo');
26    strictEqual(this, eventTarget);
27  }, 2);
28
29  const ev2 = {
30    handleEvent: common.mustCall(function(event) {
31      strictEqual(event.type, 'foo');
32      strictEqual(this, ev2);
33    })
34  };
35
36  eventTarget.addEventListener('foo', ev1);
37  eventTarget.addEventListener('foo', ev2, { once: true });
38  strictEqual(eventTarget.listenerCount('foo'), 2);
39  ok(eventTarget.dispatchEvent(new Event('foo')));
40  strictEqual(eventTarget.listenerCount('foo'), 1);
41  eventTarget.dispatchEvent(new Event('foo'));
42
43  eventTarget.removeEventListener('foo', ev1);
44  strictEqual(eventTarget.listenerCount('foo'), 0);
45  eventTarget.dispatchEvent(new Event('foo'));
46}
47
48{
49  const eventTarget = new NodeEventTarget();
50  strictEqual(eventTarget.listenerCount('foo'), 0);
51  deepStrictEqual(eventTarget.eventNames(), []);
52
53  const ev1 = common.mustCall((event) => {
54    strictEqual(event.type, 'foo');
55  }, 2);
56
57  const ev2 = {
58    handleEvent: common.mustCall((event) => {
59      strictEqual(event.type, 'foo');
60    })
61  };
62
63  strictEqual(eventTarget.on('foo', ev1), eventTarget);
64  strictEqual(eventTarget.once('foo', ev2, { once: true }), eventTarget);
65  strictEqual(eventTarget.listenerCount('foo'), 2);
66  eventTarget.dispatchEvent(new Event('foo'));
67  strictEqual(eventTarget.listenerCount('foo'), 1);
68  eventTarget.dispatchEvent(new Event('foo'));
69
70  strictEqual(eventTarget.off('foo', ev1), eventTarget);
71  strictEqual(eventTarget.listenerCount('foo'), 0);
72  eventTarget.dispatchEvent(new Event('foo'));
73}
74
75{
76  const eventTarget = new NodeEventTarget();
77  strictEqual(eventTarget.listenerCount('foo'), 0);
78  deepStrictEqual(eventTarget.eventNames(), []);
79
80  const ev1 = common.mustCall((event) => {
81    strictEqual(event.type, 'foo');
82  }, 2);
83
84  const ev2 = {
85    handleEvent: common.mustCall((event) => {
86      strictEqual(event.type, 'foo');
87    })
88  };
89
90  eventTarget.addListener('foo', ev1);
91  eventTarget.once('foo', ev2, { once: true });
92  strictEqual(eventTarget.listenerCount('foo'), 2);
93  eventTarget.dispatchEvent(new Event('foo'));
94  strictEqual(eventTarget.listenerCount('foo'), 1);
95  eventTarget.dispatchEvent(new Event('foo'));
96
97  eventTarget.removeListener('foo', ev1);
98  strictEqual(eventTarget.listenerCount('foo'), 0);
99  eventTarget.dispatchEvent(new Event('foo'));
100}
101
102{
103  const eventTarget = new NodeEventTarget();
104  strictEqual(eventTarget.listenerCount('foo'), 0);
105  deepStrictEqual(eventTarget.eventNames(), []);
106
107  // Won't actually be called.
108  const ev1 = () => {};
109
110  // Won't actually be called.
111  const ev2 = { handleEvent() {} };
112
113  eventTarget.addListener('foo', ev1);
114  eventTarget.addEventListener('foo', ev1);
115  eventTarget.once('foo', ev2, { once: true });
116  eventTarget.once('foo', ev2, { once: false });
117  eventTarget.on('bar', ev1);
118  strictEqual(eventTarget.listenerCount('foo'), 2);
119  strictEqual(eventTarget.listenerCount('bar'), 1);
120  deepStrictEqual(eventTarget.eventNames(), ['foo', 'bar']);
121  strictEqual(eventTarget.removeAllListeners('foo'), eventTarget);
122  strictEqual(eventTarget.listenerCount('foo'), 0);
123  strictEqual(eventTarget.listenerCount('bar'), 1);
124  deepStrictEqual(eventTarget.eventNames(), ['bar']);
125  strictEqual(eventTarget.removeAllListeners(), eventTarget);
126  strictEqual(eventTarget.listenerCount('foo'), 0);
127  strictEqual(eventTarget.listenerCount('bar'), 0);
128  deepStrictEqual(eventTarget.eventNames(), []);
129}
130
131{
132  const target = new NodeEventTarget();
133
134  process.on('warning', common.mustCall((warning) => {
135    ok(warning instanceof Error);
136    strictEqual(warning.name, 'MaxListenersExceededWarning');
137    strictEqual(warning.target, target);
138    strictEqual(warning.count, 2);
139    strictEqual(warning.type, 'foo');
140    ok(warning.message.includes(
141      '2 foo listeners added to NodeEventTarget'));
142  }));
143
144  strictEqual(target.getMaxListeners(), NodeEventTarget.defaultMaxListeners);
145  target.setMaxListeners(1);
146  target.on('foo', () => {});
147  target.on('foo', () => {});
148}
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}
170
171(async () => {
172  // test NodeEventTarget async-iterability
173  const emitter = new NodeEventTarget();
174  const interval = setInterval(() => {
175    emitter.dispatchEvent(new Event('foo'));
176  }, 0);
177  let count = 0;
178  for await (const [ item ] of on(emitter, 'foo')) {
179    count++;
180    strictEqual(item.type, 'foo');
181    if (count > 5) {
182      break;
183    }
184  }
185  clearInterval(interval);
186})().then(common.mustCall());
187