diff --git a/packages/reactivity/__tests__/shallowReactive.spec.ts b/packages/reactivity/__tests__/shallowReactive.spec.ts index 5997d045..a04e6170 100644 --- a/packages/reactivity/__tests__/shallowReactive.spec.ts +++ b/packages/reactivity/__tests__/shallowReactive.spec.ts @@ -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()) diff --git a/packages/reactivity/__tests__/shallowReadonly.spec.ts b/packages/reactivity/__tests__/shallowReadonly.spec.ts index 5042a01c..8e82412d 100644 --- a/packages/reactivity/__tests__/shallowReadonly.spec.ts +++ b/packages/reactivity/__tests__/shallowReadonly.spec.ts @@ -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', () => { diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index d1b0dfc2..a5726b9f 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -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 } diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index 57861aba..ea800c83 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -28,7 +28,9 @@ export interface Target { } export const reactiveMap = new WeakMap() +export const shallowReactiveMap = new WeakMap() export const readonlyMap = new WeakMap() +export const shallowReadonlyMap = new WeakMap() 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(target: T): T { target, false, shallowReactiveHandlers, - shallowCollectionHandlers + shallowCollectionHandlers, + shallowReactiveMap ) } @@ -143,7 +147,8 @@ export function readonly( target, true, readonlyHandlers, - readonlyCollectionHandlers + readonlyCollectionHandlers, + readonlyMap ) } @@ -160,7 +165,8 @@ export function shallowReadonly( target, true, shallowReadonlyHandlers, - shallowReadonlyCollectionHandlers + shallowReadonlyCollectionHandlers, + shallowReadonlyMap ) } @@ -168,7 +174,8 @@ function createReactiveObject( target: Target, isReadonly: boolean, baseHandlers: ProxyHandler, - collectionHandlers: ProxyHandler + collectionHandlers: ProxyHandler, + proxyMap: WeakMap ) { 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