wip: state -> reactive, value -> ref
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { state, immutableState, toRaw } from './index'
|
||||
import { reactive, immutable, toRaw } from './reactive'
|
||||
import { OperationTypes } from './operations'
|
||||
import { track, trigger } from './effect'
|
||||
import { LOCKED } from './lock'
|
||||
import { isObject } from '@vue/shared'
|
||||
import { isValue } from './value'
|
||||
import { isRef } from './ref'
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
|
||||
@@ -19,16 +19,16 @@ function createGetter(isImmutable: boolean) {
|
||||
if (typeof key === 'symbol' && builtInSymbols.has(key)) {
|
||||
return res
|
||||
}
|
||||
if (isValue(res)) {
|
||||
if (isRef(res)) {
|
||||
return res.value
|
||||
}
|
||||
track(target, OperationTypes.GET, key)
|
||||
return isObject(res)
|
||||
? isImmutable
|
||||
? // need to lazy access immutable and observable here to avoid
|
||||
? // need to lazy access immutable and reactive here to avoid
|
||||
// circular dependency
|
||||
immutableState(res)
|
||||
: state(res)
|
||||
immutable(res)
|
||||
: reactive(res)
|
||||
: res
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ function set(
|
||||
value = toRaw(value)
|
||||
const hadKey = hasOwnProperty.call(target, key)
|
||||
const oldValue = target[key]
|
||||
if (isValue(oldValue) && !isValue(value)) {
|
||||
if (isRef(oldValue) && !isRef(value)) {
|
||||
oldValue.value = value
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { toRaw, state, immutableState } from './index'
|
||||
import { toRaw, reactive, immutable } from './reactive'
|
||||
import { track, trigger } from './effect'
|
||||
import { OperationTypes } from './operations'
|
||||
import { LOCKED } from './lock'
|
||||
import { isObject } from '@vue/shared'
|
||||
|
||||
const toObservable = (value: any) => (isObject(value) ? state(value) : value)
|
||||
const toImmutable = (value: any) =>
|
||||
isObject(value) ? immutableState(value) : value
|
||||
const toReactive = (value: any) => (isObject(value) ? reactive(value) : value)
|
||||
const toImmutable = (value: any) => (isObject(value) ? immutable(value) : value)
|
||||
|
||||
function get(target: any, key: any, wrap: (t: any) => any): any {
|
||||
target = toRaw(target)
|
||||
@@ -117,7 +116,7 @@ function createForEach(isImmutable: boolean) {
|
||||
const observed = this
|
||||
const target = toRaw(observed)
|
||||
const proto: any = Reflect.getPrototypeOf(target)
|
||||
const wrap = isImmutable ? toImmutable : toObservable
|
||||
const wrap = isImmutable ? toImmutable : toReactive
|
||||
track(target, OperationTypes.ITERATE)
|
||||
// important: create sure the callback is
|
||||
// 1. invoked with the observable map as `this` and 3rd arg
|
||||
@@ -137,7 +136,7 @@ function createIterableMethod(method: string | symbol, isImmutable: boolean) {
|
||||
method === 'entries' ||
|
||||
(method === Symbol.iterator && target instanceof Map)
|
||||
const innerIterator = proto[method].apply(target, args)
|
||||
const wrap = isImmutable ? toImmutable : toObservable
|
||||
const wrap = isImmutable ? toImmutable : toReactive
|
||||
track(target, OperationTypes.ITERATE)
|
||||
// return a wrapped iterator which returns observed versions of the
|
||||
// values emitted from the real iterator
|
||||
@@ -182,7 +181,7 @@ function createImmutableMethod(
|
||||
|
||||
const mutableInstrumentations: any = {
|
||||
get(key: any) {
|
||||
return get(this, key, toObservable)
|
||||
return get(this, key, toReactive)
|
||||
},
|
||||
get size() {
|
||||
return size(this)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { effect } from './index'
|
||||
import { ReactiveEffect, activeReactiveEffectStack } from './effect'
|
||||
import { knownValues } from './value'
|
||||
import { effect, ReactiveEffect, activeReactiveEffectStack } from './effect'
|
||||
import { knownValues } from './ref'
|
||||
|
||||
export interface ComputedValue<T> {
|
||||
export interface ComputedRef<T> {
|
||||
readonly value: T
|
||||
readonly effect: ReactiveEffect
|
||||
}
|
||||
@@ -10,7 +9,7 @@ export interface ComputedValue<T> {
|
||||
export function computed<T>(
|
||||
getter: () => T,
|
||||
setter?: (v: T) => void
|
||||
): ComputedValue<T> {
|
||||
): ComputedRef<T> {
|
||||
let dirty: boolean = true
|
||||
let value: any = undefined
|
||||
const runner = effect(getter, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OperationTypes } from './operations'
|
||||
import { Dep, targetMap } from './state'
|
||||
import { Dep, targetMap } from './reactive'
|
||||
import { EMPTY_OBJ } from '@vue/shared'
|
||||
|
||||
export interface ReactiveEffect {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
export { value, isValue, Value, UnwrapValue } from './value'
|
||||
export { ref, isRef, Ref, UnwrapRef } from './ref'
|
||||
export {
|
||||
state,
|
||||
isState,
|
||||
immutableState,
|
||||
isImmutableState,
|
||||
reactive,
|
||||
isReactive,
|
||||
immutable,
|
||||
isImmutable,
|
||||
toRaw,
|
||||
markImmutable,
|
||||
markNonReactive
|
||||
} from './state'
|
||||
export { computed, ComputedValue } from './computed'
|
||||
} from './reactive'
|
||||
export { computed, ComputedRef } from './computed'
|
||||
export {
|
||||
effect,
|
||||
stop,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
immutableCollectionHandlers
|
||||
} from './collectionHandlers'
|
||||
|
||||
import { UnwrapValue } from './value'
|
||||
import { UnwrapRef } from './ref'
|
||||
import { ReactiveEffect } from './effect'
|
||||
|
||||
// The main WeakMap that stores {target -> key -> dep} connections.
|
||||
@@ -40,16 +40,16 @@ const canObserve = (value: any): boolean => {
|
||||
)
|
||||
}
|
||||
|
||||
type ObservableFactory = <T>(target?: T) => UnwrapValue<T>
|
||||
type ObservableFactory = <T>(target?: T) => UnwrapRef<T>
|
||||
|
||||
export const state = ((target: any = {}): any => {
|
||||
export const reactive = ((target: any = {}): any => {
|
||||
// if trying to observe an immutable proxy, return the immutable version.
|
||||
if (immutableToRaw.has(target)) {
|
||||
return target
|
||||
}
|
||||
// target is explicitly marked as immutable by user
|
||||
if (immutableValues.has(target)) {
|
||||
return immutableState(target)
|
||||
return immutable(target)
|
||||
}
|
||||
return createObservable(
|
||||
target,
|
||||
@@ -60,7 +60,7 @@ export const state = ((target: any = {}): any => {
|
||||
)
|
||||
}) as ObservableFactory
|
||||
|
||||
export const immutableState = ((target: any = {}): any => {
|
||||
export const immutable = ((target: any = {}): any => {
|
||||
// value is a mutable observable, retrive its original and return
|
||||
// a readonly version.
|
||||
if (observedToRaw.has(target)) {
|
||||
@@ -113,11 +113,11 @@ function createObservable(
|
||||
return observed
|
||||
}
|
||||
|
||||
export function isState(value: any): boolean {
|
||||
export function isReactive(value: any): boolean {
|
||||
return observedToRaw.has(value) || immutableToRaw.has(value)
|
||||
}
|
||||
|
||||
export function isImmutableState(value: any): boolean {
|
||||
export function isImmutable(value: any): boolean {
|
||||
return immutableToRaw.has(value)
|
||||
}
|
||||
|
||||
118
packages/reactivity/src/ref.ts
Normal file
118
packages/reactivity/src/ref.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { track, trigger } from './effect'
|
||||
import { OperationTypes } from './operations'
|
||||
import { isObject } from '@vue/shared'
|
||||
import { reactive } from './reactive'
|
||||
|
||||
export const knownValues = new WeakSet()
|
||||
|
||||
export interface Ref<T> {
|
||||
value: T
|
||||
}
|
||||
|
||||
const convert = (val: any): any => (isObject(val) ? reactive(val) : val)
|
||||
|
||||
export function ref<T>(raw: T): Ref<T> {
|
||||
raw = convert(raw)
|
||||
const v = {
|
||||
get value() {
|
||||
track(v, OperationTypes.GET, '')
|
||||
return raw
|
||||
},
|
||||
set value(newVal) {
|
||||
raw = convert(newVal)
|
||||
trigger(v, OperationTypes.SET, '')
|
||||
}
|
||||
}
|
||||
knownValues.add(v)
|
||||
return v
|
||||
}
|
||||
|
||||
export function isRef(v: any): v is Ref<any> {
|
||||
return knownValues.has(v)
|
||||
}
|
||||
|
||||
type BailTypes =
|
||||
| Function
|
||||
| Map<any, any>
|
||||
| Set<any>
|
||||
| WeakMap<any, any>
|
||||
| WeakSet<any>
|
||||
|
||||
// Recursively unwraps nested value bindings.
|
||||
// Unfortunately TS cannot do recursive types, but this should be enough for
|
||||
// practical use cases...
|
||||
export type UnwrapRef<T> = T extends Ref<infer V>
|
||||
? UnwrapRef2<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef2<V>>
|
||||
: T extends BailTypes
|
||||
? T // bail out on types that shouldn't be unwrapped
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef2<T[K]> } : T
|
||||
|
||||
type UnwrapRef2<T> = T extends Ref<infer V>
|
||||
? UnwrapRef3<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef3<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef3<T[K]> } : T
|
||||
|
||||
type UnwrapRef3<T> = T extends Ref<infer V>
|
||||
? UnwrapRef4<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef4<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef4<T[K]> } : T
|
||||
|
||||
type UnwrapRef4<T> = T extends Ref<infer V>
|
||||
? UnwrapRef5<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef5<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef5<T[K]> } : T
|
||||
|
||||
type UnwrapRef5<T> = T extends Ref<infer V>
|
||||
? UnwrapRef6<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef6<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef6<T[K]> } : T
|
||||
|
||||
type UnwrapRef6<T> = T extends Ref<infer V>
|
||||
? UnwrapRef7<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef7<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef7<T[K]> } : T
|
||||
|
||||
type UnwrapRef7<T> = T extends Ref<infer V>
|
||||
? UnwrapRef8<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef8<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef8<T[K]> } : T
|
||||
|
||||
type UnwrapRef8<T> = T extends Ref<infer V>
|
||||
? UnwrapRef9<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef9<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef9<T[K]> } : T
|
||||
|
||||
type UnwrapRef9<T> = T extends Ref<infer V>
|
||||
? UnwrapRef10<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapRef10<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapRef10<T[K]> } : T
|
||||
|
||||
type UnwrapRef10<T> = T extends Ref<infer V>
|
||||
? V // stop recursion
|
||||
: T
|
||||
@@ -1,118 +0,0 @@
|
||||
import { track, trigger } from './effect'
|
||||
import { OperationTypes } from './operations'
|
||||
import { isObject } from '@vue/shared'
|
||||
import { state } from './index'
|
||||
|
||||
export const knownValues = new WeakSet()
|
||||
|
||||
export interface Value<T> {
|
||||
value: T
|
||||
}
|
||||
|
||||
const convert = (val: any): any => (isObject(val) ? state(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 = convert(newVal)
|
||||
trigger(v, OperationTypes.SET, '')
|
||||
}
|
||||
}
|
||||
knownValues.add(v)
|
||||
return v
|
||||
}
|
||||
|
||||
export function isValue(v: any): v is Value<any> {
|
||||
return knownValues.has(v)
|
||||
}
|
||||
|
||||
type BailTypes =
|
||||
| Function
|
||||
| Map<any, any>
|
||||
| Set<any>
|
||||
| WeakMap<any, any>
|
||||
| WeakSet<any>
|
||||
|
||||
// Recursively unwraps nested value bindings.
|
||||
// Unfortunately TS cannot do recursive types, but this should be enough for
|
||||
// practical use cases...
|
||||
export type UnwrapValue<T> = T extends Value<infer V>
|
||||
? UnwrapValue2<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue2<V>>
|
||||
: T extends BailTypes
|
||||
? T // bail out on types that shouldn't be unwrapped
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue2<T[K]> } : T
|
||||
|
||||
type UnwrapValue2<T> = T extends Value<infer V>
|
||||
? UnwrapValue3<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue3<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue3<T[K]> } : T
|
||||
|
||||
type UnwrapValue3<T> = T extends Value<infer V>
|
||||
? UnwrapValue4<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue4<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue4<T[K]> } : T
|
||||
|
||||
type UnwrapValue4<T> = T extends Value<infer V>
|
||||
? UnwrapValue5<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue5<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue5<T[K]> } : T
|
||||
|
||||
type UnwrapValue5<T> = T extends Value<infer V>
|
||||
? UnwrapValue6<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue6<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue6<T[K]> } : T
|
||||
|
||||
type UnwrapValue6<T> = T extends Value<infer V>
|
||||
? UnwrapValue7<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue7<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue7<T[K]> } : T
|
||||
|
||||
type UnwrapValue7<T> = T extends Value<infer V>
|
||||
? UnwrapValue8<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue8<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue8<T[K]> } : T
|
||||
|
||||
type UnwrapValue8<T> = T extends Value<infer V>
|
||||
? UnwrapValue9<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue9<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue9<T[K]> } : T
|
||||
|
||||
type UnwrapValue9<T> = T extends Value<infer V>
|
||||
? UnwrapValue10<V>
|
||||
: T extends Array<infer V>
|
||||
? Array<UnwrapValue10<V>>
|
||||
: T extends BailTypes
|
||||
? T
|
||||
: T extends object ? { [K in keyof T]: UnwrapValue10<T[K]> } : T
|
||||
|
||||
type UnwrapValue10<T> = T extends Value<infer V>
|
||||
? V // stop recursion
|
||||
: T
|
||||
Reference in New Issue
Block a user