UNPKG

nstdlib-nightly

Version:

Node.js standard library converted to runtime-agnostic ES modules.

116 lines (97 loc) 3.14 kB
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/promise_hooks.js import { setPromiseHooks } from "nstdlib/stub/binding/async_wrap"; import { triggerUncaughtException } from "nstdlib/stub/binding/errors"; import { kEmptyObject } from "nstdlib/lib/internal/util"; import { validatePlainFunction } from "nstdlib/lib/internal/validators"; const hooks = { init: [], before: [], after: [], settled: [], }; function initAll(promise, parent) { const hookSet = Array.prototype.slice.call(hooks.init); const exceptions = []; for (let i = 0; i < hookSet.length; i++) { const init = hookSet[i]; try { init(promise, parent); } catch (err) { Array.prototype.push.call(exceptions, err); } } // Triggering exceptions is deferred to allow other hooks to complete for (let i = 0; i < exceptions.length; i++) { const err = exceptions[i]; triggerUncaughtException(err, false); } } function makeRunHook(list) { return (promise) => { const hookSet = Array.prototype.slice.call(list); const exceptions = []; for (let i = 0; i < hookSet.length; i++) { const hook = hookSet[i]; try { hook(promise); } catch (err) { Array.prototype.push.call(exceptions, err); } } // Triggering exceptions is deferred to allow other hooks to complete for (let i = 0; i < exceptions.length; i++) { const err = exceptions[i]; triggerUncaughtException(err, false); } }; } const beforeAll = makeRunHook(hooks.before); const afterAll = makeRunHook(hooks.after); const settledAll = makeRunHook(hooks.settled); function maybeFastPath(list, runAll) { return list.length > 1 ? runAll : list[0]; } function update() { const init = maybeFastPath(hooks.init, initAll); const before = maybeFastPath(hooks.before, beforeAll); const after = maybeFastPath(hooks.after, afterAll); const settled = maybeFastPath(hooks.settled, settledAll); setPromiseHooks(init, before, after, settled); } function stop(list, hook) { const index = Array.prototype.indexOf.call(list, hook); if (index >= 0) { Array.prototype.splice.call(list, index, 1); update(); } } function makeUseHook(name) { const list = hooks[name]; return (hook) => { validatePlainFunction(hook, `${name}Hook`); Array.prototype.push.call(list, hook); update(); return Function.prototype.bind.call(stop, null, list, hook); }; } const onInit = makeUseHook("init"); const onBefore = makeUseHook("before"); const onAfter = makeUseHook("after"); const onSettled = makeUseHook("settled"); function createHook({ init, before, after, settled } = kEmptyObject) { const hooks = []; if (init) Array.prototype.push.call(hooks, onInit(init)); if (before) Array.prototype.push.call(hooks, onBefore(before)); if (after) Array.prototype.push.call(hooks, onAfter(after)); if (settled) Array.prototype.push.call(hooks, onSettled(settled)); return () => { for (const stop of hooks) { stop(); } }; } export { createHook }; export { onInit }; export { onBefore }; export { onAfter }; export { onSettled };