From: Rizumu Ayaka Date: Tue, 28 Nov 2023 10:17:41 +0000 (+0800) Subject: feat: add vapor errors of `v-bind` / `v-on` (#3) X-Git-Tag: v3.6.0-alpha.1~16^2~797 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4200d4e2d0378843bd364722f21c180b25908246;p=thirdparty%2Fvuejs%2Fcore.git feat: add vapor errors of `v-bind` / `v-on` (#3) Co-authored-by: 三咲智子 Kevin Deng --- diff --git a/packages/compiler-core/src/index.ts b/packages/compiler-core/src/index.ts index 4898a181df..8aaa0d77e2 100644 --- a/packages/compiler-core/src/index.ts +++ b/packages/compiler-core/src/index.ts @@ -25,6 +25,8 @@ export { generate, type CodegenContext, type CodegenResult } from './codegen' export { ErrorCodes, createCompilerError, + defaultOnError, + defaultOnWarn, type CoreCompilerError, type CompilerError } from './errors' diff --git a/packages/compiler-vapor/__tests__/compile.test.ts b/packages/compiler-vapor/__tests__/compile.test.ts index ca355f2d29..e9766a8060 100644 --- a/packages/compiler-vapor/__tests__/compile.test.ts +++ b/packages/compiler-vapor/__tests__/compile.test.ts @@ -2,6 +2,7 @@ import { BindingTypes, CompilerOptions, RootNode } from '@vue/compiler-dom' // TODO remove it import { format } from 'prettier' import { compile as _compile } from '../src' +import { ErrorCodes } from '../src/errors' async function compile( template: string | RootNode, @@ -71,6 +72,25 @@ describe('compile', () => { }) expect(code).matchSnapshot() }) + + test('should error if no expression', async () => { + const onError = vi.fn() + await compile(`
`, { onError }) + + expect(onError.mock.calls[0][0]).toMatchObject({ + code: ErrorCodes.VAPOR_BIND_NO_EXPRESSION, + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 16, + }, + }, + }) + }) }) describe('v-on', () => { @@ -82,6 +102,24 @@ describe('compile', () => { }) expect(code).matchSnapshot() }) + + test('should error if no expression AND no modifier', async () => { + const onError = vi.fn() + await compile(`
`, { onError }) + expect(onError.mock.calls[0][0]).toMatchObject({ + code: ErrorCodes.VAPOR_ON_NO_EXPRESSION, + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 16, + }, + }, + }) + }) }) describe('v-html', () => { diff --git a/packages/compiler-vapor/src/errors.ts b/packages/compiler-vapor/src/errors.ts new file mode 100644 index 0000000000..0f343e7032 --- /dev/null +++ b/packages/compiler-vapor/src/errors.ts @@ -0,0 +1,19 @@ +export { + createCompilerError, + defaultOnError, + defaultOnWarn, + type CoreCompilerError, + type CompilerError, +} from '@vue/compiler-dom' + +export const enum ErrorCodes { + // transform errors + VAPOR_BIND_NO_EXPRESSION, + VAPOR_ON_NO_EXPRESSION, +} + +export const errorMessages: Record = { + // transform errors + [ErrorCodes.VAPOR_BIND_NO_EXPRESSION]: `v-bind is missing expression.`, + [ErrorCodes.VAPOR_ON_NO_EXPRESSION]: `v-on is missing expression.`, +} diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index 67355cdf79..7d38676c81 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -1,14 +1,14 @@ -import type { +import { NodeTypes, - RootNode, - Node, - TemplateChildNode, - ElementNode, - AttributeNode, - InterpolationNode, - TransformOptions, - DirectiveNode, - ExpressionNode, + type RootNode, + type Node, + type TemplateChildNode, + type ElementNode, + type AttributeNode, + type InterpolationNode, + type TransformOptions, + type DirectiveNode, + type ExpressionNode, } from '@vue/compiler-dom' import { type OperationNode, @@ -17,6 +17,12 @@ import { DynamicInfo, } from './ir' import { isVoidTag } from '@vue/shared' +import { + ErrorCodes, + createCompilerError, + defaultOnError, + defaultOnWarn, +} from './errors' export interface TransformContext { node: T @@ -129,6 +135,9 @@ export function transform( root: RootNode, options: TransformOptions = {}, ): RootIRNode { + options.onError ||= defaultOnError + options.onWarn ||= defaultOnWarn + const ir: RootIRNode = { type: IRNodeTypes.ROOT, loc: root.loc, @@ -145,6 +154,7 @@ export function transform( helpers: new Set([]), vaporHelpers: new Set([]), } + const ctx = createRootContext(ir, root, options) // TODO: transform presets, see packages/compiler-core/src/transforms @@ -344,9 +354,21 @@ function transformProp( return } - const expr = processExpression(ctx, node.exp) + const { exp, loc, modifiers } = node + + const expr = processExpression(ctx, exp) switch (name) { case 'bind': { + if ( + !exp || + (exp.type === NodeTypes.SIMPLE_EXPRESSION! && !exp.content.trim()) + ) { + ctx.options.onError!( + createCompilerError(ErrorCodes.VAPOR_BIND_NO_EXPRESSION, loc), + ) + return + } + if (expr === null) { // TODO: Vue 3.4 supported shorthand syntax // https://github.com/vuejs/core/pull/9451 @@ -371,6 +393,13 @@ function transformProp( break } case 'on': { + if (!exp && !modifiers.length) { + ctx.options.onError!( + createCompilerError(ErrorCodes.VAPOR_ON_NO_EXPRESSION, loc), + ) + return + } + if (!node.arg) { // TODO support v-on="{}" return