Skip to content

Commit ea87e45

Browse files
authored
feat: support inspecting 2.7 setup state (#1899)
1 parent 030c73b commit ea87e45

File tree

1 file changed

+146
-6
lines changed
  • packages/app-backend-vue2/src/components

1 file changed

+146
-6
lines changed

packages/app-backend-vue2/src/components/data.ts

Lines changed: 146 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { camelize, getComponentName, getCustomRefDetails, StateEditor, SharedData } from '@vue-devtools/shared-utils'
2-
import { ComponentState, HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
2+
import { ComponentState, CustomState, HookPayloads, Hooks, InspectedComponentData } from '@vue/devtools-api'
33
import { functionalVnodeMap, instanceMap } from './tree'
44
import 'core-js/modules/es.object.entries'
55

@@ -53,6 +53,7 @@ export function getInstanceDetails (instance): InspectedComponentData {
5353
function getInstanceState (instance): ComponentState[] {
5454
return processProps(instance).concat(
5555
processState(instance),
56+
processSetupState(instance),
5657
processRefs(instance),
5758
processComputed(instance),
5859
processInjected(instance),
@@ -187,6 +188,112 @@ function processState (instance): ComponentState[] {
187188
}))
188189
}
189190

191+
192+
function processSetupState (instance) {
193+
const state = instance._setupProxy
194+
const raw = instance._setupState
195+
if (!raw || !state) {
196+
return []
197+
}
198+
199+
return Object.keys(state)
200+
.filter(key => !key.startsWith('__'))
201+
.map(key => {
202+
const value = returnError(() => toRaw(state[key]))
203+
204+
const rawData = raw[key]
205+
206+
let result: any
207+
208+
if (rawData) {
209+
const info = getSetupStateInfo(rawData)
210+
211+
const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
212+
const isState = info.ref || info.computed || info.reactive
213+
const isOther = typeof value === 'function' || typeof value?.render === 'function'
214+
// effect is a Vue 2 Watcher instance
215+
const raw = rawData.effect?.expression || rawData.effect?.getter?.toString()
216+
217+
result = {
218+
...objectType ? { objectType } : {},
219+
...raw ? { raw } : {},
220+
editable: isState && !info.readonly,
221+
type: isOther ? 'setup (other)' : 'setup',
222+
}
223+
} else {
224+
result = {
225+
type: 'setup',
226+
}
227+
}
228+
229+
return {
230+
key,
231+
value,
232+
...result,
233+
}
234+
})
235+
}
236+
237+
function returnError (cb: () => any) {
238+
try {
239+
return cb()
240+
} catch (e) {
241+
return e
242+
}
243+
}
244+
245+
246+
function isRef (raw: any): boolean {
247+
return !!raw.__v_isRef
248+
}
249+
250+
function isComputed (raw: any): boolean {
251+
return isRef(raw) && !!raw.effect
252+
}
253+
254+
function isReactive (raw: any): boolean {
255+
return !!raw.__ob__
256+
}
257+
258+
function isReadOnly (raw: any): boolean {
259+
return !!raw.__v_isReadonly
260+
}
261+
262+
function toRaw (value: any) {
263+
if (value?.__v_raw) {
264+
return value.__v_raw
265+
}
266+
return value
267+
}
268+
269+
function getSetupStateInfo (raw: any) {
270+
return {
271+
ref: isRef(raw),
272+
computed: isComputed(raw),
273+
reactive: isReactive(raw),
274+
readonly: isReadOnly(raw),
275+
}
276+
}
277+
278+
export function getCustomObjectDetails (object: any, proto: string): CustomState | undefined {
279+
const info = getSetupStateInfo(object)
280+
281+
const isState = info.ref || info.computed || info.reactive
282+
if (isState) {
283+
const objectType = info.computed ? 'Computed' : info.ref ? 'Ref' : info.reactive ? 'Reactive' : null
284+
const value = toRaw(info.reactive ? object : object._value)
285+
const raw = object.effect?.raw?.toString() || object.effect?.fn?.toString()
286+
return {
287+
_custom: {
288+
type: objectType.toLowerCase(),
289+
objectType,
290+
value,
291+
...raw ? { tooltip: `<span class="font-mono">${raw}</span>` } : {},
292+
},
293+
}
294+
}
295+
}
296+
190297
/**
191298
* Process refs
192299
*/
@@ -349,10 +456,43 @@ export function findInstanceOrVnode (id) {
349456
return instanceMap.get(id)
350457
}
351458

352-
export function editState ({ componentInstance, path, state, type }: HookPayloads[Hooks.EDIT_COMPONENT_STATE], stateEditor: StateEditor) {
459+
export function editState(
460+
{
461+
componentInstance,
462+
path,
463+
state,
464+
type
465+
}: HookPayloads[Hooks.EDIT_COMPONENT_STATE],
466+
stateEditor: StateEditor
467+
) {
353468
if (!['data', 'props', 'computed', 'setup'].includes(type)) return
354-
const data = stateEditor.has(componentInstance._props, path, !!state.newKey)
355-
? componentInstance._props
356-
: componentInstance._data
357-
stateEditor.set(data, path, state.value, stateEditor.createDefaultSetCallback(state))
469+
470+
let target: any
471+
const targetPath: string[] = path.slice()
472+
473+
if (stateEditor.has(componentInstance._props, path, !!state.newKey)) {
474+
// props
475+
target = componentInstance._props
476+
} else if (
477+
componentInstance._setupState &&
478+
Object.keys(componentInstance._setupState).includes(path[0])
479+
) {
480+
// setup
481+
target = componentInstance._setupProxy
482+
483+
const currentValue = stateEditor.get(target, path)
484+
if (currentValue != null) {
485+
const info = getSetupStateInfo(currentValue)
486+
if (info.readonly) return
487+
}
488+
} else {
489+
target = componentInstance._data
490+
}
491+
492+
stateEditor.set(
493+
target,
494+
targetPath,
495+
'value' in state ? state.value : undefined,
496+
stateEditor.createDefaultSetCallback(state)
497+
)
358498
}

0 commit comments

Comments
 (0)