UNPKG

1.38 kBPlain TextView Raw
1import { Lambda, once, untrackedEnd, untrackedStart, die } from "../internal"
2
3export type IInterceptor<T> = (change: T) => T | null
4
5export interface IInterceptable<T> {
6 interceptors_: IInterceptor<T>[] | undefined
7}
8
9export function hasInterceptors(interceptable: IInterceptable<any>) {
10 return interceptable.interceptors_ !== undefined && interceptable.interceptors_.length > 0
11}
12
13export function registerInterceptor<T>(
14 interceptable: IInterceptable<T>,
15 handler: IInterceptor<T>
16): Lambda {
17 const interceptors = interceptable.interceptors_ || (interceptable.interceptors_ = [])
18 interceptors.push(handler)
19 return once(() => {
20 const idx = interceptors.indexOf(handler)
21 if (idx !== -1) interceptors.splice(idx, 1)
22 })
23}
24
25export function interceptChange<T>(
26 interceptable: IInterceptable<T | null>,
27 change: T | null
28): T | null {
29 const prevU = untrackedStart()
30 try {
31 // Interceptor can modify the array, copy it to avoid concurrent modification, see #1950
32 const interceptors = [...(interceptable.interceptors_ || [])]
33 for (let i = 0, l = interceptors.length; i < l; i++) {
34 change = interceptors[i](change)
35 if (change && !(change as any).type) die(14)
36 if (!change) break
37 }
38 return change
39 } finally {
40 untrackedEnd(prevU)
41 }
42}