From: Evan You Date: Fri, 12 Jun 2020 18:53:48 +0000 (-0400) Subject: refactor(hmr): simplify hmr force update check X-Git-Tag: v3.0.0-beta.15~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e76ed4c269d94ce7614c2ea5a40f7d1ef705dea7;p=thirdparty%2Fvuejs%2Fcore.git refactor(hmr): simplify hmr force update check --- diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 94f972d14b..2e8e56aa8b 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -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() diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index fb762cbe95..645f211009 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -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. diff --git a/packages/runtime-core/src/componentSlots.ts b/packages/runtime-core/src/componentSlots.ts index b26b6f17a2..e819ab64f9 100644 --- a/packages/runtime-core/src/componentSlots.ts +++ b/packages/runtime-core/src/componentSlots.ts @@ -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) diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index 7953a4056f..27a1985460 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -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() + 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) }) } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index d5c2c8e140..f3ec801175 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -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 diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index b7a5f33810..f6c3468fb8 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -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