Skip to content

Commit

Permalink
fix(compiler-ssr): fix wrong attrs fallthrough on non-single-root v-i…
Browse files Browse the repository at this point in the history
…f branches

fix #5140
  • Loading branch information
yyx990803 committed May 19, 2022
1 parent e8ceac7 commit 516bc54
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 22 deletions.
2 changes: 1 addition & 1 deletion packages/compiler-core/src/transform.ts
Expand Up @@ -68,7 +68,7 @@ export interface DirectiveTransformResult {
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.
export type StructuralDirectiveTransform = (
node: ElementNode,
Expand Down
21 changes: 0 additions & 21 deletions packages/compiler-ssr/__tests__/ssrComponent.spec.ts
Expand Up @@ -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
test('should push marker string if is slot root', () => {
expect(
Expand Down
60 changes: 60 additions & 0 deletions packages/compiler-ssr/__tests__/ssrFallthroughAttrs.spec.ts
@@ -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><!--]-->\`)
}"
`)
})
})
19 changes: 19 additions & 0 deletions packages/compiler-ssr/src/transforms/ssrInjectFallthroughAttrs.ts
Expand Up @@ -46,6 +46,25 @@ export const ssrInjectFallthroughAttrs: NodeTransform = (node, context) => {
}

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])
} else if (hasSingleChild(parent)) {
injectFallthroughAttrs(node)
Expand Down

0 comments on commit 516bc54

Please sign in to comment.