wip: v-bind.sync compat

This commit is contained in:
Evan You 2021-04-16 17:11:44 -04:00
parent ad97bbab85
commit 7ceb873783
4 changed files with 48 additions and 7 deletions
packages
compiler-core/src
compiler-dom/src/transforms

@ -16,8 +16,9 @@ export interface CompilerCompatOptions {
export const enum CompilerDeprecationTypes { export const enum CompilerDeprecationTypes {
COMPILER_IS_ON_ELEMENT = 'COMPILER_IS_ON_ELEMENT', COMPILER_IS_ON_ELEMENT = 'COMPILER_IS_ON_ELEMENT',
COMPILER_V_BIND_SYNC = 'COMPILER_V_BIND_SYNC', COMPILER_V_BIND_SYNC = 'COMPILER_V_BIND_SYNC',
COMPILER_V_BIND_PROP = 'COMPILER_V_BIND_PROP',
COMPILER_V_BIND_OBJECT_ORDER = 'COMPILER_V_BIND_OBJECT_ORDER', COMPILER_V_BIND_OBJECT_ORDER = 'COMPILER_V_BIND_OBJECT_ORDER',
COMPILER_V_ON_NATIVE_MODIFIER = 'COMPILER_V_ON_NATIVE_MODIFIER', COMPILER_V_ON_NATIVE = 'COMPILER_V_ON_NATIVE',
COMPILER_KEY_V_IF = 'COMPILER_KEY_V_IF', COMPILER_KEY_V_IF = 'COMPILER_KEY_V_IF',
COMPILER_KEY_V_FOR_TEMPLATE = 'COMPILER_KEY_V_FOR_TEMPLATE', COMPILER_KEY_V_FOR_TEMPLATE = 'COMPILER_KEY_V_FOR_TEMPLATE',
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE', COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
@ -46,6 +47,12 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
link: `https://v3.vuejs.org/guide/migration/v-model.html` link: `https://v3.vuejs.org/guide/migration/v-model.html`
}, },
[CompilerDeprecationTypes.COMPILER_V_BIND_PROP]: {
message:
`.prop modifier for v-bind has been removed and no longer necessary. ` +
`Vue 3 will automatically set a binding as DOM property when appropriate.`
},
[CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER]: { [CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER]: {
message: message:
`v-bind="obj" usage is now order sensitive and behaves like JavaScript ` + `v-bind="obj" usage is now order sensitive and behaves like JavaScript ` +
@ -56,7 +63,7 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
link: `https://v3.vuejs.org/guide/migration/v-bind.html` link: `https://v3.vuejs.org/guide/migration/v-bind.html`
}, },
[CompilerDeprecationTypes.COMPILER_V_ON_NATIVE_MODIFIER]: { [CompilerDeprecationTypes.COMPILER_V_ON_NATIVE]: {
message: `.native modifier for v-on has been removed as is no longer necessary.`, message: `.native modifier for v-on has been removed as is no longer necessary.`,
link: `https://v3.vuejs.org/guide/migration/v-on-native-modifier-removed.html` link: `https://v3.vuejs.org/guide/migration/v-on-native-modifier-removed.html`
}, },

@ -650,10 +650,9 @@ function parseAttribute(
name name
)! )!
const dirName = let dirName =
match[1] || match[1] ||
(startsWith(name, ':') ? 'bind' : startsWith(name, '@') ? 'on' : 'slot') (startsWith(name, ':') ? 'bind' : startsWith(name, '@') ? 'on' : 'slot')
let arg: ExpressionNode | undefined let arg: ExpressionNode | undefined
if (match[2]) { if (match[2]) {
@ -708,6 +707,25 @@ function parseAttribute(
valueLoc.source = valueLoc.source.slice(1, -1) valueLoc.source = valueLoc.source.slice(1, -1)
} }
const modifiers = match[3] ? match[3].substr(1).split('.') : []
// 2.x compat v-bind:foo.sync -> v-model:foo
if (
__COMPAT__ &&
dirName === 'bind' &&
arg &&
modifiers.includes('sync') &&
checkCompatEnabled(
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
context,
loc,
arg.loc.source
)
) {
dirName = 'model'
modifiers.splice(modifiers.indexOf('sync'), 1)
}
return { return {
type: NodeTypes.DIRECTIVE, type: NodeTypes.DIRECTIVE,
name: dirName, name: dirName,
@ -721,7 +739,7 @@ function parseAttribute(
loc: value.loc loc: value.loc
}, },
arg, arg,
modifiers: match[3] ? match[3].substr(1).split('.') : [], modifiers,
loc loc
} }
} }

@ -3,11 +3,15 @@ import { createObjectProperty, createSimpleExpression, NodeTypes } from '../ast'
import { createCompilerError, ErrorCodes } from '../errors' import { createCompilerError, ErrorCodes } from '../errors'
import { camelize } from '@vue/shared' import { camelize } from '@vue/shared'
import { CAMELIZE } from '../runtimeHelpers' import { CAMELIZE } from '../runtimeHelpers'
import {
checkCompatEnabled,
CompilerDeprecationTypes
} from '../compat/compatConfig'
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting // v-bind without arg is handled directly in ./transformElements.ts due to it affecting
// codegen for the entire props object. This transform here is only for v-bind // codegen for the entire props object. This transform here is only for v-bind
// *with* args. // *with* args.
export const transformBind: DirectiveTransform = (dir, node, context) => { export const transformBind: DirectiveTransform = (dir, _node, context) => {
const { exp, modifiers, loc } = dir const { exp, modifiers, loc } = dir
const arg = dir.arg! const arg = dir.arg!
@ -33,6 +37,18 @@ export const transformBind: DirectiveTransform = (dir, node, context) => {
} }
} }
if (__COMPAT__) {
if (modifiers.includes('prop')) {
checkCompatEnabled(
CompilerDeprecationTypes.COMPILER_V_BIND_PROP,
context,
loc
)
}
// .sync handling is performed directly in the parse phase to transform
// it into v-model:arg equivalent.
}
if ( if (
!exp || !exp ||
(exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim()) (exp.type === NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())

@ -96,7 +96,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
if (__COMPAT__ && __DEV__ && modifiers.includes('native')) { if (__COMPAT__ && __DEV__ && modifiers.includes('native')) {
warnDeprecation( warnDeprecation(
CompilerDeprecationTypes.COMPILER_V_ON_NATIVE_MODIFIER, CompilerDeprecationTypes.COMPILER_V_ON_NATIVE,
context, context,
dir.loc dir.loc
) )