await timeout()
expect(serializeInner(root)).toBe('<div>bar</div>')
})
+
+ test('rerender for nested component', () => {
+ const id = 'child-nested-rerender'
+ const Foo: ComponentOptions = {
+ __hmrId: id,
+ render() {
+ return this.$slots.default()
+ },
+ }
+ createRecord(id, Foo)
+
+ const parentId = 'parent-nested-rerender'
+ const Parent: ComponentOptions = {
+ __hmrId: parentId,
+ render() {
+ return h(Foo, null, {
+ default: () => this.$slots.default(),
+ _: 3 /* FORWARDED */,
+ })
+ },
+ }
+
+ const appId = 'app-nested-rerender'
+ const App: ComponentOptions = {
+ __hmrId: appId,
+ render: () =>
+ h(Parent, null, {
+ default: () => [
+ h(Foo, null, {
+ default: () => ['foo'],
+ }),
+ ],
+ }),
+ }
+ createRecord(parentId, App)
+
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+ expect(serializeInner(root)).toBe('foo')
+
+ rerender(id, () => 'bar')
+ expect(serializeInner(root)).toBe('bar')
+ })
})
type InternalRenderFunction,
isClassComponent,
} from './component'
-import { queueJob, queuePostFlushCb } from './scheduler'
+import { SchedulerJobFlags, queueJob, queuePostFlushCb } from './scheduler'
import { extend, getGlobalThis } from '@vue/shared'
type HMRComponent = ComponentOptions | ClassComponent
instance.renderCache = []
// this flag forces child components with slot content to update
isHmrUpdating = true
- instance.update()
+ // #13771 don't update if the job is already disposed
+ if (!(instance.job.flags! & SchedulerJobFlags.DISPOSED)) {
+ instance.update()
+ }
isHmrUpdating = false
})
}