From: Eduardo San Martin Morote Date: Tue, 31 Mar 2020 22:12:51 +0000 (+0200) Subject: fix(transition): warn only when there is more than one rendered child (#903) X-Git-Tag: v3.0.0-alpha.11~31 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=37b1dc8242608b072d14fd2a5e52f5d40829ea52;p=thirdparty%2Fvuejs%2Fcore.git fix(transition): warn only when there is more than one rendered child (#903) --- diff --git a/packages/compiler-dom/__tests__/transforms/warnTransitionChildren.spec.ts b/packages/compiler-dom/__tests__/transforms/warnTransitionChildren.spec.ts new file mode 100644 index 0000000000..8083ce72af --- /dev/null +++ b/packages/compiler-dom/__tests__/transforms/warnTransitionChildren.spec.ts @@ -0,0 +1,140 @@ +import { compile } from '../../src' + +describe('compiler warnings', () => { + describe('Transition', () => { + function checkWarning( + template: string, + shouldWarn: boolean, + message = ` expects exactly one child element or component.` + ) { + const spy = jest.fn() + compile(template.trim(), { + hoistStatic: true, + transformHoist: null, + onError: err => { + spy(err.message) + } + }) + + if (shouldWarn) expect(spy).toHaveBeenCalledWith(message) + else expect(spy).not.toHaveBeenCalled() + } + + test('warns if multiple children', () => { + checkWarning( + ` + +
hey
+
hey
+
+ `, + true + ) + }) + + test('warns with v-for', () => { + checkWarning( + ` + +
hey
+
+ `, + true + ) + }) + + test('warns with multiple v-if + v-for', () => { + checkWarning( + ` + +
hey
+
hey
+
+ `, + true + ) + }) + + test('warns with template v-if', () => { + checkWarning( + ` + + + + `, + true + ) + }) + + test('warns with multiple templates', () => { + checkWarning( + ` + + + + + `, + true + ) + }) + + test('warns if multiple children with v-if', () => { + checkWarning( + ` + +
hey
+
hey
+
+ `, + true + ) + }) + + test('does not warn with regular element', () => { + checkWarning( + ` + +
hey
+
+ `, + false + ) + }) + + test('does not warn with one single v-if', () => { + checkWarning( + ` + +
hey
+
+ `, + false + ) + }) + + test('does not warn with v-if v-else-if v-else', () => { + checkWarning( + ` + +
hey
+
hey
+
hey
+
+ `, + false + ) + }) + + test('does not warn with v-if v-else', () => { + checkWarning( + ` + +
hey
+
hey
+
+ `, + false + ) + }) + }) +}) diff --git a/packages/compiler-dom/src/transforms/warnTransitionChildren.ts b/packages/compiler-dom/src/transforms/warnTransitionChildren.ts index 0cd1d6669a..577b3a8876 100644 --- a/packages/compiler-dom/src/transforms/warnTransitionChildren.ts +++ b/packages/compiler-dom/src/transforms/warnTransitionChildren.ts @@ -1,4 +1,10 @@ -import { NodeTransform, NodeTypes, ElementTypes } from '@vue/compiler-core' +import { + NodeTransform, + NodeTypes, + ElementTypes, + ComponentNode, + IfBranchNode +} from '@vue/compiler-core' import { TRANSITION } from '../runtimeHelpers' import { createDOMCompilerError, DOMErrorCodes } from '../errors' @@ -8,17 +14,30 @@ export const warnTransitionChildren: NodeTransform = (node, context) => { node.tagType === ElementTypes.COMPONENT ) { const component = context.isBuiltInComponent(node.tag) - if ( - component === TRANSITION && - (node.children.length > 1 || node.children[0].type === NodeTypes.FOR) - ) { - context.onError( - createDOMCompilerError(DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, { - start: node.children[0].loc.start, - end: node.children[node.children.length - 1].loc.end, - source: '' - }) - ) + if (component === TRANSITION) { + return () => { + if (node.children.length && hasMultipleChildren(node)) { + context.onError( + createDOMCompilerError( + DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN, + { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '' + } + ) + ) + } + } } } } + +function hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean { + const child = node.children[0] + return ( + node.children.length !== 1 || + child.type === NodeTypes.FOR || + (child.type === NodeTypes.IF && child.branches.some(hasMultipleChildren)) + ) +}