mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-26 23:39:13 +00:00
a473e73b3e
Adds a custom oxlint rule renovate/v8-ignore-no-count that flags the count form '/* v8 ignore next <N> */'. The count is not honored by vitest's ast-v8-to-istanbul hint parser, which captures only the keyword (if/else/next/file); 'next' always exempts exactly the next AST node. Trailing counts therefore suggest a line range that is never applied and mislead readers. The rule is autofixable (drops the count, preserving actual behavior) and has been applied to all existing occurrences.
85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
// Do not static import `bunyan` here!
|
|
// Otherwise otel can't instrument it.
|
|
import { createHash } from 'node:crypto';
|
|
import { stringify } from 'safe-stable-stringify';
|
|
|
|
type OmitFn = (...args: any[]) => any;
|
|
|
|
// TODO: use `callsite` package instead?
|
|
|
|
/**
|
|
* Get the single frame of this function's callers stack.
|
|
*
|
|
* @param omitFn Starting from this function, stack frames will be ignored.
|
|
* @returns The string containing file name, line number and column name.
|
|
*
|
|
* @example getCallSite() // => 'Object.<anonymous> (/path/to/file.js:10:15)'
|
|
*/
|
|
function getCallSite(omitFn: OmitFn): string | null {
|
|
const stackTraceLimitOrig = Error.stackTraceLimit;
|
|
// We don't use `Error.captureStackTrace` directly, we simply restore it later.
|
|
// oxlint-disable-next-line typescript/unbound-method
|
|
const prepareStackTraceOrig = Error.prepareStackTrace;
|
|
|
|
let result: string | null = null;
|
|
try {
|
|
const res: { stack: string[] } = { stack: [] };
|
|
|
|
Error.stackTraceLimit = 1;
|
|
Error.prepareStackTrace = (_err, stack) => stack;
|
|
Error.captureStackTrace(res, omitFn);
|
|
|
|
const [callsite] = res.stack;
|
|
// v8 ignore else -- TODO: add test #40625
|
|
if (callsite) {
|
|
result = callsite.toString();
|
|
}
|
|
/* v8 ignore next -- should not happen */
|
|
} catch {
|
|
// no-op
|
|
} finally {
|
|
Error.stackTraceLimit = stackTraceLimitOrig;
|
|
Error.prepareStackTrace = prepareStackTraceOrig;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
const keys = new Set<string>();
|
|
|
|
export function once(
|
|
callback: () => void,
|
|
omitFn: OmitFn = once,
|
|
p1: string | Record<string, any>,
|
|
p2?: string,
|
|
): void {
|
|
const callsite = getCallSite(omitFn);
|
|
|
|
/* v8 ignore next -- should not happen */
|
|
if (!callsite) {
|
|
return;
|
|
}
|
|
|
|
const paramsKey = hashParams(p1, p2);
|
|
const key = `${callsite}|${paramsKey}`;
|
|
|
|
if (!keys.has(key)) {
|
|
keys.add(key);
|
|
callback();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Before processing each repository,
|
|
* all keys are supposed to be reset.
|
|
*/
|
|
export function reset(): void {
|
|
keys.clear();
|
|
}
|
|
|
|
function hashParams(p1: string | Record<string, any>, p2?: string): string {
|
|
const data =
|
|
p2 === undefined ? stringify(p1) : `${stringify(p1)}|${stringify(p2)}`;
|
|
return createHash('sha256').update(data).digest('hex');
|
|
}
|