2023-02-20 10:35:04 -05:00
|
|
|
// deno-fmt-ignore-file
|
|
|
|
// deno-lint-ignore-file
|
|
|
|
|
|
|
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
|
|
|
// Taken from Node 18.12.1
|
2023-06-02 02:05:32 -04:00
|
|
|
// This file is automatically generated by `tools/node_compat/setup.ts`. Do not modify this file manually.
|
2023-02-20 10:35:04 -05:00
|
|
|
|
|
|
|
// Flags: --expose-internals --no-warnings
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const common = require('../common');
|
|
|
|
const assert = require('assert');
|
|
|
|
const { on, EventEmitter } = require('events');
|
|
|
|
const {
|
2023-11-24 21:35:36 -05:00
|
|
|
NodeEventTarget,
|
2023-02-20 10:35:04 -05:00
|
|
|
} = 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'],
|
2023-11-24 21:35:36 -05:00
|
|
|
done: false,
|
2023-02-20 10:35:04 -05:00
|
|
|
}, {
|
|
|
|
value: [42],
|
2023-11-24 21:35:36 -05:00
|
|
|
done: false,
|
2023-02-20 10:35:04 -05:00
|
|
|
}, {
|
|
|
|
value: undefined,
|
2023-11-24 21:35:36 -05:00
|
|
|
done: true,
|
2023-02-20 10:35:04 -05:00
|
|
|
}]);
|
|
|
|
|
|
|
|
assert.deepStrictEqual(await iterable.next(), {
|
|
|
|
value: undefined,
|
2023-11-24 21:35:36 -05:00
|
|
|
done: true,
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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',
|
2023-11-24 21:35:36 -05:00
|
|
|
reason: _err,
|
2023-02-20 10:35:04 -05:00
|
|
|
}, {
|
|
|
|
status: 'fulfilled',
|
|
|
|
value: {
|
|
|
|
value: undefined,
|
2023-11-24 21:35:36 -05:00
|
|
|
done: true,
|
|
|
|
},
|
2023-02-20 10:35:04 -05:00
|
|
|
}, {
|
|
|
|
status: 'fulfilled',
|
|
|
|
value: {
|
|
|
|
value: undefined,
|
2023-11-24 21:35:36 -05:00
|
|
|
done: true,
|
|
|
|
},
|
2023-02-20 10:35:04 -05:00
|
|
|
}]);
|
|
|
|
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',
|
2023-11-24 21:35:36 -05:00
|
|
|
name: 'TypeError',
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
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 }), {
|
2023-11-24 21:35:36 -05:00
|
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
});
|
|
|
|
assert.throws(() => on(ee, 'foo', { signal: abortedSignal }), {
|
2023-11-24 21:35:36 -05:00
|
|
|
name: 'AbortError',
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function eventTargetAbortableOnBefore() {
|
|
|
|
const et = new EventTarget();
|
|
|
|
const abortedSignal = AbortSignal.abort();
|
|
|
|
[1, {}, null, false, 'hi'].forEach((signal) => {
|
|
|
|
assert.throws(() => on(et, 'foo', { signal }), {
|
2023-11-24 21:35:36 -05:00
|
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
});
|
|
|
|
assert.throws(() => on(et, 'foo', { signal: abortedSignal }), {
|
2023-11-24 21:35:36 -05:00
|
|
|
name: 'AbortError',
|
2023-02-20 10:35:04 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|