11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeIndexOf,
51cb0ef41Sopenharmony_ci  ArrayPrototypePush,
61cb0ef41Sopenharmony_ci  ArrayPrototypeSplice,
71cb0ef41Sopenharmony_ci  SafeFinalizationRegistry,
81cb0ef41Sopenharmony_ci  ObjectGetPrototypeOf,
91cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
101cb0ef41Sopenharmony_ci  Promise,
111cb0ef41Sopenharmony_ci  PromisePrototypeThen,
121cb0ef41Sopenharmony_ci  PromiseResolve,
131cb0ef41Sopenharmony_ci  PromiseReject,
141cb0ef41Sopenharmony_ci  ReflectApply,
151cb0ef41Sopenharmony_ci  SafeMap,
161cb0ef41Sopenharmony_ci  SymbolHasInstance,
171cb0ef41Sopenharmony_ci} = primordials;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst {
201cb0ef41Sopenharmony_ci  codes: {
211cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
221cb0ef41Sopenharmony_ci  },
231cb0ef41Sopenharmony_ci} = require('internal/errors');
241cb0ef41Sopenharmony_ciconst {
251cb0ef41Sopenharmony_ci  validateFunction,
261cb0ef41Sopenharmony_ci} = require('internal/validators');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciconst { triggerUncaughtException } = internalBinding('errors');
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst { WeakReference } = internalBinding('util');
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci// Can't delete when weakref count reaches 0 as it could increment again.
331cb0ef41Sopenharmony_ci// Only GC can be used as a valid time to clean up the channels map.
341cb0ef41Sopenharmony_ciclass WeakRefMap extends SafeMap {
351cb0ef41Sopenharmony_ci  #finalizers = new SafeFinalizationRegistry((key) => {
361cb0ef41Sopenharmony_ci    this.delete(key);
371cb0ef41Sopenharmony_ci  });
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  set(key, value) {
401cb0ef41Sopenharmony_ci    this.#finalizers.register(value, key);
411cb0ef41Sopenharmony_ci    return super.set(key, new WeakReference(value));
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  get(key) {
451cb0ef41Sopenharmony_ci    return super.get(key)?.get();
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  incRef(key) {
491cb0ef41Sopenharmony_ci    return super.get(key)?.incRef();
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  decRef(key) {
531cb0ef41Sopenharmony_ci    return super.get(key)?.decRef();
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_cifunction markActive(channel) {
581cb0ef41Sopenharmony_ci  // eslint-disable-next-line no-use-before-define
591cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf(channel, ActiveChannel.prototype);
601cb0ef41Sopenharmony_ci  channel._subscribers = [];
611cb0ef41Sopenharmony_ci  channel._stores = new SafeMap();
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_cifunction maybeMarkInactive(channel) {
651cb0ef41Sopenharmony_ci  // When there are no more active subscribers or bound, restore to fast prototype.
661cb0ef41Sopenharmony_ci  if (!channel._subscribers.length && !channel._stores.size) {
671cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-use-before-define
681cb0ef41Sopenharmony_ci    ObjectSetPrototypeOf(channel, Channel.prototype);
691cb0ef41Sopenharmony_ci    channel._subscribers = undefined;
701cb0ef41Sopenharmony_ci    channel._stores = undefined;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cifunction defaultTransform(data) {
751cb0ef41Sopenharmony_ci  return data;
761cb0ef41Sopenharmony_ci}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_cifunction wrapStoreRun(store, data, next, transform = defaultTransform) {
791cb0ef41Sopenharmony_ci  return () => {
801cb0ef41Sopenharmony_ci    let context;
811cb0ef41Sopenharmony_ci    try {
821cb0ef41Sopenharmony_ci      context = transform(data);
831cb0ef41Sopenharmony_ci    } catch (err) {
841cb0ef41Sopenharmony_ci      process.nextTick(() => {
851cb0ef41Sopenharmony_ci        triggerUncaughtException(err, false);
861cb0ef41Sopenharmony_ci      });
871cb0ef41Sopenharmony_ci      return next();
881cb0ef41Sopenharmony_ci    }
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci    return store.run(context, next);
911cb0ef41Sopenharmony_ci  };
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci// TODO(qard): should there be a C++ channel interface?
951cb0ef41Sopenharmony_ciclass ActiveChannel {
961cb0ef41Sopenharmony_ci  subscribe(subscription) {
971cb0ef41Sopenharmony_ci    validateFunction(subscription, 'subscription');
981cb0ef41Sopenharmony_ci    ArrayPrototypePush(this._subscribers, subscription);
991cb0ef41Sopenharmony_ci    channels.incRef(this.name);
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  unsubscribe(subscription) {
1031cb0ef41Sopenharmony_ci    const index = ArrayPrototypeIndexOf(this._subscribers, subscription);
1041cb0ef41Sopenharmony_ci    if (index === -1) return false;
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    ArrayPrototypeSplice(this._subscribers, index, 1);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci    channels.decRef(this.name);
1091cb0ef41Sopenharmony_ci    maybeMarkInactive(this);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci    return true;
1121cb0ef41Sopenharmony_ci  }
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  bindStore(store, transform) {
1151cb0ef41Sopenharmony_ci    const replacing = this._stores.has(store);
1161cb0ef41Sopenharmony_ci    if (!replacing) channels.incRef(this.name);
1171cb0ef41Sopenharmony_ci    this._stores.set(store, transform);
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  unbindStore(store) {
1211cb0ef41Sopenharmony_ci    if (!this._stores.has(store)) {
1221cb0ef41Sopenharmony_ci      return false;
1231cb0ef41Sopenharmony_ci    }
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci    this._stores.delete(store);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci    channels.decRef(this.name);
1281cb0ef41Sopenharmony_ci    maybeMarkInactive(this);
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci    return true;
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  get hasSubscribers() {
1341cb0ef41Sopenharmony_ci    return true;
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  publish(data) {
1381cb0ef41Sopenharmony_ci    for (let i = 0; i < this._subscribers.length; i++) {
1391cb0ef41Sopenharmony_ci      try {
1401cb0ef41Sopenharmony_ci        const onMessage = this._subscribers[i];
1411cb0ef41Sopenharmony_ci        onMessage(data, this.name);
1421cb0ef41Sopenharmony_ci      } catch (err) {
1431cb0ef41Sopenharmony_ci        process.nextTick(() => {
1441cb0ef41Sopenharmony_ci          triggerUncaughtException(err, false);
1451cb0ef41Sopenharmony_ci        });
1461cb0ef41Sopenharmony_ci      }
1471cb0ef41Sopenharmony_ci    }
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  runStores(data, fn, thisArg, ...args) {
1511cb0ef41Sopenharmony_ci    let run = () => {
1521cb0ef41Sopenharmony_ci      this.publish(data);
1531cb0ef41Sopenharmony_ci      return ReflectApply(fn, thisArg, args);
1541cb0ef41Sopenharmony_ci    };
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci    for (const entry of this._stores.entries()) {
1571cb0ef41Sopenharmony_ci      const store = entry[0];
1581cb0ef41Sopenharmony_ci      const transform = entry[1];
1591cb0ef41Sopenharmony_ci      run = wrapStoreRun(store, data, run, transform);
1601cb0ef41Sopenharmony_ci    }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci    return run();
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci}
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciclass Channel {
1671cb0ef41Sopenharmony_ci  constructor(name) {
1681cb0ef41Sopenharmony_ci    this._subscribers = undefined;
1691cb0ef41Sopenharmony_ci    this._stores = undefined;
1701cb0ef41Sopenharmony_ci    this.name = name;
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci    channels.set(name, this);
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  static [SymbolHasInstance](instance) {
1761cb0ef41Sopenharmony_ci    const prototype = ObjectGetPrototypeOf(instance);
1771cb0ef41Sopenharmony_ci    return prototype === Channel.prototype ||
1781cb0ef41Sopenharmony_ci           prototype === ActiveChannel.prototype;
1791cb0ef41Sopenharmony_ci  }
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  subscribe(subscription) {
1821cb0ef41Sopenharmony_ci    markActive(this);
1831cb0ef41Sopenharmony_ci    this.subscribe(subscription);
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  unsubscribe() {
1871cb0ef41Sopenharmony_ci    return false;
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  bindStore(store, transform) {
1911cb0ef41Sopenharmony_ci    markActive(this);
1921cb0ef41Sopenharmony_ci    this.bindStore(store, transform);
1931cb0ef41Sopenharmony_ci  }
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  unbindStore() {
1961cb0ef41Sopenharmony_ci    return false;
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  get hasSubscribers() {
2001cb0ef41Sopenharmony_ci    return false;
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  publish() {}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  runStores(data, fn, thisArg, ...args) {
2061cb0ef41Sopenharmony_ci    return ReflectApply(fn, thisArg, args);
2071cb0ef41Sopenharmony_ci  }
2081cb0ef41Sopenharmony_ci}
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ciconst channels = new WeakRefMap();
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_cifunction channel(name) {
2131cb0ef41Sopenharmony_ci  const channel = channels.get(name);
2141cb0ef41Sopenharmony_ci  if (channel) return channel;
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  if (typeof name !== 'string' && typeof name !== 'symbol') {
2171cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('channel', ['string', 'symbol'], name);
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  return new Channel(name);
2211cb0ef41Sopenharmony_ci}
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_cifunction subscribe(name, subscription) {
2241cb0ef41Sopenharmony_ci  return channel(name).subscribe(subscription);
2251cb0ef41Sopenharmony_ci}
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_cifunction unsubscribe(name, subscription) {
2281cb0ef41Sopenharmony_ci  return channel(name).unsubscribe(subscription);
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_cifunction hasSubscribers(name) {
2321cb0ef41Sopenharmony_ci  const channel = channels.get(name);
2331cb0ef41Sopenharmony_ci  if (!channel) return false;
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  return channel.hasSubscribers;
2361cb0ef41Sopenharmony_ci}
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ciconst traceEvents = [
2391cb0ef41Sopenharmony_ci  'start',
2401cb0ef41Sopenharmony_ci  'end',
2411cb0ef41Sopenharmony_ci  'asyncStart',
2421cb0ef41Sopenharmony_ci  'asyncEnd',
2431cb0ef41Sopenharmony_ci  'error',
2441cb0ef41Sopenharmony_ci];
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_cifunction assertChannel(value, name) {
2471cb0ef41Sopenharmony_ci  if (!(value instanceof Channel)) {
2481cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(name, ['Channel'], value);
2491cb0ef41Sopenharmony_ci  }
2501cb0ef41Sopenharmony_ci}
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ciclass TracingChannel {
2531cb0ef41Sopenharmony_ci  constructor(nameOrChannels) {
2541cb0ef41Sopenharmony_ci    if (typeof nameOrChannels === 'string') {
2551cb0ef41Sopenharmony_ci      this.start = channel(`tracing:${nameOrChannels}:start`);
2561cb0ef41Sopenharmony_ci      this.end = channel(`tracing:${nameOrChannels}:end`);
2571cb0ef41Sopenharmony_ci      this.asyncStart = channel(`tracing:${nameOrChannels}:asyncStart`);
2581cb0ef41Sopenharmony_ci      this.asyncEnd = channel(`tracing:${nameOrChannels}:asyncEnd`);
2591cb0ef41Sopenharmony_ci      this.error = channel(`tracing:${nameOrChannels}:error`);
2601cb0ef41Sopenharmony_ci    } else if (typeof nameOrChannels === 'object') {
2611cb0ef41Sopenharmony_ci      const { start, end, asyncStart, asyncEnd, error } = nameOrChannels;
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci      assertChannel(start, 'nameOrChannels.start');
2641cb0ef41Sopenharmony_ci      assertChannel(end, 'nameOrChannels.end');
2651cb0ef41Sopenharmony_ci      assertChannel(asyncStart, 'nameOrChannels.asyncStart');
2661cb0ef41Sopenharmony_ci      assertChannel(asyncEnd, 'nameOrChannels.asyncEnd');
2671cb0ef41Sopenharmony_ci      assertChannel(error, 'nameOrChannels.error');
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci      this.start = start;
2701cb0ef41Sopenharmony_ci      this.end = end;
2711cb0ef41Sopenharmony_ci      this.asyncStart = asyncStart;
2721cb0ef41Sopenharmony_ci      this.asyncEnd = asyncEnd;
2731cb0ef41Sopenharmony_ci      this.error = error;
2741cb0ef41Sopenharmony_ci    } else {
2751cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_TYPE('nameOrChannels',
2761cb0ef41Sopenharmony_ci                                     ['string', 'object', 'Channel'],
2771cb0ef41Sopenharmony_ci                                     nameOrChannels);
2781cb0ef41Sopenharmony_ci    }
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  subscribe(handlers) {
2821cb0ef41Sopenharmony_ci    for (const name of traceEvents) {
2831cb0ef41Sopenharmony_ci      if (!handlers[name]) continue;
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci      this[name]?.subscribe(handlers[name]);
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci  }
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  unsubscribe(handlers) {
2901cb0ef41Sopenharmony_ci    let done = true;
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci    for (const name of traceEvents) {
2931cb0ef41Sopenharmony_ci      if (!handlers[name]) continue;
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci      if (!this[name]?.unsubscribe(handlers[name])) {
2961cb0ef41Sopenharmony_ci        done = false;
2971cb0ef41Sopenharmony_ci      }
2981cb0ef41Sopenharmony_ci    }
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci    return done;
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  traceSync(fn, context = {}, thisArg, ...args) {
3041cb0ef41Sopenharmony_ci    const { start, end, error } = this;
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci    return start.runStores(context, () => {
3071cb0ef41Sopenharmony_ci      try {
3081cb0ef41Sopenharmony_ci        const result = ReflectApply(fn, thisArg, args);
3091cb0ef41Sopenharmony_ci        context.result = result;
3101cb0ef41Sopenharmony_ci        return result;
3111cb0ef41Sopenharmony_ci      } catch (err) {
3121cb0ef41Sopenharmony_ci        context.error = err;
3131cb0ef41Sopenharmony_ci        error.publish(context);
3141cb0ef41Sopenharmony_ci        throw err;
3151cb0ef41Sopenharmony_ci      } finally {
3161cb0ef41Sopenharmony_ci        end.publish(context);
3171cb0ef41Sopenharmony_ci      }
3181cb0ef41Sopenharmony_ci    });
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  tracePromise(fn, context = {}, thisArg, ...args) {
3221cb0ef41Sopenharmony_ci    const { start, end, asyncStart, asyncEnd, error } = this;
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci    function reject(err) {
3251cb0ef41Sopenharmony_ci      context.error = err;
3261cb0ef41Sopenharmony_ci      error.publish(context);
3271cb0ef41Sopenharmony_ci      asyncStart.publish(context);
3281cb0ef41Sopenharmony_ci      // TODO: Is there a way to have asyncEnd _after_ the continuation?
3291cb0ef41Sopenharmony_ci      asyncEnd.publish(context);
3301cb0ef41Sopenharmony_ci      return PromiseReject(err);
3311cb0ef41Sopenharmony_ci    }
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci    function resolve(result) {
3341cb0ef41Sopenharmony_ci      context.result = result;
3351cb0ef41Sopenharmony_ci      asyncStart.publish(context);
3361cb0ef41Sopenharmony_ci      // TODO: Is there a way to have asyncEnd _after_ the continuation?
3371cb0ef41Sopenharmony_ci      asyncEnd.publish(context);
3381cb0ef41Sopenharmony_ci      return result;
3391cb0ef41Sopenharmony_ci    }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci    return start.runStores(context, () => {
3421cb0ef41Sopenharmony_ci      try {
3431cb0ef41Sopenharmony_ci        let promise = ReflectApply(fn, thisArg, args);
3441cb0ef41Sopenharmony_ci        // Convert thenables to native promises
3451cb0ef41Sopenharmony_ci        if (!(promise instanceof Promise)) {
3461cb0ef41Sopenharmony_ci          promise = PromiseResolve(promise);
3471cb0ef41Sopenharmony_ci        }
3481cb0ef41Sopenharmony_ci        return PromisePrototypeThen(promise, resolve, reject);
3491cb0ef41Sopenharmony_ci      } catch (err) {
3501cb0ef41Sopenharmony_ci        context.error = err;
3511cb0ef41Sopenharmony_ci        error.publish(context);
3521cb0ef41Sopenharmony_ci        throw err;
3531cb0ef41Sopenharmony_ci      } finally {
3541cb0ef41Sopenharmony_ci        end.publish(context);
3551cb0ef41Sopenharmony_ci      }
3561cb0ef41Sopenharmony_ci    });
3571cb0ef41Sopenharmony_ci  }
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  traceCallback(fn, position = -1, context = {}, thisArg, ...args) {
3601cb0ef41Sopenharmony_ci    const { start, end, asyncStart, asyncEnd, error } = this;
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci    function wrappedCallback(err, res) {
3631cb0ef41Sopenharmony_ci      if (err) {
3641cb0ef41Sopenharmony_ci        context.error = err;
3651cb0ef41Sopenharmony_ci        error.publish(context);
3661cb0ef41Sopenharmony_ci      } else {
3671cb0ef41Sopenharmony_ci        context.result = res;
3681cb0ef41Sopenharmony_ci      }
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci      // Using runStores here enables manual context failure recovery
3711cb0ef41Sopenharmony_ci      asyncStart.runStores(context, () => {
3721cb0ef41Sopenharmony_ci        try {
3731cb0ef41Sopenharmony_ci          if (callback) {
3741cb0ef41Sopenharmony_ci            return ReflectApply(callback, this, arguments);
3751cb0ef41Sopenharmony_ci          }
3761cb0ef41Sopenharmony_ci        } finally {
3771cb0ef41Sopenharmony_ci          asyncEnd.publish(context);
3781cb0ef41Sopenharmony_ci        }
3791cb0ef41Sopenharmony_ci      });
3801cb0ef41Sopenharmony_ci    }
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci    const callback = args.at(position);
3831cb0ef41Sopenharmony_ci    if (typeof callback !== 'function') {
3841cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_TYPE('callback', ['function'], callback);
3851cb0ef41Sopenharmony_ci    }
3861cb0ef41Sopenharmony_ci    ArrayPrototypeSplice(args, position, 1, wrappedCallback);
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci    return start.runStores(context, () => {
3891cb0ef41Sopenharmony_ci      try {
3901cb0ef41Sopenharmony_ci        return ReflectApply(fn, thisArg, args);
3911cb0ef41Sopenharmony_ci      } catch (err) {
3921cb0ef41Sopenharmony_ci        context.error = err;
3931cb0ef41Sopenharmony_ci        error.publish(context);
3941cb0ef41Sopenharmony_ci        throw err;
3951cb0ef41Sopenharmony_ci      } finally {
3961cb0ef41Sopenharmony_ci        end.publish(context);
3971cb0ef41Sopenharmony_ci      }
3981cb0ef41Sopenharmony_ci    });
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci}
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_cifunction tracingChannel(nameOrChannels) {
4031cb0ef41Sopenharmony_ci  return new TracingChannel(nameOrChannels);
4041cb0ef41Sopenharmony_ci}
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_cimodule.exports = {
4071cb0ef41Sopenharmony_ci  channel,
4081cb0ef41Sopenharmony_ci  hasSubscribers,
4091cb0ef41Sopenharmony_ci  subscribe,
4101cb0ef41Sopenharmony_ci  tracingChannel,
4111cb0ef41Sopenharmony_ci  unsubscribe,
4121cb0ef41Sopenharmony_ci  Channel,
4131cb0ef41Sopenharmony_ci};
414