Skip to content

Commit

Permalink
wip: fix on component slot + v-if in ssr
Browse files Browse the repository at this point in the history
  • Loading branch information
edison1105 committed Jan 26, 2025
1 parent 46825ca commit 80b32bf
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 18 deletions.
8 changes: 6 additions & 2 deletions packages/compiler-core/src/transforms/vSkip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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(
Expand All @@ -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),
Expand Down
37 changes: 36 additions & 1 deletion packages/compiler-ssr/__tests__/ssrVSkip.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,49 @@ 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">
<span v-if="yes">default</span>
</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))
}
}"
`)
})

Expand Down
16 changes: 1 addition & 15 deletions packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
}
14 changes: 14 additions & 0 deletions packages/shared/src/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

0 comments on commit 80b32bf

Please sign in to comment.