import { effect } from './index'
import { ReactiveEffect, activeReactiveEffectStack } from './effect'
+import { knownValues } from './value'
-export interface ComputedGetter<T = any> {
- (): T
- effect: ReactiveEffect
+export interface ComputedValue<T> {
+ readonly value: T
+ readonly effect: ReactiveEffect
}
export function computed<T, C = null>(
getter: (this: C, ctx: C) => T,
context?: C
-): ComputedGetter<T> {
+): ComputedValue<T> {
let dirty: boolean = true
let value: any = undefined
const runner = effect(() => getter.call(context, context), {
dirty = true
}
})
- const computedGetter = (() => {
- if (dirty) {
- value = runner()
- dirty = false
- }
- // When computed effects are accessed in a parent effect, the parent
- // should track all the dependencies the computed property has tracked.
- // This should also apply for chained computed properties.
- trackChildRun(runner)
- return value
- }) as ComputedGetter
- // expose effect so computed can be stopped
- computedGetter.effect = runner
// mark effect as computed so that it gets priority during trigger
runner.computed = true
- return computedGetter
+ const computedValue = {
+ // expose effect so computed can be stopped
+ effect: runner,
+ get value() {
+ if (dirty) {
+ value = runner()
+ dirty = false
+ }
+ // When computed effects are accessed in a parent effect, the parent
+ // should track all the dependencies the computed property has tracked.
+ // This should also apply for chained computed properties.
+ trackChildRun(runner)
+ return value
+ }
+ }
+ knownValues.add(computedValue)
+ return computedValue
}
function trackChildRun(childRunner: ReactiveEffect) {
export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
export { OperationTypes } from './operations'
-export { computed, ComputedGetter } from './computed'
+export { computed, ComputedValue } from './computed'
export { lock, unlock } from './lock'
-export { value, isValue } from './value'
+export { value, isValue, Value } from './value'
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
import { track, trigger } from './effect'
import { OperationTypes } from './operations'
+import { isObject } from '@vue/shared'
+import { observable } from './index'
-const knownValues = new WeakSet()
+export const knownValues = new WeakSet()
export interface Value<T> {
value: T
}
+const convert = (val: any): any => (isObject(val) ? observable(val) : val)
+
export function value<T>(raw: T): Value<T> {
+ raw = convert(raw)
const v = {
get value() {
track(v, OperationTypes.GET, '')
return raw
},
set value(newVal) {
- raw = newVal
+ raw = convert(newVal)
trigger(v, OperationTypes.SET, '')
}
}