wip: render function compat
This commit is contained in:
parent
457a56e331
commit
f05d6dfd98
@ -1,16 +0,0 @@
|
|||||||
import Vue from '@vue/compat'
|
|
||||||
|
|
||||||
test('should work', async () => {
|
|
||||||
const el = document.createElement('div')
|
|
||||||
el.innerHTML = `{{ msg }}`
|
|
||||||
new Vue({
|
|
||||||
el,
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
msg: 'hello'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
expect('global app bootstrapping API has changed').toHaveBeenWarned()
|
|
||||||
expect(el.innerHTML).toBe('hello')
|
|
||||||
})
|
|
18
packages/runtime-core/src/compat/__tests__/global.spec.ts
Normal file
18
packages/runtime-core/src/compat/__tests__/global.spec.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Vue from '@vue/compat'
|
||||||
|
|
||||||
|
describe('compat: global API', () => {
|
||||||
|
test('should work', async () => {
|
||||||
|
const el = document.createElement('div')
|
||||||
|
el.innerHTML = `{{ msg }}`
|
||||||
|
new Vue({
|
||||||
|
el,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
msg: 'hello'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
expect('global app bootstrapping API has changed').toHaveBeenWarned()
|
||||||
|
expect(el.innerHTML).toBe('hello')
|
||||||
|
})
|
||||||
|
})
|
149
packages/runtime-core/src/compat/__tests__/renderFn.spec.ts
Normal file
149
packages/runtime-core/src/compat/__tests__/renderFn.spec.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import { ShapeFlags } from '@vue/shared/src'
|
||||||
|
import { createComponentInstance } from '../../component'
|
||||||
|
import { setCurrentRenderingInstance } from '../../componentRenderContext'
|
||||||
|
import { DirectiveBinding } from '../../directives'
|
||||||
|
import { createVNode } from '../../vnode'
|
||||||
|
import { compatH as h } from '../renderFn'
|
||||||
|
|
||||||
|
describe('compat: render function', () => {
|
||||||
|
const mockDir = {}
|
||||||
|
const mockChildComp = {}
|
||||||
|
const mockComponent = {
|
||||||
|
directives: {
|
||||||
|
mockDir
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
foo: mockChildComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mockInstance = createComponentInstance(
|
||||||
|
createVNode(mockComponent),
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
beforeEach(() => {
|
||||||
|
setCurrentRenderingInstance(mockInstance)
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
setCurrentRenderingInstance(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('string component lookup', () => {
|
||||||
|
expect(h('foo')).toMatchObject({
|
||||||
|
type: mockChildComp
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('class / style / attrs / domProps / props', () => {
|
||||||
|
expect(
|
||||||
|
h('div', {
|
||||||
|
class: 'foo',
|
||||||
|
style: { color: 'red' },
|
||||||
|
attrs: {
|
||||||
|
id: 'foo'
|
||||||
|
},
|
||||||
|
domProps: {
|
||||||
|
innerHTML: 'hi'
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
myProp: 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).toMatchObject({
|
||||||
|
props: {
|
||||||
|
class: 'foo',
|
||||||
|
style: { color: 'red' },
|
||||||
|
id: 'foo',
|
||||||
|
innerHTML: 'hi',
|
||||||
|
myProp: 'foo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('on / nativeOn', () => {
|
||||||
|
const fn = () => {}
|
||||||
|
expect(
|
||||||
|
h('div', {
|
||||||
|
on: {
|
||||||
|
click: fn,
|
||||||
|
fooBar: fn
|
||||||
|
},
|
||||||
|
nativeOn: {
|
||||||
|
click: fn,
|
||||||
|
'bar-baz': fn
|
||||||
|
}
|
||||||
|
})
|
||||||
|
).toMatchObject({
|
||||||
|
props: {
|
||||||
|
onClick: fn, // should dedupe
|
||||||
|
onFooBar: fn,
|
||||||
|
'onBar-baz': fn
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('directives', () => {
|
||||||
|
expect(
|
||||||
|
h('div', {
|
||||||
|
directives: [
|
||||||
|
{
|
||||||
|
name: 'mock-dir',
|
||||||
|
value: '2',
|
||||||
|
// expression: '1 + 1',
|
||||||
|
arg: 'foo',
|
||||||
|
modifiers: {
|
||||||
|
bar: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
).toMatchObject({
|
||||||
|
dirs: [
|
||||||
|
{
|
||||||
|
dir: mockDir,
|
||||||
|
instance: mockInstance.proxy,
|
||||||
|
value: '2',
|
||||||
|
oldValue: void 0,
|
||||||
|
arg: 'foo',
|
||||||
|
modifiers: {
|
||||||
|
bar: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] as DirectiveBinding[]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('scopedSlots', () => {
|
||||||
|
const scopedSlots = {
|
||||||
|
default() {}
|
||||||
|
}
|
||||||
|
const vnode = h(mockComponent, {
|
||||||
|
scopedSlots
|
||||||
|
})
|
||||||
|
expect(vnode).toMatchObject({
|
||||||
|
children: scopedSlots
|
||||||
|
})
|
||||||
|
expect('scopedSlots' in vnode.props!).toBe(false)
|
||||||
|
expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('legacy named slot', () => {
|
||||||
|
const vnode = h(mockComponent, [
|
||||||
|
'text',
|
||||||
|
h('div', { slot: 'foo' }, 'one'),
|
||||||
|
h('div', { slot: 'bar' }, 'two'),
|
||||||
|
h('div', { slot: 'foo' }, 'three'),
|
||||||
|
h('div', 'four')
|
||||||
|
])
|
||||||
|
expect(vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN).toBeTruthy()
|
||||||
|
const slots = vnode.children as any
|
||||||
|
|
||||||
|
// default
|
||||||
|
expect(slots.default()).toMatchObject(['text', { children: 'four' }])
|
||||||
|
expect(slots.foo()).toMatchObject([
|
||||||
|
{ children: 'one' },
|
||||||
|
{ children: 'three' }
|
||||||
|
])
|
||||||
|
expect(slots.bar()).toMatchObject([{ children: 'two' }])
|
||||||
|
})
|
||||||
|
})
|
@ -1,5 +1,5 @@
|
|||||||
import { extend } from '@vue/shared'
|
import { extend } from '@vue/shared'
|
||||||
import { ComponentOptions, getCurrentInstance } from '../component'
|
import { ComponentInternalInstance, ComponentOptions } from '../component'
|
||||||
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
||||||
|
|
||||||
export type CompatConfig = Partial<
|
export type CompatConfig = Partial<
|
||||||
@ -14,8 +14,10 @@ export function configureCompat(config: CompatConfig) {
|
|||||||
extend(globalCompatConfig, config)
|
extend(globalCompatConfig, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCompatConfigForKey(key: DeprecationTypes | 'MODE') {
|
export function getCompatConfigForKey(
|
||||||
const instance = getCurrentInstance()
|
key: DeprecationTypes | 'MODE',
|
||||||
|
instance: ComponentInternalInstance | null
|
||||||
|
) {
|
||||||
const instanceConfig =
|
const instanceConfig =
|
||||||
instance && (instance.type as ComponentOptions).compatConfig
|
instance && (instance.type as ComponentOptions).compatConfig
|
||||||
if (instanceConfig && key in instanceConfig) {
|
if (instanceConfig && key in instanceConfig) {
|
||||||
@ -24,9 +26,12 @@ export function getCompatConfigForKey(key: DeprecationTypes | 'MODE') {
|
|||||||
return globalCompatConfig[key]
|
return globalCompatConfig[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCompatEnabled(key: DeprecationTypes): boolean {
|
export function isCompatEnabled(
|
||||||
const mode = getCompatConfigForKey('MODE') || 2
|
key: DeprecationTypes,
|
||||||
const val = getCompatConfigForKey(key)
|
instance: ComponentInternalInstance | null
|
||||||
|
): boolean {
|
||||||
|
const mode = getCompatConfigForKey('MODE', instance) || 2
|
||||||
|
const val = getCompatConfigForKey(key, instance)
|
||||||
if (mode === 2) {
|
if (mode === 2) {
|
||||||
return val !== false
|
return val !== false
|
||||||
} else {
|
} else {
|
||||||
@ -34,19 +39,27 @@ export function isCompatEnabled(key: DeprecationTypes): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
|
export function assertCompatEnabled(
|
||||||
if (!isCompatEnabled(key)) {
|
key: DeprecationTypes,
|
||||||
|
instance: ComponentInternalInstance | null,
|
||||||
|
...args: any[]
|
||||||
|
) {
|
||||||
|
if (!isCompatEnabled(key, instance)) {
|
||||||
throw new Error(`${key} compat has been disabled.`)
|
throw new Error(`${key} compat has been disabled.`)
|
||||||
} else if (__DEV__) {
|
} else if (__DEV__) {
|
||||||
warnDeprecation(key, ...args)
|
warnDeprecation(key, instance, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function softAssertCompatEnabled(key: DeprecationTypes, ...args: any[]) {
|
export function softAssertCompatEnabled(
|
||||||
|
key: DeprecationTypes,
|
||||||
|
instance: ComponentInternalInstance | null,
|
||||||
|
...args: any[]
|
||||||
|
) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warnDeprecation(key, ...args)
|
warnDeprecation(key, instance, ...args)
|
||||||
}
|
}
|
||||||
return isCompatEnabled(key)
|
return isCompatEnabled(key, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable features that conflict with v3 behavior
|
// disable features that conflict with v3 behavior
|
||||||
|
@ -2,6 +2,7 @@ import { isArray, isFunction, isObject, isPromise } from '@vue/shared'
|
|||||||
import { defineAsyncComponent } from '../apiAsyncComponent'
|
import { defineAsyncComponent } from '../apiAsyncComponent'
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
|
ComponentInternalInstance,
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
FunctionalComponent,
|
FunctionalComponent,
|
||||||
getCurrentInstance
|
getCurrentInstance
|
||||||
@ -14,12 +15,18 @@ import { DeprecationTypes, warnDeprecation } from './deprecations'
|
|||||||
import { getCompatListeners } from './instanceListeners'
|
import { getCompatListeners } from './instanceListeners'
|
||||||
import { compatH } from './renderFn'
|
import { compatH } from './renderFn'
|
||||||
|
|
||||||
export function convertLegacyComponent(comp: any): Component {
|
export function convertLegacyComponent(
|
||||||
|
comp: any,
|
||||||
|
instance: ComponentInternalInstance | null
|
||||||
|
): Component {
|
||||||
// 2.x async component
|
// 2.x async component
|
||||||
// since after disabling this, plain functions are still valid usage, do not
|
// since after disabling this, plain functions are still valid usage, do not
|
||||||
// use softAssert here.
|
// use softAssert here.
|
||||||
if (isFunction(comp) && isCompatEnabled(DeprecationTypes.COMPONENT_ASYNC)) {
|
if (
|
||||||
__DEV__ && warnDeprecation(DeprecationTypes.COMPONENT_ASYNC, comp)
|
isFunction(comp) &&
|
||||||
|
isCompatEnabled(DeprecationTypes.COMPONENT_ASYNC, instance)
|
||||||
|
) {
|
||||||
|
__DEV__ && warnDeprecation(DeprecationTypes.COMPONENT_ASYNC, instance, comp)
|
||||||
return convertLegacyAsyncComponent(comp)
|
return convertLegacyAsyncComponent(comp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +34,11 @@ export function convertLegacyComponent(comp: any): Component {
|
|||||||
if (
|
if (
|
||||||
isObject(comp) &&
|
isObject(comp) &&
|
||||||
comp.functional &&
|
comp.functional &&
|
||||||
softAssertCompatEnabled(DeprecationTypes.COMPONENT_FUNCTIONAL, comp)
|
softAssertCompatEnabled(
|
||||||
|
DeprecationTypes.COMPONENT_FUNCTIONAL,
|
||||||
|
instance,
|
||||||
|
comp
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
return convertLegacyFunctionalComponent(comp)
|
return convertLegacyFunctionalComponent(comp)
|
||||||
}
|
}
|
||||||
@ -92,7 +103,7 @@ const normalizedFunctionalComponentMap = new Map<
|
|||||||
FunctionalComponent
|
FunctionalComponent
|
||||||
>()
|
>()
|
||||||
|
|
||||||
const legacySlotProxyHandlers: ProxyHandler<InternalSlots> = {
|
export const legacySlotProxyHandlers: ProxyHandler<InternalSlots> = {
|
||||||
get(target, key: string) {
|
get(target, key: string) {
|
||||||
const slot = target[key]
|
const slot = target[key]
|
||||||
return slot && slot()
|
return slot && slot()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { isArray } from '@vue/shared'
|
import { isArray } from '@vue/shared'
|
||||||
|
import { ComponentInternalInstance } from '../component'
|
||||||
import { ObjectDirective, DirectiveHook } from '../directives'
|
import { ObjectDirective, DirectiveHook } from '../directives'
|
||||||
import { softAssertCompatEnabled } from './compatConfig'
|
import { softAssertCompatEnabled } from './compatConfig'
|
||||||
import { DeprecationTypes } from './deprecations'
|
import { DeprecationTypes } from './deprecations'
|
||||||
@ -25,7 +26,8 @@ const legacyDirectiveHookMap: Partial<
|
|||||||
|
|
||||||
export function mapCompatDirectiveHook(
|
export function mapCompatDirectiveHook(
|
||||||
name: keyof ObjectDirective,
|
name: keyof ObjectDirective,
|
||||||
dir: ObjectDirective & LegacyDirective
|
dir: ObjectDirective & LegacyDirective,
|
||||||
|
instance: ComponentInternalInstance | null
|
||||||
): DirectiveHook | DirectiveHook[] | undefined {
|
): DirectiveHook | DirectiveHook[] | undefined {
|
||||||
const mappedName = legacyDirectiveHookMap[name]
|
const mappedName = legacyDirectiveHookMap[name]
|
||||||
if (mappedName) {
|
if (mappedName) {
|
||||||
@ -34,14 +36,24 @@ export function mapCompatDirectiveHook(
|
|||||||
mappedName.forEach(name => {
|
mappedName.forEach(name => {
|
||||||
const mappedHook = dir[name]
|
const mappedHook = dir[name]
|
||||||
if (mappedHook) {
|
if (mappedHook) {
|
||||||
softAssertCompatEnabled(DeprecationTypes.CUSTOM_DIR, mappedName, name)
|
softAssertCompatEnabled(
|
||||||
|
DeprecationTypes.CUSTOM_DIR,
|
||||||
|
instance,
|
||||||
|
mappedName,
|
||||||
|
name
|
||||||
|
)
|
||||||
hook.push(mappedHook)
|
hook.push(mappedHook)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return hook.length ? hook : undefined
|
return hook.length ? hook : undefined
|
||||||
} else {
|
} else {
|
||||||
if (dir[mappedName]) {
|
if (dir[mappedName]) {
|
||||||
softAssertCompatEnabled(DeprecationTypes.CUSTOM_DIR, mappedName, name)
|
softAssertCompatEnabled(
|
||||||
|
DeprecationTypes.CUSTOM_DIR,
|
||||||
|
instance,
|
||||||
|
mappedName,
|
||||||
|
name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return dir[mappedName]
|
return dir[mappedName]
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
import { isPlainObject } from '@vue/shared'
|
import { isPlainObject } from '@vue/shared'
|
||||||
|
import { ComponentInternalInstance } from '../component'
|
||||||
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
||||||
|
|
||||||
export function deepMergeData(to: any, from: any) {
|
export function deepMergeData(
|
||||||
|
to: any,
|
||||||
|
from: any,
|
||||||
|
instance: ComponentInternalInstance
|
||||||
|
) {
|
||||||
for (const key in from) {
|
for (const key in from) {
|
||||||
const toVal = to[key]
|
const toVal = to[key]
|
||||||
const fromVal = from[key]
|
const fromVal = from[key]
|
||||||
if (key in to && isPlainObject(toVal) && isPlainObject(fromVal)) {
|
if (key in to && isPlainObject(toVal) && isPlainObject(fromVal)) {
|
||||||
__DEV__ && warnDeprecation(DeprecationTypes.OPTIONS_DATA_MERGE, key)
|
__DEV__ &&
|
||||||
deepMergeData(toVal, fromVal)
|
warnDeprecation(DeprecationTypes.OPTIONS_DATA_MERGE, instance, key)
|
||||||
|
deepMergeData(toVal, fromVal, instance)
|
||||||
} else {
|
} else {
|
||||||
to[key] = fromVal
|
to[key] = fromVal
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ComponentInternalInstance,
|
||||||
formatComponentName,
|
formatComponentName,
|
||||||
getComponentName,
|
getComponentName,
|
||||||
getCurrentInstance,
|
getCurrentInstance,
|
||||||
@ -50,7 +51,9 @@ export const enum DeprecationTypes {
|
|||||||
TRANSITION_GROUP_ROOT = 'TRANSITION_GROUP_ROOT',
|
TRANSITION_GROUP_ROOT = 'TRANSITION_GROUP_ROOT',
|
||||||
|
|
||||||
COMPONENT_ASYNC = 'COMPONENT_ASYNC',
|
COMPONENT_ASYNC = 'COMPONENT_ASYNC',
|
||||||
COMPONENT_FUNCTIONAL = 'COMPONENT_FUNCTIONAL'
|
COMPONENT_FUNCTIONAL = 'COMPONENT_FUNCTIONAL',
|
||||||
|
|
||||||
|
RENDER_FUNCTION = 'RENDER_FUNCTION'
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
@ -340,25 +343,41 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
link: `https://v3.vuejs.org/guide/migration/functional-components.html`
|
link: `https://v3.vuejs.org/guide/migration/functional-components.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.RENDER_FUNCTION]: {
|
||||||
|
message:
|
||||||
|
`Vue 3's render function API has changed. ` +
|
||||||
|
`You can opt-in to the new API with:` +
|
||||||
|
`\n\n configureCompat({ ${
|
||||||
|
DeprecationTypes.RENDER_FUNCTION
|
||||||
|
}: false })\n` +
|
||||||
|
`\n (This can also be done per-component via the "compatConfig" option.)`,
|
||||||
|
link: `https://v3.vuejs.org/guide/migration/render-function-api.html`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceWarned: Record<string, true> = Object.create(null)
|
const instanceWarned: Record<string, true> = Object.create(null)
|
||||||
const warnCount: Record<string, number> = Object.create(null)
|
const warnCount: Record<string, number> = Object.create(null)
|
||||||
|
|
||||||
export function warnDeprecation(key: DeprecationTypes, ...args: any[]) {
|
export function warnDeprecation(
|
||||||
|
key: DeprecationTypes,
|
||||||
|
instance: ComponentInternalInstance | null,
|
||||||
|
...args: any[]
|
||||||
|
) {
|
||||||
if (!__DEV__) {
|
if (!__DEV__) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance = instance || getCurrentInstance()
|
||||||
|
|
||||||
// check user config
|
// check user config
|
||||||
const config = getCompatConfigForKey(key)
|
const config = getCompatConfigForKey(key, instance)
|
||||||
if (config === 'suppress-warning') {
|
if (config === 'suppress-warning') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const dupKey = key + args.join('')
|
const dupKey = key + args.join('')
|
||||||
const instance = getCurrentInstance()
|
|
||||||
const compName = instance && formatComponentName(instance, instance.type)
|
const compName = instance && formatComponentName(instance, instance.type)
|
||||||
|
|
||||||
// skip if the same warning is emitted for the same component type
|
// skip if the same warning is emitted for the same component type
|
||||||
@ -385,7 +404,7 @@ 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)) {
|
if (!isCompatEnabled(key, instance)) {
|
||||||
console.error(
|
console.error(
|
||||||
`^ The above deprecation's compat behavior is disabled and will likely ` +
|
`^ The above deprecation's compat behavior is disabled and will likely ` +
|
||||||
`lead to runtime errors.`
|
`lead to runtime errors.`
|
||||||
|
@ -96,13 +96,13 @@ 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)
|
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)
|
||||||
|
|
||||||
const { data } = options
|
const { data } = options
|
||||||
if (
|
if (
|
||||||
data &&
|
data &&
|
||||||
!isFunction(data) &&
|
!isFunction(data) &&
|
||||||
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DATA_FN)
|
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DATA_FN, null)
|
||||||
) {
|
) {
|
||||||
options.data = () => data
|
options.data = () => data
|
||||||
}
|
}
|
||||||
@ -130,7 +130,8 @@ export function createCompatVue(
|
|||||||
|
|
||||||
// copy prototype augmentations as config.globalProperties
|
// copy prototype augmentations as config.globalProperties
|
||||||
const isPrototypeEnabled = isCompatEnabled(
|
const isPrototypeEnabled = isCompatEnabled(
|
||||||
DeprecationTypes.GLOBAL_PROTOTYPE
|
DeprecationTypes.GLOBAL_PROTOTYPE,
|
||||||
|
null
|
||||||
)
|
)
|
||||||
let hasPrototypeAugmentations = false
|
let hasPrototypeAugmentations = false
|
||||||
for (const key in Ctor.prototype) {
|
for (const key in Ctor.prototype) {
|
||||||
@ -142,7 +143,7 @@ export function createCompatVue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (__DEV__ && hasPrototypeAugmentations) {
|
if (__DEV__ && hasPrototypeAugmentations) {
|
||||||
warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE)
|
warnDeprecation(DeprecationTypes.GLOBAL_PROTOTYPE, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const vm = app._createRoot!(options)
|
const vm = app._createRoot!(options)
|
||||||
@ -158,7 +159,7 @@ export function createCompatVue(
|
|||||||
Vue.nextTick = nextTick
|
Vue.nextTick = nextTick
|
||||||
|
|
||||||
Vue.extend = ((options: ComponentOptions = {}) => {
|
Vue.extend = ((options: ComponentOptions = {}) => {
|
||||||
assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND)
|
assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND, null)
|
||||||
|
|
||||||
function SubVue(inlineOptions?: ComponentOptions) {
|
function SubVue(inlineOptions?: ComponentOptions) {
|
||||||
if (!inlineOptions) {
|
if (!inlineOptions) {
|
||||||
@ -180,17 +181,17 @@ export function createCompatVue(
|
|||||||
}) as any
|
}) as any
|
||||||
|
|
||||||
Vue.set = (target, key, value) => {
|
Vue.set = (target, key, value) => {
|
||||||
assertCompatEnabled(DeprecationTypes.GLOBAL_SET)
|
assertCompatEnabled(DeprecationTypes.GLOBAL_SET, null)
|
||||||
target[key] = value
|
target[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.delete = (target, key) => {
|
Vue.delete = (target, key) => {
|
||||||
assertCompatEnabled(DeprecationTypes.GLOBAL_DELETE)
|
assertCompatEnabled(DeprecationTypes.GLOBAL_DELETE, null)
|
||||||
delete target[key]
|
delete target[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.observable = (target: any) => {
|
Vue.observable = (target: any) => {
|
||||||
assertCompatEnabled(DeprecationTypes.GLOBAL_OBSERVABLE)
|
assertCompatEnabled(DeprecationTypes.GLOBAL_OBSERVABLE, null)
|
||||||
return reactive(target)
|
return reactive(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ export function installCompatMount(
|
|||||||
for (let i = 0; i < container.attributes.length; i++) {
|
for (let i = 0; i < container.attributes.length; i++) {
|
||||||
const attr = container.attributes[i]
|
const attr = container.attributes[i]
|
||||||
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
if (attr.name !== 'v-cloak' && /^(v-|:|@)/.test(attr.name)) {
|
||||||
warnDeprecation(DeprecationTypes.GLOBAL_MOUNT_CONTAINER)
|
warnDeprecation(DeprecationTypes.GLOBAL_MOUNT_CONTAINER, null)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,14 +52,14 @@ export function installLegacyConfigTraps(config: AppConfig) {
|
|||||||
},
|
},
|
||||||
set(newVal) {
|
set(newVal) {
|
||||||
if (!isCopyingConfig) {
|
if (!isCopyingConfig) {
|
||||||
warnDeprecation(legacyConfigOptions[key])
|
warnDeprecation(legacyConfigOptions[key], null)
|
||||||
}
|
}
|
||||||
val = newVal
|
val = newVal
|
||||||
|
|
||||||
// compat for runtime ignoredElements -> isCustomElement
|
// compat for runtime ignoredElements -> isCustomElement
|
||||||
if (
|
if (
|
||||||
key === 'ignoredElements' &&
|
key === 'ignoredElements' &&
|
||||||
isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS) &&
|
isCompatEnabled(DeprecationTypes.CONFIG_IGNORED_ELEMENTS, null) &&
|
||||||
!isRuntimeOnly() &&
|
!isRuntimeOnly() &&
|
||||||
isArray(newVal)
|
isArray(newVal)
|
||||||
) {
|
) {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { extend, NOOP } from '@vue/shared'
|
import { extend, NOOP } from '@vue/shared'
|
||||||
import { PublicPropertiesMap } from '../componentPublicInstance'
|
import { PublicPropertiesMap } from '../componentPublicInstance'
|
||||||
import { getCompatChildren } from './instanceChildren'
|
import { getCompatChildren } from './instanceChildren'
|
||||||
import { assertCompatEnabled } from './compatConfig'
|
import { assertCompatEnabled, isCompatEnabled } from './compatConfig'
|
||||||
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
import { DeprecationTypes, warnDeprecation } from './deprecations'
|
||||||
import { off, on, once } from './instanceEventEmitter'
|
import { off, on, once } from './instanceEventEmitter'
|
||||||
import { getCompatListeners } from './instanceListeners'
|
import { getCompatListeners } from './instanceListeners'
|
||||||
import { shallowReadonly } from '@vue/reactivity'
|
import { shallowReadonly } from '@vue/reactivity'
|
||||||
|
import { legacySlotProxyHandlers } from './component'
|
||||||
|
|
||||||
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
||||||
const set = (target: any, key: any, val: any) => {
|
const set = (target: any, key: any, val: any) => {
|
||||||
@ -17,37 +18,48 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extend(map, {
|
extend(map, {
|
||||||
$set: () => {
|
$set: i => {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_SET)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_SET, i)
|
||||||
return set
|
return set
|
||||||
},
|
},
|
||||||
|
|
||||||
$delete: () => {
|
$delete: i => {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_DELETE, i)
|
||||||
return del
|
return del
|
||||||
},
|
},
|
||||||
|
|
||||||
$mount: i => {
|
$mount: i => {
|
||||||
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT)
|
assertCompatEnabled(
|
||||||
|
DeprecationTypes.GLOBAL_MOUNT,
|
||||||
|
null /* this warning is global */
|
||||||
|
)
|
||||||
// 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 => {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_DESTROY, i)
|
||||||
// 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
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// overrides existing accessor
|
||||||
|
$slots: i => {
|
||||||
|
if (isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i)) {
|
||||||
|
return new Proxy(i.slots, legacySlotProxyHandlers)
|
||||||
|
}
|
||||||
|
return i.slots
|
||||||
|
},
|
||||||
|
|
||||||
$scopedSlots: i => {
|
$scopedSlots: i => {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_SCOPED_SLOTS)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_SCOPED_SLOTS, i)
|
||||||
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
||||||
},
|
},
|
||||||
|
|
||||||
// overrides existing accessor
|
// overrides existing accessor
|
||||||
$attrs: i => {
|
$attrs: i => {
|
||||||
if (__DEV__ && i.type.inheritAttrs === false) {
|
if (__DEV__ && i.type.inheritAttrs === false) {
|
||||||
warnDeprecation(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE)
|
warnDeprecation(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, i)
|
||||||
}
|
}
|
||||||
return __DEV__ ? shallowReadonly(i.attrs) : i.attrs
|
return __DEV__ ? shallowReadonly(i.attrs) : i.attrs
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@ import { DeprecationTypes } from './deprecations'
|
|||||||
export function getCompatChildren(
|
export function getCompatChildren(
|
||||||
instance: ComponentInternalInstance
|
instance: ComponentInternalInstance
|
||||||
): ComponentPublicInstance[] {
|
): ComponentPublicInstance[] {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_CHILDREN, instance)
|
||||||
const root = instance.subTree
|
const root = instance.subTree
|
||||||
const children: ComponentPublicInstance[] = []
|
const children: ComponentPublicInstance[] = []
|
||||||
if (root) {
|
if (root) {
|
||||||
|
@ -32,9 +32,9 @@ export function on(
|
|||||||
event.forEach(e => on(instance, e, fn))
|
event.forEach(e => on(instance, e, fn))
|
||||||
} else {
|
} else {
|
||||||
if (event.startsWith('hook:')) {
|
if (event.startsWith('hook:')) {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
|
||||||
} else {
|
} else {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)
|
||||||
}
|
}
|
||||||
const events = getRegistry(instance)
|
const events = getRegistry(instance)
|
||||||
;(events[event] || (events[event] = [])).push(fn)
|
;(events[event] || (events[event] = [])).push(fn)
|
||||||
@ -61,7 +61,7 @@ export function off(
|
|||||||
event?: string,
|
event?: string,
|
||||||
fn?: Function
|
fn?: Function
|
||||||
) {
|
) {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_EVENT_EMITTER, instance)
|
||||||
const vm = instance.proxy
|
const vm = instance.proxy
|
||||||
// all
|
// all
|
||||||
if (!arguments.length) {
|
if (!arguments.length) {
|
||||||
|
@ -4,7 +4,7 @@ import { assertCompatEnabled } from './compatConfig'
|
|||||||
import { DeprecationTypes } from './deprecations'
|
import { DeprecationTypes } from './deprecations'
|
||||||
|
|
||||||
export function getCompatListeners(instance: ComponentInternalInstance) {
|
export function getCompatListeners(instance: ComponentInternalInstance) {
|
||||||
assertCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS)
|
assertCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)
|
||||||
|
|
||||||
const listeners: Record<string, Function | Function[]> = {}
|
const listeners: Record<string, Function | Function[]> = {}
|
||||||
const rawProps = instance.vnode.props
|
const rawProps = instance.vnode.props
|
||||||
|
@ -5,7 +5,7 @@ export function createPropsDefaultThis(propKey: string) {
|
|||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
get() {
|
get() {
|
||||||
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, propKey)
|
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
import { isArray, isObject } from '@vue/shared'
|
import {
|
||||||
|
extend,
|
||||||
|
isArray,
|
||||||
|
isObject,
|
||||||
|
ShapeFlags,
|
||||||
|
toHandlerKey
|
||||||
|
} from '@vue/shared'
|
||||||
import { Component, Data } from '../component'
|
import { Component, Data } from '../component'
|
||||||
|
import { DirectiveArguments, withDirectives } from '../directives'
|
||||||
|
import {
|
||||||
|
resolveDirective,
|
||||||
|
resolveDynamicComponent
|
||||||
|
} from '../helpers/resolveAssets'
|
||||||
import {
|
import {
|
||||||
createVNode,
|
createVNode,
|
||||||
isVNode,
|
isVNode,
|
||||||
|
normalizeChildren,
|
||||||
VNode,
|
VNode,
|
||||||
VNodeArrayChildren,
|
VNodeArrayChildren,
|
||||||
VNodeProps
|
VNodeProps
|
||||||
@ -23,6 +35,8 @@ interface LegacyVNodeProps {
|
|||||||
nativeOn?: Record<string, Function | Function[]>
|
nativeOn?: Record<string, Function | Function[]>
|
||||||
directives?: LegacyVNodeDirective[]
|
directives?: LegacyVNodeDirective[]
|
||||||
|
|
||||||
|
// component only
|
||||||
|
props?: Record<string, unknown>
|
||||||
slot?: string
|
slot?: string
|
||||||
scopedSlots?: Record<string, Function>
|
scopedSlots?: Record<string, Function>
|
||||||
}
|
}
|
||||||
@ -56,6 +70,9 @@ export function compatH(
|
|||||||
propsOrChildren?: any,
|
propsOrChildren?: any,
|
||||||
children?: any
|
children?: any
|
||||||
): VNode {
|
): VNode {
|
||||||
|
// to support v2 string component name lookup
|
||||||
|
type = resolveDynamicComponent(type)
|
||||||
|
|
||||||
const l = arguments.length
|
const l = arguments.length
|
||||||
if (l === 2) {
|
if (l === 2) {
|
||||||
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
|
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
|
||||||
@ -64,10 +81,12 @@ export function compatH(
|
|||||||
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
|
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
|
||||||
}
|
}
|
||||||
// props without children
|
// props without children
|
||||||
return convertLegacyDirectives(
|
return convertLegacySlots(
|
||||||
|
convertLegacyDirectives(
|
||||||
createVNode(type, convertLegacyProps(propsOrChildren)),
|
createVNode(type, convertLegacyProps(propsOrChildren)),
|
||||||
propsOrChildren
|
propsOrChildren
|
||||||
)
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// omit props
|
// omit props
|
||||||
return convertLegacySlots(createVNode(type, null, propsOrChildren))
|
return convertLegacySlots(createVNode(type, null, propsOrChildren))
|
||||||
@ -87,17 +106,87 @@ export function compatH(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertLegacyProps(props: LegacyVNodeProps): Data & VNodeProps {
|
function convertLegacyProps(legacyProps?: LegacyVNodeProps): Data & VNodeProps {
|
||||||
// TODO
|
const converted: Data & VNodeProps = {}
|
||||||
return props as any
|
|
||||||
|
for (const key in legacyProps) {
|
||||||
|
if (key === 'attrs' || key === 'domProps' || key === 'props') {
|
||||||
|
extend(converted, legacyProps[key])
|
||||||
|
} else if (key === 'on' || key === 'nativeOn') {
|
||||||
|
const listeners = legacyProps[key]
|
||||||
|
for (const event in listeners) {
|
||||||
|
const handlerKey = toHandlerKey(event)
|
||||||
|
const existing = converted[handlerKey]
|
||||||
|
const incoming = listeners[event]
|
||||||
|
if (existing !== incoming) {
|
||||||
|
converted[handlerKey] = existing
|
||||||
|
? [].concat(existing as any, incoming as any)
|
||||||
|
: incoming
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
converted[key] = legacyProps[key as keyof LegacyVNodeProps]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertLegacyDirectives(vnode: VNode, props: LegacyVNodeProps): VNode {
|
function convertLegacyDirectives(
|
||||||
// TODO
|
vnode: VNode,
|
||||||
|
props?: LegacyVNodeProps
|
||||||
|
): VNode {
|
||||||
|
if (props && props.directives) {
|
||||||
|
return withDirectives(
|
||||||
|
vnode,
|
||||||
|
props.directives.map(({ name, value, arg, modifiers }) => {
|
||||||
|
return [
|
||||||
|
resolveDirective(name)!,
|
||||||
|
value,
|
||||||
|
arg,
|
||||||
|
modifiers
|
||||||
|
] as DirectiveArguments[number]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertLegacySlots(vnode: VNode): VNode {
|
function convertLegacySlots(vnode: VNode): VNode {
|
||||||
// TODO
|
const { props, children } = vnode
|
||||||
|
|
||||||
|
let slots: Record<string, any> | undefined
|
||||||
|
|
||||||
|
if (vnode.shapeFlag & ShapeFlags.COMPONENT && isArray(children)) {
|
||||||
|
slots = {}
|
||||||
|
// check "slot" property on vnodes and turn them into v3 function slots
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
const child = children[i]
|
||||||
|
const slotName =
|
||||||
|
(isVNode(child) && child.props && child.props.slot) || 'default'
|
||||||
|
;(slots[slotName] || (slots[slotName] = [] as any[])).push(child)
|
||||||
|
}
|
||||||
|
if (slots) {
|
||||||
|
for (const key in slots) {
|
||||||
|
const slotChildren = slots[key]
|
||||||
|
slots[key] = () => slotChildren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const scopedSlots = props && props.scopedSlots
|
||||||
|
if (scopedSlots) {
|
||||||
|
delete props!.scopedSlots
|
||||||
|
if (slots) {
|
||||||
|
extend(slots, scopedSlots)
|
||||||
|
} else {
|
||||||
|
slots = scopedSlots
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slots) {
|
||||||
|
normalizeChildren(vnode, slots)
|
||||||
|
}
|
||||||
|
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,9 @@ import { CompilerOptions } from '@vue/compiler-core'
|
|||||||
import { markAttrsAccessed } from './componentRenderUtils'
|
import { markAttrsAccessed } from './componentRenderUtils'
|
||||||
import { currentRenderingInstance } from './componentRenderContext'
|
import { currentRenderingInstance } from './componentRenderContext'
|
||||||
import { startMeasure, endMeasure } from './profiling'
|
import { startMeasure, endMeasure } from './profiling'
|
||||||
|
import { isCompatEnabled } from './compat/compatConfig'
|
||||||
|
import { DeprecationTypes, warnDeprecation } from './compat/deprecations'
|
||||||
|
import { compatH } from './compat/renderFn'
|
||||||
|
|
||||||
export type Data = Record<string, unknown>
|
export type Data = Record<string, unknown>
|
||||||
|
|
||||||
@ -681,6 +684,18 @@ export function finishComponentSetup(
|
|||||||
) {
|
) {
|
||||||
const Component = instance.type as ComponentOptions
|
const Component = instance.type as ComponentOptions
|
||||||
|
|
||||||
|
if (
|
||||||
|
__COMPAT__ &&
|
||||||
|
Component.render &&
|
||||||
|
isCompatEnabled(DeprecationTypes.RENDER_FUNCTION)
|
||||||
|
) {
|
||||||
|
warnDeprecation(DeprecationTypes.RENDER_FUNCTION)
|
||||||
|
const originalRender = Component.render
|
||||||
|
Component.render = function compatRender() {
|
||||||
|
return originalRender.call(this, compatH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// template / render function normalization
|
// template / render function normalization
|
||||||
if (__NODE_JS__ && isSSR) {
|
if (__NODE_JS__ && isSSR) {
|
||||||
// 1. the render function may already exist, returned by `setup`
|
// 1. the render function may already exist, returned by `setup`
|
||||||
|
@ -790,13 +790,13 @@ export function applyOptions(
|
|||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
if (
|
if (
|
||||||
beforeDestroy &&
|
beforeDestroy &&
|
||||||
softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY)
|
softAssertCompatEnabled(DeprecationTypes.OPTIONS_BEFORE_DESTROY, instance)
|
||||||
) {
|
) {
|
||||||
onBeforeUnmount(beforeDestroy.bind(publicThis))
|
onBeforeUnmount(beforeDestroy.bind(publicThis))
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
destroyed &&
|
destroyed &&
|
||||||
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED)
|
softAssertCompatEnabled(DeprecationTypes.OPTIONS_DESTROYED, instance)
|
||||||
) {
|
) {
|
||||||
onUnmounted(destroyed.bind(publicThis))
|
onUnmounted(destroyed.bind(publicThis))
|
||||||
}
|
}
|
||||||
@ -930,8 +930,11 @@ 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__ && isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE)) {
|
if (
|
||||||
deepMergeData(instance.data, data)
|
__COMPAT__ &&
|
||||||
|
isCompatEnabled(DeprecationTypes.OPTIONS_DATA_MERGE, instance)
|
||||||
|
) {
|
||||||
|
deepMergeData(instance.data, data, instance)
|
||||||
} else {
|
} else {
|
||||||
extend(instance.data, data)
|
extend(instance.data, data)
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ export function invokeDirectiveHook(
|
|||||||
}
|
}
|
||||||
let hook = binding.dir[name] as DirectiveHook | DirectiveHook[] | undefined
|
let hook = binding.dir[name] as DirectiveHook | DirectiveHook[] | undefined
|
||||||
if (__COMPAT__ && !hook) {
|
if (__COMPAT__ && !hook) {
|
||||||
hook = mapCompatDirectiveHook(name, binding.dir)
|
hook = mapCompatDirectiveHook(name, binding.dir, instance)
|
||||||
}
|
}
|
||||||
if (hook) {
|
if (hook) {
|
||||||
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
|
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
|
||||||
|
@ -361,7 +361,7 @@ function _createVNode(
|
|||||||
|
|
||||||
// 2.x async/functional component compat
|
// 2.x async/functional component compat
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
type = convertLegacyComponent(type)
|
type = convertLegacyComponent(type, currentRenderingInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// class & style normalization.
|
// class & style normalization.
|
||||||
@ -677,7 +677,7 @@ export function mergeProps(...args: (Data & VNodeProps)[]) {
|
|||||||
const incoming = toMerge[key]
|
const incoming = toMerge[key]
|
||||||
if (existing !== incoming) {
|
if (existing !== incoming) {
|
||||||
ret[key] = existing
|
ret[key] = existing
|
||||||
? [].concat(existing as any, toMerge[key] as any)
|
? [].concat(existing as any, incoming as any)
|
||||||
: incoming
|
: incoming
|
||||||
}
|
}
|
||||||
} else if (key !== '') {
|
} else if (key !== '') {
|
||||||
|
Loading…
Reference in New Issue
Block a user