first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
'use strict';
function NextTickWrap() {}
module.exports = function patch() {
const hooks = this._hooks;
const state = this._state;
const oldNextTick = process.nextTick;
process.nextTick = function () {
if (!state.enabled) return oldNextTick.apply(process, arguments);
const args = new Array(arguments.length);
for (let i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
const callback = args[0];
if (typeof callback !== 'function') {
throw new TypeError('callback is not a function');
}
const handle = new NextTickWrap();
const uid = --state.counter;
// call the init hook
hooks.init.call(handle, uid, 0, null, null);
// overwrite callback
args[0] = function () {
// call the pre hook
hooks.pre.call(handle, uid);
let didThrow = true;
try {
callback.apply(this, arguments);
didThrow = false;
} finally {
// If `callback` threw and there is an uncaughtException handler
// then call the `post` and `destroy` hook after the uncaughtException
// user handlers have been invoked.
if(didThrow && process.listenerCount('uncaughtException') > 0) {
process.once('uncaughtException', function () {
hooks.post.call(handle, uid, true);
hooks.destroy.call(null, uid);
});
}
}
// callback done successfully
hooks.post.call(handle, uid, false);
hooks.destroy.call(null, uid);
};
return oldNextTick.apply(process, args);
};
}
+64
View File
@@ -0,0 +1,64 @@
'use strict';
function PromiseWrap() {}
module.exports = function patchPromise() {
const hooks = this._hooks;
const state = this._state;
const Promise = global.Promise;
/* As per ECMAScript 2015, .catch must be implemented by calling .then, as
* such we need needn't patch .catch as well. see:
* http://www.ecma-international.org/ecma-262/6.0/#sec-promise.prototype.catch
*/
const oldThen = Promise.prototype.then;
Promise.prototype.then = wrappedThen;
function makeWrappedHandler(fn, handle, uid, isOnFulfilled) {
if ('function' !== typeof fn) {
return isOnFulfilled
? makeUnhandledResolutionHandler(uid)
: makeUnhandledRejectionHandler(uid);
}
return function wrappedHandler() {
hooks.pre.call(handle, uid);
try {
return fn.apply(this, arguments);
} finally {
hooks.post.call(handle, uid, false);
hooks.destroy.call(null, uid);
}
};
}
function makeUnhandledResolutionHandler(uid) {
return function unhandledResolutionHandler(val) {
hooks.destroy.call(null, uid);
return val;
};
}
function makeUnhandledRejectionHandler(uid) {
return function unhandledRejectedHandler(val) {
hooks.destroy.call(null, uid);
throw val;
};
}
function wrappedThen(onFulfilled, onRejected) {
if (!state.enabled) return oldThen.call(this, onFulfilled, onRejected);
const handle = new PromiseWrap();
const uid = --state.counter;
hooks.init.call(handle, uid, 0, null, null);
return oldThen.call(
this,
makeWrappedHandler(onFulfilled, handle, uid, true),
makeWrappedHandler(onRejected, handle, uid, false)
);
}
};
+117
View File
@@ -0,0 +1,117 @@
'use strict';
const timers = require('timers');
function TimeoutWrap() {}
function IntervalWrap() {}
function ImmediateWrap() {}
const timeoutMap = new Map();
const intervalMap = new Map();
const ImmediateMap = new Map();
let activeCallback = null;
let clearedInCallback = false;
module.exports = function patch() {
patchTimer(this._hooks, this._state, 'setTimeout', 'clearTimeout', TimeoutWrap, timeoutMap, true);
patchTimer(this._hooks, this._state, 'setInterval', 'clearInterval', IntervalWrap, intervalMap, false);
patchTimer(this._hooks, this._state, 'setImmediate', 'clearImmediate', ImmediateWrap, ImmediateMap, true);
global.setTimeout = timers.setTimeout;
global.setInterval = timers.setInterval;
global.setImmediate = timers.setImmediate;
global.clearTimeout = timers.clearTimeout;
global.clearInterval = timers.clearInterval;
global.clearImmediate = timers.clearImmediate;
};
function patchTimer(hooks, state, setFn, clearFn, Handle, timerMap, singleCall) {
const oldSetFn = timers[setFn];
const oldClearFn = timers[clearFn];
// overwrite set[Timeout]
timers[setFn] = function () {
if (!state.enabled) return oldSetFn.apply(timers, arguments);
const args = new Array(arguments.length);
for (let i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
const callback = args[0];
if (typeof callback !== 'function') {
throw new TypeError('"callback" argument must be a function');
}
const handle = new Handle();
const uid = --state.counter;
let timerId = undefined;
// call the init hook
hooks.init.call(handle, uid, 0, null, null);
// overwrite callback
args[0] = function () {
// call the pre hook
activeCallback = timerId;
hooks.pre.call(handle, uid);
let didThrow = true;
try {
callback.apply(this, arguments);
didThrow = false;
} finally {
// If `callback` threw and there is an uncaughtException handler
// then call the `post` and `destroy` hook after the uncaughtException
// user handlers have been invoked.
if (didThrow && process.listenerCount('uncaughtException') > 0) {
process.once('uncaughtException', function () {
// call the post hook
hooks.post.call(handle, uid, true);
// setInterval won't continue
timerMap.delete(timerId);
hooks.destroy.call(null, uid);
});
}
}
// callback done successfully
hooks.post.call(handle, uid, false);
activeCallback = null;
// call the destroy hook if the callback will only be called once
if (singleCall || clearedInCallback) {
clearedInCallback = false;
timerMap.delete(timerId);
hooks.destroy.call(null, uid);
}
};
timerId = oldSetFn.apply(timers, args);
// Bind the timerId and uid for later use, in case the clear* function is
// called.
timerMap.set(timerId, uid);
return timerId;
};
// overwrite clear[Timeout]
timers[clearFn] = function (timerId) {
// If clear* was called within the timer callback, then delay the destroy
// event to after the post event has been called.
if (activeCallback === timerId && timerId !== null) {
clearedInCallback = true;
}
// clear should call the destroy hook. Note if timerId doesn't exists
// it is because asyncWrap wasn't enabled at the time.
else if (timerMap.has(timerId)) {
const uid = timerMap.get(timerId);
timerMap.delete(timerId);
hooks.destroy.call(null, uid);
}
oldClearFn.apply(timers, arguments);
};
}