diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts index e2fe090a0..a46fa80e9 100644 --- a/packages/compiler-core/src/errors.ts +++ b/packages/compiler-core/src/errors.ts @@ -81,6 +81,7 @@ export const enum ErrorCodes { X_V_MODEL_MALFORMED_EXPRESSION, X_V_MODEL_ON_SCOPE_VARIABLE, X_INVALID_EXPRESSION, + X_KEEP_ALIVE_INVALID_CHILDREN, // generic errors X_PREFIX_ID_NOT_SUPPORTED, @@ -174,6 +175,7 @@ export const errorMessages: { [code: number]: string } = { [ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`, [ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`, [ErrorCodes.X_INVALID_EXPRESSION]: `Invalid JavaScript expression.`, + [ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: ` expects exactly one child component.`, // generic errors [ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`, diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 7c9dd0fe8..1d685dce5 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -100,6 +100,17 @@ export const transformElement: NodeTransform = (node, context) => { if (!hasProps) { args.push(`null`) } + + if (__DEV__ && nodeType === KEEP_ALIVE && node.children.length > 1) { + context.onError( + createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, { + start: node.children[0].loc.start, + end: node.children[node.children.length - 1].loc.end, + source: '' + }) + ) + } + // Portal & KeepAlive should have normal children instead of slots // Portal is not a real component has dedicated handling in the renderer // KeepAlive should not track its own deps so that it can be used inside diff --git a/packages/compiler-dom/src/errors.ts b/packages/compiler-dom/src/errors.ts index 8ead25260..1519324df 100644 --- a/packages/compiler-dom/src/errors.ts +++ b/packages/compiler-dom/src/errors.ts @@ -30,6 +30,7 @@ export const enum DOMErrorCodes { X_V_MODEL_ON_FILE_INPUT_ELEMENT, X_V_MODEL_UNNECESSARY_VALUE, X_V_SHOW_NO_EXPRESSION, + X_TRANSITION_INVALID_CHILDREN, __EXTEND_POINT__ } @@ -42,5 +43,6 @@ export const DOMErrorMessages: { [code: number]: string } = { [DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT]: `v-model argument is not supported on plain elements.`, [DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT]: `v-model cannot used on file inputs since they are read-only. Use a v-on:change listener instead.`, [DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`, - [DOMErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.` + [DOMErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`, + [DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN]: ` expects exactly one child element or component.` } diff --git a/packages/compiler-dom/src/index.ts b/packages/compiler-dom/src/index.ts index 5e1d17dfd..674a3ef83 100644 --- a/packages/compiler-dom/src/index.ts +++ b/packages/compiler-dom/src/index.ts @@ -17,6 +17,7 @@ import { transformModel } from './transforms/vModel' import { transformOn } from './transforms/vOn' import { transformShow } from './transforms/vShow' import { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers' +import { warnTransitionChildren } from './transforms/warnTransitionChildren' export const parserOptions = __BROWSER__ ? parserOptionsMinimal @@ -37,7 +38,11 @@ export function compile( return baseCompile(template, { ...parserOptions, ...options, - nodeTransforms: [transformStyle, ...(options.nodeTransforms || [])], + nodeTransforms: [ + transformStyle, + ...(__DEV__ ? [warnTransitionChildren] : []), + ...(options.nodeTransforms || []) + ], directiveTransforms: { cloak: noopDirectiveTransform, html: transformVHtml, diff --git a/packages/compiler-dom/src/transforms/warnTransitionChildren.ts b/packages/compiler-dom/src/transforms/warnTransitionChildren.ts new file mode 100644 index 000000000..0cd1d6669 --- /dev/null +++ b/packages/compiler-dom/src/transforms/warnTransitionChildren.ts @@ -0,0 +1,24 @@ +import { NodeTransform, NodeTypes, ElementTypes } from '@vue/compiler-core' +import { TRANSITION } from '../runtimeHelpers' +import { createDOMCompilerError, DOMErrorCodes } from '../errors' + +export const warnTransitionChildren: NodeTransform = (node, context) => { + if ( + node.type === NodeTypes.ELEMENT && + 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: '' + }) + ) + } + } +}