Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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": [],
Expand Down
32 changes: 27 additions & 5 deletions packages/compiler-core/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2555,7 +2555,8 @@
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>
}>
} = {
Expand Down Expand Up @@ -3425,33 +3426,54 @@
],
},
],
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()

Check failure on line 3476 in packages/compiler-core/__tests__/parse.spec.ts

View workflow job for this annotation

GitHub Actions / test / unit-test

packages/compiler-core/__tests__/parse.spec.ts > compiler: parse > Errors > X_COLON_BEFORE_DIRECTIVE > <div :v-foo="obj" />

Error: Snapshot `compiler: parse > Errors > X_COLON_BEFORE_DIRECTIVE > <div :v-foo="obj" /> 1` mismatched - Expected + Received @@ -1,7 +1,7 @@ { - "cached": 0, + "cached": [], "children": [ { "children": [], "codegenNode": undefined, "isSelfClosing": true, ❯ packages/compiler-core/__tests__/parse.spec.ts:3476:27

Check failure on line 3476 in packages/compiler-core/__tests__/parse.spec.ts

View workflow job for this annotation

GitHub Actions / test / unit-test-windows

packages/compiler-core/__tests__/parse.spec.ts > compiler: parse > Errors > X_COLON_BEFORE_DIRECTIVE > <div :v-foo="obj" />

Error: Snapshot `compiler: parse > Errors > X_COLON_BEFORE_DIRECTIVE > <div :v-foo="obj" /> 1` mismatched - Expected + Received @@ -1,7 +1,7 @@ { - "cached": 0, + "cached": [], "children": [ { "children": [], "codegenNode": undefined, "isSelfClosing": true, ❯ packages/compiler-core/__tests__/parse.spec.ts:3476:27
},
)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/compiler-core/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.`,
Expand Down
17 changes: 17 additions & 0 deletions packages/compiler-core/src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,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?`,
)
}
}
},

Expand Down Expand Up @@ -1015,6 +1026,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
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-dom/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-ssr/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
Loading