// deno-fmt-ignore-file // deno-lint-ignore-file // Copyright Joyent and Node contributors. All rights reserved. MIT license. // Taken from Node 18.12.1 // This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually // Flags: --expose-internals --no-warnings 'use strict'; const common = require('../common'); const assert = require('assert'); const { on, EventEmitter } = require('events'); const { NodeEventTarget } = 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 invalidArgType() { assert.throws(() => on({}, 'foo'), common.expectsError({ code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', })); } 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 abortableOnBefore() { const ee = new EventEmitter(); const abortedSignal = AbortSignal.abort(); [1, {}, null, false, 'hi'].forEach((signal) => { assert.throws(() => on(ee, 'foo', { signal }), { code: 'ERR_INVALID_ARG_TYPE' }); }); assert.throws(() => on(ee, 'foo', { signal: abortedSignal }), { name: 'AbortError' }); } async function eventTargetAbortableOnBefore() { const et = new EventTarget(); const abortedSignal = AbortSignal.abort(); [1, {}, null, false, 'hi'].forEach((signal) => { assert.throws(() => on(et, 'foo', { signal }), { code: 'ERR_INVALID_ARG_TYPE' }); }); assert.throws(() => on(et, 'foo', { signal: abortedSignal }), { name: 'AbortError' }); } async function abortableOnAfter() { const ee = new EventEmitter(); const ac = new AbortController(); const i = setInterval(() => ee.emit('foo', 'foo'), 10); async function foo() { for await (const f of on(ee, 'foo', { signal: ac.signal })) { assert.strictEqual(f, 'foo'); } } foo().catch(common.mustCall((error) => { assert.strictEqual(error.name, 'AbortError'); })).finally(() => { clearInterval(i); }); process.nextTick(() => ac.abort()); } async function eventTargetAbortableOnAfter() { const et = new EventTarget(); const ac = new AbortController(); const i = setInterval(() => et.dispatchEvent(new Event('foo')), 10); async function foo() { for await (const f of on(et, 'foo', { signal: ac.signal })) { assert(f); } } foo().catch(common.mustCall((error) => { assert.strictEqual(error.name, 'AbortError'); })).finally(() => { clearInterval(i); }); process.nextTick(() => ac.abort()); } async function eventTargetAbortableOnAfter2() { const et = new EventTarget(); const ac = new AbortController(); const i = setInterval(() => et.dispatchEvent(new Event('foo')), 10); async function foo() { for await (const f of on(et, 'foo', { signal: ac.signal })) { assert(f); // Cancel after a single event has been triggered. ac.abort(); } } foo().catch(common.mustCall((error) => { assert.strictEqual(error.name, 'AbortError'); })).finally(() => { clearInterval(i); }); } async function abortableOnAfterDone() { const ee = new EventEmitter(); const ac = new AbortController(); const i = setInterval(() => ee.emit('foo', 'foo'), 1); let count = 0; async function foo() { for await (const f of on(ee, 'foo', { signal: ac.signal })) { assert.strictEqual(f[0], 'foo'); if (++count === 5) break; } ac.abort(); // No error will occur } foo().finally(() => { clearInterval(i); }); } async function run() { const funcs = [ basic, invalidArgType, error, errorDelayed, throwInLoop, next, nextError, iterableThrow, eventTarget, errorListenerCount, nodeEventTarget, abortableOnBefore, abortableOnAfter, eventTargetAbortableOnBefore, eventTargetAbortableOnAfter, eventTargetAbortableOnAfter2, abortableOnAfterDone, ]; for (const fn of funcs) { await fn(); } } run().then(common.mustCall());