]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(hmr): simplify hmr force update check
authorEvan You <yyx990803@gmail.com>
Fri, 12 Jun 2020 18:53:48 +0000 (14:53 -0400)
committerEvan You <yyx990803@gmail.com>
Fri, 12 Jun 2020 18:53:48 +0000 (14:53 -0400)
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentRenderUtils.ts
packages/runtime-core/src/componentSlots.ts
packages/runtime-core/src/hmr.ts
packages/runtime-core/src/renderer.ts
packages/runtime-core/src/vnode.ts

index 94f972d14b1362e47e17a7490f4c4b99a02d73d9..2e8e56aa8b1d319c632cd49b68ee5a8362300d1e 100644 (file)
@@ -71,10 +71,6 @@ export interface ComponentInternalOptions {
    * @internal
    */
   __hmrId?: string
-  /**
-   * @internal
-   */
-  __hmrUpdated?: boolean
   /**
    * This one should be exposed so that devtools can make use of it
    */
@@ -325,12 +321,6 @@ export interface ComponentInternalInstance {
    * @internal
    */
   [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
-
-  /**
-   * hmr marker (dev only)
-   * @internal
-   */
-  hmrUpdated?: boolean
 }
 
 const emptyAppContext = createAppContext()
index fb762cbe95507364617c06e4e278466e7539007b..645f211009eb696b64862f6d9bb65e6b9c0d445f 100644 (file)
@@ -16,6 +16,7 @@ import {
 import { handleError, ErrorCodes } from './errorHandling'
 import { PatchFlags, ShapeFlags, isOn } from '@vue/shared'
 import { warn } from './warning'
+import { isHmrUpdating } from './hmr'
 
 // mark the current rendering instance for asset resolution (e.g.
 // resolveComponent, resolveDirective) during render
@@ -247,13 +248,8 @@ export function shouldUpdateComponent(
   // Parent component's render function was hot-updated. Since this may have
   // caused the child component's slots content to have changed, we need to
   // force the child to update as well.
-  if (__DEV__ && (prevChildren || nextChildren) && parentComponent) {
-    let parent: ComponentInternalInstance | null = parentComponent
-    do {
-      if (parent.hmrUpdated) {
-        return true
-      }
-    } while ((parent = parent.parent))
+  if (__DEV__ && (prevChildren || nextChildren) && isHmrUpdating) {
+    return true
   }
 
   // force child update for runtime directive or transition on component vnode.
index b26b6f17a259bac32a702168f0d666ee22441e46..e819ab64f90fc7d803d86e4eb958d181d10c7b01 100644 (file)
@@ -18,7 +18,7 @@ import {
 import { warn } from './warning'
 import { isKeepAlive } from './components/KeepAlive'
 import { withCtx } from './helpers/withRenderContext'
-import { queuePostFlushCb } from './scheduler'
+import { isHmrUpdating } from './hmr'
 
 export type Slot = (...args: any[]) => VNode[]
 
@@ -125,14 +125,10 @@ export const updateSlots = (
   if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
     if ((children as RawSlots)._ === 1) {
       // compiled slots.
-      if (__DEV__ && instance.parent && instance.parent.hmrUpdated) {
+      if (__DEV__ && isHmrUpdating) {
         // Parent was HMR updated so slot content may have changed.
         // force update slots and mark instance for hmr as well
         extend(slots, children as Slots)
-        instance.hmrUpdated = true
-        queuePostFlushCb(() => {
-          instance.hmrUpdated = false
-        })
       } else if (
         // bail on dynamic slots (v-if, v-for, reference of scope variables)
         !(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS)
index 7953a4056f9769e8a2db48250b37b95ef012165b..27a1985460bfc1e716948a2b7837b2fafdbee227 100644 (file)
@@ -1,5 +1,6 @@
 /* eslint-disable no-restricted-globals */
 import {
+  Component,
   ComponentInternalInstance,
   ComponentOptions,
   InternalRenderFunction
@@ -7,6 +8,10 @@ import {
 import { queueJob, queuePostFlushCb } from './scheduler'
 import { extend } from '@vue/shared'
 
+export let isHmrUpdating = false
+
+export const hmrDirtyComponents = new Set<Component>()
+
 export interface HMRRuntime {
   createRecord: typeof createRecord
   rerender: typeof rerender
@@ -72,9 +77,9 @@ function rerender(id: string, newRender?: Function) {
     }
     instance.renderCache = []
     // this flag forces child components with slot content to update
-    instance.hmrUpdated = true
+    isHmrUpdating = true
     instance.update()
-    instance.hmrUpdated = false
+    isHmrUpdating = false
   })
 }
 
@@ -85,7 +90,7 @@ function reload(id: string, newComp: ComponentOptions) {
   // updates
   Array.from(record).forEach(instance => {
     const comp = instance.type
-    if (!comp.__hmrUpdated) {
+    if (!hmrDirtyComponents.has(comp)) {
       // 1. Update existing comp definition to match new one
       extend(comp, newComp)
       for (const key in comp) {
@@ -95,10 +100,10 @@ function reload(id: string, newComp: ComponentOptions) {
       }
       // 2. Mark component dirty. This forces the renderer to replace the component
       // on patch.
-      comp.__hmrUpdated = true
+      hmrDirtyComponents.add(comp)
       // 3. Make sure to unmark the component after the reload.
       queuePostFlushCb(() => {
-        comp.__hmrUpdated = false
+        hmrDirtyComponents.delete(comp)
       })
     }
 
index d5c2c8e140f87b3944aacb8f55962d2ee01108c5..f3ec8011759eaaa6bec2149887b2d52c87dc157f 100644 (file)
@@ -56,7 +56,7 @@ import {
 } from './components/Suspense'
 import { TeleportImpl } from './components/Teleport'
 import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
-import { registerHMR, unregisterHMR } from './hmr'
+import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
 import {
   ErrorCodes,
   callWithErrorHandling,
@@ -791,18 +791,11 @@ function baseCreateRenderer(
       invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')
     }
 
-    // check if any component of the parent chain has `hmrUpdated`
-    if (__DEV__ && parentComponent) {
-      let parent: ComponentInternalInstance | null = parentComponent
-      do {
-        if (parent.hmrUpdated) {
-          // HMR updated, force full diff
-          patchFlag = 0
-          optimized = false
-          dynamicChildren = null
-          break
-        }
-      } while ((parent = parent.parent))
+    if (__DEV__ && isHmrUpdating) {
+      // HMR updated, force full diff
+      patchFlag = 0
+      optimized = false
+      dynamicChildren = null
     }
 
     if (patchFlag > 0) {
@@ -1025,7 +1018,7 @@ function baseCreateRenderer(
       optimized = true
     }
 
-    if (__DEV__ && parentComponent && parentComponent.hmrUpdated) {
+    if (__DEV__ && isHmrUpdating) {
       // HMR updated, force full diff
       patchFlag = 0
       optimized = false
index b7a5f338102c8e25d411f943fd142623bf098bb1..f6c3468fb8461ba895bdf0561f9897ea80dcbaa3 100644 (file)
@@ -32,6 +32,7 @@ import { TeleportImpl, isTeleport } from './components/Teleport'
 import { currentRenderingInstance } from './componentRenderUtils'
 import { RendererNode, RendererElement } from './renderer'
 import { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'
+import { hmrDirtyComponents } from './hmr'
 
 export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
   __isFragment: true
@@ -236,7 +237,7 @@ export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
   if (
     __DEV__ &&
     n2.shapeFlag & ShapeFlags.COMPONENT &&
-    (n2.type as Component).__hmrUpdated
+    hmrDirtyComponents.has(n2.type as Component)
   ) {
     // HMR only: if the component has been hot-updated, force a reload.
     return false