From 152b0e34144ae0905860e3f909135e7f7aab8d2d Mon Sep 17 00:00:00 2001 From: Fan Pei Date: Sun, 25 Feb 2024 18:42:06 +0900 Subject: [PATCH 1/4] fix: Register module when new module added --- packages/devtools-kit/src/api/plugin.ts | 47 ++++++++++--------- .../devtools-kit/src/core/app-record/index.ts | 2 +- packages/devtools-kit/src/state/state.ts | 3 +- packages/devtools-kit/src/types/state.ts | 3 +- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/devtools-kit/src/api/plugin.ts b/packages/devtools-kit/src/api/plugin.ts index 21884e159..c79d28af0 100644 --- a/packages/devtools-kit/src/api/plugin.ts +++ b/packages/devtools-kit/src/api/plugin.ts @@ -1,4 +1,5 @@ import type { App } from 'vue' +import { toRaw, watch } from 'vue' import { PluginDescriptor, PluginSetupFunction } from '../types' import { devtoolsAppRecords, devtoolsState } from '../state' import { hook } from '../hook' @@ -6,7 +7,7 @@ import { getRouterDevToolsId } from '../core/router' import type { DevToolsPluginApi } from './api' export function collectDevToolsPlugin(pluginDescriptor: PluginDescriptor, setupFn: PluginSetupFunction) { - devtoolsState.pluginBuffer.push([pluginDescriptor, setupFn]) + devtoolsState.pluginBuffer.value.push([pluginDescriptor, setupFn]) } export function setupDevToolsPlugin(pluginDescriptor: PluginDescriptor, setupFn: PluginSetupFunction) { @@ -14,28 +15,32 @@ export function setupDevToolsPlugin(pluginDescriptor: PluginDescriptor, setupFn: } export function registerPlugin(app: App, api: DevToolsPluginApi) { - const plugins = devtoolsState.pluginBuffer.filter(([plugin]) => plugin.app === app) - plugins.forEach(async ([plugin, setupFn]) => { - if (plugin.packageName === 'vue-query') { - /** - * Skip it for now because plugin api doesn't support vue-query devtools plugin: - * https://github.com/TanStack/query/blob/main/packages/vue-query/src/devtools/devtools.ts - * @TODO: Need to discuss if we should be full compatible with the old devtools plugin api. - */ - return - } + watch(() => devtoolsState.pluginBuffer.value.length, (_, oldVal) => { + const pluginDiffs = devtoolsState.pluginBuffer.value.slice((oldVal || 1) - 1).filter(([plugin]) => toRaw(plugin).app === app) + pluginDiffs.forEach(([plugin, setupFn]) => { + if (plugin.packageName === 'vue-query') { + /** + * Skip it for now because plugin api doesn't support vue-query devtools plugin: + * https://github.com/TanStack/query/blob/main/packages/vue-query/src/devtools/devtools.ts + * @TODO: Need to discuss if we should be full compatible with the old devtools plugin api. + */ + return + } - // edge case for router plugin - if (plugin.packageName === 'vue-router') { - const id = getRouterDevToolsId(`${plugin.id}`) - if (plugin.app === app) { - devtoolsAppRecords.value = devtoolsAppRecords.value.map(item => ({ - ...item, - routerId: id, - })) + // edge case for router plugin + if (plugin.packageName === 'vue-router') { + const id = getRouterDevToolsId(`${plugin.id}`) + if (plugin.app === app) { + devtoolsAppRecords.value = devtoolsAppRecords.value.map(item => ({ + ...item, + routerId: id, + })) + } } - } - setupFn(api) + setupFn(api) + }) + }, { + immediate: true, }) devtoolsAppRecords.value = devtoolsAppRecords.value.map((record) => { diff --git a/packages/devtools-kit/src/core/app-record/index.ts b/packages/devtools-kit/src/core/app-record/index.ts index 300018648..b2e4c5d4b 100644 --- a/packages/devtools-kit/src/core/app-record/index.ts +++ b/packages/devtools-kit/src/core/app-record/index.ts @@ -75,7 +75,7 @@ export async function toggleActiveAppRecord(id: string) { devtoolsContext.clear() const appRecord = devtoolsAppRecords.value.find(record => record.id === id) if (appRecord) { - devtoolsState.pluginBuffer = devtoolsState.pluginBuffer.filter(([plugin]) => plugin.id !== 'components') + devtoolsState.pluginBuffer.value = devtoolsState.pluginBuffer.value.filter(([plugin]) => plugin.id !== 'components') const api = new DevToolsPluginApi() appRecord.api = api setActiveAppRecord(appRecord) diff --git a/packages/devtools-kit/src/state/state.ts b/packages/devtools-kit/src/state/state.ts index 135ffa968..3e2b19975 100644 --- a/packages/devtools-kit/src/state/state.ts +++ b/packages/devtools-kit/src/state/state.ts @@ -1,3 +1,4 @@ +import { ref } from 'vue' import { target as global } from '@vue/devtools-shared' import { debounce } from 'perfect-debounce' import type { DevToolsState } from '../types' @@ -14,7 +15,7 @@ function initStateFactory() { appRecords: [], activeAppRecord: null, selectedComponentId: null, - pluginBuffer: [], + pluginBuffer: ref([]), tabs: [], commands: [], vitePluginDetected: false, diff --git a/packages/devtools-kit/src/types/state.ts b/packages/devtools-kit/src/types/state.ts index 9f5ea35ff..1f53478a7 100644 --- a/packages/devtools-kit/src/types/state.ts +++ b/packages/devtools-kit/src/types/state.ts @@ -1,3 +1,4 @@ +import type { Ref } from 'vue' import type { CustomCommand } from '../core/custom-command' import type { CustomTab } from '../core/custom-tab' import type { AppRecord, PluginDescriptor, PluginSetupFunction } from './app' @@ -9,7 +10,7 @@ export interface DevToolsState { appRecords: AppRecord[] activeAppRecord: AppRecord | null selectedComponentId: string | null - pluginBuffer: [PluginDescriptor, PluginSetupFunction][] + pluginBuffer: Ref<[PluginDescriptor, PluginSetupFunction][]> tabs: CustomTab[] commands: CustomCommand[] activeAppRecordId: string | null From f6401c1b1eb9fcf6a7b91557430089e76d7a80f6 Mon Sep 17 00:00:00 2001 From: Fan Pei Date: Sun, 25 Feb 2024 18:42:47 +0900 Subject: [PATCH 2/4] feat: Add test case --- packages/devtools-kit/__tests__/api/plugin.test.ts | 2 +- packages/playground/basic/src/App.vue | 6 ++++++ packages/playground/basic/src/pages/Hey.vue | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/devtools-kit/__tests__/api/plugin.test.ts b/packages/devtools-kit/__tests__/api/plugin.test.ts index 6bbcd980a..50a390fb5 100644 --- a/packages/devtools-kit/__tests__/api/plugin.test.ts +++ b/packages/devtools-kit/__tests__/api/plugin.test.ts @@ -31,7 +31,7 @@ describe('vue plugin', () => { await new Promise((resolve) => { devtools.hook.on.vueAppInit(() => { const [appRecord] = devtoolsAppRecords.value - expect(devtools.state.pluginBuffer.findIndex(([descriptor]) => descriptor.packageName === 'vue-router')).toBeGreaterThanOrEqual(0) + expect(devtools.state.pluginBuffer.value.findIndex(([descriptor]) => descriptor.packageName === 'vue-router')).toBeGreaterThanOrEqual(0) expect(appRecord.moduleDetectives?.vueRouter).toBe(true) resolve() }) diff --git a/packages/playground/basic/src/App.vue b/packages/playground/basic/src/App.vue index ee9867a25..07eb3ee79 100644 --- a/packages/playground/basic/src/App.vue +++ b/packages/playground/basic/src/App.vue @@ -20,6 +20,12 @@ /hello + | + + + /hey/123123 + + diff --git a/packages/playground/basic/src/pages/Hey.vue b/packages/playground/basic/src/pages/Hey.vue index 8ae88e760..2cfec9540 100644 --- a/packages/playground/basic/src/pages/Hey.vue +++ b/packages/playground/basic/src/pages/Hey.vue @@ -1,10 +1,14 @@ From a5c16889dfff5811912ee6bcc983318137a05e66 Mon Sep 17 00:00:00 2001 From: Fan Pei Date: Mon, 26 Feb 2024 17:42:23 +0900 Subject: [PATCH 3/4] fix: Revert using ref/watch --- packages/devtools-kit/__tests__/api/plugin.test.ts | 2 +- packages/devtools-kit/src/core/app-record/index.ts | 2 +- packages/devtools-kit/src/state/state.ts | 3 +-- packages/devtools-kit/src/types/state.ts | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/devtools-kit/__tests__/api/plugin.test.ts b/packages/devtools-kit/__tests__/api/plugin.test.ts index 50a390fb5..6bbcd980a 100644 --- a/packages/devtools-kit/__tests__/api/plugin.test.ts +++ b/packages/devtools-kit/__tests__/api/plugin.test.ts @@ -31,7 +31,7 @@ describe('vue plugin', () => { await new Promise((resolve) => { devtools.hook.on.vueAppInit(() => { const [appRecord] = devtoolsAppRecords.value - expect(devtools.state.pluginBuffer.value.findIndex(([descriptor]) => descriptor.packageName === 'vue-router')).toBeGreaterThanOrEqual(0) + expect(devtools.state.pluginBuffer.findIndex(([descriptor]) => descriptor.packageName === 'vue-router')).toBeGreaterThanOrEqual(0) expect(appRecord.moduleDetectives?.vueRouter).toBe(true) resolve() }) diff --git a/packages/devtools-kit/src/core/app-record/index.ts b/packages/devtools-kit/src/core/app-record/index.ts index b2e4c5d4b..300018648 100644 --- a/packages/devtools-kit/src/core/app-record/index.ts +++ b/packages/devtools-kit/src/core/app-record/index.ts @@ -75,7 +75,7 @@ export async function toggleActiveAppRecord(id: string) { devtoolsContext.clear() const appRecord = devtoolsAppRecords.value.find(record => record.id === id) if (appRecord) { - devtoolsState.pluginBuffer.value = devtoolsState.pluginBuffer.value.filter(([plugin]) => plugin.id !== 'components') + devtoolsState.pluginBuffer = devtoolsState.pluginBuffer.filter(([plugin]) => plugin.id !== 'components') const api = new DevToolsPluginApi() appRecord.api = api setActiveAppRecord(appRecord) diff --git a/packages/devtools-kit/src/state/state.ts b/packages/devtools-kit/src/state/state.ts index 3e2b19975..135ffa968 100644 --- a/packages/devtools-kit/src/state/state.ts +++ b/packages/devtools-kit/src/state/state.ts @@ -1,4 +1,3 @@ -import { ref } from 'vue' import { target as global } from '@vue/devtools-shared' import { debounce } from 'perfect-debounce' import type { DevToolsState } from '../types' @@ -15,7 +14,7 @@ function initStateFactory() { appRecords: [], activeAppRecord: null, selectedComponentId: null, - pluginBuffer: ref([]), + pluginBuffer: [], tabs: [], commands: [], vitePluginDetected: false, diff --git a/packages/devtools-kit/src/types/state.ts b/packages/devtools-kit/src/types/state.ts index 1f53478a7..9f5ea35ff 100644 --- a/packages/devtools-kit/src/types/state.ts +++ b/packages/devtools-kit/src/types/state.ts @@ -1,4 +1,3 @@ -import type { Ref } from 'vue' import type { CustomCommand } from '../core/custom-command' import type { CustomTab } from '../core/custom-tab' import type { AppRecord, PluginDescriptor, PluginSetupFunction } from './app' @@ -10,7 +9,7 @@ export interface DevToolsState { appRecords: AppRecord[] activeAppRecord: AppRecord | null selectedComponentId: string | null - pluginBuffer: Ref<[PluginDescriptor, PluginSetupFunction][]> + pluginBuffer: [PluginDescriptor, PluginSetupFunction][] tabs: CustomTab[] commands: CustomCommand[] activeAppRecordId: string | null From 6f9a2fba3302300f57680ce522568c8d5487340d Mon Sep 17 00:00:00 2001 From: Fan Pei Date: Mon, 26 Feb 2024 17:57:18 +0900 Subject: [PATCH 4/4] feat: Register plugin when plugin is added --- packages/devtools-kit/src/api/plugin.ts | 57 ++++++++++++------------- packages/devtools-kit/src/core/index.ts | 10 ++++- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/packages/devtools-kit/src/api/plugin.ts b/packages/devtools-kit/src/api/plugin.ts index c79d28af0..b237ee309 100644 --- a/packages/devtools-kit/src/api/plugin.ts +++ b/packages/devtools-kit/src/api/plugin.ts @@ -1,5 +1,4 @@ import type { App } from 'vue' -import { toRaw, watch } from 'vue' import { PluginDescriptor, PluginSetupFunction } from '../types' import { devtoolsAppRecords, devtoolsState } from '../state' import { hook } from '../hook' @@ -7,42 +6,42 @@ import { getRouterDevToolsId } from '../core/router' import type { DevToolsPluginApi } from './api' export function collectDevToolsPlugin(pluginDescriptor: PluginDescriptor, setupFn: PluginSetupFunction) { - devtoolsState.pluginBuffer.value.push([pluginDescriptor, setupFn]) + devtoolsState.pluginBuffer.push([pluginDescriptor, setupFn]) } export function setupDevToolsPlugin(pluginDescriptor: PluginDescriptor, setupFn: PluginSetupFunction) { return hook.setupDevToolsPlugin(pluginDescriptor, setupFn) } -export function registerPlugin(app: App, api: DevToolsPluginApi) { - watch(() => devtoolsState.pluginBuffer.value.length, (_, oldVal) => { - const pluginDiffs = devtoolsState.pluginBuffer.value.slice((oldVal || 1) - 1).filter(([plugin]) => toRaw(plugin).app === app) - pluginDiffs.forEach(([plugin, setupFn]) => { - if (plugin.packageName === 'vue-query') { - /** - * Skip it for now because plugin api doesn't support vue-query devtools plugin: - * https://github.com/TanStack/query/blob/main/packages/vue-query/src/devtools/devtools.ts - * @TODO: Need to discuss if we should be full compatible with the old devtools plugin api. - */ - return - } +export function setupExternalPlugin(plugin: [PluginDescriptor, PluginSetupFunction], app: App, api: DevToolsPluginApi) { + const [pluginDescriptor, setupFn] = plugin + if (pluginDescriptor.app !== app) + return - // edge case for router plugin - if (plugin.packageName === 'vue-router') { - const id = getRouterDevToolsId(`${plugin.id}`) - if (plugin.app === app) { - devtoolsAppRecords.value = devtoolsAppRecords.value.map(item => ({ - ...item, - routerId: id, - })) - } - } - setupFn(api) - }) - }, { - immediate: true, - }) + if (pluginDescriptor.packageName === 'vue-query') { + /** + * Skip it for now because plugin api doesn't support vue-query devtools plugin: + * https://github.com/TanStack/query/blob/main/packages/vue-query/src/devtools/devtools.ts + * @TODO: Need to discuss if we should be full compatible with the old devtools plugin api. + */ + return + } + + // edge case for router plugin + if (pluginDescriptor.packageName === 'vue-router') { + const id = getRouterDevToolsId(`${pluginDescriptor.id}`) + if (pluginDescriptor.app === app) { + devtoolsAppRecords.value = devtoolsAppRecords.value.map(item => ({ + ...item, + routerId: id, + })) + } + } + setupFn(api) +} +export function registerPlugin(app: App, api: DevToolsPluginApi) { + devtoolsState.pluginBuffer.forEach(plugin => setupExternalPlugin(plugin, app, api)) devtoolsAppRecords.value = devtoolsAppRecords.value.map((record) => { const globalProperties = record.app?.config?.globalProperties if (!globalProperties) diff --git a/packages/devtools-kit/src/core/index.ts b/packages/devtools-kit/src/core/index.ts index cf936fdd1..fe829ddc4 100644 --- a/packages/devtools-kit/src/core/index.ts +++ b/packages/devtools-kit/src/core/index.ts @@ -2,7 +2,7 @@ import { target } from '@vue/devtools-shared' import { createDevToolsHook, devtoolsHooks, hook, subscribeDevToolsHook } from '../hook' import { DevToolsHooks } from '../types' import { devtoolsAppRecords, devtoolsState, getDevToolsEnv } from '../state' -import { DevToolsEvents, DevToolsPluginApi, apiHooks, collectDevToolsPlugin } from '../api' +import { DevToolsEvents, DevToolsPluginApi, apiHooks, collectDevToolsPlugin, setupExternalPlugin } from '../api' import { createAppRecord, setActiveAppRecord } from './app-record' export function initDevTools() { @@ -22,7 +22,13 @@ export function initDevTools() { target.__VUE_DEVTOOLS_GLOBAL_HOOK__ = createDevToolsHook() // setup old devtools plugin (compatible with pinia, router, etc) - hook.on.setupDevtoolsPlugin(collectDevToolsPlugin) + hook.on.setupDevtoolsPlugin((pluginDescriptor, setupFn) => { + collectDevToolsPlugin(pluginDescriptor, setupFn) + const { app, api } = devtoolsAppRecords.active || {} + if (!app || !api) + return + setupExternalPlugin([pluginDescriptor, setupFn], app, api) + }) // create app record hook.on.vueAppInit(async (app, version) => {