From df686abb4f0ac9d898e4fd93751e860f8cbbdbea Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 10 Jun 2024 17:46:59 +0800 Subject: [PATCH] fix(ssr): directive binding.instance should respect exposed during ssr close #7499 close #7502 --- packages/runtime-core/src/index.ts | 7 ++- .../__tests__/ssrDirectives.spec.ts | 43 +++++++++++++++++++ .../src/helpers/ssrGetDirectiveProps.ts | 8 +++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index d4987288206..8adbe91ee17 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -363,7 +363,11 @@ export { transformVNodeArgs } from './vnode' // **IMPORTANT** These APIs are exposed solely for @vue/server-renderer and may // change without notice between versions. User code should never rely on them. -import { createComponentInstance, setupComponent } from './component' +import { + createComponentInstance, + getComponentPublicInstance, + setupComponent, +} from './component' import { renderComponentRoot } from './componentRenderUtils' import { setCurrentRenderingInstance } from './componentRenderContext' import { isVNode, normalizeVNode } from './vnode' @@ -375,6 +379,7 @@ const _ssrUtils = { setCurrentRenderingInstance, isVNode, normalizeVNode, + getComponentPublicInstance, } /** diff --git a/packages/server-renderer/__tests__/ssrDirectives.spec.ts b/packages/server-renderer/__tests__/ssrDirectives.spec.ts index d3ced89b3d2..dfdebe971f5 100644 --- a/packages/server-renderer/__tests__/ssrDirectives.spec.ts +++ b/packages/server-renderer/__tests__/ssrDirectives.spec.ts @@ -2,7 +2,10 @@ import { renderToString } from '../src/renderToString' import { createApp, h, + mergeProps, + ref, resolveDirective, + unref, vModelCheckbox, vModelDynamic, vModelRadio, @@ -542,4 +545,44 @@ describe('ssr: directives', () => { ), ).toBe(`
`) }) + + // #7499 + test('custom directive w/ getSSRProps (expose)', async () => { + let exposeVars: null | string | undefined = null + const useTestDirective = () => ({ + vTest: { + getSSRProps({ instance }: any) { + if (instance) { + exposeVars = instance.x + } + return { id: exposeVars } + }, + }, + }) + const { vTest } = useTestDirective() + + const renderString = await renderToString( + createApp({ + setup(props, { expose }) { + const x = ref('foo') + expose({ x }) + const __returned__ = { useTestDirective, vTest, ref, x } + Object.defineProperty(__returned__, '__isScriptSetup', { + enumerable: false, + value: true, + }) + return __returned__ + }, + ssrRender(_ctx, _push, _parent, _attrs) { + _push( + ``, + ) + }, + }), + ) + expect(renderString).toBe(`
`) + expect(exposeVars).toBe('foo') + }) }) diff --git a/packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts b/packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts index 094d8564f8d..877c01d36a8 100644 --- a/packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts +++ b/packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts @@ -1,4 +1,8 @@ -import type { ComponentPublicInstance, Directive } from '@vue/runtime-core' +import { + type ComponentPublicInstance, + type Directive, + ssrUtils, +} from '@vue/runtime-core' export function ssrGetDirectiveProps( instance: ComponentPublicInstance, @@ -12,7 +16,7 @@ export function ssrGetDirectiveProps( dir.getSSRProps( { dir, - instance, + instance: ssrUtils.getComponentPublicInstance(instance.$), value, oldValue: undefined, arg,