Skip to content

Improvement compilation error for plugins / tools #1147

@kazupon

Description

@kazupon

What problem does this feature solve?

Use-Cases

  • for the plugin and the tool authors who want to enhancement and optimize with compiler
    (e.g. pre-translation using transform like i18n)

Purpose

  • distinguish between compiler errors caused by plugins / tools and Vue compilation errors
  • as the result, we offer the end-user with DX that can understand where the error occurred

Backgrounds

  • @vue/compiler-core have TransformOptions.directiveTransforms and TransformOptions.nodeTransforms at Compiler options
  • we can notify the end-user of compile error with using onError in compilation
  • TransformOptions.directiveTransforms and TransformOptions.nodeTransforms can also notify the user of compile error with using onError via context
  • However, there are currently no error codes prepared for plugin / tool authors
  • even if we notify the end-user of compile error, the end-user cannot understand whether it's Vue side error, user side error

What does the proposed API look like?

Add the field to error thrown with createCompileError

packages/compiler-core/src/errors.ts:

// NOTE: maybe, we should refactor  `createCompilerError` arguments to something like the option object.
export function createCompilerError<T extends number>(
  code: T,
  loc?: SourceLocation,
  messages?: { [code: number]: string },
  additionalMessage?: string,
  domain?: string // <- add
): T extends ErrorCodes ? CoreCompilerError : CompilerError {
  const msg =
    __DEV__ || !__BROWSER__
      ? (messages || errorMessages)[code]   (additionalMessage || ``)
      : code
  const error = new SyntaxError(String(msg)) as CompilerError
  error.code = code
  error.loc = loc
  error.domain = domain // <- add
  return error as any
}

And, when handling with onError, change to code that we can understand whether it's compilation error thrown on user side or Vue side.

packages/vue/src/index.ts:

  const { code } = compile(template, {
    hoistStatic: true,
    onError(err: CompilerError) {
      if (__DEV__) {
        const message = `Template compilation error${err.domain ? ` ` : ` (${err.domain})`}: ${err.message}`
        const codeFrame =
          err.loc &&
          generateCodeFrame(
            template as string,
            err.loc.start.offset,
            err.loc.end.offset
          )
        warn(codeFrame ? `${message}\n${codeFrame}` : message)
      } else {
        throw err
      }
    },
    ...options
  })

Regarding error codes, IMO, the error codes should be optional, because we need to decide which error code starting point for the user. If we use the error codes, we need to reserve the values.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions