1
1
import {
2
2
extend ,
3
+ hyphenate ,
3
4
isArray ,
4
5
isObject ,
6
+ makeMap ,
5
7
normalizeClass ,
6
8
normalizeStyle ,
7
9
ShapeFlags ,
@@ -14,6 +16,7 @@ import {
14
16
Data ,
15
17
InternalRenderFunction
16
18
} from '../component'
19
+ import { currentRenderingInstance } from '../componentRenderContext'
17
20
import { DirectiveArguments , withDirectives } from '../directives'
18
21
import {
19
22
resolveDirective ,
@@ -27,7 +30,12 @@ import {
27
30
VNodeArrayChildren ,
28
31
VNodeProps
29
32
} from '../vnode'
30
- import { checkCompatEnabled , DeprecationTypes } from './compatConfig'
33
+ import {
34
+ checkCompatEnabled ,
35
+ DeprecationTypes ,
36
+ isCompatEnabled
37
+ } from './compatConfig'
38
+ import { compatModelEventPrefix } from './vModel'
31
39
32
40
const v3CompiledRenderFnRE = / ^ (?: f u n c t i o n \w + ) ? \( _ c t x , _ c a c h e /
33
41
@@ -76,6 +84,11 @@ interface LegacyVNodeProps {
76
84
props ?: Record < string , unknown >
77
85
slot ?: string
78
86
scopedSlots ?: Record < string , Function >
87
+ model ?: {
88
+ value : any
89
+ callback : ( v : any ) => void
90
+ expression : string
91
+ }
79
92
}
80
93
81
94
interface LegacyVNodeDirective {
@@ -107,20 +120,30 @@ export function compatH(
107
120
propsOrChildren ?: any ,
108
121
children ?: any
109
122
) : VNode {
110
- // to support v2 string component name lookup
111
- type = resolveDynamicComponent ( type )
123
+ // to support v2 string component name look!up
124
+ if ( typeof type === 'string' ) {
125
+ const t = hyphenate ( type )
126
+ if ( t === 'transition' || t === 'transition-group' || t === 'keep-alive' ) {
127
+ // since transition and transition-group are runtime-dom-specific,
128
+ // we cannot import them directly here. Instead they are registered using
129
+ // special keys in @vue /compat entry.
130
+ type = `__compat__${ t } `
131
+ }
132
+ type = resolveDynamicComponent ( type )
133
+ }
112
134
113
135
const l = arguments . length
114
- if ( l === 2 ) {
115
- if ( isObject ( propsOrChildren ) && ! isArray ( propsOrChildren ) ) {
136
+ const is2ndArgArrayChildren = isArray ( propsOrChildren )
137
+ if ( l === 2 || is2ndArgArrayChildren ) {
138
+ if ( isObject ( propsOrChildren ) && ! is2ndArgArrayChildren ) {
116
139
// single vnode without props
117
140
if ( isVNode ( propsOrChildren ) ) {
118
141
return convertLegacySlots ( createVNode ( type , null , [ propsOrChildren ] ) )
119
142
}
120
143
// props without children
121
144
return convertLegacySlots (
122
145
convertLegacyDirectives (
123
- createVNode ( type , convertLegacyProps ( propsOrChildren ) ) ,
146
+ createVNode ( type , convertLegacyProps ( propsOrChildren , type ) ) ,
124
147
propsOrChildren
125
148
)
126
149
)
@@ -134,15 +157,20 @@ export function compatH(
134
157
}
135
158
return convertLegacySlots (
136
159
convertLegacyDirectives (
137
- createVNode ( type , convertLegacyProps ( propsOrChildren ) , children ) ,
160
+ createVNode ( type , convertLegacyProps ( propsOrChildren , type ) , children ) ,
138
161
propsOrChildren
139
162
)
140
163
)
141
164
}
142
165
}
143
166
167
+ const skipLegacyRootLevelProps = /*#__PURE__*/ makeMap (
168
+ 'refInFor,staticStyle,staticClass,directives,model'
169
+ )
170
+
144
171
function convertLegacyProps (
145
- legacyProps ?: LegacyVNodeProps
172
+ legacyProps : LegacyVNodeProps | undefined ,
173
+ type : any
146
174
) : Data & VNodeProps | null {
147
175
if ( ! legacyProps ) {
148
176
return null
@@ -172,11 +200,7 @@ function convertLegacyProps(
172
200
}
173
201
}
174
202
}
175
- } else if (
176
- key !== 'refInFor' &&
177
- key !== 'staticStyle' &&
178
- key !== 'staticClass'
179
- ) {
203
+ } else if ( ! skipLegacyRootLevelProps ( key ) ) {
180
204
converted [ key ] = legacyProps [ key as keyof LegacyVNodeProps ]
181
205
}
182
206
}
@@ -188,6 +212,13 @@ function convertLegacyProps(
188
212
converted . style = normalizeStyle ( [ legacyProps . staticStyle , converted . style ] )
189
213
}
190
214
215
+ if ( legacyProps . model && isObject ( type ) ) {
216
+ // v2 compiled component v-model
217
+ const { prop = 'value' , event = 'input' } = ( type as any ) . model || { }
218
+ converted [ prop ] = legacyProps . model . value
219
+ converted [ compatModelEventPrefix + event ] = legacyProps . model . callback
220
+ }
221
+
191
222
return converted
192
223
}
193
224
@@ -237,7 +268,12 @@ function convertLegacySlots(vnode: VNode): VNode {
237
268
const child = children [ i ]
238
269
const slotName =
239
270
( isVNode ( child ) && child . props && child . props . slot ) || 'default'
240
- ; ( slots [ slotName ] || ( slots [ slotName ] = [ ] as any [ ] ) ) . push ( child )
271
+ const slot = slots [ slotName ] || ( slots [ slotName ] = [ ] as any [ ] )
272
+ if ( isVNode ( child ) && child . type === 'template' ) {
273
+ slot . push ( child . children )
274
+ } else {
275
+ slot . push ( child )
276
+ }
241
277
}
242
278
if ( slots ) {
243
279
for ( const key in slots ) {
@@ -263,3 +299,31 @@ function convertLegacySlots(vnode: VNode): VNode {
263
299
264
300
return vnode
265
301
}
302
+
303
+ export function defineLegacyVNodeProperties ( vnode : VNode ) {
304
+ if (
305
+ isCompatEnabled ( DeprecationTypes . RENDER_FUNCTION , currentRenderingInstance )
306
+ ) {
307
+ const getInstance = ( ) => vnode . component && vnode . component . proxy
308
+ let componentOptions : any
309
+ Object . defineProperties ( vnode , {
310
+ elm : { get : ( ) => vnode . el } ,
311
+ componentInstance : { get : getInstance } ,
312
+ child : { get : getInstance } ,
313
+ componentOptions : {
314
+ get : ( ) => {
315
+ if ( vnode . shapeFlag & ShapeFlags . STATEFUL_COMPONENT ) {
316
+ if ( componentOptions ) {
317
+ return componentOptions
318
+ }
319
+ return ( componentOptions = {
320
+ Ctor : vnode . type ,
321
+ propsData : vnode . props ,
322
+ children : vnode . children
323
+ } )
324
+ }
325
+ }
326
+ }
327
+ } )
328
+ }
329
+ }
0 commit comments