]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): ensure that shallow and normal proxies are tracked seperately (close...
authorThorsten Lünborg <t.luenborg@googlemail.com>
Fri, 26 Mar 2021 19:39:56 +0000 (20:39 +0100)
committerGitHub <noreply@github.com>
Fri, 26 Mar 2021 19:39:56 +0000 (15:39 -0400)
fix #2843

packages/reactivity/__tests__/shallowReactive.spec.ts
packages/reactivity/__tests__/shallowReadonly.spec.ts
packages/reactivity/src/baseHandlers.ts
packages/reactivity/src/reactive.ts

index 5997d045b5a9dfec85ca6691606c331b5b10ba6e..a04e6170d4e6a7e5e34c400e4d79566c9c5e8430 100644 (file)
@@ -1,4 +1,5 @@
-import { shallowReactive, isReactive, reactive } from '../src/reactive'
+import { isReactive, reactive, shallowReactive } from '../src/reactive'
+
 import { effect } from '../src/effect'
 
 describe('shallowReactive', () => {
@@ -13,6 +14,16 @@ describe('shallowReactive', () => {
     expect(isReactive(props.n)).toBe(true)
   })
 
+  // #2843
+  test('should allow shallow und normal reactive for same target', async () => {
+    const original = { foo: {} }
+    const shallowProxy = shallowReactive(original)
+    const reactiveProxy = reactive(original)
+    expect(shallowProxy).not.toBe(reactiveProxy)
+    expect(isReactive(shallowProxy.foo)).toBe(false)
+    expect(isReactive(reactiveProxy.foo)).toBe(true)
+  })
+
   describe('collections', () => {
     test('should be reactive', () => {
       const shallowSet = shallowReactive(new Set())
index 5042a01c02fe95f4ab78ea1318980cd4949663ab..8e82412d2d3a8bd1f78200582714613d97432636 100644 (file)
@@ -1,4 +1,4 @@
-import { isReactive, isReadonly, shallowReadonly } from '../src'
+import { isReactive, isReadonly, readonly, shallowReadonly } from '../src'
 
 describe('reactivity/shallowReadonly', () => {
   test('should not make non-reactive properties reactive', () => {
@@ -27,6 +27,16 @@ describe('reactivity/shallowReadonly', () => {
     ).not.toHaveBeenWarned()
   })
 
+  // #2843
+  test('should differentiate from normal readonly calls', async () => {
+    const original = { foo: {} }
+    const shallowProxy = shallowReadonly(original)
+    const reactiveProxy = readonly(original)
+    expect(shallowProxy).not.toBe(reactiveProxy)
+    expect(isReadonly(shallowProxy.foo)).toBe(false)
+    expect(isReadonly(reactiveProxy.foo)).toBe(true)
+  })
+
   describe('collection/Map', () => {
     ;[Map, WeakMap].forEach(Collection => {
       test('should make the map/weak-map readonly', () => {
index d1b0dfc2b025a2e480b620b104abc79312c8f786..a5726b9fec3e6fc65a0f9bb4219a0bf5b3f48bee 100644 (file)
@@ -5,7 +5,9 @@ import {
   ReactiveFlags,
   Target,
   readonlyMap,
-  reactiveMap
+  reactiveMap,
+  shallowReactiveMap,
+  shallowReadonlyMap
 } from './reactive'
 import { TrackOpTypes, TriggerOpTypes } from './operations'
 import {
@@ -80,7 +82,15 @@ function createGetter(isReadonly = false, shallow = false) {
       return isReadonly
     } else if (
       key === ReactiveFlags.RAW &&
-      receiver === (isReadonly ? readonlyMap : reactiveMap).get(target)
+      receiver ===
+        (isReadonly
+          ? shallow
+            ? shallowReadonlyMap
+            : readonlyMap
+          : shallow
+            ? shallowReactiveMap
+            : reactiveMap
+        ).get(target)
     ) {
       return target
     }
index 57861aba5acdbfc1d71d0b5dda52e46aa9400e49..ea800c83c61f5eeda1860c21e3c2df2f89635c1d 100644 (file)
@@ -28,7 +28,9 @@ export interface Target {
 }
 
 export const reactiveMap = new WeakMap<Target, any>()
+export const shallowReactiveMap = new WeakMap<Target, any>()
 export const readonlyMap = new WeakMap<Target, any>()
+export const shallowReadonlyMap = new WeakMap<Target, any>()
 
 const enum TargetType {
   INVALID = 0,
@@ -92,7 +94,8 @@ export function reactive(target: object) {
     target,
     false,
     mutableHandlers,
-    mutableCollectionHandlers
+    mutableCollectionHandlers,
+    reactiveMap
   )
 }
 
@@ -106,7 +109,8 @@ export function shallowReactive<T extends object>(target: T): T {
     target,
     false,
     shallowReactiveHandlers,
-    shallowCollectionHandlers
+    shallowCollectionHandlers,
+    shallowReactiveMap
   )
 }
 
@@ -143,7 +147,8 @@ export function readonly<T extends object>(
     target,
     true,
     readonlyHandlers,
-    readonlyCollectionHandlers
+    readonlyCollectionHandlers,
+    readonlyMap
   )
 }
 
@@ -160,7 +165,8 @@ export function shallowReadonly<T extends object>(
     target,
     true,
     shallowReadonlyHandlers,
-    shallowReadonlyCollectionHandlers
+    shallowReadonlyCollectionHandlers,
+    shallowReadonlyMap
   )
 }
 
@@ -168,7 +174,8 @@ function createReactiveObject(
   target: Target,
   isReadonly: boolean,
   baseHandlers: ProxyHandler<any>,
-  collectionHandlers: ProxyHandler<any>
+  collectionHandlers: ProxyHandler<any>,
+  proxyMap: WeakMap<Target, any>
 ) {
   if (!isObject(target)) {
     if (__DEV__) {
@@ -185,7 +192,6 @@ function createReactiveObject(
     return target
   }
   // target already has corresponding Proxy
-  const proxyMap = isReadonly ? readonlyMap : reactiveMap
   const existingProxy = proxyMap.get(target)
   if (existingProxy) {
     return existingProxy