wip: support per-component compatConfig

This commit is contained in:
Evan You 2021-04-08 17:11:05 -04:00
parent f8e2361d83
commit 3db29eb773
4 changed files with 48 additions and 35 deletions

View File

@ -1,13 +1,11 @@
import { extend } from '@vue/shared' import { extend } from '@vue/shared'
import { ComponentOptions, getCurrentInstance } from '../component'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { DeprecationTypes, warnDeprecation } from './deprecations'
export type CompatConfig = Partial< export type CompatConfig = Partial<
Record<DeprecationTypes, DeprecationConfigItem> Record<DeprecationTypes, boolean | 'suppress-warning'>
> > & {
MODE?: 2 | 3
export interface DeprecationConfigItem {
warning?: boolean // default: true
enabled?: boolean // default: true
} }
const globalCompatConfig: CompatConfig = {} const globalCompatConfig: CompatConfig = {}
@ -16,15 +14,24 @@ export function configureCompat(config: CompatConfig) {
extend(globalCompatConfig, config) extend(globalCompatConfig, config)
} }
export function getCompatConfig( export function getCompatConfigForKey(key: DeprecationTypes | 'MODE') {
key: DeprecationTypes const instance = getCurrentInstance()
): DeprecationConfigItem | undefined { const instanceConfig =
instance && (instance.type as ComponentOptions).compatConfig
if (instanceConfig && key in instanceConfig) {
return instanceConfig[key]
}
return globalCompatConfig[key] return globalCompatConfig[key]
} }
export function isCompatEnabled(key: DeprecationTypes): boolean { export function isCompatEnabled(key: DeprecationTypes): boolean {
const config = getCompatConfig(key) const mode = getCompatConfigForKey('MODE') || 2
return !config || config.enabled !== false const val = getCompatConfigForKey(key)
if (mode === 2) {
return val !== false
} else {
return val === true || val === 'suppress-warning'
}
} }
export function assertCompatEnabled(key: DeprecationTypes, ...args: any[]) { export function assertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
@ -45,9 +52,9 @@ export function softAssertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
// disable features that conflict with v3 behavior // disable features that conflict with v3 behavior
if (__TEST__) { if (__TEST__) {
configureCompat({ configureCompat({
COMPONENT_ASYNC: { enabled: false }, COMPONENT_ASYNC: false,
COMPONENT_FUNCTIONAL: { enabled: false }, COMPONENT_FUNCTIONAL: false,
WATCH_ARRAY: { enabled: false }, WATCH_ARRAY: false,
INSTANCE_ATTRS_CLASS_STYLE: { enabled: false } INSTANCE_ATTRS_CLASS_STYLE: false
}) })
} }

View File

@ -5,7 +5,7 @@ import {
isRuntimeOnly isRuntimeOnly
} from '../component' } from '../component'
import { warn } from '../warning' import { warn } from '../warning'
import { getCompatConfig } from './compatConfig' import { getCompatConfigForKey, isCompatEnabled } from './compatConfig'
export const enum DeprecationTypes { export const enum DeprecationTypes {
GLOBAL_MOUNT = 'GLOBAL_MOUNT', GLOBAL_MOUNT = 'GLOBAL_MOUNT',
@ -203,10 +203,10 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`Components with inheritAttrs: false will no longer auto-inherit ` + `Components with inheritAttrs: false will no longer auto-inherit ` +
`class/style on its root element. If your code relies on this behavior, ` + `class/style on its root element. If your code relies on this behavior, ` +
`you may see broken styling and need to adjust your CSS. Otherwise, ` + `you may see broken styling and need to adjust your CSS. Otherwise, ` +
`you can suppress this warning with:` + `you can disable the compat behavior and suppress this warning with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${
DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE
}: { warning: false }})\n`, }: false )\n`,
link: `https://v3.vuejs.org/guide/migration/attrs-includes-class-style.html` link: `https://v3.vuejs.org/guide/migration/attrs-includes-class-style.html`
}, },
@ -238,9 +238,7 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`trigger on array mutation unless the "deep" option is specified. ` + `trigger on array mutation unless the "deep" option is specified. ` +
`If current usage is intended, you can disable the compat behavior and ` + `If current usage is intended, you can disable the compat behavior and ` +
`suppress this warning with:` + `suppress this warning with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${DeprecationTypes.WATCH_ARRAY}: false })\n`,
DeprecationTypes.WATCH_ARRAY
}: { enabled: false }})\n`,
link: `https://v3.vuejs.org/guide/migration/watch.html` link: `https://v3.vuejs.org/guide/migration/watch.html`
}, },
@ -273,7 +271,7 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`you can disable the compat behavior and suppress this warning with:` + `you can disable the compat behavior and suppress this warning with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${
DeprecationTypes.ATTR_FALSE_VALUE DeprecationTypes.ATTR_FALSE_VALUE
}: { enabled: false }})\n`, }: false })\n`,
link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html` link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html`
}, },
@ -288,7 +286,7 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`you can disable the compat behavior and suppress this warning with:` + `you can disable the compat behavior and suppress this warning with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${
DeprecationTypes.ATTR_ENUMERATED_COERSION DeprecationTypes.ATTR_ENUMERATED_COERSION
}: { enabled: false }})\n`, }: false })\n`,
link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html` link: `https://v3.vuejs.org/guide/migration/attribute-coercion.html`
}, },
@ -304,7 +302,7 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`warning with:` + `warning with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${
DeprecationTypes.TRANSITION_GROUP_ROOT DeprecationTypes.TRANSITION_GROUP_ROOT
}: { enabled: false }})\n`, }: false })\n`,
link: `https://v3.vuejs.org/guide/migration/transition-group.html` link: `https://v3.vuejs.org/guide/migration/transition-group.html`
}, },
@ -335,7 +333,7 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
`then disable compat for legacy async components with:` + `then disable compat for legacy async components with:` +
`\n\n configureCompat({ ${ `\n\n configureCompat({ ${
DeprecationTypes.COMPONENT_ASYNC DeprecationTypes.COMPONENT_ASYNC
}: { enabled: false }})\n` }: false })\n`
) )
}, },
link: `https://v3.vuejs.org/guide/migration/functional-components.html` link: `https://v3.vuejs.org/guide/migration/functional-components.html`
@ -354,12 +352,8 @@ export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
} }
// check user config // check user config
const config = getCompatConfig(key) const config = getCompatConfigForKey(key)
if ( if (config === 'suppress-warning') {
config &&
(config.warning === false ||
(config.enabled === false && config.warning !== true))
) {
return return
} }
@ -391,4 +385,10 @@ export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
typeof message === 'function' ? message(...args) : message typeof message === 'function' ? message(...args) : message
}${link ? `\n Details: ${link}` : ``}` }${link ? `\n Details: ${link}` : ``}`
) )
if (!isCompatEnabled(key)) {
console.error(
`^ The above deprecation's compat behavior is disabled and will likely ` +
`lead to runtime errors.`
)
}
} }

