]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): readonly+reactive collection should also expose readonly+reactive...
authorEvan You <yyx990803@gmail.com>
Thu, 6 Aug 2020 15:18:16 +0000 (11:18 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 6 Aug 2020 15:18:16 +0000 (11:18 -0400)
fix #1772

packages/reactivity/__tests__/readonly.spec.ts
packages/reactivity/src/collectionHandlers.ts

index e5eb52d5dff51783c20281603b8151d0afc6055c..af42c967fb360d6628576944f5565c37e5f5494d 100644 (file)
@@ -205,6 +205,22 @@ describe('reactivity/readonly', () => {
         ).toHaveBeenWarned()
       })
 
+      // #1772
+      test('readonly + reactive should make get() value also readonly + reactive', () => {
+        const map = reactive(new Collection())
+        const roMap = readonly(map)
+        const key = {}
+        map.set(key, {})
+
+        const item = map.get(key)
+        expect(isReactive(item)).toBe(true)
+        expect(isReadonly(item)).toBe(false)
+
+        const roItem = roMap.get(key)
+        expect(isReactive(roItem)).toBe(true)
+        expect(isReadonly(roItem)).toBe(true)
+      })
+
       if (Collection === Map) {
         test('should retrieve readonly values on iteration', () => {
           const key1 = {}
@@ -223,6 +239,28 @@ describe('reactivity/readonly', () => {
             expect(isReadonly(value)).toBe(true)
           }
         })
+
+        test('should retrieve reactive + readonly values on iteration', () => {
+          const key1 = {}
+          const key2 = {}
+          const original = reactive(new Collection([[key1, {}], [key2, {}]]))
+          const wrapped: any = readonly(original)
+          expect(wrapped.size).toBe(2)
+          for (const [key, value] of wrapped) {
+            expect(isReadonly(key)).toBe(true)
+            expect(isReadonly(value)).toBe(true)
+            expect(isReactive(key)).toBe(true)
+            expect(isReactive(value)).toBe(true)
+          }
+          wrapped.forEach((value: any) => {
+            expect(isReadonly(value)).toBe(true)
+            expect(isReactive(value)).toBe(true)
+          })
+          for (const value of wrapped.values()) {
+            expect(isReadonly(value)).toBe(true)
+            expect(isReactive(value)).toBe(true)
+          }
+        })
       }
     })
   })
index 4d6cd99cc94f372b4a17a3585f4407b83fe0a754..0aa93d0646a544cff35ea4edf7a96f36b3e2af2b 100644 (file)
@@ -32,17 +32,20 @@ function get(
   key: unknown,
   wrap: typeof toReactive | typeof toReadonly | typeof toShallow
 ) {
-  target = toRaw(target)
+  // #1772: readonly(reactive(Map)) should return readonly + reactive version
+  // of the value
+  target = (target as any)[ReactiveFlags.RAW]
+  const rawTarget = toRaw(target)
   const rawKey = toRaw(key)
   if (key !== rawKey) {
-    track(target, TrackOpTypes.GET, key)
+    track(rawTarget, TrackOpTypes.GET, key)
   }
-  track(target, TrackOpTypes.GET, rawKey)
-  const { has, get } = getProto(target)
-  if (has.call(target, key)) {
-    return wrap(get.call(target, key))
-  } else if (has.call(target, rawKey)) {
-    return wrap(get.call(target, rawKey))
+  track(rawTarget, TrackOpTypes.GET, rawKey)
+  const { has } = getProto(rawTarget)
+  if (has.call(rawTarget, key)) {
+    return wrap(target.get(key))
+  } else if (has.call(rawTarget, rawKey)) {
+    return wrap(target.get(rawKey))
   }
 }
 
@@ -176,15 +179,16 @@ function createIterableMethod(
     this: IterableCollections,
     ...args: unknown[]
   ): Iterable & Iterator {
-    const target = toRaw(this)
-    const isMap = target instanceof Map
+    const target = (this as any)[ReactiveFlags.RAW]
+    const rawTarget = toRaw(this)
+    const isMap = rawTarget instanceof Map
     const isPair = method === 'entries' || (method === Symbol.iterator && isMap)
     const isKeyOnly = method === 'keys' && isMap
-    const innerIterator = getProto(target)[method].apply(target, args)
+    const innerIterator = target[method](...args)
     const wrap = isReadonly ? toReadonly : shallow ? toShallow : toReactive
     !isReadonly &&
       track(
-        target,
+        rawTarget,
         TrackOpTypes.ITERATE,
         isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY
       )