wip: more compat progress
This commit is contained in:
parent
62b8f4a39c
commit
1b8f14ee76
@ -82,7 +82,7 @@ describe('component: slots', () => {
|
|||||||
expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])
|
expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])
|
||||||
})
|
})
|
||||||
|
|
||||||
test('updateSlots: instance.slots should be update correctly (when slotType is number)', async () => {
|
test('updateSlots: instance.slots should be updated correctly (when slotType is number)', async () => {
|
||||||
const flag1 = ref(true)
|
const flag1 = ref(true)
|
||||||
|
|
||||||
let instance: any
|
let instance: any
|
||||||
@ -124,7 +124,7 @@ describe('component: slots', () => {
|
|||||||
expect(instance.slots).toHaveProperty('two')
|
expect(instance.slots).toHaveProperty('two')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('updateSlots: instance.slots should be update correctly (when slotType is null)', async () => {
|
test('updateSlots: instance.slots should be updated correctly (when slotType is null)', async () => {
|
||||||
const flag1 = ref(true)
|
const flag1 = ref(true)
|
||||||
|
|
||||||
let instance: any
|
let instance: any
|
||||||
|
@ -262,7 +262,8 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
|
|
||||||
[DeprecationTypes.PROPS_DEFAULT_THIS]: {
|
[DeprecationTypes.PROPS_DEFAULT_THIS]: {
|
||||||
message: (key: string) =>
|
message: (key: string) =>
|
||||||
`props default value function no longer has access to "this". ` +
|
`props default value function no longer has access to "this". The compat ` +
|
||||||
|
`build only offers access to this.$options.` +
|
||||||
`(found in prop "${key}")`,
|
`(found in prop "${key}")`,
|
||||||
link: `https://v3.vuejs.org/guide/migration/props-default-this.html`
|
link: `https://v3.vuejs.org/guide/migration/props-default-this.html`
|
||||||
},
|
},
|
||||||
|
@ -132,7 +132,7 @@ function convertLegacyFunctionalComponent(comp: ComponentOptions) {
|
|||||||
data: instance.vnode.props || {},
|
data: instance.vnode.props || {},
|
||||||
scopedSlots: ctx.slots,
|
scopedSlots: ctx.slots,
|
||||||
parent: instance.parent && instance.parent.proxy,
|
parent: instance.parent && instance.parent.proxy,
|
||||||
get slots() {
|
slots() {
|
||||||
return new Proxy(ctx.slots, legacySlotProxyHandlers)
|
return new Proxy(ctx.slots, legacySlotProxyHandlers)
|
||||||
},
|
},
|
||||||
get listeners() {
|
get listeners() {
|
||||||
|
@ -12,13 +12,16 @@ import { getCompatListeners } from './instanceListeners'
|
|||||||
import { shallowReadonly } from '@vue/reactivity'
|
import { shallowReadonly } from '@vue/reactivity'
|
||||||
import { legacySlotProxyHandlers } from './component'
|
import { legacySlotProxyHandlers } from './component'
|
||||||
import { compatH } from './renderFn'
|
import { compatH } from './renderFn'
|
||||||
import {
|
|
||||||
legacyBindObjectProps,
|
|
||||||
legacyRenderSlot,
|
|
||||||
legacyRenderStatic
|
|
||||||
} from './renderHelpers'
|
|
||||||
import { createCommentVNode, createTextVNode } from '../vnode'
|
import { createCommentVNode, createTextVNode } from '../vnode'
|
||||||
import { renderList } from '../helpers/renderList'
|
import { renderList } from '../helpers/renderList'
|
||||||
|
import {
|
||||||
|
legacyBindObjectListeners,
|
||||||
|
legacyBindObjectProps,
|
||||||
|
legacyCheckKeyCodes,
|
||||||
|
legacyRenderSlot,
|
||||||
|
legacyRenderStatic,
|
||||||
|
legacyresolveScopedSlots
|
||||||
|
} from './renderHelpers'
|
||||||
|
|
||||||
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) => {
|
||||||
@ -98,6 +101,9 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
|||||||
_b: () => legacyBindObjectProps,
|
_b: () => legacyBindObjectProps,
|
||||||
_e: () => createCommentVNode,
|
_e: () => createCommentVNode,
|
||||||
_v: () => createTextVNode,
|
_v: () => createTextVNode,
|
||||||
_m: i => legacyRenderStatic.bind(null, i)
|
_m: i => legacyRenderStatic.bind(null, i),
|
||||||
|
_g: () => legacyBindObjectListeners,
|
||||||
|
_u: () => legacyresolveScopedSlots,
|
||||||
|
_k: i => legacyCheckKeyCodes.bind(null, i)
|
||||||
} as PublicPropertiesMap)
|
} as PublicPropertiesMap)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,39 @@
|
|||||||
|
import { isArray } from '@vue/shared'
|
||||||
|
import { inject } from '../apiInject'
|
||||||
|
import { ComponentInternalInstance, Data } from '../component'
|
||||||
|
import { ComponentOptions, resolveMergedOptions } from '../componentOptions'
|
||||||
import { DeprecationTypes, warnDeprecation } from './compatConfig'
|
import { DeprecationTypes, warnDeprecation } from './compatConfig'
|
||||||
|
|
||||||
export function createPropsDefaultThis(propKey: string) {
|
export function createPropsDefaultThis(
|
||||||
|
instance: ComponentInternalInstance,
|
||||||
|
rawProps: Data,
|
||||||
|
propKey: string
|
||||||
|
) {
|
||||||
return new Proxy(
|
return new Proxy(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
get() {
|
get(_, key: string) {
|
||||||
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)
|
__DEV__ &&
|
||||||
|
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)
|
||||||
|
// $options
|
||||||
|
if (key === '$options') {
|
||||||
|
return resolveMergedOptions(instance)
|
||||||
|
}
|
||||||
|
// props
|
||||||
|
if (key in rawProps) {
|
||||||
|
return rawProps[key]
|
||||||
|
}
|
||||||
|
// injections
|
||||||
|
const injections = (instance.type as ComponentOptions).inject
|
||||||
|
if (injections) {
|
||||||
|
if (isArray(injections)) {
|
||||||
|
if (injections.includes(key)) {
|
||||||
|
return inject(key)
|
||||||
|
}
|
||||||
|
} else if (key in injections) {
|
||||||
|
return inject(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
extend,
|
extend,
|
||||||
|
hyphenate,
|
||||||
isArray,
|
isArray,
|
||||||
isObject,
|
isObject,
|
||||||
|
makeMap,
|
||||||
normalizeClass,
|
normalizeClass,
|
||||||
normalizeStyle,
|
normalizeStyle,
|
||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
@ -14,6 +16,7 @@ import {
|
|||||||
Data,
|
Data,
|
||||||
InternalRenderFunction
|
InternalRenderFunction
|
||||||
} from '../component'
|
} from '../component'
|
||||||
|
import { currentRenderingInstance } from '../componentRenderContext'
|
||||||
import { DirectiveArguments, withDirectives } from '../directives'
|
import { DirectiveArguments, withDirectives } from '../directives'
|
||||||
import {
|
import {
|
||||||
resolveDirective,
|
resolveDirective,
|
||||||
@ -27,7 +30,12 @@ import {
|
|||||||
VNodeArrayChildren,
|
VNodeArrayChildren,
|
||||||
VNodeProps
|
VNodeProps
|
||||||
} from '../vnode'
|
} from '../vnode'
|
||||||
import { checkCompatEnabled, DeprecationTypes } from './compatConfig'
|
import {
|
||||||
|
checkCompatEnabled,
|
||||||
|
DeprecationTypes,
|
||||||
|
isCompatEnabled
|
||||||
|
} from './compatConfig'
|
||||||
|
import { compatModelEventPrefix } from './vModel'
|
||||||
|
|
||||||
const v3CompiledRenderFnRE = /^(?:function \w+)?\(_ctx, _cache/
|
const v3CompiledRenderFnRE = /^(?:function \w+)?\(_ctx, _cache/
|
||||||
|
|
||||||
@ -76,6 +84,11 @@ interface LegacyVNodeProps {
|
|||||||
props?: Record<string, unknown>
|
props?: Record<string, unknown>
|
||||||
slot?: string
|
slot?: string
|
||||||
scopedSlots?: Record<string, Function>
|
scopedSlots?: Record<string, Function>
|
||||||
|
model?: {
|
||||||
|
value: any
|
||||||
|
callback: (v: any) => void
|
||||||
|
expression: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LegacyVNodeDirective {
|
interface LegacyVNodeDirective {
|
||||||
@ -107,12 +120,22 @@ export function compatH(
|
|||||||
propsOrChildren?: any,
|
propsOrChildren?: any,
|
||||||
children?: any
|
children?: any
|
||||||
): VNode {
|
): VNode {
|
||||||
// to support v2 string component name lookup
|
// to support v2 string component name look!up
|
||||||
type = resolveDynamicComponent(type)
|
if (typeof type === 'string') {
|
||||||
|
const t = hyphenate(type)
|
||||||
|
if (t === 'transition' || t === 'transition-group' || t === 'keep-alive') {
|
||||||
|
// since transition and transition-group are runtime-dom-specific,
|
||||||
|
// we cannot import them directly here. Instead they are registered using
|
||||||
|
// special keys in @vue/compat entry.
|
||||||
|
type = `__compat__${t}`
|
||||||
|
}
|
||||||
|
type = resolveDynamicComponent(type)
|
||||||
|
}
|
||||||
|
|
||||||
const l = arguments.length
|
const l = arguments.length
|
||||||
if (l === 2) {
|
const is2ndArgArrayChildren = isArray(propsOrChildren)
|
||||||
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
|
if (l === 2 || is2ndArgArrayChildren) {
|
||||||
|
if (isObject(propsOrChildren) && !is2ndArgArrayChildren) {
|
||||||
// single vnode without props
|
// single vnode without props
|
||||||
if (isVNode(propsOrChildren)) {
|
if (isVNode(propsOrChildren)) {
|
||||||
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
|
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
|
||||||
@ -120,7 +143,7 @@ export function compatH(
|
|||||||
// props without children
|
// props without children
|
||||||
return convertLegacySlots(
|
return convertLegacySlots(
|
||||||
convertLegacyDirectives(
|
convertLegacyDirectives(
|
||||||
createVNode(type, convertLegacyProps(propsOrChildren)),
|
createVNode(type, convertLegacyProps(propsOrChildren, type)),
|
||||||
propsOrChildren
|
propsOrChildren
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -134,15 +157,20 @@ export function compatH(
|
|||||||
}
|
}
|
||||||
return convertLegacySlots(
|
return convertLegacySlots(
|
||||||
convertLegacyDirectives(
|
convertLegacyDirectives(
|
||||||
createVNode(type, convertLegacyProps(propsOrChildren), children),
|
createVNode(type, convertLegacyProps(propsOrChildren, type), children),
|
||||||
propsOrChildren
|
propsOrChildren
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const skipLegacyRootLevelProps = /*#__PURE__*/ makeMap(
|
||||||
|
'refInFor,staticStyle,staticClass,directives,model'
|
||||||
|
)
|
||||||
|
|
||||||
function convertLegacyProps(
|
function convertLegacyProps(
|
||||||
legacyProps?: LegacyVNodeProps
|
legacyProps: LegacyVNodeProps | undefined,
|
||||||
|
type: any
|
||||||
): Data & VNodeProps | null {
|
): Data & VNodeProps | null {
|
||||||
if (!legacyProps) {
|
if (!legacyProps) {
|
||||||
return null
|
return null
|
||||||
@ -172,11 +200,7 @@ function convertLegacyProps(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (!skipLegacyRootLevelProps(key)) {
|
||||||
key !== 'refInFor' &&
|
|
||||||
key !== 'staticStyle' &&
|
|
||||||
key !== 'staticClass'
|
|
||||||
) {
|
|
||||||
converted[key] = legacyProps[key as keyof LegacyVNodeProps]
|
converted[key] = legacyProps[key as keyof LegacyVNodeProps]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,6 +212,13 @@ function convertLegacyProps(
|
|||||||
converted.style = normalizeStyle([legacyProps.staticStyle, converted.style])
|
converted.style = normalizeStyle([legacyProps.staticStyle, converted.style])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (legacyProps.model && isObject(type)) {
|
||||||
|
// v2 compiled component v-model
|
||||||
|
const { prop = 'value', event = 'input' } = (type as any).model || {}
|
||||||
|
converted[prop] = legacyProps.model.value
|
||||||
|
converted[compatModelEventPrefix + event] = legacyProps.model.callback
|
||||||
|
}
|
||||||
|
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +268,12 @@ function convertLegacySlots(vnode: VNode): VNode {
|
|||||||
const child = children[i]
|
const child = children[i]
|
||||||
const slotName =
|
const slotName =
|
||||||
(isVNode(child) && child.props && child.props.slot) || 'default'
|
(isVNode(child) && child.props && child.props.slot) || 'default'
|
||||||
;(slots[slotName] || (slots[slotName] = [] as any[])).push(child)
|
const slot = slots[slotName] || (slots[slotName] = [] as any[])
|
||||||
|
if (isVNode(child) && child.type === 'template') {
|
||||||
|
slot.push(child.children)
|
||||||
|
} else {
|
||||||
|
slot.push(child)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (slots) {
|
if (slots) {
|
||||||
for (const key in slots) {
|
for (const key in slots) {
|
||||||
@ -263,3 +299,31 @@ function convertLegacySlots(vnode: VNode): VNode {
|
|||||||
|
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function defineLegacyVNodeProperties(vnode: VNode) {
|
||||||
|
if (
|
||||||
|
isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, currentRenderingInstance)
|
||||||
|
) {
|
||||||
|
const getInstance = () => vnode.component && vnode.component.proxy
|
||||||
|
let componentOptions: any
|
||||||
|
Object.defineProperties(vnode, {
|
||||||
|
elm: { get: () => vnode.el },
|
||||||
|
componentInstance: { get: getInstance },
|
||||||
|
child: { get: getInstance },
|
||||||
|
componentOptions: {
|
||||||
|
get: () => {
|
||||||
|
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
|
||||||
|
if (componentOptions) {
|
||||||
|
return componentOptions
|
||||||
|
}
|
||||||
|
return (componentOptions = {
|
||||||
|
Ctor: vnode.type,
|
||||||
|
propsData: vnode.props,
|
||||||
|
children: vnode.children
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,9 +8,22 @@ import {
|
|||||||
normalizeClass
|
normalizeClass
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { ComponentInternalInstance } from '../component'
|
import { ComponentInternalInstance } from '../component'
|
||||||
|
import { Slot } from '../componentSlots'
|
||||||
|
import { createSlots } from '../helpers/createSlots'
|
||||||
import { renderSlot } from '../helpers/renderSlot'
|
import { renderSlot } from '../helpers/renderSlot'
|
||||||
|
import { toHandlers } from '../helpers/toHandlers'
|
||||||
import { mergeProps, VNode } from '../vnode'
|
import { mergeProps, VNode } from '../vnode'
|
||||||
|
|
||||||
|
function toObject(arr: Array<any>): Object {
|
||||||
|
const res = {}
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i]) {
|
||||||
|
extend(res, arr[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
export function legacyBindObjectProps(
|
export function legacyBindObjectProps(
|
||||||
data: any,
|
data: any,
|
||||||
_tag: string,
|
_tag: string,
|
||||||
@ -49,6 +62,10 @@ export function legacyBindObjectProps(
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function legacyBindObjectListeners(props: any, listeners: any) {
|
||||||
|
return mergeProps(props, toHandlers(listeners))
|
||||||
|
}
|
||||||
|
|
||||||
export function legacyRenderSlot(
|
export function legacyRenderSlot(
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
name: string,
|
name: string,
|
||||||
@ -62,6 +79,41 @@ export function legacyRenderSlot(
|
|||||||
return renderSlot(instance.slots, name, props, fallback && (() => fallback))
|
return renderSlot(instance.slots, name, props, fallback && (() => fallback))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LegacyScopedSlotsData = Array<
|
||||||
|
| {
|
||||||
|
key: string
|
||||||
|
fn: Function
|
||||||
|
}
|
||||||
|
| LegacyScopedSlotsData
|
||||||
|
>
|
||||||
|
|
||||||
|
export function legacyresolveScopedSlots(
|
||||||
|
fns: LegacyScopedSlotsData,
|
||||||
|
raw?: Record<string, Slot>,
|
||||||
|
// the following are added in 2.6
|
||||||
|
hasDynamicKeys?: boolean
|
||||||
|
) {
|
||||||
|
// v2 default slot doesn't have name
|
||||||
|
return createSlots(
|
||||||
|
raw || ({ $stable: !hasDynamicKeys } as any),
|
||||||
|
mapKeyToName(fns)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapKeyToName(slots: LegacyScopedSlotsData) {
|
||||||
|
for (let i = 0; i < slots.length; i++) {
|
||||||
|
const fn = slots[i]
|
||||||
|
if (fn) {
|
||||||
|
if (isArray(fn)) {
|
||||||
|
mapKeyToName(fn)
|
||||||
|
} else {
|
||||||
|
;(fn as any).name = fn.key || 'default'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slots as any
|
||||||
|
}
|
||||||
|
|
||||||
const staticCacheMap = /*#__PURE__*/ new WeakMap<
|
const staticCacheMap = /*#__PURE__*/ new WeakMap<
|
||||||
ComponentInternalInstance,
|
ComponentInternalInstance,
|
||||||
any[]
|
any[]
|
||||||
@ -83,12 +135,30 @@ export function legacyRenderStatic(
|
|||||||
return (cache[index] = fn.call(ctx, null, ctx))
|
return (cache[index] = fn.call(ctx, null, ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
function toObject(arr: Array<any>): Object {
|
export function legacyCheckKeyCodes(
|
||||||
const res = {}
|
instance: ComponentInternalInstance,
|
||||||
for (let i = 0; i < arr.length; i++) {
|
eventKeyCode: number,
|
||||||
if (arr[i]) {
|
key: string,
|
||||||
extend(res, arr[i])
|
builtInKeyCode?: number | number[],
|
||||||
}
|
eventKeyName?: string,
|
||||||
|
builtInKeyName?: string | string[]
|
||||||
|
) {
|
||||||
|
const config = instance.appContext.config as any
|
||||||
|
const configKeyCodes = config.keyCodes || {}
|
||||||
|
const mappedKeyCode = configKeyCodes[key] || builtInKeyCode
|
||||||
|
if (builtInKeyName && eventKeyName && !configKeyCodes[key]) {
|
||||||
|
return isKeyNotMatch(builtInKeyName, eventKeyName)
|
||||||
|
} else if (mappedKeyCode) {
|
||||||
|
return isKeyNotMatch(mappedKeyCode, eventKeyCode)
|
||||||
|
} else if (eventKeyName) {
|
||||||
|
return hyphenate(eventKeyName) !== key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isKeyNotMatch<T>(expect: T | T[], actual: T): boolean {
|
||||||
|
if (isArray(expect)) {
|
||||||
|
return expect.indexOf(actual) === -1
|
||||||
|
} else {
|
||||||
|
return expect !== actual
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ export function convertLegacyVModelProps(vnode: VNode) {
|
|||||||
warnedTypes.add(type as ComponentOptions)
|
warnedTypes.add(type as ComponentOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v3 compiled model code -> v2 compat props
|
||||||
|
// modelValue -> value
|
||||||
|
// onUpdate:modelValue -> onModelCompat:input
|
||||||
const { prop = 'value', event = 'input' } = (type as any).model || {}
|
const { prop = 'value', event = 'input' } = (type as any).model || {}
|
||||||
props[prop] = props.modelValue
|
props[prop] = props.modelValue
|
||||||
delete props.modelValue
|
delete props.modelValue
|
||||||
@ -42,7 +45,6 @@ export function convertLegacyVModelProps(vnode: VNode) {
|
|||||||
if (dynamicProps) {
|
if (dynamicProps) {
|
||||||
dynamicProps[dynamicProps.indexOf('modelValue')] = prop
|
dynamicProps[dynamicProps.indexOf('modelValue')] = prop
|
||||||
}
|
}
|
||||||
|
|
||||||
props[compatModelEventPrefix + event] = props['onUpdate:modelValue']
|
props[compatModelEventPrefix + event] = props['onUpdate:modelValue']
|
||||||
delete props['onUpdate:modelValue']
|
delete props['onUpdate:modelValue']
|
||||||
}
|
}
|
||||||
|
@ -376,9 +376,8 @@ function resolvePropValue(
|
|||||||
setCurrentInstance(instance)
|
setCurrentInstance(instance)
|
||||||
value = propsDefaults[key] = defaultValue.call(
|
value = propsDefaults[key] = defaultValue.call(
|
||||||
__COMPAT__ &&
|
__COMPAT__ &&
|
||||||
__DEV__ &&
|
|
||||||
isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS, instance)
|
isCompatEnabled(DeprecationTypes.PROPS_DEFAULT_THIS, instance)
|
||||||
? createPropsDefaultThis(key)
|
? createPropsDefaultThis(instance, props, key)
|
||||||
: null,
|
: null,
|
||||||
props
|
props
|
||||||
)
|
)
|
||||||
|
@ -25,6 +25,10 @@ export function setCurrentRenderingInstance(
|
|||||||
const prev = currentRenderingInstance
|
const prev = currentRenderingInstance
|
||||||
currentRenderingInstance = instance
|
currentRenderingInstance = instance
|
||||||
currentScopeId = (instance && instance.type.__scopeId) || null
|
currentScopeId = (instance && instance.type.__scopeId) || null
|
||||||
|
// v2 pre-compiled components uses _scopeId instead of __scopeId
|
||||||
|
if (__COMPAT__ && !currentScopeId) {
|
||||||
|
currentScopeId = (instance && (instance.type as any)._scopeId) || null
|
||||||
|
}
|
||||||
return prev
|
return prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import { warn } from './warning'
|
|||||||
import { isKeepAlive } from './components/KeepAlive'
|
import { isKeepAlive } from './components/KeepAlive'
|
||||||
import { withCtx } from './componentRenderContext'
|
import { withCtx } from './componentRenderContext'
|
||||||
import { isHmrUpdating } from './hmr'
|
import { isHmrUpdating } from './hmr'
|
||||||
|
import { DeprecationTypes, isCompatEnabled } from './compat/compatConfig'
|
||||||
|
|
||||||
export type Slot = (...args: any[]) => VNode[]
|
export type Slot = (...args: any[]) => VNode[]
|
||||||
|
|
||||||
@ -72,7 +73,11 @@ const normalizeSlot = (
|
|||||||
return normalizeSlotValue(rawSlot(props))
|
return normalizeSlotValue(rawSlot(props))
|
||||||
}, ctx) as Slot
|
}, ctx) as Slot
|
||||||
|
|
||||||
const normalizeObjectSlots = (rawSlots: RawSlots, slots: InternalSlots) => {
|
const normalizeObjectSlots = (
|
||||||
|
rawSlots: RawSlots,
|
||||||
|
slots: InternalSlots,
|
||||||
|
instance: ComponentInternalInstance
|
||||||
|
) => {
|
||||||
const ctx = rawSlots._ctx
|
const ctx = rawSlots._ctx
|
||||||
for (const key in rawSlots) {
|
for (const key in rawSlots) {
|
||||||
if (isInternalKey(key)) continue
|
if (isInternalKey(key)) continue
|
||||||
@ -80,7 +85,13 @@ const normalizeObjectSlots = (rawSlots: RawSlots, slots: InternalSlots) => {
|
|||||||
if (isFunction(value)) {
|
if (isFunction(value)) {
|
||||||
slots[key] = normalizeSlot(key, value, ctx)
|
slots[key] = normalizeSlot(key, value, ctx)
|
||||||
} else if (value != null) {
|
} else if (value != null) {
|
||||||
if (__DEV__ && !__COMPAT__) {
|
if (
|
||||||
|
__DEV__ &&
|
||||||
|
!(
|
||||||
|
__COMPAT__ &&
|
||||||
|
isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance)
|
||||||
|
)
|
||||||
|
) {
|
||||||
warn(
|
warn(
|
||||||
`Non-function value encountered for slot "${key}". ` +
|
`Non-function value encountered for slot "${key}". ` +
|
||||||
`Prefer function slots for better performance.`
|
`Prefer function slots for better performance.`
|
||||||
@ -117,7 +128,11 @@ export const initSlots = (
|
|||||||
// make compiler marker non-enumerable
|
// make compiler marker non-enumerable
|
||||||
def(children as InternalSlots, '_', type)
|
def(children as InternalSlots, '_', type)
|
||||||
} else {
|
} else {
|
||||||
normalizeObjectSlots(children as RawSlots, (instance.slots = {}))
|
normalizeObjectSlots(
|
||||||
|
children as RawSlots,
|
||||||
|
(instance.slots = {}),
|
||||||
|
instance
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instance.slots = {}
|
instance.slots = {}
|
||||||
@ -162,7 +177,7 @@ export const updateSlots = (
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
needDeletionCheck = !(children as RawSlots).$stable
|
needDeletionCheck = !(children as RawSlots).$stable
|
||||||
normalizeObjectSlots(children as RawSlots, slots)
|
normalizeObjectSlots(children as RawSlots, slots, instance)
|
||||||
}
|
}
|
||||||
deletionComparisonTarget = children as RawSlots
|
deletionComparisonTarget = children as RawSlots
|
||||||
} else if (children) {
|
} else if (children) {
|
||||||
|
@ -43,6 +43,7 @@ import { hmrDirtyComponents } from './hmr'
|
|||||||
import { setCompiledSlotRendering } from './helpers/renderSlot'
|
import { setCompiledSlotRendering } from './helpers/renderSlot'
|
||||||
import { convertLegacyComponent } from './compat/component'
|
import { convertLegacyComponent } from './compat/component'
|
||||||
import { convertLegacyVModelProps } from './compat/vModel'
|
import { convertLegacyVModelProps } from './compat/vModel'
|
||||||
|
import { defineLegacyVNodeProperties } from './compat/renderFn'
|
||||||
|
|
||||||
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
|
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
|
||||||
__isFragment: true
|
__isFragment: true
|
||||||
@ -472,6 +473,7 @@ function _createVNode(
|
|||||||
|
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
convertLegacyVModelProps(vnode)
|
convertLegacyVModelProps(vnode)
|
||||||
|
defineLegacyVNodeProperties(vnode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return vnode
|
return vnode
|
||||||
@ -486,7 +488,7 @@ export function cloneVNode<T, U>(
|
|||||||
// key enumeration cost.
|
// key enumeration cost.
|
||||||
const { props, ref, patchFlag, children } = vnode
|
const { props, ref, patchFlag, children } = vnode
|
||||||
const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props
|
const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props
|
||||||
return {
|
const cloned: VNode = {
|
||||||
__v_isVNode: true,
|
__v_isVNode: true,
|
||||||
[ReactiveFlags.SKIP]: true,
|
[ReactiveFlags.SKIP]: true,
|
||||||
type: vnode.type,
|
type: vnode.type,
|
||||||
@ -540,6 +542,10 @@ export function cloneVNode<T, U>(
|
|||||||
el: vnode.el,
|
el: vnode.el,
|
||||||
anchor: vnode.anchor
|
anchor: vnode.anchor
|
||||||
}
|
}
|
||||||
|
if (__COMPAT__) {
|
||||||
|
defineLegacyVNodeProperties(cloned)
|
||||||
|
}
|
||||||
|
return cloned as any
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,16 +2,11 @@
|
|||||||
// and the compiler, and supports on-the-fly compilation of the template option.
|
// and the compiler, and supports on-the-fly compilation of the template option.
|
||||||
import { initDev } from './dev'
|
import { initDev } from './dev'
|
||||||
import { compile, CompilerError, CompilerOptions } from '@vue/compiler-dom'
|
import { compile, CompilerError, CompilerOptions } from '@vue/compiler-dom'
|
||||||
import {
|
import { registerRuntimeCompiler, RenderFunction, warn } from '@vue/runtime-dom'
|
||||||
registerRuntimeCompiler,
|
|
||||||
RenderFunction,
|
|
||||||
warn,
|
|
||||||
createApp,
|
|
||||||
compatUtils
|
|
||||||
} from '@vue/runtime-dom'
|
|
||||||
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
|
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
|
||||||
import { InternalRenderFunction } from 'packages/runtime-core/src/component'
|
import { InternalRenderFunction } from 'packages/runtime-core/src/component'
|
||||||
import * as runtimeDom from '@vue/runtime-dom'
|
import * as runtimeDom from '@vue/runtime-dom'
|
||||||
|
import Vue from './runtime'
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
initDev()
|
initDev()
|
||||||
@ -92,10 +87,6 @@ function compileToFunction(
|
|||||||
|
|
||||||
registerRuntimeCompiler(compileToFunction)
|
registerRuntimeCompiler(compileToFunction)
|
||||||
|
|
||||||
const Vue = compatUtils.createCompatVue(createApp)
|
|
||||||
|
|
||||||
Vue.compile = compileToFunction
|
Vue.compile = compileToFunction
|
||||||
|
|
||||||
extend(Vue, runtimeDom)
|
|
||||||
|
|
||||||
export default Vue
|
export default Vue
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
// This entry exports the runtime only, and is built as
|
// This entry exports the runtime only, and is built as
|
||||||
// `dist/vue.esm-bundler.js` which is used by default for bundlers.
|
// `dist/vue.esm-bundler.js` which is used by default for bundlers.
|
||||||
import { initDev } from './dev'
|
import { initDev } from './dev'
|
||||||
import { compatUtils, createApp, warn } from '@vue/runtime-dom'
|
import {
|
||||||
|
compatUtils,
|
||||||
|
createApp,
|
||||||
|
warn,
|
||||||
|
Transition,
|
||||||
|
TransitionGroup,
|
||||||
|
KeepAlive,
|
||||||
|
DeprecationTypes,
|
||||||
|
vShow,
|
||||||
|
vModelDynamic
|
||||||
|
} from '@vue/runtime-dom'
|
||||||
import { extend } from '@vue/shared'
|
import { extend } from '@vue/shared'
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -10,7 +20,25 @@ if (__DEV__) {
|
|||||||
|
|
||||||
import * as runtimeDom from '@vue/runtime-dom'
|
import * as runtimeDom from '@vue/runtime-dom'
|
||||||
|
|
||||||
const Vue = compatUtils.createCompatVue(createApp)
|
function wrappedCreateApp(...args: any[]) {
|
||||||
|
// @ts-ignore
|
||||||
|
const app = createApp(...args)
|
||||||
|
if (compatUtils.isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, null)) {
|
||||||
|
// register built-in components so that they can be resolved via strings
|
||||||
|
// in the legacy h() call. The __compat__ prefix is to ensure that v3 h()
|
||||||
|
// doesn't get affected.
|
||||||
|
app.component('__compat__transition', Transition)
|
||||||
|
app.component('__compat__transition-group', TransitionGroup)
|
||||||
|
app.component('__compat__keep-alive', KeepAlive)
|
||||||
|
// built-in directives. No need for prefix since there's no render fn API
|
||||||
|
// for resolving directives via string in v3.
|
||||||
|
app._context.directives.show = vShow
|
||||||
|
app._context.directives.model = vModelDynamic
|
||||||
|
}
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vue = compatUtils.createCompatVue(wrappedCreateApp)
|
||||||
|
|
||||||
Vue.compile = (() => {
|
Vue.compile = (() => {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -29,4 +57,7 @@ Vue.compile = (() => {
|
|||||||
|
|
||||||
extend(Vue, runtimeDom)
|
extend(Vue, runtimeDom)
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
Vue.createApp = wrappedCreateApp
|
||||||
|
|
||||||
export default Vue
|
export default Vue
|
||||||
|
Loading…
x
Reference in New Issue
Block a user