1
- import { installHook } from '@back/hook'
2
- import { initBackend } from '@back'
1
+ import { installHook as _installHook } from '@back/hook'
3
2
import { Bridge } from '@utils/bridge'
4
3
import { SharedData } from '@utils/shared-data'
5
4
import createUrl from 'licia/createUrl'
6
5
import devtools from 'raw-loader!./devtools.txt'
7
6
8
- installHook ( window )
9
-
10
7
let theme = 'auto'
11
8
let shareDataLoaded = false
12
9
10
+ export function installHook ( ) {
11
+ if ( window . __VUE_DEVTOOLS_GLOBAL_HOOK__ ) {
12
+ return
13
+ }
14
+ _installHook ( window )
15
+ }
16
+
13
17
export function initDevtools ( iframe ) {
14
18
const bridge = new Bridge ( {
15
19
listen ( fn ) {
@@ -31,7 +35,9 @@ export function initDevtools(iframe) {
31
35
shareDataLoaded = true
32
36
setTheme ( theme )
33
37
} )
34
- initBackend ( bridge )
38
+ import ( '@back' ) . then ( ( { initBackend } ) => {
39
+ initBackend ( bridge )
40
+ } )
35
41
36
42
const devtoolsSrc = createUrl ( devtools , { type : 'application/javascript' } )
37
43
@@ -62,3 +68,154 @@ export function setTheme(value) {
62
68
SharedData . theme = value
63
69
}
64
70
}
71
+
72
+ // Modified from vue-devtools
73
+ export function forceEnable ( ) {
74
+ if ( ! window . __VUE_DEVTOOLS_GLOBAL_HOOK__ ) {
75
+ return
76
+ }
77
+
78
+ let delay = 1000
79
+ let detectRemainingTries = 10
80
+
81
+ function runDetect ( ) {
82
+ // Method 1: Check Nuxt.js
83
+ const nuxtDetected = ! ! ( window . __NUXT__ || window . $nuxt )
84
+
85
+ if ( nuxtDetected ) {
86
+ let Vue
87
+
88
+ if ( window . $nuxt ) {
89
+ Vue = window . $nuxt . $root && window . $nuxt . $root . constructor
90
+ }
91
+
92
+ crack ( {
93
+ devtoolsEnabled :
94
+ ( Vue && Vue . config . devtools ) ||
95
+ ( window . __VUE_DEVTOOLS_GLOBAL_HOOK__ &&
96
+ window . __VUE_DEVTOOLS_GLOBAL_HOOK__ . enabled ) ,
97
+ vueDetected : true ,
98
+ nuxtDetected : true ,
99
+ } )
100
+
101
+ return
102
+ }
103
+
104
+ // Method 2: Check Vue 3
105
+ const vueDetected = ! ! window . __VUE__
106
+ if ( vueDetected ) {
107
+ crack ( {
108
+ devtoolsEnabled :
109
+ window . __VUE_DEVTOOLS_GLOBAL_HOOK__ &&
110
+ window . __VUE_DEVTOOLS_GLOBAL_HOOK__ . enabled ,
111
+ vueDetected : true ,
112
+ } )
113
+
114
+ return
115
+ }
116
+
117
+ // Method 3: Scan all elements inside document
118
+ const all = document . querySelectorAll ( '*' )
119
+ let el
120
+ for ( let i = 0 ; i < all . length ; i ++ ) {
121
+ if ( all [ i ] . __vue__ ) {
122
+ el = all [ i ]
123
+ break
124
+ }
125
+ }
126
+ if ( el ) {
127
+ let Vue = Object . getPrototypeOf ( el . __vue__ ) . constructor
128
+ while ( Vue . super ) {
129
+ Vue = Vue . super
130
+ }
131
+ crack ( {
132
+ devtoolsEnabled : Vue . config . devtools ,
133
+ vueDetected : true ,
134
+ } )
135
+ return
136
+ }
137
+
138
+ if ( detectRemainingTries > 0 ) {
139
+ detectRemainingTries --
140
+ setTimeout ( ( ) => {
141
+ runDetect ( )
142
+ } , delay )
143
+ delay *= 5
144
+ }
145
+ }
146
+
147
+ setTimeout ( ( ) => {
148
+ runDetect ( )
149
+ } , 100 )
150
+ }
151
+
152
+ // https://github.com/hzmming/vue-force-dev
153
+ function crack ( data ) {
154
+ if ( data . devtoolsEnabled ) {
155
+ return
156
+ }
157
+
158
+ // Nuxt.js
159
+ if ( data . nuxtDetected ) {
160
+ let Vue
161
+
162
+ if ( window . $nuxt ) {
163
+ Vue = window . $nuxt . $root && window . $nuxt . $root . constructor
164
+ }
165
+
166
+ // Vue 2
167
+ if ( Vue ) {
168
+ crackVue2 ( Vue )
169
+ } else {
170
+ // Vue 3.2.14+
171
+ crackVue3 ( )
172
+ }
173
+ }
174
+ // Vue 3
175
+ else if ( window . __VUE__ ) {
176
+ crackVue3 ( )
177
+ }
178
+ // Vue 2
179
+ else {
180
+ crackVue2 ( )
181
+ }
182
+ }
183
+
184
+ function crackVue2 ( Vue ) {
185
+ if ( ! Vue ) {
186
+ const app = getVueRootInstance ( 2 )
187
+ if ( ! app ) return false // Vue may not be finished yet
188
+ Vue = Object . getPrototypeOf ( app ) . constructor
189
+ while ( Vue . super ) {
190
+ Vue = Vue . super
191
+ }
192
+ }
193
+
194
+ const devtools = window . __VUE_DEVTOOLS_GLOBAL_HOOK__
195
+ Vue . config . devtools = true
196
+ devtools . emit ( 'init' , Vue )
197
+ }
198
+
199
+ function crackVue3 ( ) {
200
+ const app = getVueRootInstance ( 3 )
201
+ if ( ! app ) return false // Vue may not be finished yet
202
+ const devtools = window . __VUE_DEVTOOLS_GLOBAL_HOOK__
203
+ devtools . enabled = true
204
+ const version = app . version
205
+ devtools . emit ( 'app:init' /* APP_INIT */ , app , version , {
206
+ Fragment : Symbol . for ( 'v-fgt' ) ,
207
+ Text : Symbol . for ( 'v-txt' ) ,
208
+ Comment : Symbol . for ( 'v-cmt' ) ,
209
+ Static : Symbol . for ( 'v-stc' ) ,
210
+ } )
211
+ }
212
+
213
+ function getVueRootInstance ( version ) {
214
+ const signProperty = version === 2 ? '__vue__' : '__vue_app__'
215
+ const all = document . querySelectorAll ( '*' )
216
+ for ( let i = 0 ; i < all . length ; i ++ ) {
217
+ if ( all [ i ] [ signProperty ] ) {
218
+ return all [ i ] [ signProperty ]
219
+ }
220
+ }
221
+ }
0 commit comments