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