wip: apply compat enabled flags to currently implemented features

This commit is contained in:
Evan You 2021-04-07 15:38:04 -04:00
parent 208bef5d97
commit 1c2c77eb9f
13 changed files with 189 additions and 126 deletions

View File

@ -33,8 +33,8 @@ import {
} from './errorHandling' } from './errorHandling'
import { queuePostRenderEffect } from './renderer' import { queuePostRenderEffect } from './renderer'
import { warn } from './warning' import { warn } from './warning'
import { DeprecationTypes, warnDeprecation } from './compat/deprecations' import { DeprecationTypes } from './compat/deprecations'
import { isCompatEnabled } from './compat/compatConfig' import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
export type WatchEffect = (onInvalidate: InvalidateCbRegistrator) => void export type WatchEffect = (onInvalidate: InvalidateCbRegistrator) => void
@ -224,11 +224,11 @@ function doWatch(
const baseGetter = getter const baseGetter = getter
getter = () => { getter = () => {
const val = baseGetter() const val = baseGetter()
if (isArray(val)) { if (
__DEV__ && warnDeprecation(DeprecationTypes.WATCH_ARRAY) isArray(val) &&
if (isCompatEnabled(DeprecationTypes.WATCH_ARRAY)) { softAssertCompatEnabled(DeprecationTypes.WATCH_ARRAY)
traverse(val) ) {
} traverse(val)
} }
return val return val
} }

View File

@ -2,12 +2,13 @@ import { ShapeFlags } from '@vue/shared/src'
import { ComponentInternalInstance } from '../component' import { ComponentInternalInstance } from '../component'
import { ComponentPublicInstance } from '../componentPublicInstance' import { ComponentPublicInstance } from '../componentPublicInstance'
import { VNode } from '../vnode' import { VNode } from '../vnode'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
export function getInstanceChildren( export function getInstanceChildren(
instance: ComponentInternalInstance instance: ComponentInternalInstance
): ComponentPublicInstance[] { ): ComponentPublicInstance[] {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_CHILDREN) assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN)
const root = instance.subTree const root = instance.subTree
const children: ComponentPublicInstance[] = [] const children: ComponentPublicInstance[] = []
if (root) { if (root) {

View File

@ -1,13 +1,13 @@
import { extend } from '@vue/shared' import { extend } from '@vue/shared'
import { DeprecationTypes } from './deprecations' import { DeprecationTypes, warnDeprecation } from './deprecations'
export type CompatConfig = Partial< export type CompatConfig = Partial<
Record<DeprecationTypes, DeprecationConfigItem> Record<DeprecationTypes, DeprecationConfigItem>
> >
export interface DeprecationConfigItem { export interface DeprecationConfigItem {
warning?: boolean // defaults to true warning?: boolean // default: true
mode?: 2 | 3 // defaults to 2 enabled?: boolean // default: true
} }
const globalCompatConfig: CompatConfig = {} const globalCompatConfig: CompatConfig = {}
@ -22,10 +22,22 @@ export function getCompatConfig(
return globalCompatConfig[key] return globalCompatConfig[key]
} }
/**
* @internal
*/
export function isCompatEnabled(key: DeprecationTypes): boolean { export function isCompatEnabled(key: DeprecationTypes): boolean {
const config = getCompatConfig(key) const config = getCompatConfig(key)
return !config || config.mode !== 3 return !config || config.enabled !== false
}
export function assertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
if (!isCompatEnabled(key)) {
throw new Error(`${key} compat has been disabled.`)
} else if (__DEV__) {
warnDeprecation(key, ...args)
}
}
export function softAssertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
if (__DEV__) {
warnDeprecation(key, ...args)
}
return isCompatEnabled(key)
} }

View File

