| // Flags: --expose-internals |
| 'use strict'; |
| |
| const common = require('../common'); |
| const assert = require('assert'); |
| const { on, EventEmitter } = require('events'); |
| const { |
| EventTarget, |
| NodeEventTarget, |
| Event |
| } = require('internal/event_target'); |
| |
| async function basic() { |
| const ee = new EventEmitter(); |
| process.nextTick(() => { |
| ee.emit('foo', 'bar'); |
| // 'bar' is a spurious event, we are testing |
| // that it does not show up in the iterable |
| ee.emit('bar', 24); |
| ee.emit('foo', 42); |
| }); |
| |
| const iterable = on(ee, 'foo'); |
| |
| const expected = [['bar'], [42]]; |
| |
| for await (const event of iterable) { |
| const current = expected.shift(); |
| |
| assert.deepStrictEqual(current, event); |
| |
| if (expected.length === 0) { |
| break; |
| } |
| } |
| assert.strictEqual(ee.listenerCount('foo'), 0); |
| assert.strictEqual(ee.listenerCount('error'), 0); |
| } |
| |
| async function error() { |
| const ee = new EventEmitter(); |
| const _err = new Error('kaboom'); |
| process.nextTick(() => { |
| ee.emit('error', _err); |
| }); |
| |
| const iterable = on(ee, 'foo'); |
| let looped = false; |
| let thrown = false; |
| |
| try { |
| // eslint-disable-next-line no-unused-vars |
| for await (const event of iterable) { |
| looped = true; |
| } |
| } catch (err) { |
| thrown = true; |
| assert.strictEqual(err, _err); |
| } |
| assert.strictEqual(thrown, true); |
| assert.strictEqual(looped, false); |
| } |
| |
| async function errorDelayed() { |
| const ee = new EventEmitter(); |
| const _err = new Error('kaboom'); |
| process.nextTick(() => { |
| ee.emit('foo', 42); |
| ee.emit('error', _err); |
| }); |
| |
| const iterable = on(ee, 'foo'); |
| const expected = [[42]]; |
| let thrown = false; |
| |
| try { |
| for await (const event of iterable) { |
| const current = expected.shift(); |
| assert.deepStrictEqual(current, event); |
| } |
| } catch (err) { |
| thrown = true; |
| assert.strictEqual(err, _err); |
| } |
| assert.strictEqual(thrown, true); |
| assert.strictEqual(ee.listenerCount('foo'), 0); |
| assert.strictEqual(ee.listenerCount('error'), 0); |
| } |
| |
| async function throwInLoop() { |
| const ee = new EventEmitter(); |
| const _err = new Error('kaboom'); |
| |
| process.nextTick(() => { |
| ee.emit('foo', 42); |
| }); |
| |
| try { |
| for await (const event of on(ee, 'foo')) { |
| assert.deepStrictEqual(event, [42]); |
| throw _err; |
| } |
| } catch (err) { |
| assert.strictEqual(err, _err); |
| } |
| |
| assert.strictEqual(ee.listenerCount('foo'), 0); |
| assert.strictEqual(ee.listenerCount('error'), 0); |
| } |
| |
| async function next() { |
| const ee = new EventEmitter(); |
| const iterable = on(ee, 'foo'); |
| |
| process.nextTick(function() { |
| ee.emit('foo', 'bar'); |
| ee.emit('foo', 42); |
| iterable.return(); |
| }); |
| |
| const results = await Promise.all([ |
| iterable.next(), |
| iterable.next(), |
| iterable.next() |
| ]); |
| |
| assert.deepStrictEqual(results, [{ |
| value: ['bar'], |
| done: false |
| }, { |
| value: [42], |
| done: false |
| }, { |
| value: undefined, |
| done: true |
| }]); |
| |
| assert.deepStrictEqual(await iterable.next(), { |
| value: undefined, |
| done: true |
| }); |
| } |
| |
| async function nextError() { |
| const ee = new EventEmitter(); |
| const iterable = on(ee, 'foo'); |
| const _err = new Error('kaboom'); |
| process.nextTick(function() { |
| ee.emit('error', _err); |
| }); |
| const results = await Promise.allSettled([ |
| iterable.next(), |
| iterable.next(), |
| iterable.next() |
| ]); |
| assert.deepStrictEqual(results, [{ |
| status: 'rejected', |
| reason: _err |
| }, { |
| status: 'fulfilled', |
| value: { |
| value: undefined, |
| done: true |
| } |
| }, { |
| status: 'fulfilled', |
| value: { |
| value: undefined, |
| done: true |
| } |
| }]); |
| assert.strictEqual(ee.listeners('error').length, 0); |
| } |
| |
| async function iterableThrow() { |
| const ee = new EventEmitter(); |
| const iterable = on(ee, 'foo'); |
| |
| process.nextTick(() => { |
| ee.emit('foo', 'bar'); |
| ee.emit('foo', 42); // lost in the queue |
| iterable.throw(_err); |
| }); |
| |
| const _err = new Error('kaboom'); |
| let thrown = false; |
| |
| assert.throws(() => { |
| // No argument |
| iterable.throw(); |
| }, { |
| message: 'The "EventEmitter.AsyncIterator" property must be' + |
| ' an instance of Error. Received undefined', |
| name: 'TypeError' |
| }); |
| |
| const expected = [['bar'], [42]]; |
| |
| try { |
| for await (const event of iterable) { |
| assert.deepStrictEqual(event, expected.shift()); |
| } |
| } catch (err) { |
| thrown = true; |
| assert.strictEqual(err, _err); |
| } |
| assert.strictEqual(thrown, true); |
| assert.strictEqual(expected.length, 0); |
| assert.strictEqual(ee.listenerCount('foo'), 0); |
| assert.strictEqual(ee.listenerCount('error'), 0); |
| } |
| |
| async function eventTarget() { |
| const et = new EventTarget(); |
| const tick = () => et.dispatchEvent(new Event('tick')); |
| const interval = setInterval(tick, 0); |
| let count = 0; |
| for await (const [ event ] of on(et, 'tick')) { |
| count++; |
| assert.strictEqual(event.type, 'tick'); |
| if (count >= 5) { |
| break; |
| } |
| } |
| assert.strictEqual(count, 5); |
| clearInterval(interval); |
| } |
| |
| async function errorListenerCount() { |
| const et = new EventEmitter(); |
| on(et, 'foo'); |
| assert.strictEqual(et.listenerCount('error'), 1); |
| } |
| |
| async function nodeEventTarget() { |
| const et = new NodeEventTarget(); |
| const tick = () => et.dispatchEvent(new Event('tick')); |
| const interval = setInterval(tick, 0); |
| let count = 0; |
| for await (const [ event] of on(et, 'tick')) { |
| count++; |
| assert.strictEqual(event.type, 'tick'); |
| if (count >= 5) { |
| break; |
| } |
| } |
| assert.strictEqual(count, 5); |
| clearInterval(interval); |
| } |
| |
| |
| async function run() { |
| const funcs = [ |
| basic, |
| error, |
| errorDelayed, |
| throwInLoop, |
| next, |
| nextError, |
| iterableThrow, |
| eventTarget, |
| errorListenerCount, |
| nodeEventTarget |
| ]; |
| |
| for (const fn of funcs) { |
| await fn(); |
| } |
| } |
| |
| run().then(common.mustCall()); |