fix(lib/patcher): import types properly

This commit is contained in:
PalmDevs 2025-06-03 16:08:37 +07:00
parent a1db2dbb2c
commit e8fb54c19a
No known key found for this signature in database
GPG key ID: 6FAE8F8677ACA8BA
5 changed files with 252 additions and 104 deletions

View file

@ -1,4 +1,16 @@
export interface FunctionProxyState<T extends UnknownFunction = UnknownFunction> {
import type {
AbstractNewable,
AfterHook,
BeforeHook,
Callable,
FiniteDomain,
InsteadHook,
UnknownFunction,
} from './types'
export interface FunctionProxyState<
T extends UnknownFunction = UnknownFunction,
> {
readonly proxy: T
readonly target: T
}
@ -53,7 +65,11 @@ export const patchedFunctionProxyHandler = {
args = applyHooks(state.before, args)
const { instead } = state
let result: ReturnType<T> = Reflect.apply(instead === undefined ? state.target : instead.proxy, receiver, args)
let result: ReturnType<T> = Reflect.apply(
instead === undefined ? state.target : instead.proxy,
receiver,
args,
)
result = applyHooks(state.after, result)
@ -77,30 +93,44 @@ export const patchedFunctionProxyHandler = {
return result
},
defineProperty: (state, key, descriptor) => Reflect.defineProperty(state.target, key, descriptor),
defineProperty: (state, key, descriptor) =>
Reflect.defineProperty(state.target, key, descriptor),
deleteProperty: (state, key) => Reflect.deleteProperty(state.target, key),
get: (state, key, receiver: unknown) => Reflect.get(state.target, key, receiver),
getOwnPropertyDescriptor: (state, key) => Reflect.getOwnPropertyDescriptor(state.target, key),
get: (state, key, receiver: unknown) =>
Reflect.get(state.target, key, receiver),
getOwnPropertyDescriptor: (state, key) =>
Reflect.getOwnPropertyDescriptor(state.target, key),
getPrototypeOf: state => Reflect.getPrototypeOf(state.target),
has: (state, key) => Reflect.has(state.target, key),
isExtensible: state => Reflect.isExtensible(state.target),
ownKeys: state => Reflect.ownKeys(state.target),
preventExtensions: state => Reflect.preventExtensions(state.target),
set: (state, key, value: unknown, receiver: unknown) => Reflect.set(state.target, key, value, receiver),
setPrototypeOf: (state, prototype) => Reflect.setPrototypeOf(state.target, prototype),
set: (state, key, value: unknown, receiver: unknown) =>
Reflect.set(state.target, key, value, receiver),
setPrototypeOf: (state, prototype) =>
Reflect.setPrototypeOf(state.target, prototype),
} as const satisfies Required<ProxyHandler<FunctionProxyState>>
interface PatchedFunctionProxyStateMap extends WeakMap<UnknownFunction, any> {
readonly delete: (key: UnknownFunction) => boolean
readonly get: <K extends UnknownFunction>(key: K) => PatchedFunctionProxyState<PropertyKey, K> | undefined
readonly get: <K extends UnknownFunction>(
key: K,
) => PatchedFunctionProxyState<PropertyKey, K> | undefined
readonly has: (key: UnknownFunction) => boolean
readonly set: <K extends UnknownFunction>(key: K, value: PatchedFunctionProxyState<PropertyKey, K>) => this
readonly set: <K extends UnknownFunction>(
key: K,
value: PatchedFunctionProxyState<PropertyKey, K>,
) => this
}
/** proxy -> state */
export const patchedFunctionProxyStates: PatchedFunctionProxyStateMap = new WeakMap<UnknownFunction>()
export const patchedFunctionProxyStates: PatchedFunctionProxyStateMap =
new WeakMap<UnknownFunction>()
export function createPatchedFunctionProxy<Key extends PropertyKey, Value extends UnknownFunction>(
export function createPatchedFunctionProxy<
Key extends PropertyKey,
Value extends UnknownFunction,
>(
target: Value,
parent: Record<Key, Value>,
key: FiniteDomain<Key>,

View file

@ -1,11 +1,18 @@
import {
createPatchedFunctionProxy,
type HookNode,
type PatchedFunctionProxyState,
createPatchedFunctionProxy,
patchedFunctionProxyStates,
unproxy,
} from '../_internal'
import type {
AfterHook,
BeforeHook,
FiniteDomain,
UnknownFunction,
} from '../types'
function unpatchAfter<T extends UnknownFunction>(
state: PatchedFunctionProxyState<PropertyKey, T>,
hookNode: HookNode<BeforeHook<T>>,
@ -19,7 +26,8 @@ function unpatchAfter<T extends UnknownFunction>(
if (prev === undefined) {
state.after = next
if (next === undefined) {
if (state.before === undefined && state.instead === undefined) unproxy(state)
if (state.before === undefined && state.instead === undefined)
unproxy(state)
return
}
} else {
@ -31,7 +39,10 @@ function unpatchAfter<T extends UnknownFunction>(
hookNode.next = undefined
}
export function after<Parent extends Record<Key, UnknownFunction>, Key extends PropertyKey>(
export function after<
Parent extends Record<Key, UnknownFunction>,
Key extends PropertyKey,
>(
parent: Parent,
key: FiniteDomain<Key>,
hook: AfterHook<Parent[Key]>,
@ -48,21 +59,28 @@ export function after<Key extends PropertyKey, Value extends UnknownFunction>(
if (state !== undefined && state.parent === parent && state.key === key) {
const head = state.after
hookNode = {
unpatched: false,
hook,
prev: undefined,
next: head,
prev: undefined,
unpatched: false,
}
if (head !== undefined) head.prev = hookNode
state.after = hookNode
} else {
hookNode = {
unpatched: false,
hook,
prev: undefined,
next: undefined,
prev: undefined,
unpatched: false,
}
state = createPatchedFunctionProxy(target, parent, key, undefined, undefined, hookNode)
state = createPatchedFunctionProxy(
target,
parent,
key,
undefined,
undefined,
hookNode,
)
}
return unpatchAfter.bind(undefined, state, hookNode)

View file

@ -1,11 +1,13 @@
import {
createPatchedFunctionProxy,
type HookNode,
type PatchedFunctionProxyState,
createPatchedFunctionProxy,
patchedFunctionProxyStates,
unproxy,
} from '../_internal'
import type { BeforeHook, FiniteDomain, UnknownFunction } from '../types'
function unpatchBefore<T extends UnknownFunction>(
state: PatchedFunctionProxyState<PropertyKey, T>,
hookNode: HookNode<BeforeHook<T>>,
@ -19,7 +21,8 @@ function unpatchBefore<T extends UnknownFunction>(
if (prev === undefined) {
state.before = next
if (next === undefined) {
if (state.instead === undefined && state.after === undefined) unproxy(state)
if (state.instead === undefined && state.after === undefined)
unproxy(state)
return
}
} else {
@ -31,7 +34,10 @@ function unpatchBefore<T extends UnknownFunction>(
hookNode.next = undefined
}
export function before<Parent extends Record<Key, UnknownFunction>, Key extends PropertyKey>(
export function before<
Parent extends Record<Key, UnknownFunction>,
Key extends PropertyKey,
>(
parent: Parent,
key: FiniteDomain<Key>,
hook: BeforeHook<Parent[Key]>,
@ -48,21 +54,28 @@ export function before<Key extends PropertyKey, Value extends UnknownFunction>(
if (state !== undefined && state.parent === parent && state.key === key) {
const head = state.before
hookNode = {
unpatched: false,
hook,
prev: undefined,
next: head,
prev: undefined,
unpatched: false,
}
if (head !== undefined) head.prev = hookNode
state.before = hookNode
} else {
hookNode = {
unpatched: false,
hook,
prev: undefined,
next: undefined,
prev: undefined,
unpatched: false,
}
state = createPatchedFunctionProxy(target, parent, key, hookNode, undefined, undefined)
state = createPatchedFunctionProxy(
target,
parent,
key,
hookNode,
undefined,
undefined,
)
}
return unpatchBefore.bind(undefined, state, hookNode)

View file

@ -1,18 +1,33 @@
import {
createPatchedFunctionProxy,
type FunctionProxyState,
type InsteadHookNode,
type PatchedFunctionProxyState,
createPatchedFunctionProxy,
patchedFunctionProxyHandler,
patchedFunctionProxyStates,
unproxy,
} from '../_internal'
import type {
AbstractNewable,
Callable,
FiniteDomain,
InsteadHook,
UnknownFunction,
} from '../types'
const insteadHookProxyHandler = {
...patchedFunctionProxyHandler,
apply<T extends Callable>(hookNode: InsteadHookNode<T>, receiver: ThisParameterType<T>, args: Parameters<T>) {
apply<T extends Callable>(
hookNode: InsteadHookNode<T>,
receiver: ThisParameterType<T>,
args: Parameters<T>,
) {
const { next } = hookNode
return Reflect.apply(hookNode.hook, receiver, [args, next === undefined ? hookNode.target : next.proxy])
return Reflect.apply(hookNode.hook, receiver, [
args,
next === undefined ? hookNode.target : next.proxy,
])
},
construct<T extends AbstractNewable<never, object>>(
hookNode: InsteadHookNode<T>,
@ -20,7 +35,11 @@ const insteadHookProxyHandler = {
ctor: AbstractNewable,
) {
const { next } = hookNode
return Reflect.construct(hookNode.hook, [args, next === undefined ? hookNode.target : next.proxy], ctor)
return Reflect.construct(
hookNode.hook,
[args, next === undefined ? hookNode.target : next.proxy],
ctor,
)
},
} as const satisfies Required<ProxyHandler<FunctionProxyState>>
@ -36,7 +55,8 @@ function unpatchInstead<T extends UnknownFunction>(
if (prev === undefined) {
state.instead = next
if (next === undefined) {
if (state.before === undefined && state.after === undefined) unproxy(state)
if (state.before === undefined && state.after === undefined)
unproxy(state)
return
}
} else {
@ -48,7 +68,10 @@ function unpatchInstead<T extends UnknownFunction>(
hookNode.next = undefined
}
export function instead<Parent extends Record<Key, UnknownFunction>, Key extends PropertyKey>(
export function instead<
Parent extends Record<Key, UnknownFunction>,
Key extends PropertyKey,
>(
parent: Parent,
key: FiniteDomain<Key>,
hook: InsteadHook<Parent[Key]>,
@ -78,7 +101,14 @@ export function instead<Key extends PropertyKey, Value extends UnknownFunction>(
state.instead = hookNode
} else {
hookNode.next = undefined
state = createPatchedFunctionProxy(target, parent, key, undefined, hookNode, undefined)
state = createPatchedFunctionProxy(
target,
parent,
key,
undefined,
hookNode,
undefined,
)
}
return unpatchInstead.bind(undefined, state, hookNode)

View file

@ -1,4 +1,4 @@
type FiniteDomain<Key extends PropertyKey> = unknown extends (
export type FiniteDomain<Key extends PropertyKey> = unknown extends (
Key extends unknown
? object extends Record<Key, unknown>
? unknown
@ -8,69 +8,84 @@ type FiniteDomain<Key extends PropertyKey> = unknown extends (
? never
: Key
type UnknownFunction = Callable | AbstractNewable
export type UnknownFunction = Callable | AbstractNewable
type Callable<This = never, Args extends readonly unknown[] = never, Return = unknown> = (
this: This,
...args: Args
) => Return
export type Callable<
This = never,
Args extends readonly unknown[] = never,
Return = unknown,
> = (this: This, ...args: Args) => Return
type AbstractNewable<Args extends readonly unknown[] = never, Return = unknown> = abstract new (...args: Args) => Return
export type AbstractNewable<
Args extends readonly unknown[] = never,
Return = unknown,
> = abstract new (...args: Args) => Return
type ConcreteNewable<Args extends readonly unknown[] = never, Return = unknown> = new (...args: Args) => Return
export type ConcreteNewable<
Args extends readonly unknown[] = never,
Return = unknown,
> = new (...args: Args) => Return
type UnionToIntersection<Union> = (Union extends unknown ? (arg: Union) => unknown : never) extends (
arg: infer Intersection,
) => unknown
export type UnionToIntersection<Union> = (
Union extends unknown
? (arg: Union) => unknown
: never
) extends (arg: infer Intersection) => unknown
? Intersection & Union
: never
type BeforeHook<T extends UnknownFunction = UnknownFunction> = OverloadUnion<T> extends infer U
? 0 extends 1 & U
? (args: any) => any
: UnionToIntersection<
U extends Callable<never, infer Args>
? (args: Args) => Args
: U extends ConcreteNewable<infer Args>
? (args: Args) => Args
: never
>
: never
export type BeforeHook<T extends UnknownFunction = UnknownFunction> =
OverloadUnion<T> extends infer U
? 0 extends 1 & U
? (args: any) => any
: UnionToIntersection<
U extends Callable<never, infer Args>
? (args: Args) => Args
: U extends ConcreteNewable<infer Args>
? (args: Args) => Args
: never
>
: never
type InsteadHook<T extends UnknownFunction = UnknownFunction> = OverloadUnion<T> extends infer U
? 0 extends 1 & U
?
| ((this: any, args: any[], originalFunction: T) => any)
| (abstract new (
args: any[],
originalFunction: T,
) => any)
: UnionToIntersection<
U extends Callable<infer This, infer Args, infer Return>
? (this: This, args: Args, originalFunction: T) => Return
: U extends ConcreteNewable<infer Args, infer Return>
? abstract new (
args: Args,
originalFunction: T,
) => Return
: never
>
: never
export type InsteadHook<T extends UnknownFunction = UnknownFunction> =
OverloadUnion<T> extends infer U
? 0 extends 1 & U
?
| ((this: any, args: any[], originalFunction: T) => any)
| (abstract new (
args: any[],
originalFunction: T,
) => any)
: UnionToIntersection<
U extends Callable<infer This, infer Args, infer Return>
? (this: This, args: Args, originalFunction: T) => Return
: U extends ConcreteNewable<infer Args, infer Return>
? abstract new (
args: Args,
originalFunction: T,
) => Return
: never
>
: never
type AfterHook<T extends UnknownFunction = UnknownFunction> = OverloadUnion<T> extends infer U
? 0 extends 1 & U
? (result: any) => any
: UnionToIntersection<
U extends Callable<never, never, infer Return>
? (result: Return) => Return
: U extends ConcreteNewable<never, infer Return>
? (result: Return) => Return
: never
>
: never
export type AfterHook<T extends UnknownFunction = UnknownFunction> =
OverloadUnion<T> extends infer U
? 0 extends 1 & U
? (result: any) => any
: UnionToIntersection<
U extends Callable<never, never, infer Return>
? (result: Return) => Return
: U extends ConcreteNewable<never, infer Return>
? (result: Return) => Return
: never
>
: never
/** @see {@link https://github.com/microsoft/TypeScript/issues/32164#issuecomment-1146737709} */
type OverloadUnion<Overload extends UnknownFunction, PartialOverload = OmitOverloads<Overload>> = 0 extends 1 & Overload
export type OverloadUnion<
Overload extends UnknownFunction,
PartialOverload = OmitOverloads<Overload>,
> = 0 extends 1 & Overload
? any
: Overload extends Callable<infer CThis, infer CArgs, infer CReturn>
? Overload extends AbstractNewable<infer NArgs, infer NReturn>
@ -80,14 +95,22 @@ type OverloadUnion<Overload extends UnknownFunction, PartialOverload = OmitOverl
Callable<CThis, CArgs, CReturn>,
ConcreteNewable<NArgs, NReturn>
>
: OverloadUnionCallable<Overload, PartialOverload, Callable<CThis, CArgs, CReturn>>
: OverloadUnionCallable<
Overload,
PartialOverload,
Callable<CThis, CArgs, CReturn>
>
: Overload extends AbstractNewable<infer NArgs, infer NReturn>
? OverloadUnionNewable<Overload, PartialOverload, ConcreteNewable<NArgs, NReturn>>
? OverloadUnionNewable<
Overload,
PartialOverload,
ConcreteNewable<NArgs, NReturn>
>
: never
type OmitOverloads<T> = { [Key in keyof T]: T[Key] }
export type OmitOverloads<T> = { [Key in keyof T]: T[Key] }
type OverloadUnionCallableNewable<
export type OverloadUnionCallableNewable<
Overload extends Callable & AbstractNewable,
PartialOverload,
CurrentCallable extends Callable,
@ -101,7 +124,7 @@ type OverloadUnionCallableNewable<
| CurrentCallable
| CurrentNewable
type OverloadUnionCallableNewableInner<
export type OverloadUnionCallableNewableInner<
Overload extends Callable & AbstractNewable,
PartialOverload,
PreviousOverload extends Callable & ConcreteNewable,
@ -110,8 +133,10 @@ type OverloadUnionCallableNewableInner<
: Overload extends Callable<infer CThis, infer CArgs, infer CReturn>
? Overload extends AbstractNewable<infer NArgs, infer NReturn>
? // Detects infinite recursion caused by generic overloads.
Callable<CThis, CArgs, CReturn> & ConcreteNewable<NArgs, NReturn> extends PreviousOverload
? PreviousOverload extends Callable<CThis, CArgs, CReturn> & ConcreteNewable<NArgs, NReturn>
Callable<CThis, CArgs, CReturn> &
ConcreteNewable<NArgs, NReturn> extends PreviousOverload
? PreviousOverload extends Callable<CThis, CArgs, CReturn> &
ConcreteNewable<NArgs, NReturn>
? any
: OverloadUnionCallableNewable<
Overload,
@ -128,11 +153,19 @@ type OverloadUnionCallableNewableInner<
: never
: never
type OverloadUnionCallable<Overload extends Callable, PartialOverload, CurrentCallable extends Callable> =
| OverloadUnionCallableInner<CurrentCallable & Overload, CurrentCallable & PartialOverload, CurrentCallable>
export type OverloadUnionCallable<
Overload extends Callable,
PartialOverload,
CurrentCallable extends Callable,
> =
| OverloadUnionCallableInner<
CurrentCallable & Overload,
CurrentCallable & PartialOverload,
CurrentCallable
>
| CurrentCallable
type OverloadUnionCallableInner<
export type OverloadUnionCallableInner<
Overload extends Callable,
PartialOverload,
PreviousOverload extends Callable,
@ -143,15 +176,31 @@ type OverloadUnionCallableInner<
Callable<This, Args, Return> extends PreviousOverload
? PreviousOverload extends Callable<This, Args, Return>
? any
: OverloadUnionCallable<Overload, PartialOverload, Callable<This, Args, Return>>
: OverloadUnionCallable<Overload, PartialOverload, Callable<This, Args, Return>>
: OverloadUnionCallable<
Overload,
PartialOverload,
Callable<This, Args, Return>
>
: OverloadUnionCallable<
Overload,
PartialOverload,
Callable<This, Args, Return>
>
: never
type OverloadUnionNewable<Overload extends AbstractNewable, PartialOverload, CurrentNewable extends ConcreteNewable> =
| OverloadUnionNewableInner<CurrentNewable & Overload, CurrentNewable & PartialOverload, CurrentNewable>
export type OverloadUnionNewable<
Overload extends AbstractNewable,
PartialOverload,
CurrentNewable extends ConcreteNewable,
> =
| OverloadUnionNewableInner<
CurrentNewable & Overload,
CurrentNewable & PartialOverload,
CurrentNewable
>
| CurrentNewable
type OverloadUnionNewableInner<
export type OverloadUnionNewableInner<
Overload extends AbstractNewable,
PartialOverload,
PreviousOverload extends ConcreteNewable,
@ -162,6 +211,14 @@ type OverloadUnionNewableInner<
ConcreteNewable<Args, Return> extends PreviousOverload
? PartialOverload extends ConcreteNewable<Args, Return>
? any
: OverloadUnionNewable<Overload, PartialOverload, ConcreteNewable<Args, Return>>
: OverloadUnionNewable<Overload, PartialOverload, ConcreteNewable<Args, Return>>
: OverloadUnionNewable<
Overload,
PartialOverload,
ConcreteNewable<Args, Return>
>
: OverloadUnionNewable<
Overload,
PartialOverload,
ConcreteNewable<Args, Return>
>
: never