toRaw,
} from '../src'
import { DirtyLevels } from '../src/constants'
+import { COMPUTED_SIDE_EFFECT_WARN } from '../src/computed'
describe('reactivity/computed', () => {
it('should return updated value', () => {
expect(c3.effect._dirtyLevel).toBe(
DirtyLevels.MaybeDirty_ComputedSideEffect,
)
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
it('should work when chained(ref+computed)', () => {
expect(c2.value).toBe('0foo')
expect(c2.effect._dirtyLevel).toBe(DirtyLevels.Dirty)
expect(c2.value).toBe('1foo')
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
it('should trigger effect even computed already dirty', () => {
expect(c2.effect._dirtyLevel).toBe(DirtyLevels.Dirty)
v.value = 2
expect(fnSpy).toBeCalledTimes(2)
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
// #10185
expect(c3.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty)
expect(c3.value).toBe('yes')
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
it('should be not dirty after deps mutate (mutate deps in computed)', async () => {
await nextTick()
await nextTick()
expect(serializeInner(root)).toBe(`2`)
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
it('should not trigger effect scheduler by recurse computed effect', async () => {
v.value += ' World'
await nextTick()
expect(serializeInner(root)).toBe('Hello World World World World')
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
})
import { toRaw } from './reactive'
import type { Dep } from './dep'
import { DirtyLevels, ReactiveFlags } from './constants'
+import { warn } from './warning'
declare const ComputedRefSymbol: unique symbol
set: ComputedSetter<T>
}
+export const COMPUTED_SIDE_EFFECT_WARN =
+ `Computed is still dirty after getter evaluation,` +
+ ` likely because a computed is mutating its own dependency in its getter.` +
+ ` State mutations in computed getters should be avoided. ` +
+ ` Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`
+
export class ComputedRefImpl<T> {
public dep?: Dep = undefined
}
trackRefValue(self)
if (self.effect._dirtyLevel >= DirtyLevels.MaybeDirty_ComputedSideEffect) {
+ __DEV__ && warn(COMPUTED_SIDE_EFFECT_WARN)
triggerRefValue(self, DirtyLevels.MaybeDirty_ComputedSideEffect)
}
return self._value
getter = getterOrOptions
setter = __DEV__
? () => {
- console.warn('Write operation failed: computed value is readonly')
+ warn('Write operation failed: computed value is readonly')
}
: NOOP
} else {