@ -1,6 +1,7 @@
import { isArray } from '@vue/shared' import { isArray } from '@vue/shared'
import { ObjectDirective, DirectiveHook } from '../directives' import { ObjectDirective, DirectiveHook } from '../directives'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { softAssertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
export interface LegacyDirective { export interface LegacyDirective {
bind?: DirectiveHook bind?: DirectiveHook
@ -33,15 +34,14 @@ export function mapCompatDirectiveHook(
mappedName.forEach(name => { mappedName.forEach(name => {
const mappedHook = dir[name] const mappedHook = dir[name]
if (mappedHook) { if (mappedHook) {
__DEV__ && softAssertCompatEnabled(DeprecationTypes.CUSTOM_DIR, mappedName, name)
warnDeprecation(DeprecationTypes.CUSTOM_DIR, mappedName, name)
hook.push(mappedHook) hook.push(mappedHook)
} }
}) })
return hook.length ? hook : undefined return hook.length ? hook : undefined
} else { } else {
if (__DEV__ && dir[mappedName]) { if (dir[mappedName]) {
warnDeprecation(DeprecationTypes.CUSTOM_DIR, mappedName, name) softAssertCompatEnabled(DeprecationTypes.CUSTOM_DIR, mappedName, name)
} }
return dir[mappedName] return dir[mappedName]
} }

View File

@ -3,21 +3,22 @@ import { warn } from '../warning'
import { getCompatConfig } from './compatConfig' import { getCompatConfig } from './compatConfig'
export const enum DeprecationTypes { export const enum DeprecationTypes {
GLOBAL_MOUNT = 'GLOBAL_MOUNT',
GLOBAL_MOUNT_CONTAINER = 'GLOBAL_MOUNT_CONTAINER',
GLOBAL_EXTEND = 'GLOBAL_EXTEND',
GLOBAL_PROTOTYPE = 'GLOBAL_PROTOTYPE',
GLOBAL_SET = 'GLOBAL_SET',
GLOBAL_DELETE = 'GLOBAL_DELETE',
GLOBAL_OBSERVABLE = 'GLOBAL_OBSERVABLE',
CONFIG_SILENT = 'CONFIG_SILENT', CONFIG_SILENT = 'CONFIG_SILENT',
CONFIG_DEVTOOLS = 'CONFIG_DEVTOOLS', CONFIG_DEVTOOLS = 'CONFIG_DEVTOOLS',
CONFIG_KEY_CODES = 'CONFIG_KEY_CODES', CONFIG_KEY_CODES = 'CONFIG_KEY_CODES',
CONFIG_PRODUCTION_TIP = 'CONFIG_PRODUCTION_TIP', CONFIG_PRODUCTION_TIP = 'CONFIG_PRODUCTION_TIP',
CONFIG_IGNORED_ELEMENTS = 'CONFIG_IGNORED_ELEMENTS', CONFIG_IGNORED_ELEMENTS = 'CONFIG_IGNORED_ELEMENTS',
GLOBAL_PROTOTYPE = 'GLOBAL_PROTOTYPE',
GLOBAL_SET = 'GLOBAL_SET',
GLOBAL_DELETE = 'GLOBAL_DELETE',
GLOBAL_OBSERVABLE = 'GLOBAL_OBSERVABLE',
GLOBAL_MOUNT_CONTAINER = 'GLOBAL_MOUNT_CONTAINER',
INSTANCE_SET = 'INSTANCE_SET', INSTANCE_SET = 'INSTANCE_SET',
INSTANCE_DELETE = 'INSTANCE_DELETE', INSTANCE_DELETE = 'INSTANCE_DELETE',
INSTANCE_MOUNT = 'INSTANCE_MOUNT',
INSTANCE_DESTROY = 'INSTANCE_DESTROY', INSTANCE_DESTROY = 'INSTANCE_DESTROY',
INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER', INSTANCE_EVENT_EMITTER = 'INSTANCE_EVENT_EMITTER',
INSTANCE_EVENT_HOOKS = 'INSTANCE_EVENT_HOOKS', INSTANCE_EVENT_HOOKS = 'INSTANCE_EVENT_HOOKS',
@ -39,7 +40,55 @@ type DeprecationData = {
link?: string link?: string
} }
const deprecationMessages: Record<DeprecationTypes, DeprecationData> = { const deprecationData: Record<DeprecationTypes, DeprecationData> = {
[DeprecationTypes.GLOBAL_MOUNT]: {
message:
`The global app bootstrapping API has changed: vm.$mount() and the "el" ` +
`option have been removed. Use createApp(RootComponent).mount() instead.`,
link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
},
[DeprecationTypes.GLOBAL_MOUNT_CONTAINER]: {
message:
`Vue detected directives on the mount container. ` +
`In Vue 3, the container is no longer considered part of the template ` +
`and will not be processed/replaced.`,
link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
},
[DeprecationTypes.GLOBAL_EXTEND]: {
message:
`Vue.extend() has been removed in Vue 3. ` +
`Use defineComponent() instead.`,
link: `https://v3.vuejs.org/api/global-api.html#definecomponent`
},
[DeprecationTypes.GLOBAL_PROTOTYPE]: {
message:
`Vue.prototype is no longer available in Vue 3. ` +
`Use config.globalProperties instead.`,
link: `https://v3.vuejs.org/guide/migration/global-api.html#vue-prototype-replaced-by-config-globalproperties`
},
[DeprecationTypes.GLOBAL_SET]: {
message:
`Vue.set() has been removed as it is no longer needed in Vue 3. ` +
`Simply use native JavaScript mutations.`
},
[DeprecationTypes.GLOBAL_DELETE]: {
message:
`Vue.delete() has been removed as it is no longer needed in Vue 3. ` +
`Simply use native JavaScript mutations.`
},
[DeprecationTypes.GLOBAL_OBSERVABLE]: {
message:
`Vue.observable() has been removed. ` +
`Use \`import { reactive } from "vue"\` from Composition API instead.`,
link: `https://v3.vuejs.org/api/basic-reactivity.html`
},
[DeprecationTypes.CONFIG_SILENT]: { [DeprecationTypes.CONFIG_SILENT]: {
message: message:
`config.silent has been removed because it is not good practice to ` + `config.silent has been removed because it is not good practice to ` +
@ -79,40 +128,6 @@ const deprecationMessages: Record<DeprecationTypes, DeprecationData> = {
link: `https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement` link: `https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement`
}, },
[DeprecationTypes.GLOBAL_PROTOTYPE]: {
message:
`Vue.prototype is no longer available in Vue 3. ` +
`Use config.globalProperties instead.`,
link: `https://v3.vuejs.org/guide/migration/global-api.html#vue-prototype-replaced-by-config-globalproperties`
},
[DeprecationTypes.GLOBAL_SET]: {
message:
`Vue.set() has been removed as it is no longer needed in Vue 3. ` +
`Simply use native JavaScript mutations.`
},
[DeprecationTypes.GLOBAL_DELETE]: {
message:
`Vue.delete() has been removed as it is no longer needed in Vue 3. ` +
`Simply use native JavaScript mutations.`
},
[DeprecationTypes.GLOBAL_OBSERVABLE]: {
message:
`Vue.observable() has been removed. ` +
`Use \`import { reactive } from "vue"\` from Composition API instead.`,
link: `https://v3.vuejs.org/api/basic-reactivity.html`
},
[DeprecationTypes.GLOBAL_MOUNT_CONTAINER]: {
message:
`Vue detected directives on the mount container. ` +
`In Vue 3, the container is no longer considered part of the template ` +
`and will not be processed/replaced.`,
link: `https://v3.vuejs.org/guide/migration/mount-changes.html`
},
[DeprecationTypes.INSTANCE_SET]: { [DeprecationTypes.INSTANCE_SET]: {
message: message:
`vm.$set() has been removed as it is no longer needed in Vue 3. ` + `vm.$set() has been removed as it is no longer needed in Vue 3. ` +
@ -125,13 +140,6 @@ const deprecationMessages: Record<DeprecationTypes, DeprecationData> = {
`Simply use native JavaScript mutations.` `Simply use native JavaScript mutations.`
}, },
[DeprecationTypes.INSTANCE_MOUNT]: {
message:
`The global app bootstrapping API has changed: vm.$mount() and the "el" ` +
`option have been removed. Use createApp(RootComponent).mount() instead.`,
link: `https://v3.vuejs.org/guide/migration/global-api.html#mounting-app-instance`
},
[DeprecationTypes.INSTANCE_DESTROY]: { [DeprecationTypes.INSTANCE_DESTROY]: {
message: `vm.$destroy() has been removed. Use app.unmount() instead.`, message: `vm.$destroy() has been removed. Use app.unmount() instead.`,
link: `https://v3.vuejs.org/api/application-api.html#unmount` link: `https://v3.vuejs.org/api/application-api.html#unmount`
@ -227,7 +235,8 @@ export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
const config = getCompatConfig(key) const config = getCompatConfig(key)
if ( if (
config && config &&
(config.warning === false || (config.mode === 3 && config.warning !== true)) (config.warning === false ||
(config.enabled === false && config.warning !== true))
) { ) {
return return
} }
@ -239,7 +248,7 @@ export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
} }
hasWarned[dupKey] = true hasWarned[dupKey] = true
const { message, link } = deprecationMessages[key] const { message, link } = deprecationData[key]
warn( warn(
`(DEPRECATION ${key}) ${ `(DEPRECATION ${key}) ${
typeof message === 'function' ? message(...args) : message typeof message === 'function' ? message(...args) : message

View File

@ -1,7 +1,8 @@
import { isArray } from '@vue/shared' import { isArray } from '@vue/shared'
import { ComponentInternalInstance } from '../component' import { ComponentInternalInstance } from '../component'
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling' import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
interface EventRegistry { interface EventRegistry {
[event: string]: Function[] | undefined [event: string]: Function[] | undefined
@ -30,15 +31,13 @@ export function on(
if (isArray(event)) { if (isArray(event)) {
event.forEach(e => on(instance, e, fn)) event.forEach(e => on(instance, e, fn))
} else { } else {
if (event.startsWith('hook:')) {
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS)
} else {
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
}
const events = getRegistry(instance) const events = getRegistry(instance)
;(events[event] || (events[event] = [])).push(fn) ;(events[event] || (events[event] = [])).push(fn)
if (__DEV__) {
if (event.startsWith('hook:')) {
warnDeprecation(DeprecationTypes.INSTANCE_EVENT_HOOKS)
} else {
warnDeprecation(DeprecationTypes.INSTANCE_EVENT_EMITTER)
}
}
} }
return instance.proxy return instance.proxy
} }
@ -62,7 +61,7 @@ export function off(
event?: string, event?: string,
fn?: Function fn?: Function
) { ) {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_EVENT_EMITTER) assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
const vm = instance.proxy const vm = instance.proxy
// all // all
if (!arguments.length) { if (!arguments.length) {

View File

@ -29,7 +29,12 @@ import { warnDeprecation, DeprecationTypes } from './deprecations'
import { version } from '..' import { version } from '..'
import { LegacyConfig } from './globalConfig' import { LegacyConfig } from './globalConfig'
import { LegacyDirective } from './customDirective' import { LegacyDirective } from './customDirective'
import { configureCompat } from './compatConfig' import {
assertCompatEnabled,
configureCompat,
isCompatEnabled,
softAssertCompatEnabled
} from './compatConfig'
/** /**
* @deprecated the default `Vue` export has been removed in Vue 3. The type for * @deprecated the default `Vue` export has been removed in Vue 3. The type for
@ -91,9 +96,14 @@ export function createCompatVue(
const singletonApp = createApp({}) const singletonApp = createApp({})
function createCompatApp(options: ComponentOptions = {}, Ctor: any) { function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT)
const { data } = options const { data } = options
if (data && !isFunction(data)) { if (
__DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_FN) data &&
!isFunction(data) &&
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DATA_FN)
) {
options.data = () => data options.data = () => data
} }
@ -119,15 +129,20 @@ export function createCompatVue(
isCopyingConfig = false isCopyingConfig = false
// copy prototype augmentations as config.globalProperties // copy prototype augmentations as config.globalProperties
const isPrototypeEnabled = isCompatEnabled(
DeprecationTypes.GLOBAL_PROTOTYPE
)
let hasPrototypeAugmentations = false let hasPrototypeAugmentations = false
for (const key in Ctor.prototype) { for (const key in Ctor.prototype) {
if (key !== 'constructor') { if (key !== 'constructor') {
hasPrototypeAugmentations = true hasPrototypeAugmentations = true
} }
app.config.globalProperties[key] = Ctor.prototype[key] if (isPrototypeEnabled) {
app.config.globalProperties[key] = Ctor.prototype[key]
}
} }
if (hasPrototypeAugmentations) { if (__DEV__ && hasPrototypeAugmentations) {
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE) warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE)
} }
const vm = app._createRoot!(options) const vm = app._createRoot!(options)
@ -140,8 +155,11 @@ export function createCompatVue(
Vue.version = __VERSION__ Vue.version = __VERSION__
Vue.config = singletonApp.config Vue.config = singletonApp.config
Vue.nextTick = nextTick
Vue.extend = ((options: ComponentOptions = {}) => { Vue.extend = ((options: ComponentOptions = {}) => {
assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND)
function SubVue(inlineOptions?: ComponentOptions) { function SubVue(inlineOptions?: ComponentOptions) {
if (!inlineOptions) { if (!inlineOptions) {
return createCompatApp(options, SubVue) return createCompatApp(options, SubVue)
@ -161,24 +179,20 @@ export function createCompatVue(
return SubVue return SubVue
}) as any }) as any
Vue.nextTick = nextTick
Vue.set = (target, key, value) => { Vue.set = (target, key, value) => {
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_SET) assertCompatEnabled(DeprecationTypes.GLOBAL_SET)
target[key] = value target[key] = value
} }
Vue.delete = (target, key) => { Vue.delete = (target, key) => {
__DEV__ && warnDeprecation(DeprecationTypes.GLOBAL_DELETE) assertCompatEnabled(DeprecationTypes.GLOBAL_DELETE)
delete target[key] delete target[key]
} }
Vue.observable = __DEV__ Vue.observable = (target: any) => {
? (target: any) => { assertCompatEnabled(DeprecationTypes.GLOBAL_OBSERVABLE)
warnDeprecation(DeprecationTypes.GLOBAL_OBSERVABLE) return reactive(target)
return reactive(target) }
}
: reactive
Vue.use = (p, ...options) => { Vue.use = (p, ...options) => {
singletonApp.use(p, ...options) singletonApp.use(p, ...options)

View File

@ -1,6 +1,7 @@
import { isArray, isString } from '@vue/shared' import { isArray, isString } from '@vue/shared'
import { AppConfig } from '../apiCreateApp' import { AppConfig } from '../apiCreateApp'
import { isRuntimeOnly } from '../component' import { isRuntimeOnly } from '../component'
import { isCompatEnabled } from './compatConfig'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { DeprecationTypes, warnDeprecation } from './deprecations'
import { isCopyingConfig } from './global' import { isCopyingConfig } from './global'
@ -56,7 +57,12 @@ export function installLegacyConfigTraps(config: AppConfig) {
val = newVal val = newVal
// compat for runtime ignoredElements -> isCustomElement // compat for runtime ignoredElements -> isCustomElement
if (key === 'ignoredElements' && !isRuntimeOnly() && isArray(newVal)) { if (
key === 'ignoredElements' &&
isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS) &&
!isRuntimeOnly() &&
isArray(newVal)
) {
config.isCustomElement = tag => { config.isCustomElement = tag => {
return newVal.some( return newVal.some(
val => (isString(val) ? val === tag : val.test(tag)) val => (isString(val) ? val === tag : val.test(tag))

View File

@ -1,7 +1,8 @@
import { extend, NOOP } from '@vue/shared' import { extend, NOOP } from '@vue/shared'
import { PublicPropertiesMap } from '../componentPublicInstance' import { PublicPropertiesMap } from '../componentPublicInstance'
import { getInstanceChildren } from './children' import { getInstanceChildren } from './children'
import { DeprecationTypes, warnDeprecation } from './deprecations' import { assertCompatEnabled } from './compatConfig'
import { DeprecationTypes } from './deprecations'
import { off, on, once } from './eventEmitter' import { off, on, once } from './eventEmitter'
export function installCompatInstanceProperties(map: PublicPropertiesMap) { export function installCompatInstanceProperties(map: PublicPropertiesMap) {
@ -15,20 +16,20 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
extend(map, { extend(map, {
$set: () => { $set: () => {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_SET) assertCompatEnabled(DeprecationTypes.INSTANCE_SET)
return set return set
}, },
$delete: () => { $delete: () => {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_DELETE) assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE)
return del return del
}, },
$mount: i => { $mount: i => {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_MOUNT) assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT)
// root mount override from ./global.ts in installCompatMount // root mount override from ./global.ts in installCompatMount
return i.ctx._compat_mount || NOOP return i.ctx._compat_mount || NOOP
}, },
$destroy: i => { $destroy: i => {
__DEV__ && warnDeprecation(DeprecationTypes.INSTANCE_DESTROY) assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY)
// root destroy override from ./global.ts in installCompatMount // root destroy override from ./global.ts in installCompatMount
return i.ctx._compat_destroy || NOOP return i.ctx._compat_destroy || NOOP
}, },

View File

@ -66,7 +66,8 @@ import { VNodeChild } from './vnode'
import { callWithAsyncErrorHandling } from './errorHandling' 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, warnDeprecation } from './compat/deprecations' import { DeprecationTypes } from './compat/deprecations'
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
/** /**
* Interface for declaring custom options. * Interface for declaring custom options.
@ -805,12 +806,16 @@ export function applyOptions(
} }
if (__COMPAT__) { if (__COMPAT__) {
if (beforeDestroy) { if (
__DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_BEFORE_DESTROY) beforeDestroy &&
softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY)
) {
onBeforeUnmount(beforeDestroy.bind(publicThis)) onBeforeUnmount(beforeDestroy.bind(publicThis))
} }
if (destroyed) { if (
__DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DESTROYED) destroyed &&
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED)
) {
onUnmounted(destroyed.bind(publicThis)) onUnmounted(destroyed.bind(publicThis))
} }
} }
@ -911,7 +916,7 @@ function resolveData(
instance.data = reactive(data) instance.data = reactive(data)
} else { } else {
// existing data: this is a mixin or extends. // existing data: this is a mixin or extends.
if (__COMPAT__) { if (__COMPAT__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE)) {
deepMergeData(instance.data, data) deepMergeData(instance.data, data)
} else { } else {
extend(instance.data, data) extend(instance.data, data)

View File

@ -34,6 +34,8 @@ import { isEmitListener } from './componentEmits'
import { InternalObjectKey } from './vnode' import { InternalObjectKey } from './vnode'
import { AppContext } from './apiCreateApp' import { AppContext } from './apiCreateApp'
import { createPropsDefaultThis } from './compat/props' import { createPropsDefaultThis } from './compat/props'
import { isCompatEnabled } from './compat/compatConfig'
import { DeprecationTypes } from './compat/deprecations'
export type ComponentPropsOptions<P = Data> = export type ComponentPropsOptions<P = Data> =
| ComponentObjectPropsOptions<P> | ComponentObjectPropsOptions<P>
@ -343,10 +345,14 @@ function resolvePropValue(
value = propsDefaults[key] value = propsDefaults[key]
} else { } else {
setCurrentInstance(instance) setCurrentInstance(instance)
value = propsDefaults[key] = value = propsDefaults[key] = defaultValue.call(
__COMPAT__ && __DEV__ __COMPAT__ &&
? defaultValue.call(createPropsDefaultThis(key), props) __DEV__ &&
: defaultValue(props) isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS)
? createPropsDefaultThis(key)
: null,
props
)
setCurrentInstance(null) setCurrentInstance(null)
} }
} else { } else {

View File

@ -85,6 +85,11 @@ import {
} from './devtools' } from './devtools'
import { initFeatureFlags } from './featureFlags' import { initFeatureFlags } from './featureFlags'
import { isAsyncWrapper } from './apiAsyncComponent' import { isAsyncWrapper } from './apiAsyncComponent'
import { isCompatEnabled } from './compat/compatConfig'
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>
@ -1417,7 +1422,7 @@ function baseCreateRenderer(
if ((vnodeHook = props && props.onVnodeBeforeMount)) { if ((vnodeHook = props && props.onVnodeBeforeMount)) {
invokeVNodeHook(vnodeHook, parent, initialVNode) invokeVNodeHook(vnodeHook, parent, initialVNode)
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
instance.emit('hook:beforeMount') instance.emit('hook:beforeMount')
} }
@ -1475,7 +1480,7 @@ function baseCreateRenderer(
parentSuspense parentSuspense
) )
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
queuePostRenderEffect( queuePostRenderEffect(
() => instance.emit('hook:mounted'), () => instance.emit('hook:mounted'),
parentSuspense parentSuspense
@ -1487,7 +1492,7 @@ function baseCreateRenderer(
// since the hook may be injected by a child keep-alive // since the hook may be injected by a child keep-alive
if (initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) { if (initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
instance.a && queuePostRenderEffect(instance.a, parentSuspense) instance.a && queuePostRenderEffect(instance.a, parentSuspense)
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
queuePostRenderEffect( queuePostRenderEffect(
() => instance.emit('hook:activated'), () => instance.emit('hook:activated'),
parentSuspense parentSuspense
@ -1528,7 +1533,7 @@ function baseCreateRenderer(
if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) { if ((vnodeHook = next.props && next.props.onVnodeBeforeUpdate)) {
invokeVNodeHook(vnodeHook, parent, next, vnode) invokeVNodeHook(vnodeHook, parent, next, vnode)
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
instance.emit('hook:beforeUpdate') instance.emit('hook:beforeUpdate')
} }
@ -1578,7 +1583,7 @@ function baseCreateRenderer(
parentSuspense parentSuspense
) )
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
queuePostRenderEffect( queuePostRenderEffect(
() => instance.emit('hook:updated'), () => instance.emit('hook:updated'),
parentSuspense parentSuspense
@ -2239,7 +2244,7 @@ function baseCreateRenderer(
if (bum) { if (bum) {
invokeArrayFns(bum) invokeArrayFns(bum)
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
instance.emit('hook:beforeDestroy') instance.emit('hook:beforeDestroy')
} }
@ -2258,7 +2263,7 @@ function baseCreateRenderer(
if (um) { if (um) {
queuePostRenderEffect(um, parentSuspense) queuePostRenderEffect(um, parentSuspense)
} }
if (__COMPAT__) { if (__COMPAT__ && isHookEventCompatEnabled) {
queuePostRenderEffect( queuePostRenderEffect(
() => instance.emit('hook:destroyed'), () => instance.emit('hook:destroyed'),
parentSuspense parentSuspense

View File

@ -57,10 +57,12 @@ const keyNames: Record<string, string | string[]> = {
* @private * @private
*/ */
export const withKeys = (fn: Function, modifiers: string[]) => { export const withKeys = (fn: Function, modifiers: string[]) => {
let keyCodes: LegacyConfig['keyCodes'] let globalKeyCodes: LegacyConfig['keyCodes']
if (__COMPAT__) { if (__COMPAT__) {
keyCodes = ((getCurrentInstance()!.appContext if (compatUtils.isCompatEnabled(DeprecationTypes.CONFIG_KEY_CODES)) {
.config as any) as LegacyConfig).keyCodes globalKeyCodes = ((getCurrentInstance()!.appContext
.config as any) as LegacyConfig).keyCodes
}
if (__DEV__ && modifiers.some(m => /^\d+$/.test(m))) { if (__DEV__ && modifiers.some(m => /^\d+$/.test(m))) {
compatUtils.warnDeprecation(DeprecationTypes.V_ON_KEYCODE_MODIFIER) compatUtils.warnDeprecation(DeprecationTypes.V_ON_KEYCODE_MODIFIER)
} }
@ -78,12 +80,15 @@ export const withKeys = (fn: Function, modifiers: string[]) => {
if (__COMPAT__) { if (__COMPAT__) {
const keyCode = String(event.keyCode) const keyCode = String(event.keyCode)
if (modifiers.some(mod => mod == keyCode)) { if (
compatUtils.isCompatEnabled(DeprecationTypes.V_ON_KEYCODE_MODIFIER) &&
modifiers.some(mod => mod == keyCode)
) {
return fn(event) return fn(event)
} }
if (keyCodes) { if (globalKeyCodes) {
for (const mod of modifiers) { for (const mod of modifiers) {
const codes = keyCodes[mod] const codes = globalKeyCodes[mod]
if (codes) { if (codes) {
const matches = isArray(codes) const matches = isArray(codes)
? codes.some(code => String(code) === keyCode) ? codes.some(code => String(code) === keyCode)