]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: fix on component slot + v-if in ssr
authordaiwei <daiwei521@126.com>
Sun, 26 Jan 2025 08:02:53 +0000 (16:02 +0800)
committerdaiwei <daiwei521@126.com>
Sun, 26 Jan 2025 08:02:53 +0000 (16:02 +0800)
packages/compiler-core/src/transforms/vSkip.ts
packages/compiler-ssr/__tests__/ssrVSkip.spec.ts
packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
packages/shared/src/general.ts

index 3495a00b104eb3c0b2f8ec2a3fb59cdf93acbd82..b9e5bcf7de4febd7b1fdc9003846eb3d12a64bc2 100644 (file)
@@ -32,6 +32,7 @@ import {
 import { createCodegenNodeForBranch } from './vIf'
 import { validateBrowserExpression } from '../validateExpression'
 import { cloneLoc } from '../parser'
+import { clone } from '@vue/shared'
 
 export const transformSkip: NodeTransform = createStructuralDirectiveTransform(
   'skip',
@@ -134,7 +135,7 @@ export function processSkip(
       undefined,
       true,
     )
-    // find default slot if not has dynamic slots
+    // find default slot without slot props if not has dynamic slots
     if (!hasDynamicSlots && slots.type === NodeTypes.JS_OBJECT_EXPRESSION) {
       processAsSkipNode = true
       const prop = slots.properties.find(
@@ -145,7 +146,10 @@ export function processSkip(
           p.value.params === undefined,
       )
       if (prop) {
-        children = prop.value.returns as TemplateChildNode[]
+        const slotNode = prop.value.returns as TemplateChildNode[]
+        // clone the slot node to avoid mutating the original one, since it
+        // will be transformed again in ssr slot vnode fallback
+        children = context.inSSR ? clone(slotNode) : slotNode
       } else {
         context.onError(
           createCompilerError(ErrorCodes.X_V_SKIP_UNEXPECTED_SLOT, loc),
index 23ba0c7f04c4f2cff224ba8b16dddb0944aca7f6..2a177711bbc74f3f7684d62bd1f5cbc50d4c9c70 100644 (file)
@@ -368,7 +368,7 @@ describe('ssr: v-skip', () => {
     `)
   })
 
-  test.todo('on component with implicit default slot + v-if', () => {
+  test('on component with implicit default slot + v-if', () => {
     expect(
       compile(
         `<Comp v-skip="ok">
@@ -376,6 +376,41 @@ describe('ssr: v-skip', () => {
         </Comp>`,
       ).code,
     ).toMatchInlineSnapshot(`
+      "const { withCtx: _withCtx, resolveComponent: _resolveComponent, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = require("vue")
+      const { ssrRenderComponent: _ssrRenderComponent } = require("vue/server-renderer")
+
+      return function ssrRender(_ctx, _push, _parent, _attrs) {
+        const _component_Comp = _resolveComponent("Comp")
+
+        if (_ctx.ok) {
+          _push(\`<!--[-->\`)
+          if (_ctx.yes) {
+            _push(\`<span>default</span>\`)
+          } else {
+            _push(\`<!---->\`)
+          }
+          _push(\`<!--]-->\`)
+        } else {
+          _push(_ssrRenderComponent(_component_Comp, _attrs, {
+            default: _withCtx((_, _push, _parent, _scopeId) => {
+              if (_push) {
+                if (_ctx.yes) {
+                  _push(\`<span\${_scopeId}>default</span>\`)
+                } else {
+                  _push(\`<!---->\`)
+                }
+              } else {
+                return [
+                  (_ctx.yes)
+                    ? (_openBlock(), _createBlock("span", { key: 0 }, "default"))
+                    : _createCommentVNode("v-if", true)
+                ]
+              }
+            }),
+            _: 1 /* STABLE */
+          }, _parent))
+        }
+      }"
     `)
   })
 
index cad1ee8102897beab4c8990b99b43366c5d42655..867d61d96057180f862bbabf23ff088cc7afd0a2 100644 (file)
@@ -55,7 +55,7 @@ import {
   ssrProcessTransitionGroup,
   ssrTransformTransitionGroup,
 } from './ssrTransformTransitionGroup'
-import { extend, isArray, isObject, isPlainObject, isSymbol } from '@vue/shared'
+import { clone, extend, isObject, isSymbol } from '@vue/shared'
 import { buildSSRProps } from './ssrTransformElement'
 import {
   ssrProcessTransition,
@@ -370,17 +370,3 @@ function subTransform(
   //   node/client branches
   // - hoists are not enabled for the client branch here
 }
-
-function clone(v: any): any {
-  if (isArray(v)) {
-    return v.map(clone)
-  } else if (isPlainObject(v)) {
-    const res: any = {}
-    for (const key in v) {
-      res[key] = clone(v[key as keyof typeof v])
-    }
-    return res
-  } else {
-    return v
-  }
-}
index d5b5e0b942d691da65872cec8f63ccdd62d68f5f..ee8e98564db9fa91cf31899bd8a4b255cbe969b8 100644 (file)
@@ -217,3 +217,17 @@ export function genCacheKey(source: string, options: any): string {
     )
   )
 }
+
+export function clone(v: any): any {
+  if (isArray(v)) {
+    return v.map(clone)
+  } else if (isPlainObject(v)) {
+    const res: any = {}
+    for (const key in v) {
+      res[key] = clone(v[key as keyof typeof v])
+    }
+    return res
+  } else {
+    return v
+  }
+}