Skip to content

Commit

Permalink
fix(ssr): directive binding.instance should respect exposed during ssr
Browse files Browse the repository at this point in the history
close #7499
close #7502
  • Loading branch information
yyx990803 committed Jun 10, 2024
1 parent 9daf90e commit df686ab
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
7 changes: 6 additions & 1 deletion packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -375,6 +379,7 @@ const _ssrUtils = {
setCurrentRenderingInstance,
isVNode,
normalizeVNode,
getComponentPublicInstance,
}

/**
Expand Down
43 changes: 43 additions & 0 deletions packages/server-renderer/__tests__/ssrDirectives.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { renderToString } from '../src/renderToString'
import {
createApp,
h,
mergeProps,
ref,
resolveDirective,
unref,
vModelCheckbox,
vModelDynamic,
vModelRadio,
Expand Down Expand Up @@ -542,4 +545,44 @@ describe('ssr: directives', () => {
),
).toBe(`<div id="foo-arg-true"></div>`)
})

// #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(
`<div${ssrRenderAttrs(
mergeProps(_attrs!, ssrGetDirectiveProps(_ctx, unref(vTest))),
)}></div>`,
)
},
}),
)
expect(renderString).toBe(`<div id="foo"></div>`)
expect(exposeVars).toBe('foo')
})
})
8 changes: 6 additions & 2 deletions packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -12,7 +16,7 @@ export function ssrGetDirectiveProps(
dir.getSSRProps(
{
dir,
instance,
instance: ssrUtils.getComponentPublicInstance(instance.$),
value,
oldValue: undefined,
arg,
Expand Down

0 comments on commit df686ab

Please sign in to comment.