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'
1912
2013export const injectHook = (
2114 type : VaporLifecycleHooks ,
22- hook : Function ,
15+ hook : Function & { __weh ?: Function } ,
2316 target : ComponentInternalInstance | null = currentInstance ,
2417 prepend : boolean = false ,
2518) => {
2619 if ( target ) {
2720 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+ } )
2834 if ( prepend ) {
29- hooks . unshift ( hook )
35+ hooks . unshift ( wrappedHook )
3036 } else {
31- hooks . push ( hook )
37+ hooks . push ( wrappedHook )
3238 }
33- return hook
39+ return wrappedHook
3440 } 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+ )
3651 }
3752}
3853export const createHook =
@@ -46,3 +61,16 @@ export const onBeforeUpdate = createHook(VaporLifecycleHooks.BEFORE_UPDATE)
4661export const onUpdated = createHook ( VaporLifecycleHooks . UPDATED )
4762export const onBeforeUnmount = createHook ( VaporLifecycleHooks . BEFORE_UNMOUNT )
4863export 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