diff --git a/packages/runtime-core/src/apiAsyncComponent.ts b/packages/runtime-core/src/apiAsyncComponent.ts index d7abb25fe..07e7fc67f 100644 --- a/packages/runtime-core/src/apiAsyncComponent.ts +++ b/packages/runtime-core/src/apiAsyncComponent.ts @@ -3,6 +3,7 @@ import { type ComponentInternalInstance, type ComponentOptions, type ConcreteComponent, + type GenericComponentInstance, currentInstance, isInSSRComponentSetup, } from './component' @@ -39,7 +40,7 @@ export interface AsyncComponentOptions { ) => any } -export const isAsyncWrapper = (i: ComponentInternalInstance | VNode): boolean => +export const isAsyncWrapper = (i: GenericComponentInstance | VNode): boolean => !!(i.type as ComponentOptions).__asyncLoader /*! #__NO_SIDE_EFFECTS__ */ @@ -206,10 +207,14 @@ export function defineAsyncComponent< load() .then(() => { loaded.value = true - if (instance.parent && isKeepAlive(instance.parent.vnode)) { + if ( + instance.parent && + instance.parent.vnode && + isKeepAlive(instance.parent.vnode) + ) { // parent is keep-alive, force update so the loaded component's // name is taken into account - instance.parent.update() + ;(instance.parent as ComponentInternalInstance).update() } }) .catch(err => { diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 06f6e51ea..005e5dd3e 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -504,6 +504,26 @@ export interface GenericComponentInstance { * @internal vapor only */ hmrReload?: (newComp: any) => void + + // these only exist on vdom instances + vnode?: VNode + subTree?: VNode + + /** + * Custom Element instance (if component is created by defineCustomElement) + * @internal + */ + ce?: ComponentCustomElementInterface + /** + * is custom element? (kept only for compatibility) + * @internal + */ + isCE?: boolean + /** + * custom element specific HMR method + * @internal + */ + ceReload?: (newStyles?: string[]) => void } /** @@ -514,8 +534,8 @@ export interface ComponentInternalInstance extends GenericComponentInstance { vapor?: never uid: number type: ConcreteComponent - parent: ComponentInternalInstance | null - root: ComponentInternalInstance + parent: GenericComponentInstance | null + root: GenericComponentInstance appContext: AppContext /** * Vnode representing this component in its parent's vdom tree @@ -589,21 +609,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance { * @internal */ inheritAttrs?: boolean - /** - * Custom Element instance (if component is created by defineCustomElement) - * @internal - */ - ce?: ComponentCustomElementInterface - /** - * is custom element? (kept only for compatibility) - * @internal - */ - isCE?: boolean - /** - * custom element specific HMR method - * @internal - */ - ceReload?: (newStyles?: string[]) => void // the rest are only for stateful components --------------------------------- /** @@ -1210,7 +1215,7 @@ export function expose( } export function getComponentPublicInstance( - instance: ComponentInternalInstance, + instance: GenericComponentInstance, ): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null { if (instance.exposed) { return ( diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index c5ce317f7..d0fe97ff0 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -232,7 +232,7 @@ export function initProps( instance.attrs = attrs } -function isInHmrContext(instance: ComponentInternalInstance | null) { +function isInHmrContext(instance: GenericComponentInstance | null) { while (instance) { if (instance.type.__hmrId) return true instance = instance.parent diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index e9e7770eb..a43c99e2f 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -2,6 +2,7 @@ import { type Component, type ComponentInternalInstance, type Data, + type GenericComponentInstance, getComponentPublicInstance, isStatefulComponent, } from './component' @@ -355,10 +356,11 @@ export type PublicPropertiesMap = Record< * public $parent chains, skip functional ones and go to the parent instead. */ const getPublicInstance = ( - i: ComponentInternalInstance | null, + i: GenericComponentInstance | null, ): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null => { - if (!i) return null - if (isStatefulComponent(i)) return getComponentPublicInstance(i) + if (!i || i.vapor) return null + if (isStatefulComponent(i as ComponentInternalInstance)) + return getComponentPublicInstance(i) return getPublicInstance(i.parent) } diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 53e0b5a3e..a62b5cf4a 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -455,12 +455,12 @@ export function updateHOCHostEl( el: typeof vnode.el, // HostNode ): void { while (parent && !parent.vapor) { - const root = parent.subTree + const root = parent.subTree! if (root.suspense && root.suspense.activeBranch === vnode) { root.el = vnode.el } if (root === vnode) { - ;(vnode = parent.vnode).el = el + ;(vnode = parent.vnode!).el = el parent = parent.parent } else { break diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index 2ceaaa9e6..949de0bdd 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -2,6 +2,7 @@ import { type ComponentInternalInstance, type ComponentOptions, type ConcreteComponent, + type GenericComponentInstance, type SetupContext, getComponentName, getCurrentInstance, @@ -436,7 +437,7 @@ function registerKeepAliveHook( hook.__wdc || (hook.__wdc = () => { // only fire the hook if the target instance is NOT in a deactivated branch. - let current: ComponentInternalInstance | null = target + let current: GenericComponentInstance | null = target while (current) { if (current.isDeactivated) { return @@ -453,7 +454,7 @@ function registerKeepAliveHook( // arrays. if (target) { let current = target.parent - while (current && current.parent) { + while (current && current.parent && current.parent.vnode) { if (isKeepAlive(current.parent.vnode)) { injectToKeepAliveRoot(wrappedHook, type, target, current) } @@ -466,7 +467,7 @@ function injectToKeepAliveRoot( hook: Function & { __weh?: Function }, type: LifecycleHooks, target: ComponentInternalInstance, - keepAliveRoot: ComponentInternalInstance, + keepAliveRoot: GenericComponentInstance, ) { // injectHook wraps the original for error handling, so make sure to remove // the wrapped version. diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index 42f671e81..6fd6bb3f2 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -154,7 +154,12 @@ function reload(id: string, newComp: HMRComponent): void { // don't end up forcing the same parent to re-render multiple times. queueJob(() => { isHmrUpdating = true - instance.parent!.update() + const parent = instance.parent! + if (parent.vapor) { + parent.hmrRerender!() + } else { + ;(parent as ComponentInternalInstance).update() + } isHmrUpdating = false // #6930, #11248 avoid infinite recursion dirtyInstances.delete(instance) diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index a94ff3568..652a84680 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -768,7 +768,7 @@ export function createHydrationFunctions( if (parent.vnode.el === oldNode) { parent.vnode.el = parent.subTree.el = newNode } - parent = parent.parent + parent = parent.parent as ComponentInternalInstance } } @@ -945,7 +945,11 @@ function resolveCssVars( } } if (vnode === root && instance.parent) { - resolveCssVars(instance.parent, instance.vnode, expectedMap) + resolveCssVars( + instance.parent as ComponentInternalInstance, + instance.vnode, + expectedMap, + ) } } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index fff68dd2c..08e618081 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -19,6 +19,7 @@ import { type ComponentOptions, type ConcreteComponent, type Data, + type GenericComponentInstance, type LifecycleHook, createComponentInstance, getComponentPublicInstance, @@ -749,7 +750,7 @@ function baseCreateRenderer( vnode: VNode, scopeId: string | null, slotScopeIds: string[] | null, - parentComponent: ComponentInternalInstance | null, + parentComponent: GenericComponentInstance | null, ) => { if (scopeId) { hostSetScopeId(el, scopeId) @@ -774,7 +775,7 @@ function baseCreateRenderer( (isSuspense(subTree.type) && (subTree.ssContent === vnode || subTree.ssFallback === vnode)) ) { - const parentVNode = parentComponent!.vnode + const parentVNode = parentComponent!.vnode! setScopeId( el, parentVNode, @@ -1382,8 +1383,8 @@ function baseCreateRenderer( } } else { // custom element style injection - if (root.ce) { - root.ce._injectChildStyle(type) + if ((root as ComponentInternalInstance).ce) { + ;(root as ComponentInternalInstance).ce!._injectChildStyle(type) } if (__DEV__) { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 17efef80a..2d476bd4a 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -18,6 +18,7 @@ import { type ComponentInternalInstance, type ConcreteComponent, type Data, + type GenericComponentInstance, isClassComponent, } from './component' import type { RawSlots } from './componentSlots' @@ -903,7 +904,7 @@ export function mergeProps(...args: (Data & VNodeProps)[]): Data { export function invokeVNodeHook( hook: VNodeHook, - instance: ComponentInternalInstance | null, + instance: GenericComponentInstance | null, vnode: VNode, prevVNode: VNode | null = null, ): void { diff --git a/packages/runtime-core/src/warning.ts b/packages/runtime-core/src/warning.ts index c261bf602..361a2734b 100644 --- a/packages/runtime-core/src/warning.ts +++ b/packages/runtime-core/src/warning.ts @@ -1,5 +1,4 @@ import { - type ComponentInternalInstance, type Data, type GenericComponentInstance, formatComponentName, @@ -106,9 +105,9 @@ export function getComponentTrace(): ComponentTraceStack { }) } if (isVNode(currentCtx)) { - const parent: ComponentInternalInstance | null = + const parent: GenericComponentInstance | null = currentCtx.component && currentCtx.component.parent - currentCtx = parent && parent.vnode + currentCtx = (parent && parent.vnode) || parent } else { currentCtx = currentCtx.parent } diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index 928e5d955..8400e71d6 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -10,6 +10,7 @@ import { vtcKey, } from './Transition' import { + type ComponentInternalInstance, type ComponentOptions, DeprecationTypes, Fragment, @@ -122,7 +123,7 @@ const TransitionGroupImpl: ComponentOptions = /*@__PURE__*/ decorate({ !rawProps.tag && compatUtils.checkCompatEnabled( DeprecationTypes.TRANSITION_GROUP_ROOT, - instance.parent, + instance.parent as ComponentInternalInstance, ) ) { tag = 'span' diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts index f04080b9c..221d3895e 100644 --- a/packages/server-renderer/src/render.ts +++ b/packages/server-renderer/src/render.ts @@ -172,7 +172,7 @@ function renderComponentSubTree( if (parent && parent.subTree && parent.subTree === cur.vnode) { // parent is a non-SSR compiled component and is rendering this // component as root. inherit its scopeId if present. - cur = parent + cur = parent as ComponentInternalInstance } else { break } @@ -314,7 +314,7 @@ function renderElementVNode( if (curVnode.scopeId) { openTag += ` ${curVnode.scopeId}` } - curParent = curParent.parent + curParent = curParent.parent as ComponentInternalInstance } if (slotScopeId) { openTag += ` ${slotScopeId}`