wip: fix render fn compat detection
This commit is contained in:
parent
a2f441dc0e
commit
c55f3ed0e8
@ -30,6 +30,11 @@ export function isCompatEnabled(
|
|||||||
key: DeprecationTypes,
|
key: DeprecationTypes,
|
||||||
instance: ComponentInternalInstance | null
|
instance: ComponentInternalInstance | null
|
||||||
): boolean {
|
): boolean {
|
||||||
|
// skip compat for built-in components
|
||||||
|
if (instance && instance.type.__isBuiltIn) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const mode = getCompatConfigForKey('MODE', instance) || 2
|
const mode = getCompatConfigForKey('MODE', instance) || 2
|
||||||
const val = getCompatConfigForKey(key, instance)
|
const val = getCompatConfigForKey(key, instance)
|
||||||
if (mode === 2) {
|
if (mode === 2) {
|
||||||
|
@ -19,6 +19,10 @@ export function convertLegacyComponent(
|
|||||||
comp: any,
|
comp: any,
|
||||||
instance: ComponentInternalInstance | null
|
instance: ComponentInternalInstance | null
|
||||||
): Component {
|
): Component {
|
||||||
|
if (comp.__isBuiltIn) {
|
||||||
|
return comp
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -49,7 +49,11 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
|||||||
|
|
||||||
// overrides existing accessor
|
// overrides existing accessor
|
||||||
$slots: i => {
|
$slots: i => {
|
||||||
if (isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i)) {
|
if (
|
||||||
|
isCompatEnabled(DeprecationTypes.RENDER_FUNCTION, i) &&
|
||||||
|
i.render &&
|
||||||
|
i.render._compatWrapped
|
||||||
|
) {
|
||||||
return new Proxy(i.slots, legacySlotProxyHandlers)
|
return new Proxy(i.slots, legacySlotProxyHandlers)
|
||||||
}
|
}
|
||||||
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
||||||
|
@ -5,7 +5,13 @@ import {
|
|||||||
ShapeFlags,
|
ShapeFlags,
|
||||||
toHandlerKey
|
toHandlerKey
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { Component, Data } from '../component'
|
import {
|
||||||
|
Component,
|
||||||
|
ComponentInternalInstance,
|
||||||
|
ComponentOptions,
|
||||||
|
Data,
|
||||||
|
InternalRenderFunction
|
||||||
|
} from '../component'
|
||||||
import { DirectiveArguments, withDirectives } from '../directives'
|
import { DirectiveArguments, withDirectives } from '../directives'
|
||||||
import {
|
import {
|
||||||
resolveDirective,
|
resolveDirective,
|
||||||
@ -19,6 +25,35 @@ import {
|
|||||||
VNodeArrayChildren,
|
VNodeArrayChildren,
|
||||||
VNodeProps
|
VNodeProps
|
||||||
} from '../vnode'
|
} from '../vnode'
|
||||||
|
import { checkCompatEnabled } from './compatConfig'
|
||||||
|
import { DeprecationTypes } from './deprecations'
|
||||||
|
|
||||||
|
export function convertLegacyRenderFn(instance: ComponentInternalInstance) {
|
||||||
|
const Component = instance.type as ComponentOptions
|
||||||
|
const render = Component.render as InternalRenderFunction | undefined
|
||||||
|
|
||||||
|
// v3 runtime compiled, or already checked / wrapped
|
||||||
|
if (!render || render._rc || render._compatChecked || render._compatWrapped) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const string = render.toString()
|
||||||
|
if (string.startsWith('function render(_ctx') || string.startsWith('(_ctx')) {
|
||||||
|
// v3 pre-compiled function
|
||||||
|
render._compatChecked = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// v2 render function, try to provide compat
|
||||||
|
if (checkCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance)) {
|
||||||
|
const wrapped = (Component.render = function compatRender() {
|
||||||
|
// @ts-ignore
|
||||||
|
return render.call(this, compatH)
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
wrapped._compatWrapped = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface LegacyVNodeProps {
|
interface LegacyVNodeProps {
|
||||||
key?: string | number
|
key?: string | number
|
||||||
|
@ -54,9 +54,7 @@ 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 { checkCompatEnabled } from './compat/compatConfig'
|
import { convertLegacyRenderFn } from './compat/renderFn'
|
||||||
import { DeprecationTypes } from './compat/deprecations'
|
|
||||||
import { compatH } from './compat/renderFn'
|
|
||||||
|
|
||||||
export type Data = Record<string, unknown>
|
export type Data = Record<string, unknown>
|
||||||
|
|
||||||
@ -96,6 +94,10 @@ export interface ComponentInternalOptions {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
__hmrId?: string
|
__hmrId?: string
|
||||||
|
/**
|
||||||
|
* Compat build only, for bailing out of certain compatibility behavior
|
||||||
|
*/
|
||||||
|
__isBuiltIn?: boolean
|
||||||
/**
|
/**
|
||||||
* This one should be exposed so that devtools can make use of it
|
* This one should be exposed so that devtools can make use of it
|
||||||
*/
|
*/
|
||||||
@ -188,6 +190,10 @@ export type InternalRenderFunction = {
|
|||||||
$options: ComponentInternalInstance['ctx']
|
$options: ComponentInternalInstance['ctx']
|
||||||
): VNodeChild
|
): VNodeChild
|
||||||
_rc?: boolean // isRuntimeCompiled
|
_rc?: boolean // isRuntimeCompiled
|
||||||
|
|
||||||
|
// __COMPAT__ only
|
||||||
|
_compatChecked?: boolean // v3 and already checked for v2 compat
|
||||||
|
_compatWrapped?: boolean // is wrapped for v2 compat
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -684,15 +690,8 @@ export function finishComponentSetup(
|
|||||||
) {
|
) {
|
||||||
const Component = instance.type as ComponentOptions
|
const Component = instance.type as ComponentOptions
|
||||||
|
|
||||||
if (
|
if (__COMPAT__) {
|
||||||
__COMPAT__ &&
|
convertLegacyRenderFn(instance)
|
||||||
Component.render &&
|
|
||||||
checkCompatEnabled(DeprecationTypes.RENDER_FUNCTION, instance)
|
|
||||||
) {
|
|
||||||
const originalRender = Component.render
|
|
||||||
Component.render = function compatRender() {
|
|
||||||
return originalRender.call(this, compatH)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// template / render function normalization
|
// template / render function normalization
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
getCurrentInstance,
|
getCurrentInstance,
|
||||||
SetupContext,
|
SetupContext,
|
||||||
ComponentInternalInstance
|
ComponentInternalInstance,
|
||||||
|
ComponentOptions
|
||||||
} from '../component'
|
} from '../component'
|
||||||
import {
|
import {
|
||||||
cloneVNode,
|
cloneVNode,
|
||||||
@ -110,7 +111,7 @@ export function useTransitionState(): TransitionState {
|
|||||||
|
|
||||||
const TransitionHookValidator = [Function, Array]
|
const TransitionHookValidator = [Function, Array]
|
||||||
|
|
||||||
const BaseTransitionImpl = {
|
const BaseTransitionImpl: ComponentOptions = {
|
||||||
name: `BaseTransition`,
|
name: `BaseTransition`,
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@ -250,6 +251,10 @@ const BaseTransitionImpl = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
BaseTransitionImpl.__isBuiltIn = true
|
||||||
|
}
|
||||||
|
|
||||||
// export the public type for h/tsx inference
|
// export the public type for h/tsx inference
|
||||||
// also to avoid inline import() in generated d.ts files
|
// also to avoid inline import() in generated d.ts files
|
||||||
export const BaseTransition = (BaseTransitionImpl as any) as {
|
export const BaseTransition = (BaseTransitionImpl as any) as {
|
||||||
|
@ -5,7 +5,8 @@ import {
|
|||||||
ComponentInternalInstance,
|
ComponentInternalInstance,
|
||||||
LifecycleHooks,
|
LifecycleHooks,
|
||||||
currentInstance,
|
currentInstance,
|
||||||
getComponentName
|
getComponentName,
|
||||||
|
ComponentOptions
|
||||||
} from '../component'
|
} from '../component'
|
||||||
import { VNode, cloneVNode, isVNode, VNodeProps } from '../vnode'
|
import { VNode, cloneVNode, isVNode, VNodeProps } from '../vnode'
|
||||||
import { warn } from '../warning'
|
import { warn } from '../warning'
|
||||||
@ -62,7 +63,7 @@ export interface KeepAliveContext extends ComponentRenderContext {
|
|||||||
export const isKeepAlive = (vnode: VNode): boolean =>
|
export const isKeepAlive = (vnode: VNode): boolean =>
|
||||||
(vnode.type as any).__isKeepAlive
|
(vnode.type as any).__isKeepAlive
|
||||||
|
|
||||||
const KeepAliveImpl = {
|
const KeepAliveImpl: ComponentOptions = {
|
||||||
name: `KeepAlive`,
|
name: `KeepAlive`,
|
||||||
|
|
||||||
// Marker for special handling inside the renderer. We are not using a ===
|
// Marker for special handling inside the renderer. We are not using a ===
|
||||||
@ -298,6 +299,10 @@ const KeepAliveImpl = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
KeepAliveImpl.__isBuildIn = true
|
||||||
|
}
|
||||||
|
|
||||||
// export the public type for h/tsx inference
|
// export the public type for h/tsx inference
|
||||||
// also to avoid inline import() in generated d.ts files
|
// also to avoid inline import() in generated d.ts files
|
||||||
export const KeepAlive = (KeepAliveImpl as any) as {
|
export const KeepAlive = (KeepAliveImpl as any) as {
|
||||||
|
@ -46,6 +46,10 @@ export const Transition: FunctionalComponent<TransitionProps> = (
|
|||||||
|
|
||||||
Transition.displayName = 'Transition'
|
Transition.displayName = 'Transition'
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
Transition.__isBuiltIn = true
|
||||||
|
}
|
||||||
|
|
||||||
const DOMTransitionPropsValidators = {
|
const DOMTransitionPropsValidators = {
|
||||||
name: String,
|
name: String,
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -22,7 +22,8 @@ import {
|
|||||||
SetupContext,
|
SetupContext,
|
||||||
toRaw,
|
toRaw,
|
||||||
compatUtils,
|
compatUtils,
|
||||||
DeprecationTypes
|
DeprecationTypes,
|
||||||
|
ComponentOptions
|
||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { extend } from '@vue/shared'
|
import { extend } from '@vue/shared'
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ export type TransitionGroupProps = Omit<TransitionProps, 'mode'> & {
|
|||||||
moveClass?: string
|
moveClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const TransitionGroupImpl = {
|
const TransitionGroupImpl: ComponentOptions = {
|
||||||
name: 'TransitionGroup',
|
name: 'TransitionGroup',
|
||||||
|
|
||||||
props: /*#__PURE__*/ extend({}, TransitionPropsValidators, {
|
props: /*#__PURE__*/ extend({}, TransitionPropsValidators, {
|
||||||
@ -145,6 +146,10 @@ const TransitionGroupImpl = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
TransitionGroupImpl.__isBuiltIn = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TransitionGroup does not support "mode" so we need to remove it from the
|
* TransitionGroup does not support "mode" so we need to remove it from the
|
||||||
* props declarations, but direct delete operation is considered a side effect
|
* props declarations, but direct delete operation is considered a side effect
|
||||||
|
Loading…
x
Reference in New Issue
Block a user