-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
/
devtools.ts
142 lines (124 loc) · 3.8 KB
/
devtools.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { App } from './apiCreateApp'
import { Fragment, Text, Comment, Static } from './vnode'
import { ComponentInternalInstance } from './component'
interface AppRecord {
id: number
app: App
version: string
types: Record<string, string | Symbol>
}
const enum DevtoolsHooks {
APP_INIT = 'app:init',
APP_UNMOUNT = 'app:unmount',
COMPONENT_UPDATED = 'component:updated',
COMPONENT_ADDED = 'component:added',
COMPONENT_REMOVED = 'component:removed',
COMPONENT_EMIT = 'component:emit',
PERFORMANCE_START = 'perf:start',
PERFORMANCE_END = 'perf:end'
}
interface DevtoolsHook {
enabled?: boolean
emit: (event: string, ...payload: any[]) => void
on: (event: string, handler: Function) => void
once: (event: string, handler: Function) => void
off: (event: string, handler: Function) => void
appRecords: AppRecord[]
}
export let devtools: DevtoolsHook
let buffer: { event: string; args: any[] }[] = []
let devtoolsNotInstalled = false
function emit(event: string, ...args: any[]) {
if (devtools) {
devtools.emit(event, ...args)
} else if (!devtoolsNotInstalled) {
buffer.push({ event, args })
}
}
export function setDevtoolsHook(hook: DevtoolsHook, target: any) {
devtools = hook
if (devtools) {
devtools.enabled = true
buffer.forEach(({ event, args }) => devtools.emit(event, ...args))
buffer = []
} else if (
// handle late devtools injection - only do this if we are in an actual
// browser environment to avoid the timer handle stalling test runner exit
// (#4815)
// eslint-disable-next-line no-restricted-globals
typeof window !== 'undefined' &&
!navigator.userAgent.includes('jsdom')
) {
const replay = (target.__VUE_DEVTOOLS_HOOK_REPLAY__ =
target.__VUE_DEVTOOLS_HOOK_REPLAY__ || [])
replay.push((newHook: DevtoolsHook) => {
setDevtoolsHook(newHook, target)
})
// clear buffer after 3s - the user probably doesn't have devtools installed
// at all, and keeping the buffer will cause memory leaks (#4738)
setTimeout(() => {
if (!devtools) {
target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null
devtoolsNotInstalled = true
buffer = []
}
}, 3000)
} else {
// non-browser env, assume not installed
devtoolsNotInstalled = true
buffer = []
}
}
export function devtoolsInitApp(app: App, version: string) {
emit(DevtoolsHooks.APP_INIT, app, version, {
Fragment,
Text,
Comment,
Static
})
}
export function devtoolsUnmountApp(app: App) {
emit(DevtoolsHooks.APP_UNMOUNT, app)
}
export const devtoolsComponentAdded = /*#__PURE__*/ createDevtoolsComponentHook(
DevtoolsHooks.COMPONENT_ADDED
)
export const devtoolsComponentUpdated =
/*#__PURE__*/ createDevtoolsComponentHook(DevtoolsHooks.COMPONENT_UPDATED)
export const devtoolsComponentRemoved =
/*#__PURE__*/ createDevtoolsComponentHook(DevtoolsHooks.COMPONENT_REMOVED)
function createDevtoolsComponentHook(hook: DevtoolsHooks) {
return (component: ComponentInternalInstance) => {
emit(
hook,
component.appContext.app,
component.uid,
component.parent ? component.parent.uid : undefined,
component
)
}
}
export const devtoolsPerfStart = /*#__PURE__*/ createDevtoolsPerformanceHook(
DevtoolsHooks.PERFORMANCE_START
)
export const devtoolsPerfEnd = /*#__PURE__*/ createDevtoolsPerformanceHook(
DevtoolsHooks.PERFORMANCE_END
)
function createDevtoolsPerformanceHook(hook: DevtoolsHooks) {
return (component: ComponentInternalInstance, type: string, time: number) => {
emit(hook, component.appContext.app, component.uid, component, type, time)
}
}
export function devtoolsComponentEmit(
component: ComponentInternalInstance,
event: string,
params: any[]
) {
emit(
DevtoolsHooks.COMPONENT_EMIT,
component.appContext.app,
component,
event,
params
)
}