fix(compiler-ssr): fix wrong attrs fallthrough on non-single-root v-if branches
fix #5140
This commit is contained in:
parent
e8ceac7a11
commit
516bc548fc
@ -68,7 +68,7 @@ export interface DirectiveTransformResult {
|
|||||||
ssrTagParts?: TemplateLiteral['elements']
|
ssrTagParts?: TemplateLiteral['elements']
|
||||||
}
|
}
|
||||||
|
|
||||||
// A structural directive transform is a technically a NodeTransform;
|
// A structural directive transform is technically also a NodeTransform;
|
||||||
// Only v-if and v-for fall into this category.
|
// Only v-if and v-for fall into this category.
|
||||||
export type StructuralDirectiveTransform = (
|
export type StructuralDirectiveTransform = (
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
|
@ -306,27 +306,6 @@ describe('ssr: components', () => {
|
|||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should inject attrs if root with coomments', () => {
|
|
||||||
expect(compile(`<!--root--><transition><div/></transition>`).code)
|
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
|
||||||
|
|
||||||
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
|
||||||
_push(\`<!--[--><!--root--><div\${_ssrRenderAttrs(_attrs)}></div><!--]-->\`)
|
|
||||||
}"
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should not inject attrs if not root', () => {
|
|
||||||
expect(compile(`<div/><transition><div/></transition>`).code)
|
|
||||||
.toMatchInlineSnapshot(`
|
|
||||||
"
|
|
||||||
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
|
||||||
_push(\`<!--[--><div></div><div></div><!--]-->\`)
|
|
||||||
}"
|
|
||||||
`)
|
|
||||||
})
|
|
||||||
|
|
||||||
// #5352
|
// #5352
|
||||||
test('should push marker string if is slot root', () => {
|
test('should push marker string if is slot root', () => {
|
||||||
expect(
|
expect(
|
||||||
|
60
packages/compiler-ssr/__tests__/ssrFallthroughAttrs.spec.ts
Normal file
60
packages/compiler-ssr/__tests__/ssrFallthroughAttrs.spec.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { compile } from '../src'
|
||||||
|
|
||||||
|
describe('ssr: attrs fallthrough', () => {
|
||||||
|
test('basic', () => {
|
||||||
|
expect(compile(`<div/>`).code).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('with comments', () => {
|
||||||
|
expect(compile(`<!--!--><div/>`).code).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<!--[--><!--!--><div\${_ssrRenderAttrs(_attrs)}></div><!--]-->\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// #5140
|
||||||
|
test('should not inject to non-single-root if branches', () => {
|
||||||
|
expect(compile(`<div v-if="true"/><div/>`).code).toMatchInlineSnapshot(`
|
||||||
|
"
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<!--[-->\`)
|
||||||
|
if (true) {
|
||||||
|
_push(\`<div></div>\`)
|
||||||
|
} else {
|
||||||
|
_push(\`<!---->\`)
|
||||||
|
}
|
||||||
|
_push(\`<div></div><!--]-->\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fallthrough component content (root with coomments)', () => {
|
||||||
|
expect(compile(`<!--root--><transition><div/></transition>`).code)
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<!--[--><!--root--><div\${_ssrRenderAttrs(_attrs)}></div><!--]-->\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not inject to fallthrough component content if not root', () => {
|
||||||
|
expect(compile(`<div/><transition><div/></transition>`).code)
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<!--[--><div></div><div></div><!--]-->\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
})
|
@ -46,6 +46,25 @@ export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.type === NodeTypes.IF_BRANCH && hasSingleChild(node)) {
|
if (node.type === NodeTypes.IF_BRANCH && hasSingleChild(node)) {
|
||||||
|
// detect cases where the parent v-if is not the only root level node
|
||||||
|
let hasEncounteredIf = false
|
||||||
|
for (const c of filterChild(parent)) {
|
||||||
|
if (
|
||||||
|
c.type === NodeTypes.IF ||
|
||||||
|
(c.type === NodeTypes.ELEMENT && findDir(c, 'if'))
|
||||||
|
) {
|
||||||
|
// multiple root v-if
|
||||||
|
if (hasEncounteredIf) return
|
||||||
|
hasEncounteredIf = true
|
||||||
|
} else if (
|
||||||
|
// node before v-if
|
||||||
|
!hasEncounteredIf ||
|
||||||
|
// non else nodes
|
||||||
|
!(c.type === NodeTypes.ELEMENT && findDir(c, /else/, true))
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
injectFallthroughAttrs(node.children[0])
|
injectFallthroughAttrs(node.children[0])
|
||||||
} else if (hasSingleChild(parent)) {
|
} else if (hasSingleChild(parent)) {
|
||||||
injectFallthroughAttrs(node)
|
injectFallthroughAttrs(node)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user