diff --git a/packages/compiler-core/__tests__/parse.spec.ts b/packages/compiler-core/__tests__/parse.spec.ts index 0e839d26bc7..51cdb0e38c1 100644 --- a/packages/compiler-core/__tests__/parse.spec.ts +++ b/packages/compiler-core/__tests__/parse.spec.ts @@ -1244,6 +1244,27 @@ describe('compiler: parse', () => { } }) }) + test('directive with no name', () => { + let errorCode = -1 + const ast = baseParse('
', { + onError: err => { + errorCode = err.code as number + } + }) + const directive = (ast.children[0] as ElementNode).props[0] + + expect(errorCode).toBe(ErrorCodes.X_MISSING_DIRECTIVE_NAME) + expect(directive).toStrictEqual({ + type: NodeTypes.ATTRIBUTE, + name: 'v-', + value: undefined, + loc: { + start: { offset: 5, line: 1, column: 6 }, + end: { offset: 7, line: 1, column: 8 }, + source: 'v-' + } + }) + }) test('v-bind shorthand', () => { const ast = baseParse('
') diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts index 57f2f3b2ef7..1f2afac7e66 100644 --- a/packages/compiler-core/src/errors.ts +++ b/packages/compiler-core/src/errors.ts @@ -67,6 +67,7 @@ export const enum ErrorCodes { X_INVALID_END_TAG, X_MISSING_END_TAG, X_MISSING_INTERPOLATION_END, + X_MISSING_DIRECTIVE_NAME, X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END, // transform errors @@ -143,6 +144,7 @@ export const errorMessages: Record = { [ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END]: 'End bracket for dynamic directive argument was not found. ' + 'Note that dynamic directive argument cannot contain spaces.', + [ErrorCodes.X_MISSING_DIRECTIVE_NAME]: 'Legal directive name was expected.', // transform errors [ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`, diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index 21973878dbc..907e54d742e 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -775,7 +775,7 @@ function parseAttribute( } const loc = getSelection(context, start) - if (!context.inVPre && /^(v-|:|\.|@|#)/.test(name)) { + if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) { const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec( name @@ -888,6 +888,11 @@ function parseAttribute( } } + // missing directive name or illegal directive name + if (!context.inVPre && startsWith(name, 'v-')) { + emitError(context, ErrorCodes.X_MISSING_DIRECTIVE_NAME) + } + return { type: NodeTypes.ATTRIBUTE, name,