c3.value
expect(c1.effect._dirtyLevel).toBe(DirtyLevels.Dirty)
- expect(c2.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty)
- expect(c3.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty)
+ expect(c2.effect._dirtyLevel).toBe(
+ DirtyLevels.MaybeDirty_ComputedSideEffect,
+ )
+ expect(c3.effect._dirtyLevel).toBe(
+ DirtyLevels.MaybeDirty_ComputedSideEffect,
+ )
})
it('should work when chained(ref+computed)', () => {
c3.value
expect(c1.effect._dirtyLevel).toBe(DirtyLevels.Dirty)
- expect(c2.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty)
- expect(c3.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty)
+ expect(c2.effect._dirtyLevel).toBe(
+ DirtyLevels.MaybeDirty_ComputedSideEffect,
+ )
+ expect(c3.effect._dirtyLevel).toBe(
+ DirtyLevels.MaybeDirty_ComputedSideEffect,
+ )
v1.value.v.value = 999
expect(c1.effect._dirtyLevel).toBe(DirtyLevels.Dirty)
await nextTick()
expect(serializeInner(root)).toBe(`2`)
})
+
+ it('should not trigger effect scheduler by recurse computed effect', async () => {
+ const v = ref('Hello')
+ const c = computed(() => {
+ v.value += ' World'
+ return v.value
+ })
+ const Comp = {
+ setup: () => {
+ return () => c.value
+ },
+ }
+ const root = nodeOps.createElement('div')
+
+ render(h(Comp), root)
+ await nextTick()
+ expect(serializeInner(root)).toBe('Hello World')
+
+ v.value += ' World'
+ await nextTick()
+ expect(serializeInner(root)).toBe('Hello World World World World')
+ })
})
) {
this.effect = new ReactiveEffect(
() => getter(this._value),
- () => triggerRefValue(this, DirtyLevels.MaybeDirty),
+ () =>
+ triggerRefValue(
+ this,
+ this.effect._dirtyLevel === DirtyLevels.MaybeDirty_ComputedSideEffect
+ ? DirtyLevels.MaybeDirty_ComputedSideEffect
+ : DirtyLevels.MaybeDirty,
+ ),
)
this.effect.computed = this
this.effect.active = this._cacheable = !isSSR
triggerRefValue(self, DirtyLevels.Dirty)
}
trackRefValue(self)
- if (self.effect._dirtyLevel >= DirtyLevels.MaybeDirty) {
- triggerRefValue(self, DirtyLevels.MaybeDirty)
+ if (self.effect._dirtyLevel >= DirtyLevels.MaybeDirty_ComputedSideEffect) {
+ triggerRefValue(self, DirtyLevels.MaybeDirty_ComputedSideEffect)
}
return self._value
}
export enum DirtyLevels {
NotDirty = 0,
QueryingDirty = 1,
- MaybeDirty = 2,
- Dirty = 3,
+ MaybeDirty_ComputedSideEffect = 2,
+ MaybeDirty = 3,
+ Dirty = 4,
}
}
public get dirty() {
- if (this._dirtyLevel === DirtyLevels.MaybeDirty) {
+ if (
+ this._dirtyLevel === DirtyLevels.MaybeDirty_ComputedSideEffect ||
+ this._dirtyLevel === DirtyLevels.MaybeDirty
+ ) {
this._dirtyLevel = DirtyLevels.QueryingDirty
pauseTracking()
for (let i = 0; i < this._depsLength; i++) {
effect.onTrigger?.(extend({ effect }, debuggerEventExtraInfo))
}
effect.trigger()
- if (!effect._runnings || effect.allowRecurse) {
+ if (
+ (!effect._runnings || effect.allowRecurse) &&
+ effect._dirtyLevel !== DirtyLevels.MaybeDirty_ComputedSideEffect
+ ) {
effect._shouldSchedule = false
if (effect.scheduler) {
queueEffectSchedulers.push(effect.scheduler)
ref = toRaw(ref)
trackEffect(
activeEffect,
- ref.dep ||
- (ref.dep = createDep(
- () => (ref.dep = undefined),
- ref instanceof ComputedRefImpl ? ref : undefined,
- )),
+ (ref.dep ??= createDep(
+ () => (ref.dep = undefined),
+ ref instanceof ComputedRefImpl ? ref : undefined,
+ )),
__DEV__
? {
target: ref,