diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts
index 31c910d1..ab2de223 100644
--- a/packages/runtime-core/__tests__/hmr.spec.ts
+++ b/packages/runtime-core/__tests__/hmr.spec.ts
@@ -33,9 +33,9 @@ describe('hot module replacement', () => {
})
test('createRecord', () => {
- expect(createRecord('test1')).toBe(true)
+ expect(createRecord('test1', {})).toBe(true)
// if id has already been created, should return false
- expect(createRecord('test1')).toBe(false)
+ expect(createRecord('test1', {})).toBe(false)
})
test('rerender', async () => {
@@ -47,7 +47,7 @@ describe('hot module replacement', () => {
__hmrId: childId,
render: compileToFunction(`
`)
}
- createRecord(childId)
+ createRecord(childId, Child)
const Parent: ComponentOptions = {
__hmrId: parentId,
@@ -59,7 +59,7 @@ describe('hot module replacement', () => {
`{{ count }}{{ count }}
`
)
}
- createRecord(parentId)
+ createRecord(parentId, Parent)
render(h(Parent), root)
expect(serializeInner(root)).toBe(``)
@@ -125,7 +125,7 @@ describe('hot module replacement', () => {
unmounted: unmountSpy,
render: compileToFunction(`{{ count }}
`)
}
- createRecord(childId)
+ createRecord(childId, Child)
const Parent: ComponentOptions = {
render: () => h(Child)
@@ -164,7 +164,7 @@ describe('hot module replacement', () => {
render: compileToFunction(`{{ count }}
`)
}
}
- createRecord(childId)
+ createRecord(childId, Child)
const Parent: ComponentOptions = {
render: () => h(Child)
@@ -209,7 +209,7 @@ describe('hot module replacement', () => {
},
render: compileToFunction(template)
}
- createRecord(id)
+ createRecord(id, Comp)
render(h(Comp), root)
expect(serializeInner(root)).toBe(
@@ -246,14 +246,14 @@ describe('hot module replacement', () => {
},
render: compileToFunction(`{{ msg }}
`)
}
- createRecord(childId)
+ createRecord(childId, Child)
const Parent: ComponentOptions = {
__hmrId: parentId,
components: { Child },
render: compileToFunction(``)
}
- createRecord(parentId)
+ createRecord(parentId, Parent)
render(h(Parent), root)
expect(serializeInner(root)).toBe(`foo
`)
@@ -272,14 +272,14 @@ describe('hot module replacement', () => {
__hmrId: childId,
render: compileToFunction(`child
`)
}
- createRecord(childId)
+ createRecord(childId, Child)
const Parent: ComponentOptions = {
__hmrId: parentId,
components: { Child },
render: compileToFunction(``)
}
- createRecord(parentId)
+ createRecord(parentId, Parent)
render(h(Parent), root)
expect(serializeInner(root)).toBe(`child
`)
@@ -299,7 +299,7 @@ describe('hot module replacement', () => {
__hmrId: childId,
render: compileToFunction(`child
`)
}
- createRecord(childId)
+ createRecord(childId, Child)
const components: ComponentOptions[] = []
@@ -321,7 +321,7 @@ describe('hot module replacement', () => {
}
}
- createRecord(parentId)
+ createRecord(parentId, parentComp)
}
const last = components[components.length - 1]
diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts
index faf4cb24..9a2d20de 100644
--- a/packages/runtime-core/src/hmr.ts
+++ b/packages/runtime-core/src/hmr.ts
@@ -42,7 +42,10 @@ if (__DEV__ && (__BROWSER__ || __TEST__)) {
} as HMRRuntime
}
-type HMRRecord = Set
+type HMRRecord = {
+ component: ComponentOptions
+ instances: Set
+}
const map: Map = new Map()
@@ -50,30 +53,37 @@ export function registerHMR(instance: ComponentInternalInstance) {
const id = instance.type.__hmrId!
let record = map.get(id)
if (!record) {
- createRecord(id)
+ createRecord(id, instance.type as ComponentOptions)
record = map.get(id)!
}
- record.add(instance)
+ record.instances.add(instance)
}
export function unregisterHMR(instance: ComponentInternalInstance) {
- map.get(instance.type.__hmrId!)!.delete(instance)
+ map.get(instance.type.__hmrId!)!.instances.delete(instance)
}
-function createRecord(id: string): boolean {
+function createRecord(
+ id: string,
+ component: ComponentOptions | ClassComponent
+): boolean {
if (map.has(id)) {
return false
}
- map.set(id, new Set())
+ map.set(id, {
+ component: isClassComponent(component) ? component.__vccOpts : component,
+ instances: new Set()
+ })
return true
}
function rerender(id: string, newRender?: Function) {
const record = map.get(id)
if (!record) return
+ if (newRender) record.component.render = newRender
// Array.from creates a snapshot which avoids the set being mutated during
// updates
- Array.from(record).forEach(instance => {
+ Array.from(record.instances).forEach(instance => {
if (newRender) {
instance.render = newRender as InternalRenderFunction
}
@@ -90,26 +100,27 @@ function reload(id: string, newComp: ComponentOptions | ClassComponent) {
if (!record) return
// Array.from creates a snapshot which avoids the set being mutated during
// updates
- Array.from(record).forEach(instance => {
- const comp = instance.type
- if (!hmrDirtyComponents.has(comp)) {
- // 1. Update existing comp definition to match new one
- newComp = isClassComponent(newComp) ? newComp.__vccOpts : newComp
- extend(comp, newComp)
- for (const key in comp) {
- if (!(key in newComp)) {
- delete (comp as any)[key]
- }
- }
- // 2. Mark component dirty. This forces the renderer to replace the component
- // on patch.
- hmrDirtyComponents.add(comp)
- // 3. Make sure to unmark the component after the reload.
- queuePostFlushCb(() => {
- hmrDirtyComponents.delete(comp)
- })
- }
+ const { component, instances } = record
+ if (!hmrDirtyComponents.has(component)) {
+ // 1. Update existing comp definition to match new one
+ newComp = isClassComponent(newComp) ? newComp.__vccOpts : newComp
+ extend(component, newComp)
+ for (const key in component) {
+ if (!(key in newComp)) {
+ delete (component as any)[key]
+ }
+ }
+ // 2. Mark component dirty. This forces the renderer to replace the component
+ // on patch.
+ hmrDirtyComponents.add(component)
+ // 3. Make sure to unmark the component after the reload.
+ queuePostFlushCb(() => {
+ hmrDirtyComponents.delete(component)
+ })
+ }
+
+ Array.from(instances).forEach(instance => {
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