]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: prepare hmr for vapor
authorEvan You <evan@vuejs.org>
Sun, 8 Dec 2024 08:32:29 +0000 (16:32 +0800)
committerEvan You <evan@vuejs.org>
Sun, 8 Dec 2024 08:32:29 +0000 (16:32 +0800)
packages/runtime-core/src/component.ts
packages/runtime-core/src/hmr.ts

index c7424abc7bfe2d3298ddc6573ccef921cb9670fd..f9dae3d2121aa2d285ac9b37d720379fef24f865 100644 (file)
@@ -348,6 +348,10 @@ export interface GenericComponentInstance {
    * @internal
    */
   scope: EffectScope
+  /**
+   * render function will have different types between vdom and vapor
+   */
+  render?: Function | null
   /**
    * SSR render function
    * (they are the same between vdom and vapor components.)
index 7aedf52dd3ea562045200e411947c7ca937aa90f..643f8ffff28707f66d4d62e49a8a9d0b43044e16 100644 (file)
@@ -4,7 +4,7 @@ import {
   type ComponentInternalInstance,
   type ComponentOptions,
   type ConcreteComponent,
-  type InternalRenderFunction,
+  type GenericComponentInstance,
   isClassComponent,
 } from './component'
 import { queueJob, queuePostFlushCb } from './scheduler'
@@ -16,8 +16,8 @@ export let isHmrUpdating = false
 
 export const hmrDirtyComponents: Map<
   ConcreteComponent,
-  Set<ComponentInternalInstance>
-> = new Map<ConcreteComponent, Set<ComponentInternalInstance>>()
+  Set<GenericComponentInstance>
+> = new Map<ConcreteComponent, Set<GenericComponentInstance>>()
 
 export interface HMRRuntime {
   createRecord: typeof createRecord
@@ -45,11 +45,11 @@ const map: Map<
     // to apply hot updates to the component even when there are no actively
     // rendered instance.
     initialDef: ComponentOptions
-    instances: Set<ComponentInternalInstance>
+    instances: Set<GenericComponentInstance>
   }
 > = new Map()
 
-export function registerHMR(instance: ComponentInternalInstance): void {
+export function registerHMR(instance: GenericComponentInstance): void {
   const id = instance.type.__hmrId!
   let record = map.get(id)
   if (!record) {
@@ -59,7 +59,7 @@ export function registerHMR(instance: ComponentInternalInstance): void {
   record.instances.add(instance)
 }
 
-export function unregisterHMR(instance: ComponentInternalInstance): void {
+export function unregisterHMR(instance: GenericComponentInstance): void {
   map.get(instance.type.__hmrId!)!.instances.delete(instance)
 }
 
@@ -90,13 +90,18 @@ function rerender(id: string, newRender?: Function): void {
   // Create a snapshot which avoids the set being mutated during updates
   ;[...record.instances].forEach(instance => {
     if (newRender) {
-      instance.render = newRender as InternalRenderFunction
+      instance.render = newRender
       normalizeClassComponent(instance.type as HMRComponent).render = newRender
     }
-    instance.renderCache = []
     // this flag forces child components with slot content to update
     isHmrUpdating = true
-    instance.update()
+    if (instance.vapor) {
+      // TODO
+    } else {
+      const i = instance as ComponentInternalInstance
+      i.renderCache = []
+      i.update()
+    }
     isHmrUpdating = false
   })
 }
@@ -112,62 +117,64 @@ function reload(id: string, newComp: HMRComponent): void {
   // create a snapshot which avoids the set being mutated during updates
   const instances = [...record.instances]
 
-  for (let i = 0; i < instances.length; i++) {
-    const instance = instances[i]
-    const oldComp = normalizeClassComponent(instance.type as HMRComponent)
-
-    let dirtyInstances = hmrDirtyComponents.get(oldComp)
-    if (!dirtyInstances) {
-      // 1. Update existing comp definition to match new one
-      if (oldComp !== record.initialDef) {
-        updateComponentDef(oldComp, newComp)
+  if (newComp.vapor) {
+    // TODO
+  } else {
+    for (const instance of instances as ComponentInternalInstance[]) {
+      const oldComp = normalizeClassComponent(instance.type as HMRComponent)
+
+      let dirtyInstances = hmrDirtyComponents.get(oldComp)
+      if (!dirtyInstances) {
+        // 1. Update existing comp definition to match new one
+        if (oldComp !== record.initialDef) {
+          updateComponentDef(oldComp, newComp)
+        }
+        // 2. mark definition dirty. This forces the renderer to replace the
+        // component on patch.
+        hmrDirtyComponents.set(oldComp, (dirtyInstances = new Set()))
       }
-      // 2. mark definition dirty. This forces the renderer to replace the
-      // component on patch.
-      hmrDirtyComponents.set(oldComp, (dirtyInstances = new Set()))
-    }
-    dirtyInstances.add(instance)
+      dirtyInstances.add(instance)
 
-    // 3. invalidate options resolution cache
-    instance.appContext.propsCache.delete(instance.type as any)
-    instance.appContext.emitsCache.delete(instance.type as any)
-    instance.appContext.optionsCache.delete(instance.type as any)
+      // 3. invalidate options resolution cache
+      instance.appContext.propsCache.delete(instance.type as any)
+      instance.appContext.emitsCache.delete(instance.type as any)
+      instance.appContext.optionsCache.delete(instance.type as any)
 
-    // 4. actually update
-    if (instance.ceReload) {
-      // custom element
-      dirtyInstances.add(instance)
-      instance.ceReload((newComp as any).styles)
-      dirtyInstances.delete(instance)
-    } else if (instance.parent) {
-      // 4. Force the parent instance to re-render. This will cause all updated
-      // components to be unmounted and re-mounted. Queue the update so that we
-      // don't end up forcing the same parent to re-render multiple times.
-      queueJob(() => {
-        isHmrUpdating = true
-        instance.parent!.update()
-        isHmrUpdating = false
-        // #6930, #11248 avoid infinite recursion
+      // 4. actually update
+      if (instance.ceReload) {
+        // custom element
+        dirtyInstances.add(instance)
+        instance.ceReload((newComp as any).styles)
         dirtyInstances.delete(instance)
-      })
-    } else if (instance.appContext.reload) {
-      // root instance mounted via createApp() has a reload method
-      instance.appContext.reload()
-    } else if (typeof window !== 'undefined') {
-      // root instance inside tree created via raw render(). Force reload.
-      window.location.reload()
-    } else {
-      console.warn(
-        '[HMR] Root or manually mounted instance modified. Full reload required.',
-      )
-    }
+      } else if (instance.parent) {
+        // 4. Force the parent instance to re-render. This will cause all updated
+        // components to be unmounted and re-mounted. Queue the update so that we
+        // don't end up forcing the same parent to re-render multiple times.
+        queueJob(() => {
+          isHmrUpdating = true
+          instance.parent!.update()
+          isHmrUpdating = false
+          // #6930, #11248 avoid infinite recursion
+          dirtyInstances.delete(instance)
+        })
+      } else if (instance.appContext.reload) {
+        // root instance mounted via createApp() has a reload method
+        instance.appContext.reload()
+      } else if (typeof window !== 'undefined') {
+        // root instance inside tree created via raw render(). Force reload.
+        window.location.reload()
+      } else {
+        console.warn(
+          '[HMR] Root or manually mounted instance modified. Full reload required.',
+        )
+      }
 
-    // update custom element child style
-    if (instance.root.ce && instance !== instance.root) {
-      instance.root.ce._removeChildStyle(oldComp)
+      // update custom element child style
+      if (instance.root.ce && instance !== instance.root) {
+        instance.root.ce._removeChildStyle(oldComp)
+      }
     }
   }
-
   // 5. make sure to cleanup dirty hmr components after update
   queuePostFlushCb(() => {
     hmrDirtyComponents.clear()