|
1 | 1 | 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' |
3 | 3 | import { functionalVnodeMap, instanceMap } from './tree'
|
4 | 4 | import 'core-js/modules/es.object.entries'
|
5 | 5 |
|
@@ -53,6 +53,7 @@ export function getInstanceDetails (instance): InspectedComponentData {
|
53 | 53 | function getInstanceState (instance): ComponentState[] {
|
54 | 54 | return processProps(instance).concat(
|
55 | 55 | processState(instance),
|
| 56 | + processSetupState(instance), |
56 | 57 | processRefs(instance),
|
57 | 58 | processComputed(instance),
|
58 | 59 | processInjected(instance),
|
@@ -187,6 +188,112 @@ function processState (instance): ComponentState[] {
|
187 | 188 | }))
|
188 | 189 | }
|
189 | 190 |
|
| 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 | + |
190 | 297 | /**
|
191 | 298 | * Process refs
|
192 | 299 | */
|
@@ -349,10 +456,43 @@ export function findInstanceOrVnode (id) {
|
349 | 456 | return instanceMap.get(id)
|
350 | 457 | }
|
351 | 458 |
|
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 | +) { |
353 | 468 | 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 | + ) |
358 | 498 | }
|
0 commit comments