11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci// Flags: --expose-internals --no-warnings
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst common = require('../common');
51cb0ef41Sopenharmony_ciconst { once, EventEmitter } = require('events');
61cb0ef41Sopenharmony_ciconst {
71cb0ef41Sopenharmony_ci  strictEqual,
81cb0ef41Sopenharmony_ci  deepStrictEqual,
91cb0ef41Sopenharmony_ci  fail,
101cb0ef41Sopenharmony_ci  rejects,
111cb0ef41Sopenharmony_ci} = require('assert');
121cb0ef41Sopenharmony_ciconst { kEvents } = require('internal/event_target');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciasync function onceAnEvent() {
151cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci  process.nextTick(() => {
181cb0ef41Sopenharmony_ci    ee.emit('myevent', 42);
191cb0ef41Sopenharmony_ci  });
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  const [value] = await once(ee, 'myevent');
221cb0ef41Sopenharmony_ci  strictEqual(value, 42);
231cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 0);
241cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('myevent'), 0);
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciasync function onceAnEventWithNullOptions() {
281cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  process.nextTick(() => {
311cb0ef41Sopenharmony_ci    ee.emit('myevent', 42);
321cb0ef41Sopenharmony_ci  });
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  const [value] = await once(ee, 'myevent', null);
351cb0ef41Sopenharmony_ci  strictEqual(value, 42);
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciasync function onceAnEventWithTwoArgs() {
401cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  process.nextTick(() => {
431cb0ef41Sopenharmony_ci    ee.emit('myevent', 42, 24);
441cb0ef41Sopenharmony_ci  });
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  const value = await once(ee, 'myevent');
471cb0ef41Sopenharmony_ci  deepStrictEqual(value, [42, 24]);
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciasync function catchesErrors() {
511cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  const expected = new Error('kaboom');
541cb0ef41Sopenharmony_ci  let err;
551cb0ef41Sopenharmony_ci  process.nextTick(() => {
561cb0ef41Sopenharmony_ci    ee.emit('error', expected);
571cb0ef41Sopenharmony_ci  });
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  try {
601cb0ef41Sopenharmony_ci    await once(ee, 'myevent');
611cb0ef41Sopenharmony_ci  } catch (_e) {
621cb0ef41Sopenharmony_ci    err = _e;
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci  strictEqual(err, expected);
651cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 0);
661cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('myevent'), 0);
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciasync function catchesErrorsWithAbortSignal() {
701cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
711cb0ef41Sopenharmony_ci  const ac = new AbortController();
721cb0ef41Sopenharmony_ci  const signal = ac.signal;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  const expected = new Error('boom');
751cb0ef41Sopenharmony_ci  let err;
761cb0ef41Sopenharmony_ci  process.nextTick(() => {
771cb0ef41Sopenharmony_ci    ee.emit('error', expected);
781cb0ef41Sopenharmony_ci  });
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  try {
811cb0ef41Sopenharmony_ci    const promise = once(ee, 'myevent', { signal });
821cb0ef41Sopenharmony_ci    strictEqual(ee.listenerCount('error'), 1);
831cb0ef41Sopenharmony_ci    strictEqual(signal[kEvents].size, 1);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci    await promise;
861cb0ef41Sopenharmony_ci  } catch (e) {
871cb0ef41Sopenharmony_ci    err = e;
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci  strictEqual(err, expected);
901cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 0);
911cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('myevent'), 0);
921cb0ef41Sopenharmony_ci  strictEqual(signal[kEvents].size, 0);
931cb0ef41Sopenharmony_ci}
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ciasync function stopListeningAfterCatchingError() {
961cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  const expected = new Error('kaboom');
991cb0ef41Sopenharmony_ci  let err;
1001cb0ef41Sopenharmony_ci  process.nextTick(() => {
1011cb0ef41Sopenharmony_ci    ee.emit('error', expected);
1021cb0ef41Sopenharmony_ci    ee.emit('myevent', 42, 24);
1031cb0ef41Sopenharmony_ci  });
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  try {
1061cb0ef41Sopenharmony_ci    await once(ee, 'myevent');
1071cb0ef41Sopenharmony_ci  } catch (_e) {
1081cb0ef41Sopenharmony_ci    err = _e;
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci  process.removeAllListeners('multipleResolves');
1111cb0ef41Sopenharmony_ci  strictEqual(err, expected);
1121cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 0);
1131cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('myevent'), 0);
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciasync function onceError() {
1171cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  const expected = new Error('kaboom');
1201cb0ef41Sopenharmony_ci  process.nextTick(() => {
1211cb0ef41Sopenharmony_ci    ee.emit('error', expected);
1221cb0ef41Sopenharmony_ci  });
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  const promise = once(ee, 'error');
1251cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 1);
1261cb0ef41Sopenharmony_ci  const [ err ] = await promise;
1271cb0ef41Sopenharmony_ci  strictEqual(err, expected);
1281cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('error'), 0);
1291cb0ef41Sopenharmony_ci  strictEqual(ee.listenerCount('myevent'), 0);
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ciasync function onceWithEventTarget() {
1331cb0ef41Sopenharmony_ci  const et = new EventTarget();
1341cb0ef41Sopenharmony_ci  const event = new Event('myevent');
1351cb0ef41Sopenharmony_ci  process.nextTick(() => {
1361cb0ef41Sopenharmony_ci    et.dispatchEvent(event);
1371cb0ef41Sopenharmony_ci  });
1381cb0ef41Sopenharmony_ci  const [ value ] = await once(et, 'myevent');
1391cb0ef41Sopenharmony_ci  strictEqual(value, event);
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ciasync function onceWithEventTargetError() {
1431cb0ef41Sopenharmony_ci  const et = new EventTarget();
1441cb0ef41Sopenharmony_ci  const error = new Event('error');
1451cb0ef41Sopenharmony_ci  process.nextTick(() => {
1461cb0ef41Sopenharmony_ci    et.dispatchEvent(error);
1471cb0ef41Sopenharmony_ci  });
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  const [ err ] = await once(et, 'error');
1501cb0ef41Sopenharmony_ci  strictEqual(err, error);
1511cb0ef41Sopenharmony_ci}
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ciasync function onceWithInvalidEventEmmiter() {
1541cb0ef41Sopenharmony_ci  const ac = new AbortController();
1551cb0ef41Sopenharmony_ci  return rejects(once(ac, 'myevent'), {
1561cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1571cb0ef41Sopenharmony_ci  });
1581cb0ef41Sopenharmony_ci}
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ciasync function prioritizesEventEmitter() {
1611cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
1621cb0ef41Sopenharmony_ci  ee.addEventListener = fail;
1631cb0ef41Sopenharmony_ci  ee.removeAllListeners = fail;
1641cb0ef41Sopenharmony_ci  process.nextTick(() => ee.emit('foo'));
1651cb0ef41Sopenharmony_ci  await once(ee, 'foo');
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ciasync function abortSignalBefore() {
1691cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
1701cb0ef41Sopenharmony_ci  ee.on('error', common.mustNotCall());
1711cb0ef41Sopenharmony_ci  const abortedSignal = AbortSignal.abort();
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  await Promise.all([1, {}, 'hi', null, false].map((signal) => {
1741cb0ef41Sopenharmony_ci    return rejects(once(ee, 'foo', { signal }), {
1751cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
1761cb0ef41Sopenharmony_ci    });
1771cb0ef41Sopenharmony_ci  }));
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  return rejects(once(ee, 'foo', { signal: abortedSignal }), {
1801cb0ef41Sopenharmony_ci    name: 'AbortError',
1811cb0ef41Sopenharmony_ci  });
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ciasync function abortSignalAfter() {
1851cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
1861cb0ef41Sopenharmony_ci  const ac = new AbortController();
1871cb0ef41Sopenharmony_ci  ee.on('error', common.mustNotCall());
1881cb0ef41Sopenharmony_ci  const r = rejects(once(ee, 'foo', { signal: ac.signal }), {
1891cb0ef41Sopenharmony_ci    name: 'AbortError',
1901cb0ef41Sopenharmony_ci  });
1911cb0ef41Sopenharmony_ci  process.nextTick(() => ac.abort());
1921cb0ef41Sopenharmony_ci  return r;
1931cb0ef41Sopenharmony_ci}
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciasync function abortSignalAfterEvent() {
1961cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
1971cb0ef41Sopenharmony_ci  const ac = new AbortController();
1981cb0ef41Sopenharmony_ci  process.nextTick(() => {
1991cb0ef41Sopenharmony_ci    ee.emit('foo');
2001cb0ef41Sopenharmony_ci    ac.abort();
2011cb0ef41Sopenharmony_ci  });
2021cb0ef41Sopenharmony_ci  const promise = once(ee, 'foo', { signal: ac.signal });
2031cb0ef41Sopenharmony_ci  strictEqual(ac.signal[kEvents].size, 1);
2041cb0ef41Sopenharmony_ci  await promise;
2051cb0ef41Sopenharmony_ci  strictEqual(ac.signal[kEvents].size, 0);
2061cb0ef41Sopenharmony_ci}
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ciasync function abortSignalRemoveListener() {
2091cb0ef41Sopenharmony_ci  const ee = new EventEmitter();
2101cb0ef41Sopenharmony_ci  const ac = new AbortController();
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  try {
2131cb0ef41Sopenharmony_ci    process.nextTick(() => ac.abort());
2141cb0ef41Sopenharmony_ci    await once(ee, 'test', { signal: ac.signal });
2151cb0ef41Sopenharmony_ci  } catch {
2161cb0ef41Sopenharmony_ci    strictEqual(ee.listeners('test').length, 0);
2171cb0ef41Sopenharmony_ci    strictEqual(ee.listeners('error').length, 0);
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci}
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ciasync function eventTargetAbortSignalBefore() {
2221cb0ef41Sopenharmony_ci  const et = new EventTarget();
2231cb0ef41Sopenharmony_ci  const abortedSignal = AbortSignal.abort();
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  await Promise.all([1, {}, 'hi', null, false].map((signal) => {
2261cb0ef41Sopenharmony_ci    return rejects(once(et, 'foo', { signal }), {
2271cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2281cb0ef41Sopenharmony_ci    });
2291cb0ef41Sopenharmony_ci  }));
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  return rejects(once(et, 'foo', { signal: abortedSignal }), {
2321cb0ef41Sopenharmony_ci    name: 'AbortError',
2331cb0ef41Sopenharmony_ci  });
2341cb0ef41Sopenharmony_ci}
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ciasync function eventTargetAbortSignalBeforeEvenWhenSignalPropagationStopped() {
2371cb0ef41Sopenharmony_ci  const et = new EventTarget();
2381cb0ef41Sopenharmony_ci  const ac = new AbortController();
2391cb0ef41Sopenharmony_ci  const { signal } = ac;
2401cb0ef41Sopenharmony_ci  signal.addEventListener('abort', (e) => e.stopImmediatePropagation(), { once: true });
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  process.nextTick(() => ac.abort());
2431cb0ef41Sopenharmony_ci  return rejects(once(et, 'foo', { signal }), {
2441cb0ef41Sopenharmony_ci    name: 'AbortError',
2451cb0ef41Sopenharmony_ci  });
2461cb0ef41Sopenharmony_ci}
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ciasync function eventTargetAbortSignalAfter() {
2491cb0ef41Sopenharmony_ci  const et = new EventTarget();
2501cb0ef41Sopenharmony_ci  const ac = new AbortController();
2511cb0ef41Sopenharmony_ci  const r = rejects(once(et, 'foo', { signal: ac.signal }), {
2521cb0ef41Sopenharmony_ci    name: 'AbortError',
2531cb0ef41Sopenharmony_ci  });
2541cb0ef41Sopenharmony_ci  process.nextTick(() => ac.abort());
2551cb0ef41Sopenharmony_ci  return r;
2561cb0ef41Sopenharmony_ci}
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ciasync function eventTargetAbortSignalAfterEvent() {
2591cb0ef41Sopenharmony_ci  const et = new EventTarget();
2601cb0ef41Sopenharmony_ci  const ac = new AbortController();
2611cb0ef41Sopenharmony_ci  process.nextTick(() => {
2621cb0ef41Sopenharmony_ci    et.dispatchEvent(new Event('foo'));
2631cb0ef41Sopenharmony_ci    ac.abort();
2641cb0ef41Sopenharmony_ci  });
2651cb0ef41Sopenharmony_ci  await once(et, 'foo', { signal: ac.signal });
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ciPromise.all([
2691cb0ef41Sopenharmony_ci  onceAnEvent(),
2701cb0ef41Sopenharmony_ci  onceAnEventWithNullOptions(),
2711cb0ef41Sopenharmony_ci  onceAnEventWithTwoArgs(),
2721cb0ef41Sopenharmony_ci  catchesErrors(),
2731cb0ef41Sopenharmony_ci  catchesErrorsWithAbortSignal(),
2741cb0ef41Sopenharmony_ci  stopListeningAfterCatchingError(),
2751cb0ef41Sopenharmony_ci  onceError(),
2761cb0ef41Sopenharmony_ci  onceWithEventTarget(),
2771cb0ef41Sopenharmony_ci  onceWithEventTargetError(),
2781cb0ef41Sopenharmony_ci  onceWithInvalidEventEmmiter(),
2791cb0ef41Sopenharmony_ci  prioritizesEventEmitter(),
2801cb0ef41Sopenharmony_ci  abortSignalBefore(),
2811cb0ef41Sopenharmony_ci  abortSignalAfter(),
2821cb0ef41Sopenharmony_ci  abortSignalAfterEvent(),
2831cb0ef41Sopenharmony_ci  abortSignalRemoveListener(),
2841cb0ef41Sopenharmony_ci  eventTargetAbortSignalBefore(),
2851cb0ef41Sopenharmony_ci  eventTargetAbortSignalBeforeEvenWhenSignalPropagationStopped(),
2861cb0ef41Sopenharmony_ci  eventTargetAbortSignalAfter(),
2871cb0ef41Sopenharmony_ci  eventTargetAbortSignalAfterEvent(),
2881cb0ef41Sopenharmony_ci]).then(common.mustCall());
289