From 38a6b8dfa0a36853e718d5715c1e47e9d17234fb Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 21 Sep 2021 11:09:24 -0400 Subject: [PATCH 1/5] fix(devtools): fix devtools detection in prod --- packages/runtime-core/src/devtools.ts | 2 ++ packages/runtime-core/src/renderer.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/devtools.ts b/packages/runtime-core/src/devtools.ts index 4c52388524e..33d9841c605 100644 --- a/packages/runtime-core/src/devtools.ts +++ b/packages/runtime-core/src/devtools.ts @@ -21,6 +21,7 @@ const enum DevtoolsHooks { } interface DevtoolsHook { + enabled?: boolean emit: (event: string, ...payload: any[]) => void on: (event: string, handler: Function) => void once: (event: string, handler: Function) => void @@ -32,6 +33,7 @@ export let devtools: DevtoolsHook export function setDevtoolsHook(hook: DevtoolsHook) { devtools = hook + if (devtools) devtools.enabled = true } export function devtoolsInitApp(app: App, version: string) { diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 76848cb52f3..24c600a9a67 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -340,9 +340,9 @@ function baseCreateRenderer( initFeatureFlags() } + const target = getGlobalThis() + target.__VUE__ = true if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { - const target = getGlobalThis() - target.__VUE__ = true setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__) } From 225d109cc7a2b4f065a3c246df9affa3f979d103 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 21 Sep 2021 18:04:10 +0200 Subject: [PATCH 2/5] feat: implement devtools hook buffer --- packages/runtime-core/src/devtools.ts | 47 +++++++++++++++------------ packages/runtime-core/src/renderer.ts | 2 +- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/packages/runtime-core/src/devtools.ts b/packages/runtime-core/src/devtools.ts index 33d9841c605..b26fae85d06 100644 --- a/packages/runtime-core/src/devtools.ts +++ b/packages/runtime-core/src/devtools.ts @@ -31,15 +31,33 @@ interface DevtoolsHook { export let devtools: DevtoolsHook -export function setDevtoolsHook(hook: DevtoolsHook) { +let buffer: { event: string; args: any[] }[] = [] + +function emit(event: string, ...args: any[]) { + if (devtools) { + devtools.emit(event, ...args) + } else { + buffer.push({ event, args }) + } +} + +export function setDevtoolsHook(hook: DevtoolsHook, target: any) { devtools = hook - if (devtools) devtools.enabled = true + if (devtools) { + devtools.enabled = true + buffer.forEach(({ event, args }) => devtools.emit(event, ...args)) + buffer = [] + } else { + const replay = (target.__VUE_DEVTOOLS_HOOK_REPLAY__ = + target.__VUE_DEVTOOLS_HOOK_REPLAY__ || []) + replay.push((newHook: DevtoolsHook) => { + setDevtoolsHook(newHook, target) + }) + } } export function devtoolsInitApp(app: App, version: string) { - // TODO queue if devtools is undefined - if (!devtools) return - devtools.emit(DevtoolsHooks.APP_INIT, app, version, { + emit(DevtoolsHooks.APP_INIT, app, version, { Fragment, Text, Comment, @@ -48,8 +66,7 @@ export function devtoolsInitApp(app: App, version: string) { } export function devtoolsUnmountApp(app: App) { - if (!devtools) return - devtools.emit(DevtoolsHooks.APP_UNMOUNT, app) + emit(DevtoolsHooks.APP_UNMOUNT, app) } export const devtoolsComponentAdded = /*#__PURE__*/ createDevtoolsComponentHook( @@ -64,8 +81,7 @@ export const devtoolsComponentRemoved = function createDevtoolsComponentHook(hook: DevtoolsHooks) { return (component: ComponentInternalInstance) => { - if (!devtools) return - devtools.emit( + emit( hook, component.appContext.app, component.uid, @@ -85,15 +101,7 @@ export const devtoolsPerfEnd = /*#__PURE__*/ createDevtoolsPerformanceHook( function createDevtoolsPerformanceHook(hook: DevtoolsHooks) { return (component: ComponentInternalInstance, type: string, time: number) => { - if (!devtools) return - devtools.emit( - hook, - component.appContext.app, - component.uid, - component, - type, - time - ) + emit(hook, component.appContext.app, component.uid, component, type, time) } } @@ -102,8 +110,7 @@ export function devtoolsComponentEmit( event: string, params: any[] ) { - if (!devtools) return - devtools.emit( + emit( DevtoolsHooks.COMPONENT_EMIT, component.appContext.app, component, diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 24c600a9a67..e61e5421efc 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -343,7 +343,7 @@ function baseCreateRenderer( const target = getGlobalThis() target.__VUE__ = true if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { - setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__) + setDevtoolsHook(target.__VUE_DEVTOOLS_GLOBAL_HOOK__, target) } const { From cb4108b26634382062421c9e2b8d44fb1a8e8f31 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 21 Sep 2021 18:57:56 +0200 Subject: [PATCH 3/5] chore(playground): add devtools defaultSelectedAppId --- packages/sfc-playground/src/main.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/sfc-playground/src/main.ts b/packages/sfc-playground/src/main.ts index 1ef69e7d28f..e645bb2bd0f 100644 --- a/packages/sfc-playground/src/main.ts +++ b/packages/sfc-playground/src/main.ts @@ -2,4 +2,9 @@ import { createApp } from 'vue' import App from './App.vue' import '@vue/repl/style.css' +// @ts-expect-error Custom window property +window.VUE_DEVTOOLS_CONFIG = { + defaultSelectedAppId: 'id:repl' +} + createApp(App).mount('#app') From b9a93855c8fea14b86b111d6a8ea6de4853829f5 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 21 Sep 2021 19:02:45 +0200 Subject: [PATCH 4/5] chore(playground): enable devtools in production --- packages/sfc-playground/vite.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/sfc-playground/vite.config.ts b/packages/sfc-playground/vite.config.ts index 8fdff8ee8a2..6e5cdc450f6 100644 --- a/packages/sfc-playground/vite.config.ts +++ b/packages/sfc-playground/vite.config.ts @@ -9,7 +9,8 @@ const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7) export default defineConfig({ plugins: [vue(), copyVuePlugin()], define: { - __COMMIT__: JSON.stringify(commit) + __COMMIT__: JSON.stringify(commit), + __VUE_PROD_DEVTOOLS__: JSON.stringify(true) }, optimizeDeps: { exclude: ['@vue/repl'] From 390d368528fcfd1b4aad580a16851e092b7b0989 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Wed, 22 Sep 2021 12:43:55 +0200 Subject: [PATCH 5/5] test: fix appContext null --- packages/runtime-core/__tests__/helpers/renderSlot.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts b/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts index 9af91ce1c03..4e661c406e6 100644 --- a/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts +++ b/packages/runtime-core/__tests__/helpers/renderSlot.spec.ts @@ -47,7 +47,7 @@ describe('renderSlot', () => { return [createVNode('div', null, 'foo', PatchFlags.TEXT)] }, // mock instance - { type: {} } as any + { type: {}, appContext: {} } as any ) as Slot // manual invocation should not track