File size: 3,769 Bytes
4d70170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { BuiltinBackendFeature, defineBackend } from '@vue-devtools/app-backend-api'
import { backendInjections, getComponentName } from '@vue-devtools/shared-utils'
import type { ComponentInstance } from '@vue/devtools-api'
import { editState, getCustomInstanceDetails, getInstanceDetails } from './components/data'
import { findRelatedComponent, getInstanceOrVnodeRect, getRootElementsFromComponentInstance } from './components/el'
import { initPerf } from './components/perf.js'
import { getComponentParents, getInstanceMap, walkTree } from './components/tree'
import { initUpdateTracking } from './components/update-tracking.js'
import { getInstanceName } from './components/util'
import { wrapVueForEvents } from './events'
import { setupPlugin } from './plugin'

export const backend = defineBackend({
  frameworkVersion: 2,
  features: [
    BuiltinBackendFeature.FLUSH,
  ],
  setup(api) {
    api.on.getAppRecordName((payload) => {
      if (payload.app.name) {
        payload.name = payload.app.name
      }
      else if (payload.app.$options.name) {
        payload.name = payload.app.$options.name
      }
    })

    api.on.getAppRootInstance((payload) => {
      payload.root = payload.app as unknown as ComponentInstance
    })

    api.on.walkComponentTree(async (payload, ctx) => {
      payload.componentTreeData = await walkTree(payload.componentInstance, payload.filter, payload.recursively, api, ctx)
    })

    api.on.walkComponentParents((payload, ctx) => {
      payload.parentInstances = getComponentParents(payload.componentInstance, api, ctx)
    })

    api.on.inspectComponent((payload) => {
      injectToUtils()
      payload.instanceData = getInstanceDetails(payload.componentInstance)
    })

    api.on.getComponentBounds((payload) => {
      payload.bounds = getInstanceOrVnodeRect(payload.componentInstance)
    })

    api.on.getComponentName((payload) => {
      const instance = payload.componentInstance
      payload.name = instance.fnContext ? getComponentName(instance.fnOptions) : getInstanceName(instance)
    })

    api.on.getElementComponent((payload) => {
      payload.componentInstance = findRelatedComponent(payload.element)
    })

    api.on.editComponentState((payload) => {
      editState(payload, api.stateEditor)
    })

    api.on.getComponentRootElements((payload) => {
      payload.rootElements = getRootElementsFromComponentInstance(payload.componentInstance)
    })

    api.on.getComponentDevtoolsOptions((payload) => {
      payload.options = payload.componentInstance.$options.devtools
    })

    api.on.getComponentRenderCode((payload) => {
      payload.code = payload.componentInstance.$options.render.toString()
    })

    api.on.getComponentInstances(() => {
      console.warn('on.getComponentInstances is not implemented for Vue 2')
    })
  },

  setupApp(api, appRecord) {
    const { Vue } = appRecord.options.meta
    const app = appRecord.options.app

    // State editor overrides
    api.stateEditor.createDefaultSetCallback = (state) => {
      return (obj, field, value) => {
        if (state.remove || state.newKey) {
          Vue.delete(obj, field)
        }
        if (!state.remove) {
          Vue.set(obj, state.newKey || field, value)
        }
      }
    }

    // Utils
    injectToUtils()
    wrapVueForEvents(app, Vue, api.ctx)

    // Plugin
    setupPlugin(api, app, Vue)

    // Perf
    initPerf(api, app, Vue)
    // Update tracking
    initUpdateTracking(api, Vue)
  },
})

// @TODO refactor
function injectToUtils() {
  backendInjections.getCustomInstanceDetails = getCustomInstanceDetails
  backendInjections.getCustomObjectDetails = () => undefined
  backendInjections.instanceMap = getInstanceMap()
  backendInjections.isVueInstance = val => val._isVue
}