type ComponentInternalInstance,
type ComponentOptions,
type ConcreteComponent,
- type InternalRenderFunction,
+ type GenericComponentInstance,
isClassComponent,
} from './component'
import { queueJob, queuePostFlushCb } from './scheduler'
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
// 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) {
record.instances.add(instance)
}
-export function unregisterHMR(instance: ComponentInternalInstance): void {
+export function unregisterHMR(instance: GenericComponentInstance): void {
map.get(instance.type.__hmrId!)!.instances.delete(instance)
}
// 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
})
}
// 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()