Skip to content

Commit

Permalink
chore: update
Browse files Browse the repository at this point in the history
  • Loading branch information
webfansplz committed Oct 9, 2024
1 parent 9885469 commit 8acab1d
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 42 deletions.
7 changes: 7 additions & 0 deletions packages/applet/src/components/timeline/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ rpc.functions.on(DevToolsMessagingEvents.TIMELINE_EVENT_UPDATED, onTimelineEvent
onUnmounted(() => {
rpc.functions.off(DevToolsMessagingEvents.TIMELINE_EVENT_UPDATED, onTimelineEventUpdated)
})
defineExpose({
clear() {
eventList.value = []
groupList.value.clear()
},
})
</script>

<template>
Expand Down
26 changes: 23 additions & 3 deletions packages/client/src/pages/timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
} from '@vue/devtools-core'
import { Pane, Splitpanes } from 'splitpanes'
const timelineRef = ref()
// responsive layout
const splitpanesRef = ref<HTMLDivElement>()
const splitpanesReady = ref(false)
Expand All @@ -32,20 +34,38 @@ watchEffect(() => {
function toggleApp(id: string) {
rpc.value.toggleApp(id).then(() => {
clearTimelineEvents()
})
}
// #endregion
const activeTimelineLayer = 'component-event'
const activeTimelineLayer = ref('component-event')
const timelineLayers = [
{
label: 'Mouse',
id: 'mouse',
},
{
label: 'Keyboard',
id: 'keyboard',
},
{
label: 'Component events',
id: 'component-event',
},
{
label: 'Performance',
id: 'performance',
},
]
function toggleTimelineLayer(id: string) {
function clearTimelineEvents() {
timelineRef.value?.clear()
}
function toggleTimelineLayer() {
clearTimelineEvents()
}
</script>

Expand All @@ -66,7 +86,7 @@ function toggleTimelineLayer(id: string) {
</Pane>
<Pane relative h-full size="65">
<div class="h-full flex flex-col p2">
<Timeline :layer-ids="['component-event']" :header-visible="false" doc-link="" />
<Timeline ref="timelineRef" :layer-ids="[activeTimelineLayer]" :header-visible="false" doc-link="" />
</div>
</Pane>
</Splitpanes>
Expand Down
1 change: 1 addition & 0 deletions packages/devtools-kit/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export function createAppRecord(app: VueAppInstance['appContext']['app']): AppRe
id,
name,
instanceMap: new Map(),
perfGroupIds: new Map(),
rootInstance,
}

Expand Down
42 changes: 3 additions & 39 deletions packages/devtools-kit/src/core/plugin/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { debounce } from 'perfect-debounce'
import { getInstanceState } from '../../core/component/state'
import { editState } from '../../core/component/state/editor'
import { ComponentWalker } from '../../core/component/tree/walker'
import { getAppRecord, getComponentId, getComponentInstance, getInstanceName } from '../../core/component/utils'
import { getAppRecord, getComponentId, getComponentInstance } from '../../core/component/utils'
import { activeAppRecord, devtoolsContext, devtoolsState, DevToolsV6PluginAPIHookKeys } from '../../ctx'
import { hook } from '../../hook'
import { setupBuiltinTimelineLayers } from '../timeline'
import { exposeInstanceToWindow } from '../vm'

const INSPECTOR_ID = 'components'
const COMPONENT_EVENT_LAYER_ID = 'component-event'

export function createComponentsDevToolsPlugin(app: App): [PluginDescriptor, PluginSetupFunction] {
const descriptor: PluginDescriptor = {
Expand All @@ -25,11 +25,7 @@ export function createComponentsDevToolsPlugin(app: App): [PluginDescriptor, Plu
treeFilterPlaceholder: 'Search components',
})

api.addTimelineLayer({
id: COMPONENT_EVENT_LAYER_ID,
label: 'Component events',
color: 0x4FC08D,
})
setupBuiltinTimelineLayers(api)

api.on.getInspectorTree(async (payload) => {
if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
Expand Down Expand Up @@ -89,38 +85,6 @@ export function createComponentsDevToolsPlugin(app: App): [PluginDescriptor, Plu
api.sendInspectorState(INSPECTOR_ID)
}, 120)

hook.on.componentEmit(async (app, instance, event, params) => {
const appRecord = await getAppRecord(app)

if (!appRecord)
return

const componentId = `${appRecord.id}:${instance.uid}`
const componentName = getInstanceName(instance) || 'Unknown Component'

api.addTimelineEvent({
layerId: COMPONENT_EVENT_LAYER_ID,
event: {
time: Date.now(),
data: {
component: {
_custom: {
type: 'component-definition',
display: componentName,
},
},
event,
params,
},
title: event,
subtitle: `by ${componentName}`,
meta: {
componentId,
},
},
})
})

const componentAddedCleanup = hook.on.componentAdded(async (app, uid, parentUid, component) => {
if (devtoolsState.highPerfModeEnabled)
return
Expand Down
127 changes: 127 additions & 0 deletions packages/devtools-kit/src/core/timeline/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import type { DevToolsV6PluginAPI } from '../../api/v6'
import { isBrowser } from '@vue/devtools-shared'
import { getAppRecord, getInstanceName } from '../../core/component/utils'
import { hook } from '../../hook'
import { PERFORMANCE_EVENT_LAYER_ID, performanceMarkEnd, performanceMarkStart } from './perf'

const COMPONENT_EVENT_LAYER_ID = 'component-event'

export function setupBuiltinTimelineLayers(api: DevToolsV6PluginAPI) {
if (!isBrowser)
return

// Mouse events timeline layer

api.addTimelineLayer({
id: 'mouse',
label: 'Mouse',
color: 0xA451AF,
})

;(['mousedown', 'mouseup', 'click', 'dblclick'] as const).forEach((eventType) => {
window.addEventListener(eventType, async (event: MouseEvent) => {
await api.addTimelineEvent({
layerId: 'mouse',
event: {
time: Date.now(),
data: {
type: eventType,
x: event.clientX,
y: event.clientY,
},
title: eventType,
},
})
}, {
capture: true,
passive: true,
})
})

// Keyboard events timeline layer

api.addTimelineLayer({
id: 'keyboard',
label: 'Keyboard',
color: 0x8151AF,
})

;(['keyup', 'keydown', 'keypress'] as const).forEach((eventType) => {
window.addEventListener(eventType, async (event: KeyboardEvent) => {
await api.addTimelineEvent({
layerId: 'keyboard',
event: {
time: Date.now(),
data: {
type: eventType,
key: event.key,
ctrlKey: event.ctrlKey,
shiftKey: event.shiftKey,
altKey: event.altKey,
metaKey: event.metaKey,
},
title: event.key,
},
})
}, {
capture: true,
passive: true,
})
})

// Component events timeline layer

api.addTimelineLayer({
id: COMPONENT_EVENT_LAYER_ID,
label: 'Component events',
color: 0x4FC08D,
})

hook.on.componentEmit(async (app, instance, event, params) => {
const appRecord = await getAppRecord(app)

if (!appRecord)
return

const componentId = `${appRecord.id}:${instance.uid}`
const componentName = getInstanceName(instance) || 'Unknown Component'

api.addTimelineEvent({
layerId: COMPONENT_EVENT_LAYER_ID,
event: {
time: Date.now(),
data: {
component: {
_custom: {
type: 'component-definition',
display: componentName,
},
},
event,
params,
},
title: event,
subtitle: `by ${componentName}`,
meta: {
componentId,
},
},
})
})

// Performance timeline layer

api.addTimelineLayer({
id: 'performance',
label: PERFORMANCE_EVENT_LAYER_ID,
color: 0x41B86A,
})

hook.on.perfStart((app, uid, vm, type, time) => {
performanceMarkStart(api, app, uid, vm, type, time)
})

hook.on.perfEnd((app, uid, vm, type, time) => {
performanceMarkEnd(api, app, uid, vm, type, time)
})
}
97 changes: 97 additions & 0 deletions packages/devtools-kit/src/core/timeline/perf.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import type { App } from 'vue'
import type { DevToolsV6PluginAPI } from '../../api/v6'
import type { VueAppInstance } from '../../types'
import { getAppRecord, getInstanceName } from '../../core/component/utils'
import { devtoolsState } from '../../ctx/state'

type HookAppInstance = App & VueAppInstance
const markEndQueue = new Map<string, {
app: App
uid: number
instance: HookAppInstance
type: string
time: number
}>()
export const PERFORMANCE_EVENT_LAYER_ID = 'performance'

export async function performanceMarkStart(api: DevToolsV6PluginAPI, app: App, uid: number, vm: HookAppInstance, type: string, time: number) {
const appRecord = await getAppRecord(app)
if (!appRecord) {
return
}
const componentName = getInstanceName(vm) || 'Unknown Component'
const groupId = devtoolsState.perfUniqueGroupId++
const groupKey = `${uid}-${type}`
appRecord.perfGroupIds.set(groupKey, { groupId, time })
await api.addTimelineEvent({
layerId: PERFORMANCE_EVENT_LAYER_ID,
event: {
time: Date.now(),
data: {
component: componentName,
type,
measure: 'start',
},
title: componentName,
subtitle: type,
groupId,
},
})
if (markEndQueue.has(groupKey)) {
const {
app,
uid,
instance,
type,
time,
} = markEndQueue.get(groupKey)!
markEndQueue.delete(groupKey)
await performanceMarkEnd(
api,
app,
uid,
instance,
type,
time,
)
}
}

export function performanceMarkEnd(api: DevToolsV6PluginAPI, app: App, uid: number, vm: HookAppInstance, type: string, time: number) {
const appRecord = getAppRecord(app)
if (!appRecord)
return

const componentName = getInstanceName(vm) || 'Unknown Component'
const groupKey = `${uid}-${type}`
const groupInfo = appRecord.perfGroupIds.get(groupKey)
if (groupInfo) {
const groupId = groupInfo.groupId
const startTime = groupInfo.time
const duration = time - startTime
api.addTimelineEvent({
layerId: PERFORMANCE_EVENT_LAYER_ID,
event: {
time: Date.now(),
data: {
component: componentName,
type,
measure: 'end',
duration: {
_custom: {
type: 'Duration',
value: duration,
display: `${duration} ms`,
},
},
},
title: componentName,
subtitle: type,
groupId,
},
})
}
else {
markEndQueue.set(groupKey, { app, uid, instance: vm, type, time })
}
}
2 changes: 2 additions & 0 deletions packages/devtools-kit/src/ctx/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface DevToolsState {
devtoolsClientDetected: {
[key: string]: boolean
}
perfUniqueGroupId: number
}

global.__VUE_DEVTOOLS_KIT_APP_RECORDS__ ??= []
Expand All @@ -38,6 +39,7 @@ function initStateFactory() {
commands: [],
highPerfModeEnabled: true,
devtoolsClientDetected: {},
perfUniqueGroupId: 0,
}
}
global[STATE_KEY] ??= initStateFactory()
Expand Down
Loading

0 comments on commit 8acab1d

Please sign in to comment.