fix(runtime-core): ensure watchers are always registered to correct instance owner (#2495)
close: #2381
This commit is contained in:
parent
ce4915d8be
commit
735af1c7b7
@ -5,16 +5,26 @@ import {
|
|||||||
computed,
|
computed,
|
||||||
nextTick,
|
nextTick,
|
||||||
ref,
|
ref,
|
||||||
h
|
defineComponent,
|
||||||
|
getCurrentInstance,
|
||||||
|
ComponentInternalInstance,
|
||||||
|
ComponentPublicInstance
|
||||||
} from '../src/index'
|
} from '../src/index'
|
||||||
import { render, nodeOps, serializeInner, TestElement } from '@vue/runtime-test'
|
import {
|
||||||
|
render,
|
||||||
|
nodeOps,
|
||||||
|
serializeInner,
|
||||||
|
TestElement,
|
||||||
|
h
|
||||||
|
} from '@vue/runtime-test'
|
||||||
import {
|
import {
|
||||||
ITERATE_KEY,
|
ITERATE_KEY,
|
||||||
DebuggerEvent,
|
DebuggerEvent,
|
||||||
TrackOpTypes,
|
TrackOpTypes,
|
||||||
TriggerOpTypes,
|
TriggerOpTypes,
|
||||||
triggerRef,
|
triggerRef,
|
||||||
shallowRef
|
shallowRef,
|
||||||
|
Ref
|
||||||
} from '@vue/reactivity'
|
} from '@vue/reactivity'
|
||||||
|
|
||||||
// reference: https://vue-composition-api-rfc.netlify.com/api.html#watch
|
// reference: https://vue-composition-api-rfc.netlify.com/api.html#watch
|
||||||
@ -799,4 +809,52 @@ describe('api: watch', () => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
expect(spy).toHaveBeenCalledTimes(1)
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// https://github.com/vuejs/vue-next/issues/2381
|
||||||
|
test('$watch should always register its effects with itw own instance', async () => {
|
||||||
|
let instance: ComponentInternalInstance | null
|
||||||
|
let _show: Ref<boolean>
|
||||||
|
|
||||||
|
const Child = defineComponent({
|
||||||
|
render: () => h('div'),
|
||||||
|
mounted() {
|
||||||
|
instance = getCurrentInstance()
|
||||||
|
},
|
||||||
|
unmounted() {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const Comp = defineComponent({
|
||||||
|
setup() {
|
||||||
|
const comp = ref<ComponentPublicInstance | undefined>()
|
||||||
|
const show = ref(true)
|
||||||
|
_show = show
|
||||||
|
return { comp, show }
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return this.show
|
||||||
|
? h(Child, {
|
||||||
|
ref: vm => void (this.comp = vm as ComponentPublicInstance)
|
||||||
|
})
|
||||||
|
: null
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// this call runs while Comp is currentInstance, but
|
||||||
|
// the effect for this `$watch` should nontheless be registered with Child
|
||||||
|
this.comp!.$watch(() => this.show, () => void 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
render(h(Comp), nodeOps.createElement('div'))
|
||||||
|
|
||||||
|
expect(instance!).toBeDefined()
|
||||||
|
expect(instance!.effects).toBeInstanceOf(Array)
|
||||||
|
expect(instance!.effects!.length).toBe(1)
|
||||||
|
|
||||||
|
_show!.value = false
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
expect(instance!.effects![0].active).toBe(false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -285,7 +285,7 @@ function doWatch(
|
|||||||
scheduler
|
scheduler
|
||||||
})
|
})
|
||||||
|
|
||||||
recordInstanceBoundEffect(runner)
|
recordInstanceBoundEffect(runner, instance)
|
||||||
|
|
||||||
// initial run
|
// initial run
|
||||||
if (cb) {
|
if (cb) {
|
||||||
|
@ -786,9 +786,12 @@ export function createSetupContext(
|
|||||||
|
|
||||||
// record effects created during a component's setup() so that they can be
|
// record effects created during a component's setup() so that they can be
|
||||||
// stopped when the component unmounts
|
// stopped when the component unmounts
|
||||||
export function recordInstanceBoundEffect(effect: ReactiveEffect) {
|
export function recordInstanceBoundEffect(
|
||||||
if (currentInstance) {
|
effect: ReactiveEffect,
|
||||||
;(currentInstance.effects || (currentInstance.effects = [])).push(effect)
|
instance = currentInstance
|
||||||
|
) {
|
||||||
|
if (instance) {
|
||||||
|
;(instance.effects || (instance.effects = [])).push(effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user