11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeIndexOf,
51cb0ef41Sopenharmony_ci  ArrayPrototypeSlice,
61cb0ef41Sopenharmony_ci  ArrayPrototypeSplice,
71cb0ef41Sopenharmony_ci  ArrayPrototypePush,
81cb0ef41Sopenharmony_ci  FunctionPrototypeBind,
91cb0ef41Sopenharmony_ci} = primordials;
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst { setPromiseHooks } = internalBinding('async_wrap');
121cb0ef41Sopenharmony_ciconst { triggerUncaughtException } = internalBinding('errors');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst { kEmptyObject } = require('internal/util');
151cb0ef41Sopenharmony_ciconst { validatePlainFunction } = require('internal/validators');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciconst hooks = {
181cb0ef41Sopenharmony_ci  init: [],
191cb0ef41Sopenharmony_ci  before: [],
201cb0ef41Sopenharmony_ci  after: [],
211cb0ef41Sopenharmony_ci  settled: [],
221cb0ef41Sopenharmony_ci};
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cifunction initAll(promise, parent) {
251cb0ef41Sopenharmony_ci  const hookSet = ArrayPrototypeSlice(hooks.init);
261cb0ef41Sopenharmony_ci  const exceptions = [];
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  for (let i = 0; i < hookSet.length; i++) {
291cb0ef41Sopenharmony_ci    const init = hookSet[i];
301cb0ef41Sopenharmony_ci    try {
311cb0ef41Sopenharmony_ci      init(promise, parent);
321cb0ef41Sopenharmony_ci    } catch (err) {
331cb0ef41Sopenharmony_ci      ArrayPrototypePush(exceptions, err);
341cb0ef41Sopenharmony_ci    }
351cb0ef41Sopenharmony_ci  }
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  // Triggering exceptions is deferred to allow other hooks to complete
381cb0ef41Sopenharmony_ci  for (let i = 0; i < exceptions.length; i++) {
391cb0ef41Sopenharmony_ci    const err = exceptions[i];
401cb0ef41Sopenharmony_ci    triggerUncaughtException(err, false);
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cifunction makeRunHook(list) {
451cb0ef41Sopenharmony_ci  return (promise) => {
461cb0ef41Sopenharmony_ci    const hookSet = ArrayPrototypeSlice(list);
471cb0ef41Sopenharmony_ci    const exceptions = [];
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci    for (let i = 0; i < hookSet.length; i++) {
501cb0ef41Sopenharmony_ci      const hook = hookSet[i];
511cb0ef41Sopenharmony_ci      try {
521cb0ef41Sopenharmony_ci        hook(promise);
531cb0ef41Sopenharmony_ci      } catch (err) {
541cb0ef41Sopenharmony_ci        ArrayPrototypePush(exceptions, err);
551cb0ef41Sopenharmony_ci      }
561cb0ef41Sopenharmony_ci    }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci    // Triggering exceptions is deferred to allow other hooks to complete
591cb0ef41Sopenharmony_ci    for (let i = 0; i < exceptions.length; i++) {
601cb0ef41Sopenharmony_ci      const err = exceptions[i];
611cb0ef41Sopenharmony_ci      triggerUncaughtException(err, false);
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci  };
641cb0ef41Sopenharmony_ci}
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ciconst beforeAll = makeRunHook(hooks.before);
671cb0ef41Sopenharmony_ciconst afterAll = makeRunHook(hooks.after);
681cb0ef41Sopenharmony_ciconst settledAll = makeRunHook(hooks.settled);
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_cifunction maybeFastPath(list, runAll) {
711cb0ef41Sopenharmony_ci  return list.length > 1 ? runAll : list[0];
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cifunction update() {
751cb0ef41Sopenharmony_ci  const init = maybeFastPath(hooks.init, initAll);
761cb0ef41Sopenharmony_ci  const before = maybeFastPath(hooks.before, beforeAll);
771cb0ef41Sopenharmony_ci  const after = maybeFastPath(hooks.after, afterAll);
781cb0ef41Sopenharmony_ci  const settled = maybeFastPath(hooks.settled, settledAll);
791cb0ef41Sopenharmony_ci  setPromiseHooks(init, before, after, settled);
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_cifunction stop(list, hook) {
831cb0ef41Sopenharmony_ci  const index = ArrayPrototypeIndexOf(list, hook);
841cb0ef41Sopenharmony_ci  if (index >= 0) {
851cb0ef41Sopenharmony_ci    ArrayPrototypeSplice(list, index, 1);
861cb0ef41Sopenharmony_ci    update();
871cb0ef41Sopenharmony_ci  }
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_cifunction makeUseHook(name) {
911cb0ef41Sopenharmony_ci  const list = hooks[name];
921cb0ef41Sopenharmony_ci  return (hook) => {
931cb0ef41Sopenharmony_ci    validatePlainFunction(hook, `${name}Hook`);
941cb0ef41Sopenharmony_ci    ArrayPrototypePush(list, hook);
951cb0ef41Sopenharmony_ci    update();
961cb0ef41Sopenharmony_ci    return FunctionPrototypeBind(stop, null, list, hook);
971cb0ef41Sopenharmony_ci  };
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ciconst onInit = makeUseHook('init');
1011cb0ef41Sopenharmony_ciconst onBefore = makeUseHook('before');
1021cb0ef41Sopenharmony_ciconst onAfter = makeUseHook('after');
1031cb0ef41Sopenharmony_ciconst onSettled = makeUseHook('settled');
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_cifunction createHook({ init, before, after, settled } = kEmptyObject) {
1061cb0ef41Sopenharmony_ci  const hooks = [];
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  if (init) ArrayPrototypePush(hooks, onInit(init));
1091cb0ef41Sopenharmony_ci  if (before) ArrayPrototypePush(hooks, onBefore(before));
1101cb0ef41Sopenharmony_ci  if (after) ArrayPrototypePush(hooks, onAfter(after));
1111cb0ef41Sopenharmony_ci  if (settled) ArrayPrototypePush(hooks, onSettled(settled));
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  return () => {
1141cb0ef41Sopenharmony_ci    for (const stop of hooks) {
1151cb0ef41Sopenharmony_ci      stop();
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci  };
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_cimodule.exports = {
1211cb0ef41Sopenharmony_ci  createHook,
1221cb0ef41Sopenharmony_ci  onInit,
1231cb0ef41Sopenharmony_ci  onBefore,
1241cb0ef41Sopenharmony_ci  onAfter,
1251cb0ef41Sopenharmony_ci  onSettled,
1261cb0ef41Sopenharmony_ci};
127