Skip to content

Commit e130c7d

Browse files
committed
wip: compiler deprecation config
1 parent 115372d commit e130c7d

File tree

9 files changed

+198
-18
lines changed

9 files changed

+198
-18
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { SourceLocation } from '../ast'
2+
import { CompilerError } from '../errors'
3+
import { ParserContext } from '../parse'
4+
import { TransformContext } from '../transform'
5+
6+
export type CompilerCompatConfig = Partial<
7+
Record<CompilerDeprecationTypes, boolean | 'suppress-warning'>
8+
> & {
9+
MODE?: 2 | 3
10+
}
11+
12+
export interface CompilerCompatOptions {
13+
compatConfig?: CompilerCompatConfig
14+
}
15+
16+
export const enum CompilerDeprecationTypes {
17+
IS_ON_ELEMENT = 'IS_ON_ELEMENT',
18+
V_BIND_SYNC = 'V_BIND_SYNC',
19+
V_BIND_OBJECT_ORDER = 'V_BIND_OBJECT_ORDER',
20+
V_ON_NATIVE_MODIFIER = 'V_ON_NATIVE_MODIFIER',
21+
KEY_V_IF = 'KEY_V_IF',
22+
KEY_V_FOR_TEMPLATE = 'KEY_V_FOR_TEMPLATE',
23+
V_IF_V_FOR_PRECEDENCE = 'V_IF_V_FOR_PRECEDENCE',
24+
NATIVE_TEMPLATE = 'NATIVE_TEMPLATE'
25+
}
26+
27+
type DeprecationData = {
28+
message: string | ((...args: any[]) => string)
29+
link?: string
30+
}
31+
32+
const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
33+
[CompilerDeprecationTypes.IS_ON_ELEMENT]: {
34+
message: ``,
35+
link: `https://v3.vuejs.org/guide/migration/custom-elements-interop.html`
36+
},
37+
38+
[CompilerDeprecationTypes.V_BIND_SYNC]: {
39+
message: key =>
40+
`.sync modifier for v-bind has been removed. Use v-model with ` +
41+
`argument instead. \`v-bind:${key}.sync\` should be changed to ` +
42+
`\`v-model:${key}\`.`,
43+
link: `https://v3.vuejs.org/guide/migration/v-model.html`
44+
},
45+
46+
[CompilerDeprecationTypes.V_BIND_OBJECT_ORDER]: {
47+
message:
48+
`v-bind="obj" usage is now order sensitive and behaves like JavaScript ` +
49+
`object spread: it will now overwrite an existing attribute that appears ` +
50+
`before v-bind in the case of conflicting keys. To retain 2.x behavior, ` +
51+
`move v-bind to and make it the first attribute. If all occurences ` +
52+
`of this warning are working as intended, you can suppress it.`,
53+
link: `https://v3.vuejs.org/guide/migration/v-bind.html`
54+
},
55+
56+
[CompilerDeprecationTypes.V_ON_NATIVE_MODIFIER]: {
57+
message: `.native modifier for v-on has been removed as is no longer necessary.`,
58+
link: `https://v3.vuejs.org/guide/migration/v-on-native-modifier-removed.html`
59+
},
60+
61+
[CompilerDeprecationTypes.KEY_V_IF]: {
62+
message: ``,
63+
link: `https://v3.vuejs.org/guide/migration/key-attribute.html#on-conditional-branches`
64+
},
65+
66+
[CompilerDeprecationTypes.KEY_V_FOR_TEMPLATE]: {
67+
message: ``,
68+
link: `https://v3.vuejs.org/guide/migration/key-attribute.html#with-template-v-for`
69+
},
70+
71+
[CompilerDeprecationTypes.V_IF_V_FOR_PRECEDENCE]: {
72+
message:
73+
`v-if / v-for precedence when used on the same element has changed ` +
74+
`in Vue 3. It is best to avoid the ambiguity with either <template> tags ` +
75+
`or a computed property that filters v-for data source.`,
76+
link: `https://v3.vuejs.org/guide/migration/v-if-v-for.html`
77+
},
78+
79+
[CompilerDeprecationTypes.NATIVE_TEMPLATE]: {
80+
message:
81+
`<template> with no special directives will render as a native template` +
82+
`element instead of its inner content in Vue 3.`
83+
}
84+
}
85+
86+
function getCompatValue(
87+
key: CompilerDeprecationTypes,
88+
context: ParserContext | TransformContext
89+
) {
90+
const config = (context as ParserContext).options
91+
? (context as ParserContext).options.compatConfig
92+
: (context as TransformContext).compatConfig
93+
return config && config[key]
94+
}
95+
96+
export function checkCompatEnabled(
97+
key: CompilerDeprecationTypes,
98+
context: ParserContext | TransformContext,
99+
loc: SourceLocation | null,
100+
...args: any[]
101+
): boolean {
102+
const enabled = getCompatValue(key, context) !== false
103+
if (__DEV__ && enabled) {
104+
warnDeprecation(key, context, loc, ...args)
105+
}
106+
return enabled
107+
}
108+
109+
export function warnDeprecation(
110+
key: CompilerDeprecationTypes,
111+
context: ParserContext | TransformContext,
112+
loc: SourceLocation | null,
113+
...args: any[]
114+
) {
115+
const val = getCompatValue(key, context)
116+
if (val === 'suppress-warning') {
117+
return
118+
}
119+
const { message, link } = deprecationData[key]
120+
const msg = `(deprecation ${key}) ${
121+
typeof message === 'function' ? message(...args) : message
122+
}${link ? `\n Details: ${link}` : ``}`
123+
124+
if (loc) {
125+
const err = new SyntaxError(msg) as CompilerError
126+
err.code = key
127+
err.loc = loc
128+
context.onWarn(err)
129+
return
130+
}
131+
132+
context.onWarn(msg)
133+
}

