wip: attr coersion compat
This commit is contained in:
parent
cf6bcdf895
commit
c1e5cfe7d6
@ -29,10 +29,14 @@ export const enum DeprecationTypes {
|
|||||||
OPTIONS_BEFORE_DESTROY = 'OPTIONS_BEFORE_DESTROY',
|
OPTIONS_BEFORE_DESTROY = 'OPTIONS_BEFORE_DESTROY',
|
||||||
OPTIONS_DESTROYED = 'OPTIONS_DESTROYED',
|
OPTIONS_DESTROYED = 'OPTIONS_DESTROYED',
|
||||||
|
|
||||||
V_ON_KEYCODE_MODIFIER = 'V_ON_KEYCODE_MODIFIER',
|
|
||||||
PROPS_DEFAULT_THIS = 'PROPS_DEFAULT_THIS',
|
|
||||||
CUSTOM_DIR = 'CUSTOM_DIR',
|
|
||||||
WATCH_ARRAY = 'WATCH_ARRAY',
|
WATCH_ARRAY = 'WATCH_ARRAY',
|
||||||
|
PROPS_DEFAULT_THIS = 'PROPS_DEFAULT_THIS',
|
||||||
|
|
||||||
|
V_ON_KEYCODE_MODIFIER = 'V_ON_KEYCODE_MODIFIER',
|
||||||
|
CUSTOM_DIR = 'CUSTOM_DIR',
|
||||||
|
|
||||||
|
ATTR_FALSE_VALUE = 'ATTR_FALSE_VALUE',
|
||||||
|
ATTR_ENUMERATED_COERSION = 'ATTR_ENUMERATED_COERSION',
|
||||||
|
|
||||||
TRANSITION_CLASSES = 'TRANSITION_CLASSES',
|
TRANSITION_CLASSES = 'TRANSITION_CLASSES',
|
||||||
TRANSITION_GROUP_ROOT = 'TRANSITION_GROUP_ROOT'
|
TRANSITION_GROUP_ROOT = 'TRANSITION_GROUP_ROOT'
|
||||||
@ -191,11 +195,16 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
message: `\`destroyed\` has been renamed to \`unmounted\`.`
|
message: `\`destroyed\` has been renamed to \`unmounted\`.`
|
||||||
},
|
},
|
||||||
|
|
||||||
[DeprecationTypes.V_ON_KEYCODE_MODIFIER]: {
|
[DeprecationTypes.WATCH_ARRAY]: {
|
||||||
message:
|
message:
|
||||||
`Using keyCode as v-on modifier is no longer supported. ` +
|
`"watch" option or vm.$watch on an array value will no longer ` +
|
||||||
`Use kebab-case key name modifiers instead.`,
|
`trigger on array mutation unless the "deep" option is specified. ` +
|
||||||
link: `https://v3.vuejs.org/guide/migration/keycode-modifiers.html`
|
`If current usage is intended, you can disable the compat behavior and ` +
|
||||||
|
`suppress this warning with:` +
|
||||||
|
`\n\n configureCompat({ ${
|
||||||
|
DeprecationTypes.WATCH_ARRAY
|
||||||
|
}: { enabled: false }})\n`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/watch.html`
|
||||||
},
|
},
|
||||||
|
|
||||||
[DeprecationTypes.PROPS_DEFAULT_THIS]: {
|
[DeprecationTypes.PROPS_DEFAULT_THIS]: {
|
||||||
@ -212,16 +221,38 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
link: `https://v3.vuejs.org/guide/migration/custom-directives.html`
|
link: `https://v3.vuejs.org/guide/migration/custom-directives.html`
|
||||||
},
|
},
|
||||||
|
|
||||||
[DeprecationTypes.WATCH_ARRAY]: {
|
[DeprecationTypes.V_ON_KEYCODE_MODIFIER]: {
|
||||||
message:
|
message:
|
||||||
`"watch" option or vm.$watch on an array value will no longer ` +
|
`Using keyCode as v-on modifier is no longer supported. ` +
|
||||||
`trigger on array mutation unless the "deep" option is specified. ` +
|
`Use kebab-case key name modifiers instead.`,
|
||||||
`If current usage is intended, you can disable the compat behavior and ` +
|
link: `https://v3.vuejs.org/guide/migration/keycode-modifiers.html`
|
||||||
`suppress this warning with:` +
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.ATTR_FALSE_VALUE]: {
|
||||||
|
message: (name: string) =>
|
||||||
|
`Attribute "${name}" with v-bind value \`false\` will render ` +
|
||||||
|
`${name}="false" instead of removing it in Vue 3. To remove the attribute, ` +
|
||||||
|
`use \`null\` or \`undefined\` instead. If the usage is intended, ` +
|
||||||
|
`you can disable the compat behavior and suppress this warning with:` +
|
||||||
`\n\n configureCompat({ ${
|
`\n\n configureCompat({ ${
|
||||||
DeprecationTypes.WATCH_ARRAY
|
DeprecationTypes.ATTR_FALSE_VALUE
|
||||||
}: { enabled: false }})\n`,
|
}: { enabled: false }})\n`,
|
||||||
link: `https://v3.vuejs.org/guide/migration/watch.html`
|
link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.ATTR_ENUMERATED_COERSION]: {
|
||||||
|
message: (name: string, value: any, coerced: string) =>
|
||||||
|
`Enumerated attribute "${name}" with v-bind value \`${value}\` will ` +
|
||||||
|
`${
|
||||||
|
value === null ? `be removed` : `render the value as-is`
|
||||||
|
} instead of coercing the value to "${coerced}" in Vue 3. ` +
|
||||||
|
`Always use explicit "true" or "false" values for enumerated attributes. ` +
|
||||||
|
`If the usage is intended, ` +
|
||||||
|
`you can disable the compat behavior and suppress this warning with:` +
|
||||||
|
`\n\n configureCompat({ ${
|
||||||
|
DeprecationTypes.ATTR_ENUMERATED_COERSION
|
||||||
|
}: { enabled: false }})\n`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html`
|
||||||
},
|
},
|
||||||
|
|
||||||
[DeprecationTypes.TRANSITION_CLASSES]: {
|
[DeprecationTypes.TRANSITION_CLASSES]: {
|
||||||
|
@ -15,6 +15,10 @@ export function patchAttr(
|
|||||||
el.setAttributeNS(xlinkNS, key, value)
|
el.setAttributeNS(xlinkNS, key, value)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (__COMPAT__ && compatCoerceAttr(el, key, value)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// note we are only checking boolean attributes that don't have a
|
// note we are only checking boolean attributes that don't have a
|
||||||
// corresponding dom prop of the same name here.
|
// corresponding dom prop of the same name here.
|
||||||
const isBoolean = isSpecialBooleanAttr(key)
|
const isBoolean = isSpecialBooleanAttr(key)
|
||||||
@ -25,3 +29,46 @@ export function patchAttr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2.x compat
|
||||||
|
import { makeMap, NOOP } from '@vue/shared'
|
||||||
|
import { compatUtils, DeprecationTypes } from '@vue/runtime-core'
|
||||||
|
|
||||||
|
const isEnumeratedAttr = __COMPAT__
|
||||||
|
? /*#__PURE__*/ makeMap('contenteditable,draggable,spellcheck')
|
||||||
|
: NOOP
|
||||||
|
|
||||||
|
export function compatCoerceAttr(
|
||||||
|
el: Element,
|
||||||
|
key: string,
|
||||||
|
value: unknown
|
||||||
|
): boolean {
|
||||||
|
if (isEnumeratedAttr(key)) {
|
||||||
|
const v2CocercedValue =
|
||||||
|
value === null
|
||||||
|
? 'false'
|
||||||
|
: typeof value !== 'boolean' && value !== undefined
|
||||||
|
? 'true'
|
||||||
|
: null
|
||||||
|
if (
|
||||||
|
v2CocercedValue &&
|
||||||
|
compatUtils.softAssertCompatEnabled(
|
||||||
|
DeprecationTypes.ATTR_ENUMERATED_COERSION,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
v2CocercedValue
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
el.setAttribute(key, v2CocercedValue)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
value === false &&
|
||||||
|
!isSpecialBooleanAttr(key) &&
|
||||||
|
compatUtils.softAssertCompatEnabled(DeprecationTypes.ATTR_FALSE_VALUE, key)
|
||||||
|
) {
|
||||||
|
el.removeAttribute(key)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user