This commit is contained in:
skirtle 2025-05-05 20:41:54 +00:00 committed by GitHub
commit af09ca41ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 159 additions and 7 deletions

View File

@ -3848,6 +3848,117 @@ exports[`compiler: parse > Errors > UNEXPECTED_SOLIDUS_IN_TAG > <template><div a
}
`;
exports[`compiler: parse > Errors > X_COLON_BEFORE_DIRECTIVE > <div :v-foo="obj" /> 1`] = `
{
"cached": 0,
"children": [
{
"children": [],
"codegenNode": undefined,
"isSelfClosing": true,
"loc": {
"end": {
"column": 21,
"line": 1,
"offset": 20,
},
"source": "<div :v-foo="obj" />",
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"ns": 0,
"props": [
{
"arg": {
"constType": 3,
"content": "v-foo",
"isStatic": true,
"loc": {
"end": {
"column": 12,
"line": 1,
"offset": 11,
},
"source": "v-foo",
"start": {
"column": 7,
"line": 1,
"offset": 6,
},
},
"type": 4,
},
"exp": {
"constType": 0,
"content": "obj",
"isStatic": false,
"loc": {
"end": {
"column": 17,
"line": 1,
"offset": 16,
},
"source": "obj",
"start": {
"column": 14,
"line": 1,
"offset": 13,
},
},
"type": 4,
},
"loc": {
"end": {
"column": 18,
"line": 1,
"offset": 17,
},
"source": ":v-foo="obj"",
"start": {
"column": 6,
"line": 1,
"offset": 5,
},
},
"modifiers": [],
"name": "bind",
"rawName": ":v-foo",
"type": 7,
},
],
"tag": "div",
"tagType": 0,
"type": 1,
},
],
"codegenNode": undefined,
"components": [],
"directives": [],
"helpers": Set {},
"hoists": [],
"imports": [],
"loc": {
"end": {
"column": 21,
"line": 1,
"offset": 20,
},
"source": "<div :v-foo="obj" />",
"start": {
"column": 1,
"line": 1,
"offset": 0,
},
},
"source": "<div :v-foo="obj" />",
"temps": 0,
"type": 0,
}
`;
exports[`compiler: parse > Errors > X_INVALID_END_TAG > <svg><![CDATA[</div>]]></svg> 1`] = `
{
"cached": [],

View File

@ -2550,7 +2550,8 @@ describe('compiler: parse', () => {
const patterns: {
[key: string]: Array<{
code: string
errors: Array<{ type: ErrorCodes; loc: Position }>
errors?: Array<{ type: ErrorCodes; loc: Position }>
warnings?: Array<{ type: ErrorCodes; loc: Position }>
options?: Partial<ParserOptions>
}>
} = {
@ -3420,32 +3421,53 @@ describe('compiler: parse', () => {
],
},
],
X_COLON_BEFORE_DIRECTIVE: [
{
code: `<div :v-foo="obj" />`,
warnings: [
{
type: ErrorCodes.X_COLON_BEFORE_DIRECTIVE,
loc: { offset: 5, line: 1, column: 6 },
},
],
},
],
}
for (const key of Object.keys(patterns)) {
describe(key, () => {
for (const { code, errors, options } of patterns[key]) {
for (const { code, errors = [], warnings = [], options } of patterns[
key
]) {
test(
code.replace(
/[\r\n]/g,
c => `\\x0${c.codePointAt(0)!.toString(16)};`,
),
() => {
const spy = vi.fn()
const errorSpy = vi.fn()
const warnSpy = vi.fn()
const ast = baseParse(code, {
parseMode: 'html',
getNamespace: tag =>
tag === 'svg' ? Namespaces.SVG : Namespaces.HTML,
...options,
onError: spy,
onError: errorSpy,
onWarn: warnSpy,
})
expect(
spy.mock.calls.map(([err]) => ({
errorSpy.mock.calls.map(([err]) => ({
type: err.code,
loc: err.loc.start,
})),
).toMatchObject(errors)
expect(
warnSpy.mock.calls.map(([err]) => ({
type: err.code,
loc: err.loc.start,
})),
).toMatchObject(warnings)
expect(ast).toMatchSnapshot()
},
)

View File

@ -90,6 +90,7 @@ export enum ErrorCodes {
X_V_MODEL_ON_PROPS,
X_INVALID_EXPRESSION,
X_KEEP_ALIVE_INVALID_CHILDREN,
X_COLON_BEFORE_DIRECTIVE,
// generic errors
X_PREFIX_ID_NOT_SUPPORTED,
@ -179,6 +180,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
[ErrorCodes.X_INVALID_EXPRESSION]: `Error parsing JavaScript expression: `,
[ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN]: `<KeepAlive> expects exactly one child component.`,
[ErrorCodes.X_VNODE_HOOKS]: `@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.`,
[ErrorCodes.X_COLON_BEFORE_DIRECTIVE]: `Colon before directive: `,
// generic errors
[ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`,

View File

@ -257,6 +257,17 @@ const tokenizer = new Tokenizer(stack, {
getLoc(start, end),
isStatic ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT,
)
if (
__DEV__ &&
arg.startsWith('v-') &&
(currentProp as DirectiveNode).rawName === ':'
) {
emitWarning(
ErrorCodes.X_COLON_BEFORE_DIRECTIVE,
start - 1,
`the attribute name :${arg} is probably a mistake. Did you mean ${arg} instead?`,
)
}
}
},
@ -1025,6 +1036,12 @@ function emitError(code: ErrorCodes, index: number, message?: string) {
)
}
function emitWarning(code: ErrorCodes, index: number, message?: string) {
currentOptions.onWarn(
createCompilerError(code, getLoc(index, index), undefined, message),
)
}
function reset() {
tokenizer.reset()
currentOpenTag = null

View File

@ -21,7 +21,7 @@ export function createDOMCompilerError(
}
export enum DOMErrorCodes {
X_V_HTML_NO_EXPRESSION = 53 /* ErrorCodes.__EXTEND_POINT__ */,
X_V_HTML_NO_EXPRESSION = 54 /* ErrorCodes.__EXTEND_POINT__ */,
X_V_HTML_WITH_CHILDREN,
X_V_TEXT_NO_EXPRESSION,
X_V_TEXT_WITH_CHILDREN,

View File

@ -17,7 +17,7 @@ export function createSSRCompilerError(
}
export enum SSRErrorCodes {
X_SSR_UNSAFE_ATTR_NAME = 65 /* DOMErrorCodes.__EXTEND_POINT__ */,
X_SSR_UNSAFE_ATTR_NAME = 66 /* DOMErrorCodes.__EXTEND_POINT__ */,
X_SSR_NO_TELEPORT_TARGET,
X_SSR_INVALID_AST_NODE,
}