packages/compiler-core/src/errors.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SourceLocation } from './ast'
22

33
export interface CompilerError extends SyntaxError {
4-
code: number
4+
code: number | string
55
loc?: SourceLocation
66
}
77

@@ -13,6 +13,11 @@ export function defaultOnError(error: CompilerError) {
1313
throw error
1414
}
1515

16+
export function defaultOnWarn(msg: string | CompilerError) {
17+
__DEV__ &&
18+
console.warn(`[Vue warn]`, typeof msg === 'string' ? msg : msg.message)
19+
}
20+
1621
export function createCompilerError<T extends number>(
1722
code: T,
1823
loc?: SourceLocation,

packages/compiler-core/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,10 @@ export {
5757
} from './transforms/transformElement'
5858
export { processSlotOutlet } from './transforms/transformSlotOutlet'
5959
export { generateCodeFrame } from '@vue/shared'
60+
61+
// v2 compat only
62+
export {
63+
checkCompatEnabled,
64+
warnDeprecation,
65+
CompilerDeprecationTypes
66+
} from './compat/compatConfig'

packages/compiler-core/src/options.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ import {
66
DirectiveTransform,
77
TransformContext
88
} from './transform'
9+
import { CompilerCompatOptions } from './compat/compatConfig'
910
import { ParserPlugin } from '@babel/parser'
1011

11-
export interface ParserOptions {
12+
export interface ErrorHandlingOptions {
13+
onWarn?: (msg: string | CompilerError) => void
14+
onError?: (error: CompilerError) => void
15+
}
16+
17+
export interface ParserOptions
18+
extends ErrorHandlingOptions,
19+
CompilerCompatOptions {
1220
/**
1321
* e.g. platform native elements, e.g. `<div>` for browsers
1422
*/
@@ -48,7 +56,6 @@ export interface ParserOptions {
4856
* Only needed for DOM compilers
4957
*/
5058
decodeEntities?: (rawText: string, asAttr: boolean) => string
51-
onError?: (error: CompilerError) => void
5259
/**
5360
* Keep comments in the templates AST, even in production
5461
*/
@@ -138,7 +145,10 @@ interface SharedTransformCodegenOptions {
138145
filename?: string
139146
}
140147

141-
export interface TransformOptions extends SharedTransformCodegenOptions {
148+
export interface TransformOptions
149+
extends SharedTransformCodegenOptions,
150+
ErrorHandlingOptions,
151+
CompilerCompatOptions {
142152
/**
143153
* An array of node transforms to be applied to every AST node.
144154
*/
@@ -213,7 +223,6 @@ export interface TransformOptions extends SharedTransformCodegenOptions {
213223
* needed to render inline CSS variables on component root
214224
*/
215225
ssrCssVars?: string
216-
onError?: (error: CompilerError) => void
217226
}
218227

219228
export interface CodegenOptions extends SharedTransformCodegenOptions {

packages/compiler-core/src/parse.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
import { ParserOptions } from './options'
1+
import { ErrorHandlingOptions, ParserOptions } from './options'
22
import { NO, isArray, makeMap, extend } from '@vue/shared'
3-
import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
3+
import {
4+
ErrorCodes,
5+
createCompilerError,
6+
defaultOnError,
7+
defaultOnWarn
8+
} from './errors'
49
import {
510
assert,
611
advancePositionWithMutation,
@@ -25,8 +30,12 @@ import {
2530
createRoot,
2631
ConstantTypes
2732
} from './ast'
33+
import { CompilerCompatOptions } from './compat/compatConfig'
2834

29-
type OptionalOptions = 'isNativeTag' | 'isBuiltInComponent'
35+
type OptionalOptions =
36+
| 'isNativeTag'
37+
| 'isBuiltInComponent'
38+
| keyof CompilerCompatOptions
3039
type MergedParserOptions = Omit<Required<ParserOptions>, OptionalOptions> &
3140
Pick<ParserOptions, OptionalOptions>
3241
type AttributeValue =
@@ -59,6 +68,7 @@ export const defaultParserOptions: MergedParserOptions = {
5968
decodeEntities: (rawText: string): string =>
6069
rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),
6170
onError: defaultOnError,
71+
onWarn: defaultOnWarn,
6272
comments: false
6373
}
6474

@@ -80,6 +90,7 @@ export interface ParserContext {
8090
column: number
8191
inPre: boolean // HTML <pre> tag, preserve whitespaces
8292
inVPre: boolean // v-pre, do not process directives and interpolations
93+
onWarn: NonNullable<ErrorHandlingOptions['onWarn']>
8394
}
8495

8596
export function baseParse(
@@ -111,7 +122,8 @@ function createParserContext(
111122
originalSource: content,
112123
source: content,
113124
inPre: false,
114-
inVPre: false
125+
inVPre: false,
126+
onWarn: options.onWarn
115127
}
116128
}
117129

packages/compiler-core/src/transform.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
capitalize,
2929
camelize
3030
} from '@vue/shared'
31-
import { defaultOnError } from './errors'
31+
import { defaultOnError, defaultOnWarn } from './errors'
3232
import {
3333
TO_DISPLAY_STRING,
3434
FRAGMENT,
@@ -40,6 +40,7 @@ import {
4040
} from './runtimeHelpers'
4141
import { isVSlot } from './utils'
4242
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
43+
import { CompilerCompatOptions } from './compat/compatConfig'
4344

4445
// There are two types of transforms:
4546
//
@@ -83,7 +84,10 @@ export interface ImportItem {
8384
}
8485

8586
export interface TransformContext
86-
extends Required<Omit<TransformOptions, 'filename'>> {
87+
extends Required<
88+
Omit<TransformOptions, 'filename' | keyof CompilerCompatOptions>
89+
>,
90+
CompilerCompatOptions {
8791
selfName: string | null
8892
root: RootNode
8993
helpers: Map<symbol, number>
@@ -136,7 +140,9 @@ export function createTransformContext(
136140
bindingMetadata = EMPTY_OBJ,
137141
inline = false,
138142
isTS = false,
139-
onError = defaultOnError
143+
onError = defaultOnError,
144+
onWarn = defaultOnWarn,
145+
compatConfig
140146
}: TransformOptions
141147
): TransformContext {
142148
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
@@ -160,6 +166,8 @@ export function createTransformContext(
160166
inline,
161167
isTS,
162168
onError,
169+
onWarn,
170+
compatConfig,
163171

164172
// state
165173
root,

packages/compiler-dom/src/errors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ export interface DOMCompilerError extends CompilerError {
1212
export function createDOMCompilerError(
1313
code: DOMErrorCodes,
1414
loc?: SourceLocation
15-
): DOMCompilerError {
15+
) {
1616
return createCompilerError(
1717
code,
1818
loc,
1919
__DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined
20-
)
20+
) as DOMCompilerError
2121
}
2222

2323
export const enum DOMErrorCodes {

packages/compiler-dom/src/transforms/vOn.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {
88
createCompoundExpression,
99
ExpressionNode,
1010
SimpleExpressionNode,
11-
isStaticExp
11+
isStaticExp,
12+
warnDeprecation,
13+
CompilerDeprecationTypes
1214
} from '@vue/compiler-core'
1315
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
1416
import { makeMap, capitalize } from '@vue/shared'
@@ -93,7 +95,11 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
9395
if (!modifiers.length) return baseResult
9496

9597
if (__COMPAT__ && __DEV__ && modifiers.includes('native')) {
96-
console.warn('.native modifier for v-on has been removed')
98+
warnDeprecation(
99+
CompilerDeprecationTypes.V_ON_NATIVE_MODIFIER,
100+
context,
101+
dir.loc
102+
)
97103
}
98104

99105
let { key, value: handlerExp } = baseResult.props[0]

packages/compiler-ssr/src/errors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export interface SSRCompilerError extends CompilerError {
1212
export function createSSRCompilerError(
1313
code: SSRErrorCodes,
1414
loc?: SourceLocation
15-
): SSRCompilerError {
16-
return createCompilerError(code, loc, SSRErrorMessages)
15+
) {
16+
return createCompilerError(code, loc, SSRErrorMessages) as SSRCompilerError
1717
}
1818

1919
export const enum SSRErrorCodes {

0 commit comments

Comments
 (0)