View File

@ -67,7 +67,11 @@ import { callWithAsyncErrorHandling } from './errorHandling'
import { UnionToIntersection } from './helpers/typeUtils' import { UnionToIntersection } from './helpers/typeUtils'
import { deepMergeData } from './compat/data' import { deepMergeData } from './compat/data'
import { DeprecationTypes } from './compat/deprecations' import { DeprecationTypes } from './compat/deprecations'
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig' import {
CompatConfig,
isCompatEnabled,
softAssertCompatEnabled
} from './compat/compatConfig'
/** /**
* Interface for declaring custom options. * Interface for declaring custom options.
@ -374,6 +378,8 @@ interface LegacyOptions<
Mixin extends ComponentOptionsMixin, Mixin extends ComponentOptionsMixin,
Extends extends ComponentOptionsMixin Extends extends ComponentOptionsMixin
> { > {
compatConfig?: CompatConfig
// allow any custom options // allow any custom options
[key: string]: any [key: string]: any

View File

@ -88,9 +88,6 @@ import { isAsyncWrapper } from './apiAsyncComponent'
import { isCompatEnabled } from './compat/compatConfig' import { isCompatEnabled } from './compat/compatConfig'
import { DeprecationTypes } from './compat/deprecations' import { DeprecationTypes } from './compat/deprecations'
const isHookEventCompatEnabled =
__COMPAT__ && isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS)
export interface Renderer<HostElement = RendererElement> { export interface Renderer<HostElement = RendererElement> {
render: RootRenderFunction<HostElement> render: RootRenderFunction<HostElement>
createApp: CreateAppFunction<HostElement> createApp: CreateAppFunction<HostElement>
@ -445,6 +442,9 @@ function baseCreateRenderer(
options: RendererOptions, options: RendererOptions,
createHydrationFns?: typeof createHydrationFunctions createHydrationFns?: typeof createHydrationFunctions
): any { ): any {
const isHookEventCompatEnabled =
__COMPAT__ && isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS)
// compile-time feature flags check // compile-time feature flags check
if (__ESM_BUNDLER__ && !__TEST__) { if (__ESM_BUNDLER__ && !__TEST__) {
initFeatureFlags() initFeatureFlags()