Jelajahi Sumber

wip: vdom in vapor hmr reload

Evan You 1 tahun lalu
induk
melakukan
be5c2a2f51

+ 8 - 3
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<T = any> {
   ) => 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 => {

+ 23 - 18
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 (

+ 1 - 1
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

+ 5 - 3
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)
 }
 

+ 2 - 2
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

+ 4 - 3
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.

+ 6 - 1
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)

+ 6 - 2
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,
+    )
   }
 }
 

+ 5 - 4
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__) {

+ 2 - 1
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 {

+ 2 - 3
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
     }

+ 2 - 1
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'

+ 2 - 2
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}`