parent
b3890a93e3
commit
b8c1be18f3
@ -26,12 +26,12 @@ export interface VOnDirectiveNode extends DirectiveNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const transformOn: DirectiveTransform = (
|
export const transformOn: DirectiveTransform = (
|
||||||
dir: VOnDirectiveNode,
|
dir,
|
||||||
node,
|
node,
|
||||||
context,
|
context,
|
||||||
augmentor
|
augmentor
|
||||||
) => {
|
) => {
|
||||||
const { loc, modifiers, arg } = dir
|
const { loc, modifiers, arg } = dir as VOnDirectiveNode
|
||||||
if (!dir.exp && !modifiers.length) {
|
if (!dir.exp && !modifiers.length) {
|
||||||
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))
|
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))
|
||||||
}
|
}
|
||||||
@ -55,7 +55,9 @@ export const transformOn: DirectiveTransform = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handler processing
|
// handler processing
|
||||||
let exp: ExpressionNode | undefined = dir.exp
|
let exp: ExpressionNode | undefined = dir.exp as
|
||||||
|
| SimpleExpressionNode
|
||||||
|
| undefined
|
||||||
if (exp && !exp.content.trim()) {
|
if (exp && !exp.content.trim()) {
|
||||||
exp = undefined
|
exp = undefined
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
AttributeNode,
|
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
ExpressionNode,
|
ExpressionNode,
|
||||||
NodeTransform,
|
NodeTransform,
|
||||||
@ -42,7 +41,7 @@ export const transformAssetUrl: NodeTransform = (
|
|||||||
if ((tag === '*' || node.tag === tag) && node.props.length) {
|
if ((tag === '*' || node.tag === tag) && node.props.length) {
|
||||||
const attributes = options[tag]
|
const attributes = options[tag]
|
||||||
attributes.forEach(item => {
|
attributes.forEach(item => {
|
||||||
node.props.forEach((attr: AttributeNode, index) => {
|
node.props.forEach((attr, index) => {
|
||||||
if (attr.type !== NodeTypes.ATTRIBUTE) return
|
if (attr.type !== NodeTypes.ATTRIBUTE) return
|
||||||
if (attr.name !== item) return
|
if (attr.name !== item) return
|
||||||
if (!attr.value) return
|
if (!attr.value) return
|
||||||
|
@ -21,7 +21,7 @@ export interface ReactiveEffect<T = any> {
|
|||||||
export interface ReactiveEffectOptions {
|
export interface ReactiveEffectOptions {
|
||||||
lazy?: boolean
|
lazy?: boolean
|
||||||
computed?: boolean
|
computed?: boolean
|
||||||
scheduler?: (run: Function) => void
|
scheduler?: (job: () => void) => void
|
||||||
onTrack?: (event: DebuggerEvent) => void
|
onTrack?: (event: DebuggerEvent) => void
|
||||||
onTrigger?: (event: DebuggerEvent) => void
|
onTrigger?: (event: DebuggerEvent) => void
|
||||||
onStop?: () => void
|
onStop?: () => void
|
||||||
|
@ -10,7 +10,8 @@ import {
|
|||||||
withDirectives,
|
withDirectives,
|
||||||
Plugin,
|
Plugin,
|
||||||
ref,
|
ref,
|
||||||
getCurrentInstance
|
getCurrentInstance,
|
||||||
|
defineComponent
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { mockWarn } from '@vue/shared'
|
import { mockWarn } from '@vue/shared'
|
||||||
|
|
||||||
@ -18,16 +19,16 @@ describe('api: createApp', () => {
|
|||||||
mockWarn()
|
mockWarn()
|
||||||
|
|
||||||
test('mount', () => {
|
test('mount', () => {
|
||||||
const Comp = {
|
const Comp = defineComponent({
|
||||||
props: {
|
props: {
|
||||||
count: {
|
count: {
|
||||||
default: 0
|
default: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props: { count: number }) {
|
setup(props) {
|
||||||
return () => props.count
|
return () => props.count
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
const root1 = nodeOps.createElement('div')
|
const root1 = nodeOps.createElement('div')
|
||||||
createApp(Comp).mount(root1)
|
createApp(Comp).mount(root1)
|
||||||
@ -47,16 +48,16 @@ describe('api: createApp', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('unmount', () => {
|
test('unmount', () => {
|
||||||
const Comp = {
|
const Comp = defineComponent({
|
||||||
props: {
|
props: {
|
||||||
count: {
|
count: {
|
||||||
default: 0
|
default: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props: { count: number }) {
|
setup(props) {
|
||||||
return () => props.count
|
return () => props.count
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
const root = nodeOps.createElement('div')
|
const root = nodeOps.createElement('div')
|
||||||
const app = createApp(Comp)
|
const app = createApp(Comp)
|
||||||
|
@ -9,7 +9,8 @@ import {
|
|||||||
serializeInner,
|
serializeInner,
|
||||||
serialize,
|
serialize,
|
||||||
VNodeProps,
|
VNodeProps,
|
||||||
KeepAlive
|
KeepAlive,
|
||||||
|
TestElement
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
|
|
||||||
function mount(
|
function mount(
|
||||||
@ -42,13 +43,13 @@ function mockProps(extra: BaseTransitionProps = {}, withKeepAlive = false) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
onEnter: jest.fn((el, done) => {
|
onEnter: jest.fn((el, done) => {
|
||||||
cbs.doneEnter[serialize(el)] = done
|
cbs.doneEnter[serialize(el as TestElement)] = done
|
||||||
}),
|
}),
|
||||||
onAfterEnter: jest.fn(),
|
onAfterEnter: jest.fn(),
|
||||||
onEnterCancelled: jest.fn(),
|
onEnterCancelled: jest.fn(),
|
||||||
onBeforeLeave: jest.fn(),
|
onBeforeLeave: jest.fn(),
|
||||||
onLeave: jest.fn((el, done) => {
|
onLeave: jest.fn((el, done) => {
|
||||||
cbs.doneLeave[serialize(el)] = done
|
cbs.doneLeave[serialize(el as TestElement)] = done
|
||||||
}),
|
}),
|
||||||
onAfterLeave: jest.fn(),
|
onAfterLeave: jest.fn(),
|
||||||
onLeaveCancelled: jest.fn(),
|
onLeaveCancelled: jest.fn(),
|
||||||
@ -64,8 +65,10 @@ function assertCalls(
|
|||||||
props: BaseTransitionProps,
|
props: BaseTransitionProps,
|
||||||
calls: Record<string, number>
|
calls: Record<string, number>
|
||||||
) {
|
) {
|
||||||
Object.keys(calls).forEach((key: keyof BaseTransitionProps) => {
|
Object.keys(calls).forEach(key => {
|
||||||
expect(props[key]).toHaveBeenCalledTimes(calls[key])
|
expect(props[key as keyof BaseTransitionProps]).toHaveBeenCalledTimes(
|
||||||
|
calls[key]
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,19 +150,19 @@ describe('BaseTransition', () => {
|
|||||||
const toggle = ref(true)
|
const toggle = ref(true)
|
||||||
const hooks: VNodeProps = {
|
const hooks: VNodeProps = {
|
||||||
onVnodeBeforeMount(vnode) {
|
onVnodeBeforeMount(vnode) {
|
||||||
vnode.transition!.beforeEnter(vnode.el)
|
vnode.transition!.beforeEnter(vnode.el!)
|
||||||
},
|
},
|
||||||
onVnodeMounted(vnode) {
|
onVnodeMounted(vnode) {
|
||||||
vnode.transition!.enter(vnode.el)
|
vnode.transition!.enter(vnode.el!)
|
||||||
},
|
},
|
||||||
onVnodeUpdated(vnode, oldVnode) {
|
onVnodeUpdated(vnode, oldVnode) {
|
||||||
if (oldVnode.props!.id !== vnode.props!.id) {
|
if (oldVnode.props!.id !== vnode.props!.id) {
|
||||||
if (vnode.props!.id) {
|
if (vnode.props!.id) {
|
||||||
vnode.transition!.beforeEnter(vnode.el)
|
vnode.transition!.beforeEnter(vnode.el!)
|
||||||
state.show = true
|
state.show = true
|
||||||
vnode.transition!.enter(vnode.el)
|
vnode.transition!.enter(vnode.el!)
|
||||||
} else {
|
} else {
|
||||||
vnode.transition!.leave(vnode.el, () => {
|
vnode.transition!.leave(vnode.el!, () => {
|
||||||
state.show = false
|
state.show = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ function mountWithHydration(html: string, render: () => any) {
|
|||||||
render
|
render
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
vnode: app.mount(container).$.subTree,
|
vnode: app.mount(container).$.subTree as VNode<Node, Element> & {
|
||||||
|
el: Element
|
||||||
|
},
|
||||||
container
|
container
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +92,7 @@ describe('SSR hydration', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// event handler
|
// event handler
|
||||||
triggerEvent('click', vnode.el.querySelector('.foo'))
|
triggerEvent('click', vnode.el.querySelector('.foo')!)
|
||||||
expect(fn).toHaveBeenCalled()
|
expect(fn).toHaveBeenCalled()
|
||||||
|
|
||||||
msg.value = 'bar'
|
msg.value = 'bar'
|
||||||
@ -120,7 +122,7 @@ describe('SSR hydration', () => {
|
|||||||
const fragment1Children = fragment1.children as VNode[]
|
const fragment1Children = fragment1.children as VNode[]
|
||||||
|
|
||||||
// first <span>
|
// first <span>
|
||||||
expect(fragment1Children[0].el.tagName).toBe('SPAN')
|
expect(fragment1Children[0].el!.tagName).toBe('SPAN')
|
||||||
expect(fragment1Children[0].el).toBe(vnode.el.childNodes[1])
|
expect(fragment1Children[0].el).toBe(vnode.el.childNodes[1])
|
||||||
|
|
||||||
// start fragment 2
|
// start fragment 2
|
||||||
@ -129,7 +131,7 @@ describe('SSR hydration', () => {
|
|||||||
const fragment2Children = fragment2.children as VNode[]
|
const fragment2Children = fragment2.children as VNode[]
|
||||||
|
|
||||||
// second <span>
|
// second <span>
|
||||||
expect(fragment2Children[0].el.tagName).toBe('SPAN')
|
expect(fragment2Children[0].el!.tagName).toBe('SPAN')
|
||||||
expect(fragment2Children[0].el).toBe(vnode.el.childNodes[3])
|
expect(fragment2Children[0].el).toBe(vnode.el.childNodes[3])
|
||||||
|
|
||||||
// end fragment 2
|
// end fragment 2
|
||||||
@ -139,7 +141,7 @@ describe('SSR hydration', () => {
|
|||||||
expect(fragment1.anchor).toBe(vnode.el.childNodes[5])
|
expect(fragment1.anchor).toBe(vnode.el.childNodes[5])
|
||||||
|
|
||||||
// event handler
|
// event handler
|
||||||
triggerEvent('click', vnode.el.querySelector('.foo'))
|
triggerEvent('click', vnode.el.querySelector('.foo')!)
|
||||||
expect(fn).toHaveBeenCalled()
|
expect(fn).toHaveBeenCalled()
|
||||||
|
|
||||||
msg.value = 'bar'
|
msg.value = 'bar'
|
||||||
|
@ -12,6 +12,7 @@ import { InjectionKey } from './apiInject'
|
|||||||
import { isFunction, NO, isObject } from '@vue/shared'
|
import { isFunction, NO, isObject } from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { createVNode, cloneVNode, VNode } from './vnode'
|
import { createVNode, cloneVNode, VNode } from './vnode'
|
||||||
|
import { RootHydrateFunction } from './hydration'
|
||||||
|
|
||||||
export interface App<HostElement = any> {
|
export interface App<HostElement = any> {
|
||||||
config: AppConfig
|
config: AppConfig
|
||||||
@ -91,11 +92,11 @@ export type CreateAppFunction<HostElement> = (
|
|||||||
rootProps?: Data | null
|
rootProps?: Data | null
|
||||||
) => App<HostElement>
|
) => App<HostElement>
|
||||||
|
|
||||||
export function createAppAPI<HostNode, HostElement>(
|
export function createAppAPI<HostElement>(
|
||||||
render: RootRenderFunction<HostNode, HostElement>,
|
render: RootRenderFunction,
|
||||||
hydrate?: (vnode: VNode, container: Element) => void
|
hydrate?: RootHydrateFunction
|
||||||
): CreateAppFunction<HostElement> {
|
): CreateAppFunction<HostElement> {
|
||||||
return function createApp(rootComponent: Component, rootProps = null) {
|
return function createApp(rootComponent, rootProps = null) {
|
||||||
if (rootProps != null && !isObject(rootProps)) {
|
if (rootProps != null && !isObject(rootProps)) {
|
||||||
__DEV__ && warn(`root props passed to app.mount() must be an object.`)
|
__DEV__ && warn(`root props passed to app.mount() must be an object.`)
|
||||||
rootProps = null
|
rootProps = null
|
||||||
@ -107,7 +108,7 @@ export function createAppAPI<HostNode, HostElement>(
|
|||||||
let isMounted = false
|
let isMounted = false
|
||||||
|
|
||||||
const app: App = {
|
const app: App = {
|
||||||
_component: rootComponent,
|
_component: rootComponent as Component,
|
||||||
_props: rootProps,
|
_props: rootProps,
|
||||||
_container: null,
|
_container: null,
|
||||||
_context: context,
|
_context: context,
|
||||||
@ -189,7 +190,7 @@ export function createAppAPI<HostNode, HostElement>(
|
|||||||
|
|
||||||
mount(rootContainer: HostElement, isHydrate?: boolean): any {
|
mount(rootContainer: HostElement, isHydrate?: boolean): any {
|
||||||
if (!isMounted) {
|
if (!isMounted) {
|
||||||
const vnode = createVNode(rootComponent, rootProps)
|
const vnode = createVNode(rootComponent as Component, rootProps)
|
||||||
// store app context on the root VNode.
|
// store app context on the root VNode.
|
||||||
// this will be set on the root instance on initial mount.
|
// this will be set on the root instance on initial mount.
|
||||||
vnode.appContext = context
|
vnode.appContext = context
|
||||||
@ -202,7 +203,7 @@ export function createAppAPI<HostNode, HostElement>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isHydrate && hydrate) {
|
if (isHydrate && hydrate) {
|
||||||
hydrate(vnode, rootContainer as any)
|
hydrate(vnode as VNode<Node, Element>, rootContainer as any)
|
||||||
} else {
|
} else {
|
||||||
render(vnode, rootContainer)
|
render(vnode, rootContainer)
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ export type ComponentOptionsWithoutProps<
|
|||||||
D = {},
|
D = {},
|
||||||
C extends ComputedOptions = {},
|
C extends ComputedOptions = {},
|
||||||
M extends MethodOptions = {}
|
M extends MethodOptions = {}
|
||||||
> = ComponentOptionsBase<Readonly<Props>, RawBindings, D, C, M> & {
|
> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
|
||||||
props?: undefined
|
props?: undefined
|
||||||
} & ThisType<ComponentPublicInstance<{}, RawBindings, D, C, M, Readonly<Props>>>
|
} & ThisType<ComponentPublicInstance<{}, RawBindings, D, C, M, Readonly<Props>>>
|
||||||
|
|
||||||
@ -116,12 +116,9 @@ export type ComponentOptionsWithObjectProps<
|
|||||||
} & ThisType<ComponentPublicInstance<Props, RawBindings, D, C, M>>
|
} & ThisType<ComponentPublicInstance<Props, RawBindings, D, C, M>>
|
||||||
|
|
||||||
export type ComponentOptions =
|
export type ComponentOptions =
|
||||||
| ComponentOptionsWithoutProps
|
| ComponentOptionsWithoutProps<any, any, any, any, any>
|
||||||
| ComponentOptionsWithObjectProps
|
| ComponentOptionsWithObjectProps<any, any, any, any, any>
|
||||||
| ComponentOptionsWithArrayProps
|
| ComponentOptionsWithArrayProps<any, any, any, any, any>
|
||||||
|
|
||||||
// TODO legacy component definition also supports constructors with .options
|
|
||||||
type LegacyComponent = ComponentOptions
|
|
||||||
|
|
||||||
export type ComputedOptions = Record<
|
export type ComputedOptions = Record<
|
||||||
string,
|
string,
|
||||||
@ -167,7 +164,10 @@ export interface LegacyOptions<
|
|||||||
// Limitation: we cannot expose RawBindings on the `this` context for data
|
// Limitation: we cannot expose RawBindings on the `this` context for data
|
||||||
// since that leads to some sort of circular inference and breaks ThisType
|
// since that leads to some sort of circular inference and breaks ThisType
|
||||||
// for the entire component.
|
// for the entire component.
|
||||||
data?: (this: ComponentPublicInstance<Props>) => D
|
data?: (
|
||||||
|
this: ComponentPublicInstance<Props>,
|
||||||
|
vm: ComponentPublicInstance<Props>
|
||||||
|
) => D
|
||||||
computed?: C
|
computed?: C
|
||||||
methods?: M
|
methods?: M
|
||||||
watch?: ComponentWatchOptions
|
watch?: ComponentWatchOptions
|
||||||
@ -175,8 +175,8 @@ export interface LegacyOptions<
|
|||||||
inject?: ComponentInjectOptions
|
inject?: ComponentInjectOptions
|
||||||
|
|
||||||
// composition
|
// composition
|
||||||
mixins?: LegacyComponent[]
|
mixins?: ComponentOptions[]
|
||||||
extends?: LegacyComponent
|
extends?: ComponentOptions
|
||||||
|
|
||||||
// lifecycle
|
// lifecycle
|
||||||
beforeCreate?(): void
|
beforeCreate?(): void
|
||||||
|
@ -179,7 +179,7 @@ function doWatch(
|
|||||||
getter = () => traverse(baseGetter())
|
getter = () => traverse(baseGetter())
|
||||||
}
|
}
|
||||||
|
|
||||||
let cleanup: Function
|
let cleanup: () => void
|
||||||
const onInvalidate: InvalidateCbRegistrator = (fn: () => void) => {
|
const onInvalidate: InvalidateCbRegistrator = (fn: () => void) => {
|
||||||
cleanup = runner.options.onStop = () => {
|
cleanup = runner.options.onStop = () => {
|
||||||
callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP)
|
callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP)
|
||||||
|
@ -63,7 +63,7 @@ export interface ClassComponent {
|
|||||||
__vccOpts: ComponentOptions
|
__vccOpts: ComponentOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Component = ComponentOptions | FunctionalComponent
|
export type Component = ComponentOptions | FunctionalComponent<any>
|
||||||
|
|
||||||
// A type used in public APIs where a component type is expected.
|
// A type used in public APIs where a component type is expected.
|
||||||
// The constructor type is an artificial type returned by defineComponent().
|
// The constructor type is an artificial type returned by defineComponent().
|
||||||
@ -100,7 +100,10 @@ export interface SetupContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type RenderFunction = {
|
export type RenderFunction = {
|
||||||
(): VNodeChild
|
(
|
||||||
|
ctx: ComponentPublicInstance,
|
||||||
|
cache: ComponentInternalInstance['renderCache']
|
||||||
|
): VNodeChild
|
||||||
_rc?: boolean // isRuntimeCompiled
|
_rc?: boolean // isRuntimeCompiled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export function renderComponentRoot(
|
|||||||
// runtime-compiled render functions using `with` block.
|
// runtime-compiled render functions using `with` block.
|
||||||
const proxyToUse = withProxy || proxy
|
const proxyToUse = withProxy || proxy
|
||||||
result = normalizeVNode(
|
result = normalizeVNode(
|
||||||
instance.render!.call(proxyToUse, proxyToUse, renderCache)
|
instance.render!.call(proxyToUse, proxyToUse!, renderCache)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// functional
|
// functional
|
||||||
|
@ -17,8 +17,9 @@ import { toRaw } from '@vue/reactivity'
|
|||||||
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
|
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
|
||||||
import { ShapeFlags } from '@vue/shared'
|
import { ShapeFlags } from '@vue/shared'
|
||||||
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
|
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
|
||||||
|
import { RendererElement } from '../renderer'
|
||||||
|
|
||||||
export interface BaseTransitionProps {
|
export interface BaseTransitionProps<HostElement = RendererElement> {
|
||||||
mode?: 'in-out' | 'out-in' | 'default'
|
mode?: 'in-out' | 'out-in' | 'default'
|
||||||
appear?: boolean
|
appear?: boolean
|
||||||
|
|
||||||
@ -32,25 +33,25 @@ export interface BaseTransitionProps {
|
|||||||
// Hooks. Using camel case for easier usage in render functions & JSX.
|
// Hooks. Using camel case for easier usage in render functions & JSX.
|
||||||
// In templates these can be written as @before-enter="xxx" as prop names
|
// In templates these can be written as @before-enter="xxx" as prop names
|
||||||
// are camelized.
|
// are camelized.
|
||||||
onBeforeEnter?: (el: any) => void
|
onBeforeEnter?: (el: HostElement) => void
|
||||||
onEnter?: (el: any, done: () => void) => void
|
onEnter?: (el: HostElement, done: () => void) => void
|
||||||
onAfterEnter?: (el: any) => void
|
onAfterEnter?: (el: HostElement) => void
|
||||||
onEnterCancelled?: (el: any) => void
|
onEnterCancelled?: (el: HostElement) => void
|
||||||
// leave
|
// leave
|
||||||
onBeforeLeave?: (el: any) => void
|
onBeforeLeave?: (el: HostElement) => void
|
||||||
onLeave?: (el: any, done: () => void) => void
|
onLeave?: (el: HostElement, done: () => void) => void
|
||||||
onAfterLeave?: (el: any) => void
|
onAfterLeave?: (el: HostElement) => void
|
||||||
onLeaveCancelled?: (el: any) => void // only fired in persisted mode
|
onLeaveCancelled?: (el: HostElement) => void // only fired in persisted mode
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransitionHooks {
|
export interface TransitionHooks {
|
||||||
persisted: boolean
|
persisted: boolean
|
||||||
beforeEnter(el: object): void
|
beforeEnter(el: RendererElement): void
|
||||||
enter(el: object): void
|
enter(el: RendererElement): void
|
||||||
leave(el: object, remove: () => void): void
|
leave(el: RendererElement, remove: () => void): void
|
||||||
afterLeave?(): void
|
afterLeave?(): void
|
||||||
delayLeave?(
|
delayLeave?(
|
||||||
el: object,
|
el: RendererElement,
|
||||||
earlyRemove: () => void,
|
earlyRemove: () => void,
|
||||||
delayedLeave: () => void
|
delayedLeave: () => void
|
||||||
): void
|
): void
|
||||||
@ -222,7 +223,7 @@ if (__DEV__) {
|
|||||||
// 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 {
|
||||||
new (): {
|
new (): {
|
||||||
$props: BaseTransitionProps
|
$props: BaseTransitionProps<any>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +255,7 @@ export function resolveTransitionHooks(
|
|||||||
onLeave,
|
onLeave,
|
||||||
onAfterLeave,
|
onAfterLeave,
|
||||||
onLeaveCancelled
|
onLeaveCancelled
|
||||||
}: BaseTransitionProps,
|
}: BaseTransitionProps<any>,
|
||||||
state: TransitionState,
|
state: TransitionState,
|
||||||
instance: ComponentInternalInstance
|
instance: ComponentInternalInstance
|
||||||
): TransitionHooks {
|
): TransitionHooks {
|
||||||
@ -286,10 +287,10 @@ export function resolveTransitionHooks(
|
|||||||
if (
|
if (
|
||||||
leavingVNode &&
|
leavingVNode &&
|
||||||
isSameVNodeType(vnode, leavingVNode) &&
|
isSameVNodeType(vnode, leavingVNode) &&
|
||||||
leavingVNode.el._leaveCb
|
leavingVNode.el!._leaveCb
|
||||||
) {
|
) {
|
||||||
// force early removal (not cancelled)
|
// force early removal (not cancelled)
|
||||||
leavingVNode.el._leaveCb()
|
leavingVNode.el!._leaveCb()
|
||||||
}
|
}
|
||||||
callHook(onBeforeEnter, [el])
|
callHook(onBeforeEnter, [el])
|
||||||
},
|
},
|
||||||
|
@ -17,7 +17,9 @@ import {
|
|||||||
RendererInternals,
|
RendererInternals,
|
||||||
queuePostRenderEffect,
|
queuePostRenderEffect,
|
||||||
invokeHooks,
|
invokeHooks,
|
||||||
MoveType
|
MoveType,
|
||||||
|
RendererElement,
|
||||||
|
RendererNode
|
||||||
} from '../renderer'
|
} from '../renderer'
|
||||||
import { setTransitionHooks } from './BaseTransition'
|
import { setTransitionHooks } from './BaseTransition'
|
||||||
|
|
||||||
@ -36,7 +38,11 @@ type Keys = Set<CacheKey>
|
|||||||
export interface KeepAliveSink {
|
export interface KeepAliveSink {
|
||||||
renderer: RendererInternals
|
renderer: RendererInternals
|
||||||
parentSuspense: SuspenseBoundary | null
|
parentSuspense: SuspenseBoundary | null
|
||||||
activate: (vnode: VNode, container: object, anchor: object | null) => void
|
activate: (
|
||||||
|
vnode: VNode,
|
||||||
|
container: RendererElement,
|
||||||
|
anchor: RendererNode | null
|
||||||
|
) => void
|
||||||
deactivate: (vnode: VNode) => void
|
deactivate: (vnode: VNode) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import { ComponentInternalInstance } from '../component'
|
import { ComponentInternalInstance } from '../component'
|
||||||
import { SuspenseBoundary } from './Suspense'
|
import { SuspenseBoundary } from './Suspense'
|
||||||
import { RendererInternals, MoveType } from '../renderer'
|
import {
|
||||||
|
RendererInternals,
|
||||||
|
MoveType,
|
||||||
|
RendererElement,
|
||||||
|
RendererNode
|
||||||
|
} from '../renderer'
|
||||||
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
|
import { VNode, VNodeArrayChildren, VNodeProps } from '../vnode'
|
||||||
import { isString, ShapeFlags, PatchFlags } from '@vue/shared'
|
import { isString, ShapeFlags, PatchFlags } from '@vue/shared'
|
||||||
import { warn } from '../warning'
|
import { warn } from '../warning'
|
||||||
@ -16,8 +21,8 @@ export const PortalImpl = {
|
|||||||
process(
|
process(
|
||||||
n1: VNode | null,
|
n1: VNode | null,
|
||||||
n2: VNode,
|
n2: VNode,
|
||||||
container: object,
|
container: RendererElement,
|
||||||
anchor: object | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
|
@ -2,7 +2,13 @@ import { VNode, normalizeVNode, VNodeChild, VNodeProps } from '../vnode'
|
|||||||
import { isFunction, isArray, ShapeFlags } from '@vue/shared'
|
import { isFunction, isArray, ShapeFlags } from '@vue/shared'
|
||||||
import { ComponentInternalInstance, handleSetupResult } from '../component'
|
import { ComponentInternalInstance, handleSetupResult } from '../component'
|
||||||
import { Slots } from '../componentSlots'
|
import { Slots } from '../componentSlots'
|
||||||
import { RendererInternals, MoveType, SetupRenderEffectFn } from '../renderer'
|
import {
|
||||||
|
RendererInternals,
|
||||||
|
MoveType,
|
||||||
|
SetupRenderEffectFn,
|
||||||
|
RendererNode,
|
||||||
|
RendererElement
|
||||||
|
} from '../renderer'
|
||||||
import { queuePostFlushCb, queueJob } from '../scheduler'
|
import { queuePostFlushCb, queueJob } from '../scheduler'
|
||||||
import { updateHOCHostEl } from '../componentRenderUtils'
|
import { updateHOCHostEl } from '../componentRenderUtils'
|
||||||
import { pushWarningContext, popWarningContext } from '../warning'
|
import { pushWarningContext, popWarningContext } from '../warning'
|
||||||
@ -27,8 +33,8 @@ export const SuspenseImpl = {
|
|||||||
process(
|
process(
|
||||||
n1: VNode | null,
|
n1: VNode | null,
|
||||||
n2: VNode,
|
n2: VNode,
|
||||||
container: object,
|
container: RendererElement,
|
||||||
anchor: object | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
@ -73,8 +79,8 @@ export const Suspense = ((__FEATURE_SUSPENSE__
|
|||||||
|
|
||||||
function mountSuspense(
|
function mountSuspense(
|
||||||
n2: VNode,
|
n2: VNode,
|
||||||
container: object,
|
container: RendererElement,
|
||||||
anchor: object | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
@ -132,8 +138,8 @@ function mountSuspense(
|
|||||||
function patchSuspense(
|
function patchSuspense(
|
||||||
n1: VNode,
|
n1: VNode,
|
||||||
n2: VNode,
|
n2: VNode,
|
||||||
container: object,
|
container: RendererElement,
|
||||||
anchor: object | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean,
|
optimized: boolean,
|
||||||
@ -190,21 +196,17 @@ function patchSuspense(
|
|||||||
suspense.fallbackTree = fallback
|
suspense.fallbackTree = fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SuspenseBoundary<
|
export interface SuspenseBoundary {
|
||||||
HostNode = any,
|
vnode: VNode
|
||||||
HostElement = any,
|
parent: SuspenseBoundary | null
|
||||||
HostVNode = VNode<HostNode, HostElement>
|
|
||||||
> {
|
|
||||||
vnode: HostVNode
|
|
||||||
parent: SuspenseBoundary<HostNode, HostElement> | null
|
|
||||||
parentComponent: ComponentInternalInstance | null
|
parentComponent: ComponentInternalInstance | null
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
container: HostElement
|
container: RendererElement
|
||||||
hiddenContainer: HostElement
|
hiddenContainer: RendererElement
|
||||||
anchor: HostNode | null
|
anchor: RendererNode | null
|
||||||
subTree: HostVNode
|
subTree: VNode
|
||||||
fallbackTree: HostVNode
|
fallbackTree: VNode
|
||||||
deps: number
|
deps: number
|
||||||
isHydrating: boolean
|
isHydrating: boolean
|
||||||
isResolved: boolean
|
isResolved: boolean
|
||||||
@ -212,30 +214,31 @@ export interface SuspenseBoundary<
|
|||||||
effects: Function[]
|
effects: Function[]
|
||||||
resolve(): void
|
resolve(): void
|
||||||
recede(): void
|
recede(): void
|
||||||
move(container: HostElement, anchor: HostNode | null, type: MoveType): void
|
move(
|
||||||
next(): HostNode | null
|
container: RendererElement,
|
||||||
|
anchor: RendererNode | null,
|
||||||
|
type: MoveType
|
||||||
|
): void
|
||||||
|
next(): RendererNode | null
|
||||||
registerDep(
|
registerDep(
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
setupRenderEffect: SetupRenderEffectFn<HostNode, HostElement>
|
setupRenderEffect: SetupRenderEffectFn
|
||||||
): void
|
|
||||||
unmount(
|
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
|
||||||
doRemove?: boolean
|
|
||||||
): void
|
): void
|
||||||
|
unmount(parentSuspense: SuspenseBoundary | null, doRemove?: boolean): void
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSuspenseBoundary<HostNode, HostElement>(
|
function createSuspenseBoundary(
|
||||||
vnode: VNode<HostNode, HostElement>,
|
vnode: VNode,
|
||||||
parent: SuspenseBoundary<HostNode, HostElement> | null,
|
parent: SuspenseBoundary | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
hiddenContainer: HostElement,
|
hiddenContainer: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean,
|
optimized: boolean,
|
||||||
rendererInternals: RendererInternals<HostNode, HostElement>,
|
rendererInternals: RendererInternals,
|
||||||
isHydrating = false
|
isHydrating = false
|
||||||
): SuspenseBoundary<HostNode, HostElement> {
|
): SuspenseBoundary {
|
||||||
const {
|
const {
|
||||||
p: patch,
|
p: patch,
|
||||||
m: move,
|
m: move,
|
||||||
@ -250,7 +253,7 @@ function createSuspenseBoundary<HostNode, HostElement>(
|
|||||||
: suspense.fallbackTree
|
: suspense.fallbackTree
|
||||||
|
|
||||||
const { content, fallback } = normalizeSuspenseChildren(vnode)
|
const { content, fallback } = normalizeSuspenseChildren(vnode)
|
||||||
const suspense: SuspenseBoundary<HostNode, HostElement> = {
|
const suspense: SuspenseBoundary = {
|
||||||
vnode,
|
vnode,
|
||||||
parent,
|
parent,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -430,7 +433,7 @@ function createSuspenseBoundary<HostNode, HostElement>(
|
|||||||
// placeholder.
|
// placeholder.
|
||||||
hydratedEl
|
hydratedEl
|
||||||
? parentNode(hydratedEl)!
|
? parentNode(hydratedEl)!
|
||||||
: parentNode(instance.subTree.el)!,
|
: parentNode(instance.subTree.el!)!,
|
||||||
// anchor will not be used if this is hydration, so only need to
|
// anchor will not be used if this is hydration, so only need to
|
||||||
// consider the comment placeholder case.
|
// consider the comment placeholder case.
|
||||||
hydratedEl ? null : next(instance.subTree),
|
hydratedEl ? null : next(instance.subTree),
|
||||||
@ -484,7 +487,7 @@ function hydrateSuspense(
|
|||||||
vnode,
|
vnode,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
node.parentNode,
|
node.parentNode!,
|
||||||
document.createElement('div'),
|
document.createElement('div'),
|
||||||
null,
|
null,
|
||||||
isSVG,
|
isSVG,
|
||||||
|
@ -13,7 +13,7 @@ export function withCtx(
|
|||||||
return function renderFnWithContext() {
|
return function renderFnWithContext() {
|
||||||
const owner = currentRenderingInstance
|
const owner = currentRenderingInstance
|
||||||
setCurrentRenderingInstance(ctx)
|
setCurrentRenderingInstance(ctx)
|
||||||
const res = fn.apply(null, arguments)
|
const res = fn.apply(null, arguments as any)
|
||||||
setCurrentRenderingInstance(owner)
|
setCurrentRenderingInstance(owner)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -71,21 +71,24 @@ import { invokeDirectiveHook } from './directives'
|
|||||||
|
|
||||||
const __HMR__ = __BUNDLER__ && __DEV__
|
const __HMR__ = __BUNDLER__ && __DEV__
|
||||||
|
|
||||||
export interface Renderer<HostNode = any, HostElement = any> {
|
export interface Renderer<HostElement = any> {
|
||||||
render: RootRenderFunction<HostNode, HostElement>
|
render: RootRenderFunction<HostElement>
|
||||||
createApp: CreateAppFunction<HostElement>
|
createApp: CreateAppFunction<HostElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HydrationRenderer extends Renderer<Node, Element> {
|
export interface HydrationRenderer extends Renderer<Element> {
|
||||||
hydrate: RootHydrateFunction
|
hydrate: RootHydrateFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RootRenderFunction<HostNode, HostElement> = (
|
export type RootRenderFunction<HostElement = RendererElement> = (
|
||||||
vnode: VNode<HostNode, HostElement> | null,
|
vnode: VNode | null,
|
||||||
container: HostElement
|
container: HostElement
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export interface RendererOptions<HostNode = any, HostElement = any> {
|
export interface RendererOptions<
|
||||||
|
HostNode = RendererNode,
|
||||||
|
HostElement = RendererElement
|
||||||
|
> {
|
||||||
patchProp(
|
patchProp(
|
||||||
el: HostElement,
|
el: HostElement,
|
||||||
key: string,
|
key: string,
|
||||||
@ -94,8 +97,8 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
|
|||||||
isSVG?: boolean,
|
isSVG?: boolean,
|
||||||
prevChildren?: VNode<HostNode, HostElement>[],
|
prevChildren?: VNode<HostNode, HostElement>[],
|
||||||
parentComponent?: ComponentInternalInstance | null,
|
parentComponent?: ComponentInternalInstance | null,
|
||||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense?: SuspenseBoundary | null,
|
||||||
unmountChildren?: UnmountChildrenFn<HostNode, HostElement>
|
unmountChildren?: UnmountChildrenFn
|
||||||
): void
|
): void
|
||||||
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
|
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
|
||||||
remove(el: HostNode): void
|
remove(el: HostNode): void
|
||||||
@ -117,115 +120,126 @@ export interface RendererOptions<HostNode = any, HostElement = any> {
|
|||||||
): HostElement
|
): HostElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Renderer Node can technically be any object in the context of core renderer
|
||||||
|
// logic - they are never directly operated on and always passed to the node op
|
||||||
|
// functions provided via options, so the internal constraint is really just
|
||||||
|
// a generic object.
|
||||||
|
export interface RendererNode {
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RendererElement extends RendererNode {}
|
||||||
|
|
||||||
// An object exposing the internals of a renderer, passed to tree-shakeable
|
// An object exposing the internals of a renderer, passed to tree-shakeable
|
||||||
// features so that they can be decoupled from this file. Keys are shortened
|
// features so that they can be decoupled from this file. Keys are shortened
|
||||||
// to optimize bundle size.
|
// to optimize bundle size.
|
||||||
export interface RendererInternals<HostNode = any, HostElement = any> {
|
export interface RendererInternals<
|
||||||
p: PatchFn<HostNode, HostElement>
|
HostNode = RendererNode,
|
||||||
um: UnmountFn<HostNode, HostElement>
|
HostElement = RendererElement
|
||||||
m: MoveFn<HostNode, HostElement>
|
> {
|
||||||
mt: MountComponentFn<HostNode, HostElement>
|
p: PatchFn
|
||||||
mc: MountChildrenFn<HostNode, HostElement>
|
um: UnmountFn
|
||||||
pc: PatchChildrenFn<HostNode, HostElement>
|
m: MoveFn
|
||||||
pbc: PatchBlockChildrenFn<HostNode, HostElement>
|
mt: MountComponentFn
|
||||||
n: NextFn<HostNode, HostElement>
|
mc: MountChildrenFn
|
||||||
|
pc: PatchChildrenFn
|
||||||
|
pbc: PatchBlockChildrenFn
|
||||||
|
n: NextFn
|
||||||
o: RendererOptions<HostNode, HostElement>
|
o: RendererOptions<HostNode, HostElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
// These functions are created inside a closure and therefore their types cannot
|
// These functions are created inside a closure and therefore their types cannot
|
||||||
// be directly exported. In order to avoid maintaining function signatures in
|
// be directly exported. In order to avoid maintaining function signatures in
|
||||||
// two places, we declare them once here and use them inside the closure.
|
// two places, we declare them once here and use them inside the closure.
|
||||||
type PatchFn<HostNode, HostElement> = (
|
type PatchFn = (
|
||||||
n1: VNode<HostNode, HostElement> | null, // null means this is a mount
|
n1: VNode | null, // null means this is a mount
|
||||||
n2: VNode<HostNode, HostElement>,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor?: HostNode | null,
|
anchor?: RendererNode | null,
|
||||||
parentComponent?: ComponentInternalInstance | null,
|
parentComponent?: ComponentInternalInstance | null,
|
||||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense?: SuspenseBoundary | null,
|
||||||
isSVG?: boolean,
|
isSVG?: boolean,
|
||||||
optimized?: boolean
|
optimized?: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type MountChildrenFn<HostNode, HostElement> = (
|
type MountChildrenFn = (
|
||||||
children: VNodeArrayChildren<HostNode, HostElement>,
|
children: VNodeArrayChildren,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean,
|
optimized: boolean,
|
||||||
start?: number
|
start?: number
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type PatchChildrenFn<HostNode, HostElement> = (
|
type PatchChildrenFn = (
|
||||||
n1: VNode<HostNode, HostElement> | null,
|
n1: VNode | null,
|
||||||
n2: VNode<HostNode, HostElement>,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized?: boolean
|
optimized?: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type PatchBlockChildrenFn<HostNode, HostElement> = (
|
type PatchBlockChildrenFn = (
|
||||||
oldChildren: VNode<HostNode, HostElement>[],
|
oldChildren: VNode[],
|
||||||
newChildren: VNode<HostNode, HostElement>[],
|
newChildren: VNode[],
|
||||||
fallbackContainer: HostElement,
|
fallbackContainer: RendererElement,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type MoveFn<HostNode, HostElement> = (
|
type MoveFn = (
|
||||||
vnode: VNode<HostNode, HostElement>,
|
vnode: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
type: MoveType,
|
type: MoveType,
|
||||||
parentSuspense?: SuspenseBoundary<HostNode, HostElement> | null
|
parentSuspense?: SuspenseBoundary | null
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type NextFn<HostNode, HostElement> = (
|
type NextFn = (vnode: VNode) => RendererNode | null
|
||||||
vnode: VNode<HostNode, HostElement>
|
|
||||||
) => HostNode | null
|
|
||||||
|
|
||||||
type UnmountFn<HostNode, HostElement> = (
|
type UnmountFn = (
|
||||||
vnode: VNode<HostNode, HostElement>,
|
vnode: VNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type UnmountChildrenFn<HostNode, HostElement> = (
|
type UnmountChildrenFn = (
|
||||||
children: VNode<HostNode, HostElement>[],
|
children: VNode[],
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
doRemove?: boolean,
|
doRemove?: boolean,
|
||||||
start?: number
|
start?: number
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export type MountComponentFn<HostNode, HostElement> = (
|
export type MountComponentFn = (
|
||||||
initialVNode: VNode<HostNode, HostElement>,
|
initialVNode: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type ProcessTextOrCommentFn<HostNode, HostElement> = (
|
type ProcessTextOrCommentFn = (
|
||||||
n1: VNode<HostNode, HostElement> | null,
|
n1: VNode | null,
|
||||||
n2: VNode<HostNode, HostElement>,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null
|
anchor: RendererNode | null
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export type SetupRenderEffectFn<HostNode, HostElement> = (
|
export type SetupRenderEffectFn = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
initialVNode: VNode<HostNode, HostElement>,
|
initialVNode: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentSuspense: SuspenseBoundary<HostNode, HostElement> | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
@ -275,8 +289,8 @@ export const queuePostRenderEffect = __FEATURE_SUSPENSE__
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function createRenderer<
|
export function createRenderer<
|
||||||
HostNode extends object = any,
|
HostNode = RendererNode,
|
||||||
HostElement extends HostNode = any
|
HostElement = RendererElement
|
||||||
>(options: RendererOptions<HostNode, HostElement>) {
|
>(options: RendererOptions<HostNode, HostElement>) {
|
||||||
return baseCreateRenderer<HostNode, HostElement>(options)
|
return baseCreateRenderer<HostNode, HostElement>(options)
|
||||||
}
|
}
|
||||||
@ -287,38 +301,26 @@ export function createRenderer<
|
|||||||
export function createHydrationRenderer(
|
export function createHydrationRenderer(
|
||||||
options: RendererOptions<Node, Element>
|
options: RendererOptions<Node, Element>
|
||||||
) {
|
) {
|
||||||
return baseCreateRenderer<Node, Element>(options, createHydrationFunctions)
|
return baseCreateRenderer(options, createHydrationFunctions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload 1: no hydration
|
// overload 1: no hydration
|
||||||
function baseCreateRenderer<
|
function baseCreateRenderer<
|
||||||
HostNode extends object = any,
|
HostNode = RendererNode,
|
||||||
HostElement extends HostNode = any
|
HostElement = RendererElement
|
||||||
>(
|
>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement>
|
||||||
options: RendererOptions<HostNode, HostElement>
|
|
||||||
): Renderer<HostNode, HostElement>
|
|
||||||
|
|
||||||
// overload 2: with hydration
|
// overload 2: with hydration
|
||||||
function baseCreateRenderer<
|
function baseCreateRenderer(
|
||||||
HostNode extends object = any,
|
options: RendererOptions<Node, Element>,
|
||||||
HostElement extends HostNode = any
|
|
||||||
>(
|
|
||||||
options: RendererOptions<HostNode, HostElement>,
|
|
||||||
createHydrationFns: typeof createHydrationFunctions
|
createHydrationFns: typeof createHydrationFunctions
|
||||||
): HydrationRenderer
|
): HydrationRenderer
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
function baseCreateRenderer<
|
function baseCreateRenderer(
|
||||||
HostNode extends object = any,
|
options: RendererOptions,
|
||||||
HostElement extends HostNode = any
|
|
||||||
>(
|
|
||||||
options: RendererOptions<HostNode, HostElement>,
|
|
||||||
createHydrationFns?: typeof createHydrationFunctions
|
createHydrationFns?: typeof createHydrationFunctions
|
||||||
) {
|
): any {
|
||||||
type HostVNode = VNode<HostNode, HostElement>
|
|
||||||
type HostVNodeChildren = VNodeArrayChildren<HostNode, HostElement>
|
|
||||||
type HostSuspenseBoundary = SuspenseBoundary<HostNode, HostElement>
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
insert: hostInsert,
|
insert: hostInsert,
|
||||||
remove: hostRemove,
|
remove: hostRemove,
|
||||||
@ -337,7 +339,7 @@ function baseCreateRenderer<
|
|||||||
|
|
||||||
// Note: functions inside this closure should use `const xxx = () => {}`
|
// Note: functions inside this closure should use `const xxx = () => {}`
|
||||||
// style in order to prevent being inlined by minifiers.
|
// style in order to prevent being inlined by minifiers.
|
||||||
const patch: PatchFn<HostNode, HostElement> = (
|
const patch: PatchFn = (
|
||||||
n1,
|
n1,
|
||||||
n2,
|
n2,
|
||||||
container,
|
container,
|
||||||
@ -427,17 +429,12 @@ function baseCreateRenderer<
|
|||||||
internals
|
internals
|
||||||
)
|
)
|
||||||
} else if (__DEV__) {
|
} else if (__DEV__) {
|
||||||
warn('Invalid HostVNode type:', type, `(${typeof type})`)
|
warn('Invalid VNode type:', type, `(${typeof type})`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const processText: ProcessTextOrCommentFn<HostNode, HostElement> = (
|
const processText: ProcessTextOrCommentFn = (n1, n2, container, anchor) => {
|
||||||
n1,
|
|
||||||
n2,
|
|
||||||
container,
|
|
||||||
anchor
|
|
||||||
) => {
|
|
||||||
if (n1 == null) {
|
if (n1 == null) {
|
||||||
hostInsert(
|
hostInsert(
|
||||||
(n2.el = hostCreateText(n2.children as string)),
|
(n2.el = hostCreateText(n2.children as string)),
|
||||||
@ -445,14 +442,14 @@ function baseCreateRenderer<
|
|||||||
anchor
|
anchor
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const el = (n2.el = n1.el) as HostNode
|
const el = (n2.el = n1.el!)
|
||||||
if (n2.children !== n1.children) {
|
if (n2.children !== n1.children) {
|
||||||
hostSetText(el, n2.children as string)
|
hostSetText(el, n2.children as string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const processCommentNode: ProcessTextOrCommentFn<HostNode, HostElement> = (
|
const processCommentNode: ProcessTextOrCommentFn = (
|
||||||
n1,
|
n1,
|
||||||
n2,
|
n2,
|
||||||
container,
|
container,
|
||||||
@ -471,9 +468,9 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mountStaticNode = (
|
const mountStaticNode = (
|
||||||
n2: HostVNode,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) => {
|
) => {
|
||||||
if (n2.el && hostCloneNode !== undefined) {
|
if (n2.el && hostCloneNode !== undefined) {
|
||||||
@ -491,12 +488,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processElement = (
|
const processElement = (
|
||||||
n1: HostVNode | null,
|
n1: VNode | null,
|
||||||
n2: HostVNode,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
@ -520,15 +517,15 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mountElement = (
|
const mountElement = (
|
||||||
vnode: HostVNode,
|
vnode: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
let el: HostElement
|
let el: RendererElement
|
||||||
let vnodeHook: VNodeHook | undefined | null
|
let vnodeHook: VNodeHook | undefined | null
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
@ -547,7 +544,7 @@ function baseCreateRenderer<
|
|||||||
// If a vnode has non-null el, it means it's being reused.
|
// If a vnode has non-null el, it means it's being reused.
|
||||||
// Only static vnodes can be reused, so its mounted DOM nodes should be
|
// Only static vnodes can be reused, so its mounted DOM nodes should be
|
||||||
// exactly the same, and we can simply do a clone here.
|
// exactly the same, and we can simply do a clone here.
|
||||||
el = vnode.el = hostCloneNode(vnode.el) as HostElement
|
el = vnode.el = hostCloneNode(vnode.el)
|
||||||
} else {
|
} else {
|
||||||
el = vnode.el = hostCreateElement(vnode.type as string, isSVG)
|
el = vnode.el = hostCreateElement(vnode.type as string, isSVG)
|
||||||
// props
|
// props
|
||||||
@ -583,7 +580,7 @@ function baseCreateRenderer<
|
|||||||
hostSetElementText(el, vnode.children as string)
|
hostSetElementText(el, vnode.children as string)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
mountChildren(
|
mountChildren(
|
||||||
vnode.children as HostVNodeChildren,
|
vnode.children as VNodeArrayChildren,
|
||||||
el,
|
el,
|
||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -611,7 +608,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mountChildren: MountChildrenFn<HostNode, HostElement> = (
|
const mountChildren: MountChildrenFn = (
|
||||||
children,
|
children,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
@ -623,7 +620,7 @@ function baseCreateRenderer<
|
|||||||
) => {
|
) => {
|
||||||
for (let i = start; i < children.length; i++) {
|
for (let i = start; i < children.length; i++) {
|
||||||
const child = (children[i] = optimized
|
const child = (children[i] = optimized
|
||||||
? cloneIfMounted(children[i] as HostVNode)
|
? cloneIfMounted(children[i] as VNode)
|
||||||
: normalizeVNode(children[i]))
|
: normalizeVNode(children[i]))
|
||||||
patch(
|
patch(
|
||||||
null,
|
null,
|
||||||
@ -639,14 +636,14 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const patchElement = (
|
const patchElement = (
|
||||||
n1: HostVNode,
|
n1: VNode,
|
||||||
n2: HostVNode,
|
n2: VNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
const el = (n2.el = n1.el) as HostElement
|
const el = (n2.el = n1.el!)
|
||||||
let { patchFlag, dynamicChildren, dirs } = n2
|
let { patchFlag, dynamicChildren, dirs } = n2
|
||||||
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
const oldProps = (n1 && n1.props) || EMPTY_OBJ
|
||||||
const newProps = n2.props || EMPTY_OBJ
|
const newProps = n2.props || EMPTY_OBJ
|
||||||
@ -717,7 +714,7 @@ function baseCreateRenderer<
|
|||||||
prev,
|
prev,
|
||||||
next,
|
next,
|
||||||
isSVG,
|
isSVG,
|
||||||
n1.children as HostVNode[],
|
n1.children as VNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
@ -779,7 +776,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The fast path for blocks.
|
// The fast path for blocks.
|
||||||
const patchBlockChildren: PatchBlockChildrenFn<HostNode, HostElement> = (
|
const patchBlockChildren: PatchBlockChildrenFn = (
|
||||||
oldChildren,
|
oldChildren,
|
||||||
newChildren,
|
newChildren,
|
||||||
fallbackContainer,
|
fallbackContainer,
|
||||||
@ -818,12 +815,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const patchProps = (
|
const patchProps = (
|
||||||
el: HostElement,
|
el: RendererElement,
|
||||||
vnode: HostVNode,
|
vnode: VNode,
|
||||||
oldProps: Data,
|
oldProps: Data,
|
||||||
newProps: Data,
|
newProps: Data,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean
|
isSVG: boolean
|
||||||
) => {
|
) => {
|
||||||
if (oldProps !== newProps) {
|
if (oldProps !== newProps) {
|
||||||
@ -838,7 +835,7 @@ function baseCreateRenderer<
|
|||||||
prev,
|
prev,
|
||||||
next,
|
next,
|
||||||
isSVG,
|
isSVG,
|
||||||
vnode.children as HostVNode[],
|
vnode.children as VNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
@ -854,7 +851,7 @@ function baseCreateRenderer<
|
|||||||
oldProps[key],
|
oldProps[key],
|
||||||
null,
|
null,
|
||||||
isSVG,
|
isSVG,
|
||||||
vnode.children as HostVNode[],
|
vnode.children as VNode[],
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
unmountChildren
|
unmountChildren
|
||||||
@ -866,12 +863,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processFragment = (
|
const processFragment = (
|
||||||
n1: HostVNode | null,
|
n1: VNode | null,
|
||||||
n2: HostVNode,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
@ -897,7 +894,7 @@ function baseCreateRenderer<
|
|||||||
// since they are either generated by the compiler, or implicitly created
|
// since they are either generated by the compiler, or implicitly created
|
||||||
// from arrays.
|
// from arrays.
|
||||||
mountChildren(
|
mountChildren(
|
||||||
n2.children as HostVNodeChildren,
|
n2.children as VNodeArrayChildren,
|
||||||
container,
|
container,
|
||||||
fragmentEndAnchor,
|
fragmentEndAnchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -937,12 +934,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processComponent = (
|
const processComponent = (
|
||||||
n1: HostVNode | null,
|
n1: VNode | null,
|
||||||
n2: HostVNode,
|
n2: VNode,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
@ -1010,7 +1007,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mountComponent: MountComponentFn<HostNode, HostElement> = (
|
const mountComponent: MountComponentFn = (
|
||||||
initialVNode,
|
initialVNode,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
@ -1073,7 +1070,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupRenderEffect: SetupRenderEffectFn<HostNode, HostElement> = (
|
const setupRenderEffect: SetupRenderEffectFn = (
|
||||||
instance,
|
instance,
|
||||||
initialVNode,
|
initialVNode,
|
||||||
container,
|
container,
|
||||||
@ -1137,7 +1134,7 @@ function baseCreateRenderer<
|
|||||||
} else {
|
} else {
|
||||||
// updateComponent
|
// updateComponent
|
||||||
// This is triggered by mutation of component's own state (next: null)
|
// This is triggered by mutation of component's own state (next: null)
|
||||||
// OR parent calling processComponent (next: HostVNode)
|
// OR parent calling processComponent (next: VNode)
|
||||||
let { next, bu, u, parent, vnode } = instance
|
let { next, bu, u, parent, vnode } = instance
|
||||||
let vnodeHook: VNodeHook | null | undefined
|
let vnodeHook: VNodeHook | null | undefined
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -1170,7 +1167,7 @@ function baseCreateRenderer<
|
|||||||
prevTree,
|
prevTree,
|
||||||
nextTree,
|
nextTree,
|
||||||
// parent may have changed if it's in a portal
|
// parent may have changed if it's in a portal
|
||||||
hostParentNode(prevTree.el as HostNode) as HostElement,
|
hostParentNode(prevTree.el!)!,
|
||||||
// anchor may have changed if it's in a fragment
|
// anchor may have changed if it's in a fragment
|
||||||
getNextHostNode(prevTree),
|
getNextHostNode(prevTree),
|
||||||
instance,
|
instance,
|
||||||
@ -1203,7 +1200,7 @@ function baseCreateRenderer<
|
|||||||
|
|
||||||
const updateComponentPreRender = (
|
const updateComponentPreRender = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
nextVNode: HostVNode
|
nextVNode: VNode
|
||||||
) => {
|
) => {
|
||||||
nextVNode.component = instance
|
nextVNode.component = instance
|
||||||
instance.vnode = nextVNode
|
instance.vnode = nextVNode
|
||||||
@ -1212,7 +1209,7 @@ function baseCreateRenderer<
|
|||||||
resolveSlots(instance, nextVNode.children)
|
resolveSlots(instance, nextVNode.children)
|
||||||
}
|
}
|
||||||
|
|
||||||
const patchChildren: PatchChildrenFn<HostNode, HostElement> = (
|
const patchChildren: PatchChildrenFn = (
|
||||||
n1,
|
n1,
|
||||||
n2,
|
n2,
|
||||||
container,
|
container,
|
||||||
@ -1236,8 +1233,8 @@ function baseCreateRenderer<
|
|||||||
// this could be either fully-keyed or mixed (some keyed some not)
|
// this could be either fully-keyed or mixed (some keyed some not)
|
||||||
// presence of patchFlag means children are guaranteed to be arrays
|
// presence of patchFlag means children are guaranteed to be arrays
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
c1 as HostVNode[],
|
c1 as VNode[],
|
||||||
c2 as HostVNodeChildren,
|
c2 as VNodeArrayChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -1249,8 +1246,8 @@ function baseCreateRenderer<
|
|||||||
} else if (patchFlag & PatchFlags.UNKEYED_FRAGMENT) {
|
} else if (patchFlag & PatchFlags.UNKEYED_FRAGMENT) {
|
||||||
// unkeyed
|
// unkeyed
|
||||||
patchUnkeyedChildren(
|
patchUnkeyedChildren(
|
||||||
c1 as HostVNode[],
|
c1 as VNode[],
|
||||||
c2 as HostVNodeChildren,
|
c2 as VNodeArrayChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -1266,7 +1263,7 @@ function baseCreateRenderer<
|
|||||||
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
|
||||||
// text children fast path
|
// text children fast path
|
||||||
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
unmountChildren(c1 as HostVNode[], parentComponent, parentSuspense)
|
unmountChildren(c1 as VNode[], parentComponent, parentSuspense)
|
||||||
}
|
}
|
||||||
if (c2 !== c1) {
|
if (c2 !== c1) {
|
||||||
hostSetElementText(container, c2 as string)
|
hostSetElementText(container, c2 as string)
|
||||||
@ -1277,8 +1274,8 @@ function baseCreateRenderer<
|
|||||||
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
// two arrays, cannot assume anything, do full diff
|
// two arrays, cannot assume anything, do full diff
|
||||||
patchKeyedChildren(
|
patchKeyedChildren(
|
||||||
c1 as HostVNode[],
|
c1 as VNode[],
|
||||||
c2 as HostVNodeChildren,
|
c2 as VNodeArrayChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -1288,12 +1285,7 @@ function baseCreateRenderer<
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// no new children, just unmount old
|
// no new children, just unmount old
|
||||||
unmountChildren(
|
unmountChildren(c1 as VNode[], parentComponent, parentSuspense, true)
|
||||||
c1 as HostVNode[],
|
|
||||||
parentComponent,
|
|
||||||
parentSuspense,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// prev children was text OR null
|
// prev children was text OR null
|
||||||
@ -1304,7 +1296,7 @@ function baseCreateRenderer<
|
|||||||
// mount new if array
|
// mount new if array
|
||||||
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
mountChildren(
|
mountChildren(
|
||||||
c2 as HostVNodeChildren,
|
c2 as VNodeArrayChildren,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -1318,12 +1310,12 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const patchUnkeyedChildren = (
|
const patchUnkeyedChildren = (
|
||||||
c1: HostVNode[],
|
c1: VNode[],
|
||||||
c2: HostVNodeChildren,
|
c2: VNodeArrayChildren,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
anchor: HostNode | null,
|
anchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
@ -1335,7 +1327,7 @@ function baseCreateRenderer<
|
|||||||
let i
|
let i
|
||||||
for (i = 0; i < commonLength; i++) {
|
for (i = 0; i < commonLength; i++) {
|
||||||
const nextChild = (c2[i] = optimized
|
const nextChild = (c2[i] = optimized
|
||||||
? cloneIfMounted(c2[i] as HostVNode)
|
? cloneIfMounted(c2[i] as VNode)
|
||||||
: normalizeVNode(c2[i]))
|
: normalizeVNode(c2[i]))
|
||||||
patch(
|
patch(
|
||||||
c1[i],
|
c1[i],
|
||||||
@ -1368,12 +1360,12 @@ function baseCreateRenderer<
|
|||||||
|
|
||||||
// can be all-keyed or mixed
|
// can be all-keyed or mixed
|
||||||
const patchKeyedChildren = (
|
const patchKeyedChildren = (
|
||||||
c1: HostVNode[],
|
c1: VNode[],
|
||||||
c2: HostVNodeChildren,
|
c2: VNodeArrayChildren,
|
||||||
container: HostElement,
|
container: RendererElement,
|
||||||
parentAnchor: HostNode | null,
|
parentAnchor: RendererNode | null,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
isSVG: boolean,
|
isSVG: boolean,
|
||||||
optimized: boolean
|
optimized: boolean
|
||||||
) => {
|
) => {
|
||||||
@ -1388,7 +1380,7 @@ function baseCreateRenderer<
|
|||||||
while (i <= e1 && i <= e2) {
|
while (i <= e1 && i <= e2) {
|
||||||
const n1 = c1[i]
|
const n1 = c1[i]
|
||||||
const n2 = (c2[i] = optimized
|
const n2 = (c2[i] = optimized
|
||||||
? cloneIfMounted(c2[i] as HostVNode)
|
? cloneIfMounted(c2[i] as VNode)
|
||||||
: normalizeVNode(c2[i]))
|
: normalizeVNode(c2[i]))
|
||||||
if (isSameVNodeType(n1, n2)) {
|
if (isSameVNodeType(n1, n2)) {
|
||||||
patch(
|
patch(
|
||||||
@ -1413,7 +1405,7 @@ function baseCreateRenderer<
|
|||||||
while (i <= e1 && i <= e2) {
|
while (i <= e1 && i <= e2) {
|
||||||
const n1 = c1[e1]
|
const n1 = c1[e1]
|
||||||
const n2 = (c2[e2] = optimized
|
const n2 = (c2[e2] = optimized
|
||||||
? cloneIfMounted(c2[e2] as HostVNode)
|
? cloneIfMounted(c2[e2] as VNode)
|
||||||
: normalizeVNode(c2[e2]))
|
: normalizeVNode(c2[e2]))
|
||||||
if (isSameVNodeType(n1, n2)) {
|
if (isSameVNodeType(n1, n2)) {
|
||||||
patch(
|
patch(
|
||||||
@ -1443,13 +1435,12 @@ function baseCreateRenderer<
|
|||||||
if (i > e1) {
|
if (i > e1) {
|
||||||
if (i <= e2) {
|
if (i <= e2) {
|
||||||
const nextPos = e2 + 1
|
const nextPos = e2 + 1
|
||||||
const anchor =
|
const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchor
|
||||||
nextPos < l2 ? (c2[nextPos] as HostVNode).el : parentAnchor
|
|
||||||
while (i <= e2) {
|
while (i <= e2) {
|
||||||
patch(
|
patch(
|
||||||
null,
|
null,
|
||||||
(c2[i] = optimized
|
(c2[i] = optimized
|
||||||
? cloneIfMounted(c2[i] as HostVNode)
|
? cloneIfMounted(c2[i] as VNode)
|
||||||
: normalizeVNode(c2[i])),
|
: normalizeVNode(c2[i])),
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
@ -1488,7 +1479,7 @@ function baseCreateRenderer<
|
|||||||
const keyToNewIndexMap: Map<string | number, number> = new Map()
|
const keyToNewIndexMap: Map<string | number, number> = new Map()
|
||||||
for (i = s2; i <= e2; i++) {
|
for (i = s2; i <= e2; i++) {
|
||||||
const nextChild = (c2[i] = optimized
|
const nextChild = (c2[i] = optimized
|
||||||
? cloneIfMounted(c2[i] as HostVNode)
|
? cloneIfMounted(c2[i] as VNode)
|
||||||
: normalizeVNode(c2[i]))
|
: normalizeVNode(c2[i]))
|
||||||
if (nextChild.key != null) {
|
if (nextChild.key != null) {
|
||||||
if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {
|
if (__DEV__ && keyToNewIndexMap.has(nextChild.key)) {
|
||||||
@ -1533,7 +1524,7 @@ function baseCreateRenderer<
|
|||||||
for (j = s2; j <= e2; j++) {
|
for (j = s2; j <= e2; j++) {
|
||||||
if (
|
if (
|
||||||
newIndexToOldIndexMap[j - s2] === 0 &&
|
newIndexToOldIndexMap[j - s2] === 0 &&
|
||||||
isSameVNodeType(prevChild, c2[j] as HostVNode)
|
isSameVNodeType(prevChild, c2[j] as VNode)
|
||||||
) {
|
) {
|
||||||
newIndex = j
|
newIndex = j
|
||||||
break
|
break
|
||||||
@ -1551,7 +1542,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
patch(
|
patch(
|
||||||
prevChild,
|
prevChild,
|
||||||
c2[newIndex] as HostVNode,
|
c2[newIndex] as VNode,
|
||||||
container,
|
container,
|
||||||
null,
|
null,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
@ -1572,11 +1563,9 @@ function baseCreateRenderer<
|
|||||||
// looping backwards so that we can use last patched node as anchor
|
// looping backwards so that we can use last patched node as anchor
|
||||||
for (i = toBePatched - 1; i >= 0; i--) {
|
for (i = toBePatched - 1; i >= 0; i--) {
|
||||||
const nextIndex = s2 + i
|
const nextIndex = s2 + i
|
||||||
const nextChild = c2[nextIndex] as HostVNode
|
const nextChild = c2[nextIndex] as VNode
|
||||||
const anchor =
|
const anchor =
|
||||||
nextIndex + 1 < l2
|
nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchor
|
||||||
? (c2[nextIndex + 1] as HostVNode).el
|
|
||||||
: parentAnchor
|
|
||||||
if (newIndexToOldIndexMap[i] === 0) {
|
if (newIndexToOldIndexMap[i] === 0) {
|
||||||
// mount new
|
// mount new
|
||||||
patch(
|
patch(
|
||||||
@ -1602,7 +1591,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const move: MoveFn<HostNode, HostElement> = (
|
const move: MoveFn = (
|
||||||
vnode,
|
vnode,
|
||||||
container,
|
container,
|
||||||
anchor,
|
anchor,
|
||||||
@ -1619,7 +1608,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
if (vnode.type === Fragment) {
|
if (vnode.type === Fragment) {
|
||||||
hostInsert(vnode.el!, container, anchor)
|
hostInsert(vnode.el!, container, anchor)
|
||||||
const children = vnode.children as HostVNode[]
|
const children = vnode.children as VNode[]
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
move(children[i], container, anchor, type)
|
move(children[i], container, anchor, type)
|
||||||
}
|
}
|
||||||
@ -1657,7 +1646,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unmount: UnmountFn<HostNode, HostElement> = (
|
const unmount: UnmountFn = (
|
||||||
vnode,
|
vnode,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
@ -1696,11 +1685,7 @@ function baseCreateRenderer<
|
|||||||
// fast path for block nodes: only need to unmount dynamic children.
|
// fast path for block nodes: only need to unmount dynamic children.
|
||||||
unmountChildren(dynamicChildren, parentComponent, parentSuspense)
|
unmountChildren(dynamicChildren, parentComponent, parentSuspense)
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
unmountChildren(
|
unmountChildren(children as VNode[], parentComponent, parentSuspense)
|
||||||
children as HostVNode[],
|
|
||||||
parentComponent,
|
|
||||||
parentSuspense
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doRemove) {
|
if (doRemove) {
|
||||||
@ -1717,7 +1702,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const remove = (vnode: HostVNode) => {
|
const remove = (vnode: VNode) => {
|
||||||
const { type, el, anchor, transition } = vnode
|
const { type, el, anchor, transition } = vnode
|
||||||
if (type === Fragment) {
|
if (type === Fragment) {
|
||||||
removeFragment(el!, anchor!)
|
removeFragment(el!, anchor!)
|
||||||
@ -1748,7 +1733,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeFragment = (cur: HostNode, end: HostNode) => {
|
const removeFragment = (cur: RendererNode, end: RendererNode) => {
|
||||||
// For fragments, directly remove all contained DOM nodes.
|
// For fragments, directly remove all contained DOM nodes.
|
||||||
// (fragment child nodes cannot have transition)
|
// (fragment child nodes cannot have transition)
|
||||||
let next
|
let next
|
||||||
@ -1762,7 +1747,7 @@ function baseCreateRenderer<
|
|||||||
|
|
||||||
const unmountComponent = (
|
const unmountComponent = (
|
||||||
instance: ComponentInternalInstance,
|
instance: ComponentInternalInstance,
|
||||||
parentSuspense: HostSuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean
|
||||||
) => {
|
) => {
|
||||||
if (__HMR__ && instance.type.__hmrId) {
|
if (__HMR__ && instance.type.__hmrId) {
|
||||||
@ -1819,7 +1804,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unmountChildren: UnmountChildrenFn<HostNode, HostElement> = (
|
const unmountChildren: UnmountChildrenFn = (
|
||||||
children,
|
children,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
@ -1831,7 +1816,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNextHostNode: NextFn<HostNode, HostElement> = vnode => {
|
const getNextHostNode: NextFn = vnode => {
|
||||||
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
if (vnode.shapeFlag & ShapeFlags.COMPONENT) {
|
||||||
return getNextHostNode(vnode.component!.subTree)
|
return getNextHostNode(vnode.component!.subTree)
|
||||||
}
|
}
|
||||||
@ -1845,7 +1830,7 @@ function baseCreateRenderer<
|
|||||||
rawRef: VNodeNormalizedRef,
|
rawRef: VNodeNormalizedRef,
|
||||||
oldRawRef: VNodeNormalizedRef | null,
|
oldRawRef: VNodeNormalizedRef | null,
|
||||||
parent: ComponentInternalInstance,
|
parent: ComponentInternalInstance,
|
||||||
value: HostNode | ComponentPublicInstance | null
|
value: RendererNode | ComponentPublicInstance | null
|
||||||
) => {
|
) => {
|
||||||
const [owner, ref] = rawRef
|
const [owner, ref] = rawRef
|
||||||
if (__DEV__ && !owner) {
|
if (__DEV__ && !owner) {
|
||||||
@ -1887,12 +1872,7 @@ function baseCreateRenderer<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostRootElement = HostElement & { _vnode: HostVNode | null }
|
const render: RootRenderFunction = (vnode, container) => {
|
||||||
|
|
||||||
const render: RootRenderFunction<HostNode, HostElement> = (
|
|
||||||
vnode,
|
|
||||||
container: HostRootElement
|
|
||||||
) => {
|
|
||||||
if (vnode == null) {
|
if (vnode == null) {
|
||||||
if (container._vnode) {
|
if (container._vnode) {
|
||||||
unmount(container._vnode, null, null, true)
|
unmount(container._vnode, null, null, true)
|
||||||
@ -1904,7 +1884,7 @@ function baseCreateRenderer<
|
|||||||
container._vnode = vnode
|
container._vnode = vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
const internals: RendererInternals<HostNode, HostElement> = {
|
const internals: RendererInternals = {
|
||||||
p: patch,
|
p: patch,
|
||||||
um: unmount,
|
um: unmount,
|
||||||
m: move,
|
m: move,
|
||||||
@ -1928,7 +1908,7 @@ function baseCreateRenderer<
|
|||||||
return {
|
return {
|
||||||
render,
|
render,
|
||||||
hydrate,
|
hydrate,
|
||||||
createApp: createAppAPI(render, hydrate) as CreateAppFunction<HostElement>
|
createApp: createAppAPI(render, hydrate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import { warn } from './warning'
|
|||||||
import { currentScopeId } from './helpers/scopeId'
|
import { currentScopeId } from './helpers/scopeId'
|
||||||
import { PortalImpl, isPortal } from './components/Portal'
|
import { PortalImpl, isPortal } from './components/Portal'
|
||||||
import { currentRenderingInstance } from './componentRenderUtils'
|
import { currentRenderingInstance } from './componentRenderUtils'
|
||||||
|
import { RendererNode, RendererElement } from './renderer'
|
||||||
|
|
||||||
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
|
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
|
||||||
__isFragment: true
|
__isFragment: true
|
||||||
@ -81,40 +82,31 @@ export interface VNodeProps {
|
|||||||
onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[]
|
onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type VNodeChildAtom<HostNode, HostElement> =
|
type VNodeChildAtom = VNode | string | number | boolean | null | void
|
||||||
| VNode<HostNode, HostElement>
|
|
||||||
|
export interface VNodeArrayChildren<
|
||||||
|
HostNode = RendererNode,
|
||||||
|
HostElement = RendererElement
|
||||||
|
> extends Array<VNodeArrayChildren | VNodeChildAtom> {}
|
||||||
|
|
||||||
|
export type VNodeChild = VNodeChildAtom | VNodeArrayChildren
|
||||||
|
|
||||||
|
export type VNodeNormalizedChildren =
|
||||||
| string
|
| string
|
||||||
| number
|
| VNodeArrayChildren
|
||||||
| boolean
|
|
||||||
| null
|
|
||||||
| void
|
|
||||||
|
|
||||||
export interface VNodeArrayChildren<HostNode = any, HostElement = any>
|
|
||||||
extends Array<
|
|
||||||
| VNodeArrayChildren<HostNode, HostElement>
|
|
||||||
| VNodeChildAtom<HostNode, HostElement>
|
|
||||||
> {}
|
|
||||||
|
|
||||||
export type VNodeChild<HostNode = any, HostElement = any> =
|
|
||||||
| VNodeChildAtom<HostNode, HostElement>
|
|
||||||
| VNodeArrayChildren<HostNode, HostElement>
|
|
||||||
|
|
||||||
export type VNodeNormalizedChildren<HostNode = any, HostElement = any> =
|
|
||||||
| string
|
|
||||||
| VNodeArrayChildren<HostNode, HostElement>
|
|
||||||
| RawSlots
|
| RawSlots
|
||||||
| null
|
| null
|
||||||
|
|
||||||
export interface VNode<HostNode = any, HostElement = any> {
|
export interface VNode<HostNode = RendererNode, HostElement = RendererElement> {
|
||||||
_isVNode: true
|
_isVNode: true
|
||||||
type: VNodeTypes
|
type: VNodeTypes
|
||||||
props: VNodeProps | null
|
props: VNodeProps | null
|
||||||
key: string | number | null
|
key: string | number | null
|
||||||
ref: VNodeNormalizedRef | null
|
ref: VNodeNormalizedRef | null
|
||||||
scopeId: string | null // SFC only
|
scopeId: string | null // SFC only
|
||||||
children: VNodeNormalizedChildren<HostNode, HostElement>
|
children: VNodeNormalizedChildren
|
||||||
component: ComponentInternalInstance | null
|
component: ComponentInternalInstance | null
|
||||||
suspense: SuspenseBoundary<HostNode, HostElement> | null
|
suspense: SuspenseBoundary | null
|
||||||
dirs: DirectiveBinding[] | null
|
dirs: DirectiveBinding[] | null
|
||||||
transition: TransitionHooks | null
|
transition: TransitionHooks | null
|
||||||
|
|
||||||
@ -376,7 +368,7 @@ export function createCommentVNode(
|
|||||||
: createVNode(Comment, null, text)
|
: createVNode(Comment, null, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeVNode<T, U>(child: VNodeChild<T, U>): VNode<T, U> {
|
export function normalizeVNode(child: VNodeChild): VNode {
|
||||||
if (child == null || typeof child === 'boolean') {
|
if (child == null || typeof child === 'boolean') {
|
||||||
// empty placeholder
|
// empty placeholder
|
||||||
return createVNode(Comment)
|
return createVNode(Comment)
|
||||||
|
@ -13,7 +13,7 @@ import { ErrorCodes } from 'packages/runtime-core/src/errorHandling'
|
|||||||
const TRANSITION = 'transition'
|
const TRANSITION = 'transition'
|
||||||
const ANIMATION = 'animation'
|
const ANIMATION = 'animation'
|
||||||
|
|
||||||
export interface TransitionProps extends BaseTransitionProps {
|
export interface TransitionProps extends BaseTransitionProps<Element> {
|
||||||
name?: string
|
name?: string
|
||||||
type?: typeof TRANSITION | typeof ANIMATION
|
type?: typeof TRANSITION | typeof ANIMATION
|
||||||
css?: boolean
|
css?: boolean
|
||||||
@ -76,7 +76,7 @@ export function resolveTransitionProps({
|
|||||||
leaveActiveClass = `${name}-leave-active`,
|
leaveActiveClass = `${name}-leave-active`,
|
||||||
leaveToClass = `${name}-leave-to`,
|
leaveToClass = `${name}-leave-to`,
|
||||||
...baseProps
|
...baseProps
|
||||||
}: TransitionProps): BaseTransitionProps {
|
}: TransitionProps): BaseTransitionProps<Element> {
|
||||||
if (!css) {
|
if (!css) {
|
||||||
return baseProps
|
return baseProps
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ export function resolveTransitionProps({
|
|||||||
enterToClass = appearToClass
|
enterToClass = appearToClass
|
||||||
}
|
}
|
||||||
|
|
||||||
type Hook = (el: HTMLElement, done?: () => void) => void
|
type Hook = (el: Element, done?: () => void) => void
|
||||||
|
|
||||||
const finishEnter: Hook = (el, done) => {
|
const finishEnter: Hook = (el, done) => {
|
||||||
removeTransitionClass(el, enterToClass)
|
removeTransitionClass(el, enterToClass)
|
||||||
@ -124,7 +124,7 @@ export function resolveTransitionProps({
|
|||||||
onEnter(el, done) {
|
onEnter(el, done) {
|
||||||
nextFrame(() => {
|
nextFrame(() => {
|
||||||
const resolve = () => finishEnter(el, done)
|
const resolve = () => finishEnter(el, done)
|
||||||
onEnter && callHookWithErrorHandling(onEnter, [el, resolve])
|
onEnter && callHookWithErrorHandling(onEnter as Hook, [el, resolve])
|
||||||
removeTransitionClass(el, enterFromClass)
|
removeTransitionClass(el, enterFromClass)
|
||||||
addTransitionClass(el, enterToClass)
|
addTransitionClass(el, enterToClass)
|
||||||
if (!(onEnter && onEnter.length > 1)) {
|
if (!(onEnter && onEnter.length > 1)) {
|
||||||
@ -141,7 +141,7 @@ export function resolveTransitionProps({
|
|||||||
addTransitionClass(el, leaveFromClass)
|
addTransitionClass(el, leaveFromClass)
|
||||||
nextFrame(() => {
|
nextFrame(() => {
|
||||||
const resolve = () => finishLeave(el, done)
|
const resolve = () => finishLeave(el, done)
|
||||||
onLeave && callHookWithErrorHandling(onLeave, [el, resolve])
|
onLeave && callHookWithErrorHandling(onLeave as Hook, [el, resolve])
|
||||||
removeTransitionClass(el, leaveFromClass)
|
removeTransitionClass(el, leaveFromClass)
|
||||||
addTransitionClass(el, leaveToClass)
|
addTransitionClass(el, leaveToClass)
|
||||||
if (!(onLeave && onLeave.length > 1)) {
|
if (!(onLeave && onLeave.length > 1)) {
|
||||||
@ -199,17 +199,21 @@ export interface ElementWithTransition extends HTMLElement {
|
|||||||
_vtc?: Set<string>
|
_vtc?: Set<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addTransitionClass(el: ElementWithTransition, cls: string) {
|
export function addTransitionClass(el: Element, cls: string) {
|
||||||
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
|
cls.split(/\s+/).forEach(c => c && el.classList.add(c))
|
||||||
;(el._vtc || (el._vtc = new Set())).add(cls)
|
;(
|
||||||
|
(el as ElementWithTransition)._vtc ||
|
||||||
|
((el as ElementWithTransition)._vtc = new Set())
|
||||||
|
).add(cls)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeTransitionClass(el: ElementWithTransition, cls: string) {
|
export function removeTransitionClass(el: Element, cls: string) {
|
||||||
cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
|
cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
|
||||||
if (el._vtc) {
|
const { _vtc } = el as ElementWithTransition
|
||||||
el._vtc.delete(cls)
|
if (_vtc) {
|
||||||
if (!el._vtc!.size) {
|
_vtc.delete(cls)
|
||||||
el._vtc = undefined
|
if (!_vtc!.size) {
|
||||||
|
;(el as ElementWithTransition)._vtc = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ const TransitionGroupImpl = {
|
|||||||
hasMove =
|
hasMove =
|
||||||
hasMove === null
|
hasMove === null
|
||||||
? (hasMove = hasCSSTransform(
|
? (hasMove = hasCSSTransform(
|
||||||
prevChildren[0].el,
|
prevChildren[0].el as ElementWithTransition,
|
||||||
instance.vnode.el,
|
instance.vnode.el as Node,
|
||||||
moveClass
|
moveClass
|
||||||
))
|
))
|
||||||
: hasMove
|
: hasMove
|
||||||
@ -71,17 +71,17 @@ const TransitionGroupImpl = {
|
|||||||
forceReflow()
|
forceReflow()
|
||||||
|
|
||||||
movedChildren.forEach(c => {
|
movedChildren.forEach(c => {
|
||||||
const el = c.el
|
const el = c.el as ElementWithTransition
|
||||||
const style = el.style
|
const style = el.style
|
||||||
addTransitionClass(el, moveClass)
|
addTransitionClass(el, moveClass)
|
||||||
style.transform = style.WebkitTransform = style.transitionDuration = ''
|
style.transform = style.webkitTransform = style.transitionDuration = ''
|
||||||
const cb = (el._moveCb = (e: TransitionEvent) => {
|
const cb = ((el as any)._moveCb = (e: TransitionEvent) => {
|
||||||
if (e && e.target !== el) {
|
if (e && e.target !== el) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!e || /transform$/.test(e.propertyName)) {
|
if (!e || /transform$/.test(e.propertyName)) {
|
||||||
el.removeEventListener('transitionend', cb)
|
el.removeEventListener('transitionend', cb)
|
||||||
el._moveCb = null
|
;(el as any)._moveCb = null
|
||||||
removeTransitionClass(el, moveClass)
|
removeTransitionClass(el, moveClass)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -120,7 +120,7 @@ const TransitionGroupImpl = {
|
|||||||
child,
|
child,
|
||||||
resolveTransitionHooks(child, cssTransitionProps, state, instance)
|
resolveTransitionHooks(child, cssTransitionProps, state, instance)
|
||||||
)
|
)
|
||||||
positionMap.set(child, child.el.getBoundingClientRect())
|
positionMap.set(child, (child.el as Element).getBoundingClientRect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,16 +145,17 @@ if (__DEV__) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function callPendingCbs(c: VNode) {
|
function callPendingCbs(c: VNode) {
|
||||||
if (c.el._moveCb) {
|
const el = c.el as any
|
||||||
c.el._moveCb()
|
if (el._moveCb) {
|
||||||
|
el._moveCb()
|
||||||
}
|
}
|
||||||
if (c.el._enterCb) {
|
if (el._enterCb) {
|
||||||
c.el._enterCb()
|
el._enterCb()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function recordPosition(c: VNode) {
|
function recordPosition(c: VNode) {
|
||||||
newPositionMap.set(c, c.el.getBoundingClientRect())
|
newPositionMap.set(c, (c.el as Element).getBoundingClientRect())
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTranslation(c: VNode): VNode | undefined {
|
function applyTranslation(c: VNode): VNode | undefined {
|
||||||
@ -163,8 +164,8 @@ function applyTranslation(c: VNode): VNode | undefined {
|
|||||||
const dx = oldPos.left - newPos.left
|
const dx = oldPos.left - newPos.left
|
||||||
const dy = oldPos.top - newPos.top
|
const dy = oldPos.top - newPos.top
|
||||||
if (dx || dy) {
|
if (dx || dy) {
|
||||||
const s = c.el.style
|
const s = (c.el as HTMLElement).style
|
||||||
s.transform = s.WebkitTransform = `translate(${dx}px,${dy}px)`
|
s.transform = s.webkitTransform = `translate(${dx}px,${dy}px)`
|
||||||
s.transitionDuration = '0s'
|
s.transitionDuration = '0s'
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ import { isArray, looseEqual, looseIndexOf } from '@vue/shared'
|
|||||||
const getModelAssigner = (vnode: VNode): ((value: any) => void) =>
|
const getModelAssigner = (vnode: VNode): ((value: any) => void) =>
|
||||||
vnode.props!['onUpdate:modelValue']
|
vnode.props!['onUpdate:modelValue']
|
||||||
|
|
||||||
function onCompositionStart(e: CompositionEvent) {
|
function onCompositionStart(e: Event) {
|
||||||
;(e.target as any).composing = true
|
;(e.target as any).composing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCompositionEnd(e: CompositionEvent) {
|
function onCompositionEnd(e: Event) {
|
||||||
const target = e.target as any
|
const target = e.target as any
|
||||||
if (target.composing) {
|
if (target.composing) {
|
||||||
target.composing = false
|
target.composing = false
|
||||||
|
@ -6,7 +6,7 @@ type KeyedEvent = KeyboardEvent | MouseEvent | TouchEvent
|
|||||||
|
|
||||||
const modifierGuards: Record<
|
const modifierGuards: Record<
|
||||||
string,
|
string,
|
||||||
(e: Event, modifiers?: string[]) => void | boolean
|
(e: Event, modifiers: string[]) => void | boolean
|
||||||
> = {
|
> = {
|
||||||
stop: e => e.stopPropagation(),
|
stop: e => e.stopPropagation(),
|
||||||
prevent: e => e.preventDefault(),
|
prevent: e => e.preventDefault(),
|
||||||
@ -18,7 +18,7 @@ const modifierGuards: Record<
|
|||||||
left: e => 'button' in e && (e as MouseEvent).button !== 0,
|
left: e => 'button' in e && (e as MouseEvent).button !== 0,
|
||||||
middle: e => 'button' in e && (e as MouseEvent).button !== 1,
|
middle: e => 'button' in e && (e as MouseEvent).button !== 1,
|
||||||
right: e => 'button' in e && (e as MouseEvent).button !== 2,
|
right: e => 'button' in e && (e as MouseEvent).button !== 2,
|
||||||
exact: (e, modifiers: string[]) =>
|
exact: (e, modifiers) =>
|
||||||
systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers.includes(m))
|
systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers.includes(m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ function ensureHydrationRenderer() {
|
|||||||
// use explicit type casts here to avoid import() calls in rolled-up d.ts
|
// use explicit type casts here to avoid import() calls in rolled-up d.ts
|
||||||
export const render = ((...args) => {
|
export const render = ((...args) => {
|
||||||
ensureRenderer().render(...args)
|
ensureRenderer().render(...args)
|
||||||
}) as RootRenderFunction<Node, Element>
|
}) as RootRenderFunction<Element>
|
||||||
|
|
||||||
export const hydrate = ((...args) => {
|
export const hydrate = ((...args) => {
|
||||||
ensureHydrationRenderer().hydrate(...args)
|
ensureHydrationRenderer().hydrate(...args)
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
RootRenderFunction,
|
RootRenderFunction,
|
||||||
CreateAppFunction
|
CreateAppFunction
|
||||||
} from '@vue/runtime-core'
|
} from '@vue/runtime-core'
|
||||||
import { nodeOps, TestNode, TestElement } from './nodeOps'
|
import { nodeOps, TestElement } from './nodeOps'
|
||||||
import { patchProp } from './patchProp'
|
import { patchProp } from './patchProp'
|
||||||
import { serializeInner } from './serialize'
|
import { serializeInner } from './serialize'
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ const { render: baseRender, createApp: baseCreateApp } = createRenderer({
|
|||||||
...nodeOps
|
...nodeOps
|
||||||
})
|
})
|
||||||
|
|
||||||
export const render = baseRender as RootRenderFunction<TestNode, TestElement>
|
export const render = baseRender as RootRenderFunction<TestElement>
|
||||||
export const createApp = baseCreateApp as CreateAppFunction<TestElement>
|
export const createApp = baseCreateApp as CreateAppFunction<TestElement>
|
||||||
|
|
||||||
// convenience for one-off render validations
|
// convenience for one-off render validations
|
||||||
|
@ -42,7 +42,7 @@ export function setupPuppeteer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function value(selector: string) {
|
async function value(selector: string) {
|
||||||
return await page.$eval(selector, (node: HTMLInputElement) => node.value)
|
return await page.$eval(selector, node => (node as HTMLInputElement).value)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function html(selector: string) {
|
async function html(selector: string) {
|
||||||
@ -58,14 +58,17 @@ export function setupPuppeteer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function isVisible(selector: string) {
|
async function isVisible(selector: string) {
|
||||||
const display = await page.$eval(selector, (node: HTMLElement) => {
|
const display = await page.$eval(selector, node => {
|
||||||
return window.getComputedStyle(node).display
|
return window.getComputedStyle(node).display
|
||||||
})
|
})
|
||||||
return display !== 'none'
|
return display !== 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isChecked(selector: string) {
|
async function isChecked(selector: string) {
|
||||||
return await page.$eval(selector, (node: HTMLInputElement) => node.checked)
|
return await page.$eval(
|
||||||
|
selector,
|
||||||
|
node => (node as HTMLInputElement).checked
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isFocused(selector: string) {
|
async function isFocused(selector: string) {
|
||||||
@ -74,13 +77,13 @@ export function setupPuppeteer() {
|
|||||||
|
|
||||||
async function setValue(selector: string, value: string) {
|
async function setValue(selector: string, value: string) {
|
||||||
const el = (await page.$(selector))!
|
const el = (await page.$(selector))!
|
||||||
await el.evaluate((node: HTMLInputElement) => (node.value = ''))
|
await el.evaluate(node => ((node as HTMLInputElement).value = ''))
|
||||||
await el.type(value)
|
await el.type(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function enterValue(selector: string, value: string) {
|
async function enterValue(selector: string, value: string) {
|
||||||
const el = (await page.$(selector))!
|
const el = (await page.$(selector))!
|
||||||
await el.evaluate((node: HTMLInputElement) => (node.value = ''))
|
await el.evaluate(node => ((node as HTMLInputElement).value = ''))
|
||||||
await el.type(value)
|
await el.type(value)
|
||||||
await el.press('Enter')
|
await el.press('Enter')
|
||||||
}
|
}
|
||||||
@ -88,7 +91,7 @@ export function setupPuppeteer() {
|
|||||||
async function clearValue(selector: string) {
|
async function clearValue(selector: string) {
|
||||||
return await page.$eval(
|
return await page.$eval(
|
||||||
selector,
|
selector,
|
||||||
(node: HTMLInputElement) => (node.value = '')
|
node => ((node as HTMLInputElement).value = '')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe('e2e: markdown', () => {
|
|||||||
await page().type('textarea', '\n## foo\n\n- bar\n- baz')
|
await page().type('textarea', '\n## foo\n\n- bar\n- baz')
|
||||||
// assert the output is not updated yet because of debounce
|
// assert the output is not updated yet because of debounce
|
||||||
expect(await html('#editor div')).toBe('<h1 id="hello">hello</h1>\n')
|
expect(await html('#editor div')).toBe('<h1 id="hello">hello</h1>\n')
|
||||||
await page().waitFor(30)
|
await page().waitFor(100)
|
||||||
expect(await html('#editor div')).toBe(
|
expect(await html('#editor div')).toBe(
|
||||||
'<h1 id="hello">hello</h1>\n' +
|
'<h1 id="hello">hello</h1>\n' +
|
||||||
'<h2 id="foo">foo</h2>\n' +
|
'<h2 id="foo">foo</h2>\n' +
|
||||||
|
@ -7,10 +7,8 @@
|
|||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"strictNullChecks": true,
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"noImplicitThis": true,
|
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user