]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): directive binding.instance should respect exposed during ssr
authorEvan You <yyx990803@gmail.com>
Mon, 10 Jun 2024 09:46:59 +0000 (17:46 +0800)
committerEvan You <yyx990803@gmail.com>
Mon, 10 Jun 2024 09:46:59 +0000 (17:46 +0800)
close #7499
close #7502

packages/runtime-core/src/index.ts
packages/server-renderer/__tests__/ssrDirectives.spec.ts
packages/server-renderer/src/helpers/ssrGetDirectiveProps.ts

index d498728820669f7ee0280f46284a1e53dbc7e8fa..8adbe91ee17c82a591459340f79c1cff8430c8e9 100644 (file)
@@ -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,
 }
 
 /**
index d3ced89b3d2381113cd7a52893978c51465f5201..dfdebe971f55888229ccf155148a17863ab93799 100644 (file)
@@ -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(`<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')
+  })
 })
index 094d8564f8d262f3b75c8f2468728ef03ff25dae..877c01d36a81a1e2a8a4725f131165abe1da65fe 100644 (file)
@@ -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,