@contrast/patcher
Advanced tools
Comparing version 1.7.1 to 1.7.2
/* | ||
* Copyright: 2023 Contrast Security, Inc | ||
* Copyright: 2024 Contrast Security, Inc | ||
* Contact: support@contrastsecurity.com | ||
@@ -18,7 +18,7 @@ * License: Commercial | ||
interface Core { | ||
export interface Core { | ||
logger: Logger; | ||
} | ||
interface HookData<T, P extends readonly any[] = any[], R = any> { | ||
export interface HookData<T, P extends readonly any[] = any[], R = any> { | ||
hooked(...args: P): R; | ||
@@ -32,3 +32,3 @@ orig(...args: P): R; | ||
interface ResultHookData<T, P extends readonly any[] = any[], R = any> | ||
export interface ResultHookData<T, P extends readonly any[] = any[], R = any> | ||
extends HookData<T, P, R> { | ||
@@ -38,15 +38,41 @@ result: R; | ||
interface PatchOptions<T, P extends readonly any[] = any[], R = any> { | ||
export interface PreHook<T, P extends readonly any[] = any[], R = any> { | ||
(data: HookData<T, P, R>): void; | ||
} | ||
export interface AroundHook<T, P extends readonly any[] = any[], R = any> { | ||
(next: () => R, data: HookData<T, P, R>): void; | ||
} | ||
export interface PostHook<T, P extends readonly any[] = any[], R = any> { | ||
(data: ResultHookData<T, P, R>): void | ||
} | ||
export type Hook<T, P extends readonly any[] = any[], R = any> = | ||
PreHook<T, P, R> | AroundHook<T, P, R> | PostHook<T, P, R>; | ||
export interface PatchOptions<T, P extends readonly any[] = any[], R = any> { | ||
name: string; | ||
patchType: string; | ||
pre?(data: HookData<T, P, R>): void; | ||
around?(next: () => R, data: HookData<T, P, R>): void; | ||
post?(data: ResultHookData<T, P, R>): void; | ||
pre?: PreHook<T, P, R>; | ||
around?: AroundHook<T, P, R>; | ||
post?: PostHook<T, P, R>; | ||
} | ||
export type HookedFunctionsMap = WeakMap<(...args: any[]) => any, { | ||
fn: (...args: any[]) => any; | ||
}>; | ||
export type HooksMap = WeakMap<(...args: any[]) => any, { | ||
pre: Map<string, PreHook<any>>, | ||
around: Map<string, AroundHook<any>>, | ||
post: Map<string, PostHook<any>>, | ||
funcKeys: Set<string>, | ||
}>; | ||
export interface Patcher { | ||
patch<T extends (...args: any[]) => any>( | ||
fn: T, | ||
options: PatchOptions<T, Parameters<T>, ReturnType<T>>, | ||
): T | null; | ||
patch<F extends (...args: any[]) => any>( | ||
fn: F, | ||
options: PatchOptions<F, Parameters<F>, ReturnType<F>>, | ||
): F | null; | ||
@@ -70,3 +96,4 @@ patch<T, K extends keyof T>( | ||
hookedFunctionToString<T extends (...args: any[]) => any>(fn: T): string; | ||
hookedFunctions: WeakMap<(...args: any[]) => any, (...args: any[]) => any>; | ||
hookedFunctions: HookedFunctionsMap; | ||
hooks: HooksMap; | ||
} | ||
@@ -73,0 +100,0 @@ |
/* | ||
* Copyright: 2023 Contrast Security, Inc | ||
* Copyright: 2024 Contrast Security, Inc | ||
* Contact: support@contrastsecurity.com | ||
@@ -18,2 +18,4 @@ * License: Commercial | ||
const { threadId } = require('worker_threads'); | ||
/** | ||
@@ -51,3 +53,3 @@ * Disable the prefer-rest-params rule, which disallows use of `arguments`. | ||
module.exports = function init(core) { | ||
const logger = core.logger.child({ name: 'contrast:patcher' }); | ||
const logger = core.logger.child({ name: 'contrast:patcher', tid: threadId }); | ||
const promisifyCustom = Symbol.for('nodejs.util.promisify.custom'); | ||
@@ -168,2 +170,3 @@ | ||
orig: fn, | ||
funcKey: options.funcKey, | ||
obj: new.target || this, | ||
@@ -322,3 +325,4 @@ name: options.name, | ||
if (!patchType || !name) { | ||
logger.error({ err: new Error('patchType and name are required options') }); | ||
const err = new Error('patchType and name are required options'); | ||
logger.error({ err, options }); | ||
return null; | ||
@@ -340,11 +344,10 @@ } | ||
if (!isFunction(obj) && !isFunction(obj[prop])) { | ||
const loggerArgs = prop | ||
? ['attempted to hook %s property from %o that is not a method or does not exist', prop, obj] | ||
: ['attempted to hook %o that is not a function', obj]; | ||
logger.error({ funcKey }, ...loggerArgs); | ||
logger.error( | ||
{ funcKey, obj }, | ||
prop ? 'attempted to hook property %s that is not a method or does not exist' : 'attempted to hook an object that is not a function', | ||
prop, | ||
); | ||
return null; | ||
} | ||
logger.trace('adding hooks: %s', funcKey); | ||
const fn = hook(obj, prop, options); | ||
@@ -359,3 +362,3 @@ const fnHooks = hooks.get(fn) || { | ||
if (fnHooks.funcKeys.has(funcKey)) { | ||
logger.debug('%s already patched. ignoring', funcKey); | ||
logger.debug({ funcKey }, '%s already patched. ignoring', funcKey); | ||
} else { | ||
@@ -362,0 +365,0 @@ if (pre) fnHooks.pre.set(funcKey, pre); |
{ | ||
"name": "@contrast/patcher", | ||
"version": "1.7.1", | ||
"version": "1.7.2", | ||
"description": "Advanced monkey patching--registers hooks to run in and around functions", | ||
@@ -14,3 +14,3 @@ "license": "SEE LICENSE IN LICENSE", | ||
"npm": ">=6.13.7 <7 || >= 8.3.1", | ||
"node": ">= 14.15.0" | ||
"node": ">= 14.18.0" | ||
}, | ||
@@ -17,0 +17,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19858
473