File size: 2,585 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
import type { App as VueApp } from 'vue'
import { createApp as createVueApp } from 'vue'
import { BridgeEvents, SharedData, destroySharedData, initEnv, initSharedData, isChrome } from '@vue-devtools/shared-utils'
import App from './features/App.vue'
import { createRouterInstance } from './router'
import { getBridge, setBridge } from './features/bridge'
import { setAppConnected, setAppInitializing } from './features/connection'
import { setupAppsBridgeEvents } from './features/apps'
import { setupComponentsBridgeEvents } from './features/components/composable'
import { setupTimelineBridgeEvents } from './features/timeline/composable'
import { setupCustomInspectorBridgeEvents } from './features/inspector/custom/composable'
import { setupPluginsBridgeEvents } from './features/plugin'
import { setupPlugins } from './plugins'

// Capture and log devtool errors when running as actual extension
// so that we can debug it by inspecting the background page.
// We do want the errors to be thrown in the dev shell though.
export function createApp() {
  const router = createRouterInstance()

  const app = createVueApp(App)
  app.use(router)
  setupPlugins(app)

  if (isChrome) {
    app.config.errorHandler = (e, vm) => {
      getBridge()?.send('ERROR', {
        message: (e as Error).message,
        stack: (e as Error).stack,
        component: vm?.$options.name || (vm?.$options as any)._componentTag || 'anonymous',
      })
    }
  }

  return app
}

/**
 * Connect then init the app. We need to reconnect on every reload, because a
 * new backend will be injected.
 */
export function connectApp(app: VueApp, shell) {
  shell.connect(async (bridge) => {
    setBridge(bridge)
    // @TODO remove
    // @ts-expect-error custom prop on window
    window.bridge = bridge

    if (app.config.globalProperties.$shared) {
      destroySharedData()
    }
    else {
      Object.defineProperty(app.config.globalProperties, '$shared', {
        get: () => SharedData,
      })
    }

    initEnv(app)

    bridge.on(BridgeEvents.TO_FRONT_TITLE, ({ title }: { title: string }) => {
      document.title = `${title} - Vue devtools`
    })

    await initSharedData({
      bridge,
      persist: true,
    })

    if (SharedData.logDetected) {
      bridge.send('log-detected-vue')
    }

    setupAppsBridgeEvents(bridge)
    setupComponentsBridgeEvents(bridge)
    setupTimelineBridgeEvents(bridge)
    setupCustomInspectorBridgeEvents(bridge)
    setupPluginsBridgeEvents(bridge)

    // @TODO bridge listeners

    setAppConnected(true)
    setAppInitializing(false)
  })
}