From f44087e171282cb77f1e23d86516a527e4c5804b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20L=C3=BCnborg?= Date: Tue, 12 Apr 2022 09:54:03 +0200 Subject: [PATCH] fix(runtime-core): ensure custom directive instance properly exposes properties on closed instances. (#5022) fix #5018 --- .../runtime-core/__tests__/directives.spec.ts | 28 ++++++++++++++++++- packages/runtime-core/src/directives.ts | 6 ++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/directives.spec.ts b/packages/runtime-core/__tests__/directives.spec.ts index 02d24711804..c2a183b12ef 100644 --- a/packages/runtime-core/__tests__/directives.spec.ts +++ b/packages/runtime-core/__tests__/directives.spec.ts @@ -7,7 +7,8 @@ import { DirectiveHook, VNode, DirectiveBinding, - nextTick + nextTick, + defineComponent } from '@vue/runtime-test' import { currentInstance, ComponentInternalInstance } from '../src/component' @@ -395,4 +396,29 @@ describe('directives', () => { expect(beforeUpdate).toHaveBeenCalledTimes(1) expect(count.value).toBe(1) }) + + test('should receive exposeProxy for closed instances', async () => { + let res: string + const App = defineComponent({ + setup(_, { expose }) { + expose({ + msg: 'Test' + }) + + return () => + withDirectives(h('p', 'Lore Ipsum'), [ + [ + { + mounted(el, { instance }) { + res = (instance as any).msg as string + } + } + ] + ]) + } + }) + const root = nodeOps.createElement('div') + render(h(App), root) + expect(res!).toBe('Test') + }) }) diff --git a/packages/runtime-core/src/directives.ts b/packages/runtime-core/src/directives.ts index a3cf81dd0af..6f0eb4c2c0a 100644 --- a/packages/runtime-core/src/directives.ts +++ b/packages/runtime-core/src/directives.ts @@ -14,7 +14,7 @@ return withDirectives(h(comp), [ import { VNode } from './vnode' import { isFunction, EMPTY_OBJ, isBuiltInDirective } from '@vue/shared' import { warn } from './warning' -import { ComponentInternalInstance, Data } from './component' +import { ComponentInternalInstance, Data, getExposeProxy } from './component' import { currentRenderingInstance } from './componentRenderContext' import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling' import { ComponentPublicInstance } from './componentPublicInstance' @@ -89,7 +89,9 @@ export function withDirectives( __DEV__ && warn(`withDirectives can only be used inside render functions.`) return vnode } - const instance = internalInstance.proxy + const instance = + (getExposeProxy(internalInstance) as ComponentPublicInstance) || + internalInstance.proxy const bindings: DirectiveBinding[] = vnode.dirs || (vnode.dirs = []) for (let i = 0; i < directives.length; i++) { let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]