fix(hmr): force full update in child component on slot update
This commit is contained in:
		
							parent
							
								
									5ddd9d2417
								
							
						
					
					
						commit
						2408a65662
					
				| @ -45,7 +45,7 @@ describe('hot module replacement', () => { | |||||||
| 
 | 
 | ||||||
|     const Child: ComponentOptions = { |     const Child: ComponentOptions = { | ||||||
|       __hmrId: childId, |       __hmrId: childId, | ||||||
|       render: compileToFunction(`<slot/>`) |       render: compileToFunction(`<div><slot/></div>`) | ||||||
|     } |     } | ||||||
|     createRecord(childId, Child) |     createRecord(childId, Child) | ||||||
| 
 | 
 | ||||||
| @ -62,13 +62,13 @@ describe('hot module replacement', () => { | |||||||
|     createRecord(parentId, Parent) |     createRecord(parentId, Parent) | ||||||
| 
 | 
 | ||||||
|     render(h(Parent), root) |     render(h(Parent), root) | ||||||
|     expect(serializeInner(root)).toBe(`<div>00</div>`) |     expect(serializeInner(root)).toBe(`<div>0<div>0</div></div>`) | ||||||
| 
 | 
 | ||||||
|     // Perform some state change. This change should be preserved after the
 |     // Perform some state change. This change should be preserved after the
 | ||||||
|     // re-render!
 |     // re-render!
 | ||||||
|     triggerEvent(root.children[0] as TestElement, 'click') |     triggerEvent(root.children[0] as TestElement, 'click') | ||||||
|     await nextTick() |     await nextTick() | ||||||
|     expect(serializeInner(root)).toBe(`<div>11</div>`) |     expect(serializeInner(root)).toBe(`<div>1<div>1</div></div>`) | ||||||
| 
 | 
 | ||||||
|     // // Update text while preserving state
 |     // // Update text while preserving state
 | ||||||
|     rerender( |     rerender( | ||||||
| @ -77,7 +77,7 @@ describe('hot module replacement', () => { | |||||||
|         `<div @click="count++">{{ count }}!<Child>{{ count }}</Child></div>` |         `<div @click="count++">{{ count }}!<Child>{{ count }}</Child></div>` | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|     expect(serializeInner(root)).toBe(`<div>1!1</div>`) |     expect(serializeInner(root)).toBe(`<div>1!<div>1</div></div>`) | ||||||
| 
 | 
 | ||||||
|     // Should force child update on slot content change
 |     // Should force child update on slot content change
 | ||||||
|     rerender( |     rerender( | ||||||
| @ -86,7 +86,7 @@ describe('hot module replacement', () => { | |||||||
|         `<div @click="count++">{{ count }}!<Child>{{ count }}!</Child></div>` |         `<div @click="count++">{{ count }}!<Child>{{ count }}!</Child></div>` | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|     expect(serializeInner(root)).toBe(`<div>1!1!</div>`) |     expect(serializeInner(root)).toBe(`<div>1!<div>1!</div></div>`) | ||||||
| 
 | 
 | ||||||
|     // Should force update element children despite block optimization
 |     // Should force update element children despite block optimization
 | ||||||
|     rerender( |     rerender( | ||||||
| @ -97,7 +97,7 @@ describe('hot module replacement', () => { | |||||||
|       </div>` |       </div>` | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|     expect(serializeInner(root)).toBe(`<div>1<span>1</span>1!</div>`) |     expect(serializeInner(root)).toBe(`<div>1<span>1</span><div>1!</div></div>`) | ||||||
| 
 | 
 | ||||||
|     // Should force update child slot elements
 |     // Should force update child slot elements
 | ||||||
|     rerender( |     rerender( | ||||||
| @ -108,7 +108,7 @@ describe('hot module replacement', () => { | |||||||
|       </div>` |       </div>` | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|     expect(serializeInner(root)).toBe(`<div><span>1</span></div>`) |     expect(serializeInner(root)).toBe(`<div><div><span>1</span></div></div>`) | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
|   test('reload', async () => { |   test('reload', async () => { | ||||||
|  | |||||||
| @ -313,7 +313,7 @@ export interface ComponentInternalInstance { | |||||||
|    * hmr marker (dev only) |    * hmr marker (dev only) | ||||||
|    * @internal |    * @internal | ||||||
|    */ |    */ | ||||||
|   renderUpdated?: boolean |   hmrUpdated?: boolean | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const emptyAppContext = createAppContext() | const emptyAppContext = createAppContext() | ||||||
|  | |||||||
| @ -251,7 +251,7 @@ export function shouldUpdateComponent( | |||||||
|     __DEV__ && |     __DEV__ && | ||||||
|     (prevChildren || nextChildren) && |     (prevChildren || nextChildren) && | ||||||
|     parentComponent && |     parentComponent && | ||||||
|     parentComponent.renderUpdated |     parentComponent.hmrUpdated | ||||||
|   ) { |   ) { | ||||||
|     return true |     return true | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import { | |||||||
| import { warn } from './warning' | import { warn } from './warning' | ||||||
| import { isKeepAlive } from './components/KeepAlive' | import { isKeepAlive } from './components/KeepAlive' | ||||||
| import { withCtx } from './helpers/withRenderContext' | import { withCtx } from './helpers/withRenderContext' | ||||||
|  | import { queuePostFlushCb } from './scheduler' | ||||||
| 
 | 
 | ||||||
| export type Slot = (...args: any[]) => VNode[] | export type Slot = (...args: any[]) => VNode[] | ||||||
| 
 | 
 | ||||||
| @ -124,11 +125,17 @@ export const updateSlots = ( | |||||||
|   if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { |   if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) { | ||||||
|     if ((children as RawSlots)._ === 1) { |     if ((children as RawSlots)._ === 1) { | ||||||
|       // compiled slots.
 |       // compiled slots.
 | ||||||
|       if ( |       if (__DEV__ && instance.parent && instance.parent.hmrUpdated) { | ||||||
|  |         // 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)
 |         // bail on dynamic slots (v-if, v-for, reference of scope variables)
 | ||||||
|         !(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS) && |         !(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS) | ||||||
|         // bail on HRM updates
 |  | ||||||
|         !(__DEV__ && instance.parent && instance.parent.renderUpdated) |  | ||||||
|       ) { |       ) { | ||||||
|         // compiled AND static.
 |         // compiled AND static.
 | ||||||
|         // no need to update, and skip stale slots removal.
 |         // no need to update, and skip stale slots removal.
 | ||||||
|  | |||||||
| @ -70,9 +70,9 @@ function rerender(id: string, newRender?: Function) { | |||||||
|     } |     } | ||||||
|     instance.renderCache = [] |     instance.renderCache = [] | ||||||
|     // this flag forces child components with slot content to update
 |     // this flag forces child components with slot content to update
 | ||||||
|     instance.renderUpdated = true |     instance.hmrUpdated = true | ||||||
|     instance.update() |     instance.update() | ||||||
|     instance.renderUpdated = false |     instance.hmrUpdated = false | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -779,7 +779,7 @@ function baseCreateRenderer( | |||||||
|       invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate') |       invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate') | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (__DEV__ && parentComponent && parentComponent.renderUpdated) { |     if (__DEV__ && parentComponent && parentComponent.hmrUpdated) { | ||||||
|       // HMR updated, force full diff
 |       // HMR updated, force full diff
 | ||||||
|       patchFlag = 0 |       patchFlag = 0 | ||||||
|       optimized = false |       optimized = false | ||||||
| @ -1006,7 +1006,7 @@ function baseCreateRenderer( | |||||||
|       optimized = true |       optimized = true | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (__DEV__ && parentComponent && parentComponent.renderUpdated) { |     if (__DEV__ && parentComponent && parentComponent.hmrUpdated) { | ||||||
|       // HMR updated, force full diff
 |       // HMR updated, force full diff
 | ||||||
|       patchFlag = 0 |       patchFlag = 0 | ||||||
|       optimized = false |       optimized = false | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user