Skip to content

Commit 1b8f14e

Browse files
committed
wip: more compat progress
1 parent 62b8f4a commit 1b8f14e

14 files changed

+270
-53
lines changed

packages/runtime-core/__tests__/componentSlots.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('component: slots', () => {
8282
expect(slots.default()).toMatchObject([normalizeVNode(h('span'))])
8383
})
8484

85-
test('updateSlots: instance.slots should be update correctly (when slotType is number)', async () => {
85+
test('updateSlots: instance.slots should be updated correctly (when slotType is number)', async () => {
8686
const flag1 = ref(true)
8787

8888
let instance: any
@@ -124,7 +124,7 @@ describe('component: slots', () => {
124124
expect(instance.slots).toHaveProperty('two')
125125
})
126126

127-
test('updateSlots: instance.slots should be update correctly (when slotType is null)', async () => {
127+
test('updateSlots: instance.slots should be updated correctly (when slotType is null)', async () => {
128128
const flag1 = ref(true)
129129

130130
let instance: any

packages/runtime-core/src/compat/compatConfig.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
262262

263263
[DeprecationTypes.PROPS_DEFAULT_THIS]: {
264264
message: (key: string) =>
265-
`props default value function no longer has access to "this". ` +
265+
`props default value function no longer has access to "this". The compat ` +
266+
`build only offers access to this.$options.` +
266267
`(found in prop "${key}")`,
267268
link: `https://v3.vuejs.org/guide/migration/props-default-this.html`
268269
},

packages/runtime-core/src/compat/component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ function convertLegacyFunctionalComponent(comp: ComponentOptions) {
132132
data: instance.vnode.props || {},
133133
scopedSlots: ctx.slots,
134134
parent: instance.parent && instance.parent.proxy,
135-
get slots() {
135+
slots() {
136136
return new Proxy(ctx.slots, legacySlotProxyHandlers)
137137
},
138138
get listeners() {

packages/runtime-core/src/compat/instance.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ import { getCompatListeners } from './instanceListeners'
1212
import { shallowReadonly } from '@vue/reactivity'
1313
import { legacySlotProxyHandlers } from './component'
1414
import { compatH } from './renderFn'
15+
import { createCommentVNode, createTextVNode } from '../vnode'
16+
import { renderList } from '../helpers/renderList'
1517
import {
18+
legacyBindObjectListeners,
1619
legacyBindObjectProps,
20+
legacyCheckKeyCodes,
1721
legacyRenderSlot,
18-
legacyRenderStatic
22+
legacyRenderStatic,
23+
legacyresolveScopedSlots
1924
} from './renderHelpers'
20-
import { createCommentVNode, createTextVNode } from '../vnode'
21-
import { renderList } from '../helpers/renderList'
2225

2326
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
2427
const set = (target: any, key: any, val: any) => {
@@ -98,6 +101,9 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
98101
_b: () => legacyBindObjectProps,
99102
_e: () => createCommentVNode,
100103
_v: () => createTextVNode,
101-
_m: i => legacyRenderStatic.bind(null, i)
104+
_m: i => legacyRenderStatic.bind(null, i),
105+
_g: () => legacyBindObjectListeners,
106+
_u: () => legacyresolveScopedSlots,
107+
_k: i => legacyCheckKeyCodes.bind(null, i)
102108
} as PublicPropertiesMap)
103109
}

packages/runtime-core/src/compat/props.ts

+31-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
1+
import { isArray } from '@vue/shared'
2+
import { inject } from '../apiInject'
3+
import { ComponentInternalInstance, Data } from '../component'
4+
import { ComponentOptions, resolveMergedOptions } from '../componentOptions'
15
import { DeprecationTypes, warnDeprecation } from './compatConfig'
26

3-
export function createPropsDefaultThis(propKey: string) {
7+
export function createPropsDefaultThis(
8+
instance: ComponentInternalInstance,
9+
rawProps: Data,
10+
propKey: string
11+
) {
412
return new Proxy(
513
{},
614
{
7-
get() {
8-
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)
15+
get(_, key: string) {
16+
__DEV__ &&
17+
warnDeprecation(DeprecationTypes.PROPS_DEFAULT_THIS, null, propKey)
18+
// $options
19+
if (key === '$options') {
20+
return resolveMergedOptions(instance)
21+
}
22+
// props
23+
if (key in rawProps) {
24+
return rawProps[key]
25+
}
26+
// injections
27+
const injections = (instance.type as ComponentOptions).inject
28+
if (injections) {
29+
if (isArray(injections)) {
30+
if (injections.includes(key)) {
31+
return inject(key)
32+
}
33+
} else if (key in injections) {
34+
return inject(key)
35+
}
36+
}
937
}
1038
}
1139
)

packages/runtime-core/src/compat/renderFn.ts

+78-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
22
extend,
3+
hyphenate,
34
isArray,
45
isObject,
6+
makeMap,
57
normalizeClass,
68
normalizeStyle,
79
ShapeFlags,
@@ -14,6 +16,7 @@ import {
1416
Data,
1517
InternalRenderFunction
1618
} from '../component'
19+
import { currentRenderingInstance } from '../componentRenderContext'
1720
import { DirectiveArguments, withDirectives } from '../directives'
1821
import {
1922
resolveDirective,
@@ -27,7 +30,12 @@ import {
2730
VNodeArrayChildren,
2831
VNodeProps
2932
} from '../vnode'
30-
import { checkCompatEnabled, DeprecationTypes } from './compatConfig'
33+
import {
34+
checkCompatEnabled,
35+
DeprecationTypes,
36+
isCompatEnabled
37+
} from './compatConfig'
38+
import { compatModelEventPrefix } from './vModel'
3139

3240
const v3CompiledRenderFnRE = /^(?:function \w+)?\(_ctx, _cache/
3341

@@ -76,6 +84,11 @@ interface LegacyVNodeProps {
7684
props?: Record<string, unknown>
7785
slot?: string
7886
scopedSlots?: Record<string, Function>
87+
model?: {
88+
value: any
89+
callback: (v: any) => void
90+
expression: string
91+
}
7992
}
8093

8194
interface LegacyVNodeDirective {
@@ -107,20 +120,30 @@ export function compatH(
107120
propsOrChildren?: any,
108121
children?: any
109122
): 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+
}
112134

113135
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) {
116139
// single vnode without props
117140
if (isVNode(propsOrChildren)) {
118141
return convertLegacySlots(createVNode(type, null, [propsOrChildren]))
119142
}
120143
// props without children
121144
return convertLegacySlots(
122145
convertLegacyDirectives(
123-
createVNode(type, convertLegacyProps(propsOrChildren)),
146+
createVNode(type, convertLegacyProps(propsOrChildren, type)),
124147
propsOrChildren
125148
)
126149
)
@@ -134,15 +157,20 @@ export function compatH(
134157
}
135158
return convertLegacySlots(
136159
convertLegacyDirectives(
137-
createVNode(type, convertLegacyProps(propsOrChildren), children),
160+
createVNode(type, convertLegacyProps(propsOrChildren, type), children),
138161
propsOrChildren
139162
)
140163
)
141164
}
142165
}
143166

167+
const skipLegacyRootLevelProps = /*#__PURE__*/ makeMap(
168+
'refInFor,staticStyle,staticClass,directives,model'
169+
)
170+
144171
function convertLegacyProps(
145-
legacyProps?: LegacyVNodeProps
172+
legacyProps: LegacyVNodeProps | undefined,
173+
type: any
146174
): Data & VNodeProps | null {
147175
if (!legacyProps) {
148176
return null
@@ -172,11 +200,7 @@ function convertLegacyProps(
172200
}
173201
}
174202
}
175-
} else if (
176-
key !== 'refInFor' &&
177-
key !== 'staticStyle' &&
178-
key !== 'staticClass'
179-
) {
203+
} else if (!skipLegacyRootLevelProps(key)) {
180204
converted[key] = legacyProps[key as keyof LegacyVNodeProps]
181205
}
182206
}
@@ -188,6 +212,13 @@ function convertLegacyProps(
188212
converted.style = normalizeStyle([legacyProps.staticStyle, converted.style])
189213
}
190214

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+
191222
return converted
192223
}
193224

@@ -237,7 +268,12 @@ function convertLegacySlots(vnode: VNode): VNode {
237268
const child = children[i]
238269
const slotName =
239270
(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+
}
241277
}
242278
if (slots) {
243279
for (const key in slots) {
@@ -263,3 +299,31 @@ function convertLegacySlots(vnode: VNode): VNode {
263299

264300
return vnode
265301
}
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

Comments
 (0)