Skip to content

Commit 7e0224a

Browse files
committed
wip: more compat tweaks
1 parent 98bc9a2 commit 7e0224a

File tree

9 files changed

+86
-14
lines changed

9 files changed

+86
-14
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
createApp,
77
shallowReadonly
88
} from '@vue/runtime-test'
9-
import { ComponentInternalInstance } from '../src/component'
9+
import { ComponentInternalInstance, ComponentOptions } from '../src/component'
1010

1111
describe('component: proxy', () => {
1212
test('data', () => {
@@ -93,7 +93,9 @@ describe('component: proxy', () => {
9393
expect(instanceProxy.$root).toBe(instance!.root.proxy)
9494
expect(instanceProxy.$emit).toBe(instance!.emit)
9595
expect(instanceProxy.$el).toBe(instance!.vnode.el)
96-
expect(instanceProxy.$options).toBe(instance!.type)
96+
expect(instanceProxy.$options).toBe(
97+
(instance!.type as ComponentOptions).__merged
98+
)
9799
expect(() => (instanceProxy.$data = {})).toThrow(TypeError)
98100
expect(`Attempting to mutate public property "$data"`).toHaveBeenWarned()
99101

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@ export function convertLegacyComponent(
2626
return comp
2727
}
2828

29+
// 2.x constructor
30+
if (isFunction(comp) && comp.cid) {
31+
comp = comp.options
32+
}
33+
2934
// 2.x async component
30-
// since after disabling this, plain functions are still valid usage, do not
31-
// use softAssert here.
3235
if (
3336
isFunction(comp) &&
3437
checkCompatEnabled(DeprecationTypes.COMPONENT_ASYNC, instance, comp)
3538
) {
39+
// since after disabling this, plain functions are still valid usage, do not
40+
// use softAssert here.
3641
return convertLegacyAsyncComponent(comp)
3742
}
3843

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

+37-7
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ export type CompatVue = Pick<App, 'version' | 'component' | 'directive'> & {
9494
* @deprecated filters have been removed from Vue 3.
9595
*/
9696
filter(name: string, arg: any): null
97+
/**
98+
* @internal
99+
*/
100+
cid: number
101+
/**
102+
* @internal
103+
*/
104+
options: ComponentOptions
97105

98106
configureCompat: typeof configureCompat
99107
}
@@ -109,8 +117,6 @@ export function createCompatVue(
109117
} as any
110118

111119
const singletonApp = createApp({})
112-
// @ts-ignore
113-
singletonApp.prototype = singletonApp.config.globalProperties
114120

115121
function createCompatApp(options: ComponentOptions = {}, Ctor: any) {
116122
assertCompatEnabled(DeprecationTypes.GLOBAL_MOUNT, null)
@@ -174,18 +180,26 @@ export function createCompatVue(
174180
Vue.version = __VERSION__
175181
Vue.config = singletonApp.config
176182
Vue.nextTick = nextTick
183+
Vue.options = { _base: Vue }
184+
185+
let cid = 1
186+
Vue.cid = cid
177187

178-
Vue.extend = ((options: ComponentOptions = {}) => {
188+
function extendCtor(this: any, extendOptions: ComponentOptions = {}) {
179189
assertCompatEnabled(DeprecationTypes.GLOBAL_EXTEND, null)
190+
if (isFunction(extendOptions)) {
191+
extendOptions = extendOptions.options
192+
}
180193

194+
const Super = this
181195
function SubVue(inlineOptions?: ComponentOptions) {
182196
if (!inlineOptions) {
183-
return createCompatApp(options, SubVue)
197+
return createCompatApp(extendOptions, SubVue)
184198
} else {
185199
return createCompatApp(
186200
{
187201
el: inlineOptions.el,
188-
extends: options,
202+
extends: extendOptions,
189203
mixins: [inlineOptions]
190204
},
191205
SubVue
@@ -194,8 +208,20 @@ export function createCompatVue(
194208
}
195209
SubVue.prototype = Object.create(Vue.prototype)
196210
SubVue.prototype.constructor = SubVue
211+
SubVue.options = mergeOptions(
212+
extend({}, Super.options) as ComponentOptions,
213+
extendOptions
214+
)
215+
216+
SubVue.options._base = SubVue
217+
SubVue.extend = extendCtor.bind(SubVue)
218+
SubVue.mixin = Super.mixin
219+
SubVue.use = Super.use
220+
SubVue.cid = ++cid
197221
return SubVue
198-
}) as any
222+
}
223+
224+
Vue.extend = extendCtor.bind(Vue) as any
199225

200226
Vue.set = (target, key, value) => {
201227
assertCompatEnabled(DeprecationTypes.GLOBAL_SET, null)
@@ -213,7 +239,11 @@ export function createCompatVue(
213239
}
214240

215241
Vue.use = (p, ...options) => {
216-
singletonApp.use(p, ...options)
242+
if (p && isFunction(p.install)) {
243+
p.install(Vue as any, ...options)
244+
} else if (isFunction(p)) {
245+
p(Vue as any, ...options)
246+
}
217247
return Vue
218248
}
219249

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,11 @@ export function installLegacyConfigProperties(config: AppConfig) {
110110
strats.watch = mergeObjectOptions
111111
}
112112

113-
function mergeHook(to: Function[] | undefined, from: Function | Function[]) {
114-
return Array.from(new Set([...(to || []), from]))
113+
function mergeHook(
114+
to: Function[] | Function | undefined,
115+
from: Function | Function[]
116+
) {
117+
return Array.from(new Set([...(isArray(to) ? to : to ? [to] : []), from]))
115118
}
116119

117120
function mergeObjectOptions(to: Object | undefined, from: Object | undefined) {

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

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
legacyresolveScopedSlots
3333
} from './renderHelpers'
3434
import { resolveFilter } from '../helpers/resolveAssets'
35+
import { resolveMergedOptions } from '../componentOptions'
3536

3637
export function installCompatInstanceProperties(map: PublicPropertiesMap) {
3738
const set = (target: any, key: any, val: any) => {
@@ -92,9 +93,18 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
9293
$children: getCompatChildren,
9394
$listeners: getCompatListeners,
9495

96+
// inject parent into $options for compat
97+
$options: i => {
98+
let res = resolveMergedOptions(i)
99+
if (res === i.type) res = i.type.__merged = extend({}, res)
100+
res.parent = i.proxy!.$parent
101+
return res
102+
},
103+
95104
// v2 render helpers
96105
$createElement: () => compatH,
97106
_self: i => i.proxy,
107+
_uid: i => i.uid,
98108
_c: () => compatH,
99109
_o: () => legacyMarkOnce,
100110
_n: () => toNumber,

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

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
hyphenate,
44
isArray,
55
isObject,
6+
isString,
67
makeMap,
78
normalizeClass,
89
normalizeStyle,
@@ -304,12 +305,17 @@ export function defineLegacyVNodeProperties(vnode: VNode) {
304305
if (
305306
isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, currentRenderingInstance)
306307
) {
308+
const context = currentRenderingInstance
307309
const getInstance = () => vnode.component && vnode.component.proxy
308310
let componentOptions: any
309311
Object.defineProperties(vnode, {
312+
tag: { get: () => vnode.type },
313+
data: { get: () => vnode.props, set: p => (vnode.props = p) },
310314
elm: { get: () => vnode.el },
311315
componentInstance: { get: getInstance },
312316
child: { get: getInstance },
317+
text: { get: () => (isString(vnode.children) ? vnode.children : null) },
318+
context: { get: () => context && context.proxy },
313319
componentOptions: {
314320
get: () => {
315321
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {

packages/runtime-core/src/componentOptions.ts

+9
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ export function applyOptions(
509509
deferredProvide: (Data | Function)[] = [],
510510
asMixin: boolean = false
511511
) {
512+
if (__COMPAT__ && isFunction(options)) {
513+
options = options.options
514+
}
515+
512516
const {
513517
// composition
514518
mixins,
@@ -1005,6 +1009,10 @@ export function mergeOptions(
10051009
from: any,
10061010
instance?: ComponentInternalInstance
10071011
) {
1012+
if (__COMPAT__ && isFunction(from)) {
1013+
from = from.options
1014+
}
1015+
10081016
const strats = instance && instance.appContext.config.optionMergeStrategies
10091017
const { mixins, extends: extendsOptions } = from
10101018

@@ -1019,4 +1027,5 @@ export function mergeOptions(
10191027
to[key] = from[key]
10201028
}
10211029
}
1030+
return to
10221031
}

packages/runtime-core/src/componentProps.ts

+3
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ export function normalizePropsOptions(
429429
let hasExtends = false
430430
if (__FEATURE_OPTIONS_API__ && !isFunction(comp)) {
431431
const extendProps = (raw: ComponentOptions) => {
432+
if (__COMPAT__ && isFunction(raw)) {
433+
raw = raw.options
434+
}
432435
hasExtends = true
433436
const [props, keys] = normalizePropsOptions(raw, appContext, true)
434437
extend(normalized, props)

packages/runtime-core/src/componentSlots.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ const normalizeVNodeSlots = (
107107
instance: ComponentInternalInstance,
108108
children: VNodeNormalizedChildren
109109
) => {
110-
if (__DEV__ && !isKeepAlive(instance.vnode)) {
110+
if (
111+
__DEV__ &&
112+
!isKeepAlive(instance.vnode) &&
113+
!(__COMPAT__ && isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance))
114+
) {
111115
warn(
112116
`Non-function value encountered for default slot. ` +
113117
`Prefer function slots for better performance.`

0 commit comments

Comments
 (0)