]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: value()
authorEvan You <yyx990803@gmail.com>
Wed, 29 May 2019 09:36:53 +0000 (17:36 +0800)
committerEvan You <yyx990803@gmail.com>
Wed, 29 May 2019 09:36:53 +0000 (17:36 +0800)
packages/observer/src/baseHandlers.ts
packages/observer/src/effect.ts
packages/observer/src/index.ts
packages/observer/src/value.ts [new file with mode: 0644]
packages/runtime-core/src/componentProxy.ts
packages/runtime-core/src/createRenderer.ts

index 62515469186a77f91785424c20ea8ac20bbd65f1..40f57fd8c1c5330f6bcbe360a95c817b07a5b96b 100644 (file)
@@ -3,6 +3,7 @@ import { OperationTypes } from './operations'
 import { track, trigger } from './effect'
 import { LOCKED } from './lock'
 import { isObject } from '@vue/shared'
+import { isValue } from './value'
 
 const hasOwnProperty = Object.prototype.hasOwnProperty
 
@@ -18,6 +19,9 @@ function createGetter(isImmutable: boolean) {
     if (typeof key === 'symbol' && builtInSymbols.has(key)) {
       return res
     }
+    if (isValue(res)) {
+      return res.value
+    }
     track(target, OperationTypes.GET, key)
     return isObject(res)
       ? isImmutable
@@ -38,6 +42,10 @@ function set(
   value = unwrap(value)
   const hadKey = hasOwnProperty.call(target, key)
   const oldValue = target[key]
+  if (isValue(oldValue)) {
+    oldValue.value = value
+    return true
+  }
   const result = Reflect.set(target, key, value, receiver)
   // don't trigger if target is something up in the prototype chain of original
   if (target === unwrap(receiver)) {
index e4ae3d92d27f88aa339b59902c1ce171121f45c1..e149de048c02d9a995f3405695140bbe1be1e2bf 100644 (file)
@@ -1,5 +1,5 @@
 import { OperationTypes } from './operations'
-import { Dep, KeyToDepMap, targetMap } from './state'
+import { Dep, targetMap } from './state'
 
 export interface ReactiveEffect {
   (): any
@@ -84,8 +84,10 @@ export function track(
     if (type === OperationTypes.ITERATE) {
       key = ITERATE_KEY
     }
-    // keyMap must exist because only an observed target can call this function
-    const depsMap = targetMap.get(target) as KeyToDepMap
+    let depsMap = targetMap.get(target)
+    if (depsMap === void 0) {
+      targetMap.set(target, (depsMap = new Map()))
+    }
     let dep = depsMap.get(key as string | symbol)
     if (!dep) {
       depsMap.set(key as string | symbol, (dep = new Set()))
@@ -111,7 +113,11 @@ export function trigger(
   key?: string | symbol,
   extraInfo?: any
 ) {
-  const depsMap = targetMap.get(target) as KeyToDepMap
+  const depsMap = targetMap.get(target)
+  if (depsMap === void 0) {
+    // never been tracked
+    return
+  }
   const effects = new Set()
   const computedRunners = new Set()
   if (type === OperationTypes.CLEAR) {
index a2cdf80698871bd2fd5737eeb9ec68582fac21fe..35b13ec3981f2655ac6c449f3b92d66ac85ab25f 100644 (file)
@@ -28,6 +28,7 @@ export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
 export { OperationTypes } from './operations'
 export { computed, ComputedGetter } from './computed'
 export { lock, unlock } from './lock'
+export { value, isValue } from './value'
 
 const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
 const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
diff --git a/packages/observer/src/value.ts b/packages/observer/src/value.ts
new file mode 100644 (file)
index 0000000..b37e100
--- /dev/null
@@ -0,0 +1,27 @@
+import { track, trigger } from './effect'
+import { OperationTypes } from './operations'
+
+const knownValues = new WeakSet()
+
+export interface Value<T> {
+  value: T
+}
+
+export function value<T>(raw: T): Value<T> {
+  const v = {
+    get value() {
+      track(v, OperationTypes.GET, '')
+      return raw
+    },
+    set value(newVal) {
+      raw = newVal
+      trigger(v, OperationTypes.SET, '')
+    }
+  }
+  knownValues.add(v)
+  return v
+}
+
+export function isValue(v: any): boolean {
+  return knownValues.has(v)
+}
index 0974e6cbabf6fb308ef012158559885117f14fdc..0b11228f35795c6f64feaa352a59d5fd4626192f 100644 (file)
@@ -1,17 +1,10 @@
 import { ComponentInstance } from './component'
-import { isObservable, unwrap } from '@vue/observer'
-
-// TODO use proper implementation
-function isValue(binding: any) {
-  return isObservable(binding) && unwrap(binding).hasOwnProperty('value')
-}
 
 export const RenderProxyHandlers = {
   get(target: ComponentInstance, key: string) {
     const { state, props } = target
     if (state.hasOwnProperty(key)) {
-      const value = state[key]
-      return isValue(value) ? value.value : value
+      return state[key]
     } else if (props.hasOwnProperty(key)) {
       return props[key]
     } else {
@@ -34,12 +27,7 @@ export const RenderProxyHandlers = {
   set(target: ComponentInstance, key: string, value: any): boolean {
     const { state } = target
     if (state.hasOwnProperty(key)) {
-      const binding = state[key]
-      if (isValue(binding)) {
-        binding.value = value
-      } else {
-        state[key] = value
-      }
+      state[key] = value
       return true
     } else {
       if (__DEV__) {
index 3edf4866f1f49ce28c3b74d43c03870cb20c28d9..ba8ff88a294adeb6f22c3cf227264a5099342097 100644 (file)
@@ -128,6 +128,7 @@ export function createRenderer(options: RendererOptions) {
         } else {
           if (__DEV__ && !isFunction(type) && !isObject(type)) {
             // TODO warn invalid node type
+            debugger
           }
           processComponent(n1, n2, container, anchor)
         }