* @internal
*/
__hmrId?: string
- /**
- * @internal
- */
- __hmrUpdated?: boolean
/**
* This one should be exposed so that devtools can make use of it
*/
* @internal
*/
[LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
-
- /**
- * hmr marker (dev only)
- * @internal
- */
- hmrUpdated?: boolean
}
const emptyAppContext = createAppContext()
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
// 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.
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[]
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)
/* eslint-disable no-restricted-globals */
import {
+ Component,
ComponentInternalInstance,
ComponentOptions,
InternalRenderFunction
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
}
instance.renderCache = []
// this flag forces child components with slot content to update
- instance.hmrUpdated = true
+ isHmrUpdating = true
instance.update()
- instance.hmrUpdated = false
+ isHmrUpdating = false
})
}
// 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) {
}
// 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)
})
}
} 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,
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) {
optimized = true
}
- if (__DEV__ && parentComponent && parentComponent.hmrUpdated) {
+ if (__DEV__ && isHmrUpdating) {
// HMR updated, force full diff
patchFlag = 0
optimized = false
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
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