1
- import { type ComponentInternalInstance , currentInstance } from './component'
2
-
3
- export enum VaporLifecycleHooks {
4
- BEFORE_CREATE = 'bc' ,
5
- CREATED = 'c' ,
6
- BEFORE_MOUNT = 'bm' ,
7
- MOUNTED = 'm' ,
8
- BEFORE_UPDATE = 'bu' ,
9
- UPDATED = 'u' ,
10
- BEFORE_UNMOUNT = 'bum' ,
11
- UNMOUNTED = 'um' ,
12
- DEACTIVATED = 'da' ,
13
- ACTIVATED = 'a' ,
14
- RENDER_TRIGGERED = 'rtg' ,
15
- RENDER_TRACKED = 'rtc' ,
16
- ERROR_CAPTURED = 'ec' ,
17
- // SERVER_PREFETCH = 'sp',
18
- }
1
+ import {
2
+ type ComponentInternalInstance ,
3
+ currentInstance ,
4
+ setCurrentInstance ,
5
+ unsetCurrentInstance ,
6
+ } from './component'
7
+ import { warn } from './warning'
8
+ import { pauseTracking , resetTracking } from '@vue/reactivity'
9
+ import { ErrorTypeStrings , callWithAsyncErrorHandling } from './errorHandling'
10
+ import { toHandlerKey } from '@vue/shared'
11
+ import { VaporLifecycleHooks } from './enums'
19
12
20
13
export const injectHook = (
21
14
type : VaporLifecycleHooks ,
22
- hook : Function ,
15
+ hook : Function & { __weh ?: Function } ,
23
16
target : ComponentInternalInstance | null = currentInstance ,
24
17
prepend : boolean = false ,
25
18
) => {
26
19
if ( target ) {
27
20
const hooks = target [ type ] || ( target [ type ] = [ ] )
21
+ const wrappedHook =
22
+ hook . __weh ||
23
+ ( hook . __weh = ( ...args : unknown [ ] ) => {
24
+ if ( target . isUnmounted ) {
25
+ return
26
+ }
27
+ pauseTracking ( )
28
+ setCurrentInstance ( target )
29
+ const res = callWithAsyncErrorHandling ( hook , target , type , args )
30
+ unsetCurrentInstance ( )
31
+ resetTracking ( )
32
+ return res
33
+ } )
28
34
if ( prepend ) {
29
- hooks . unshift ( hook )
35
+ hooks . unshift ( wrappedHook )
30
36
} else {
31
- hooks . push ( hook )
37
+ hooks . push ( wrappedHook )
32
38
}
33
- return hook
39
+ return wrappedHook
34
40
} else if ( __DEV__ ) {
35
- // TODO: warn need
41
+ const apiName = toHandlerKey ( ErrorTypeStrings [ type ] . replace ( / h o o k $ / , '' ) )
42
+ warn (
43
+ `${ apiName } is called when there is no active component instance to be ` +
44
+ `associated with. ` +
45
+ `Lifecycle injection APIs can only be used during execution of setup().` +
46
+ ( __FEATURE_SUSPENSE__
47
+ ? ` If you are using async setup(), make sure to register lifecycle ` +
48
+ `hooks before the first await statement.`
49
+ : `` ) ,
50
+ )
36
51
}
37
52
}
38
53
export const createHook =
@@ -46,3 +61,16 @@ export const onBeforeUpdate = createHook(VaporLifecycleHooks.BEFORE_UPDATE)
46
61
export const onUpdated = createHook ( VaporLifecycleHooks . UPDATED )
47
62
export const onBeforeUnmount = createHook ( VaporLifecycleHooks . BEFORE_UNMOUNT )
48
63
export const onUnmounted = createHook ( VaporLifecycleHooks . UNMOUNTED )
64
+
65
+ export type ErrorCapturedHook < TError = unknown > = (
66
+ err : TError ,
67
+ instance : ComponentInternalInstance | null ,
68
+ info : string ,
69
+ ) => boolean | void
70
+
71
+ export function onErrorCaptured < TError = Error > (
72
+ hook : ErrorCapturedHook < TError > ,
73
+ target : ComponentInternalInstance | null = currentInstance ,
74
+ ) {
75
+ injectHook ( VaporLifecycleHooks . ERROR_CAPTURED , hook , target )
76
+ }
0 commit comments