mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
a596af0819
PR-URL: https://github.com/nodejs/node/pull/52592 Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
127 lines
3.0 KiB
JavaScript
127 lines
3.0 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
ArrayPrototypeIndexOf,
|
|
ArrayPrototypePush,
|
|
ArrayPrototypeSlice,
|
|
ArrayPrototypeSplice,
|
|
FunctionPrototypeBind,
|
|
} = primordials;
|
|
|
|
const { setPromiseHooks } = internalBinding('async_wrap');
|
|
const { triggerUncaughtException } = internalBinding('errors');
|
|
|
|
const { kEmptyObject } = require('internal/util');
|
|
const { validatePlainFunction } = require('internal/validators');
|
|
|
|
const hooks = {
|
|
init: [],
|
|
before: [],
|
|
after: [],
|
|
settled: [],
|
|
};
|
|
|
|
function initAll(promise, parent) {
|
|
const hookSet = ArrayPrototypeSlice(hooks.init);
|
|
const exceptions = [];
|
|
|
|
for (let i = 0; i < hookSet.length; i++) {
|
|
const init = hookSet[i];
|
|
try {
|
|
init(promise, parent);
|
|
} catch (err) {
|
|
ArrayPrototypePush(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 = ArrayPrototypeSlice(list);
|
|
const exceptions = [];
|
|
|
|
for (let i = 0; i < hookSet.length; i++) {
|
|
const hook = hookSet[i];
|
|
try {
|
|
hook(promise);
|
|
} catch (err) {
|
|
ArrayPrototypePush(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 = ArrayPrototypeIndexOf(list, hook);
|
|
if (index >= 0) {
|
|
ArrayPrototypeSplice(list, index, 1);
|
|
update();
|
|
}
|
|
}
|
|
|
|
function makeUseHook(name) {
|
|
const list = hooks[name];
|
|
return (hook) => {
|
|
validatePlainFunction(hook, `${name}Hook`);
|
|
ArrayPrototypePush(list, hook);
|
|
update();
|
|
return FunctionPrototypeBind(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) ArrayPrototypePush(hooks, onInit(init));
|
|
if (before) ArrayPrototypePush(hooks, onBefore(before));
|
|
if (after) ArrayPrototypePush(hooks, onAfter(after));
|
|
if (settled) ArrayPrototypePush(hooks, onSettled(settled));
|
|
|
|
return () => {
|
|
for (const stop of hooks) {
|
|
stop();
|
|
}
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
createHook,
|
|
onInit,
|
|
onBefore,
|
|
onAfter,
|
|
onSettled,
|
|
};
|