From 9c304bfe7942a20264235865b4bb5f6e53fdee0d Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 18 Jan 2022 09:22:03 +0800 Subject: [PATCH] fix(reactivity): differentiate shallow/deep proxies of same target when nested in reactive fix #5271 --- .../__tests__/shallowReactive.spec.ts | 20 +++++++++++++++++++ packages/reactivity/src/baseHandlers.ts | 9 ++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/__tests__/shallowReactive.spec.ts b/packages/reactivity/__tests__/shallowReactive.spec.ts index f7c7e07b055..200aa462496 100644 --- a/packages/reactivity/__tests__/shallowReactive.spec.ts +++ b/packages/reactivity/__tests__/shallowReactive.spec.ts @@ -35,6 +35,26 @@ describe('shallowReactive', () => { expect(isShallow(shallowReadonly({}))).toBe(true) }) + // #5271 + test('should respect shallow reactive nested inside reactive on reset', () => { + const r = reactive({ foo: shallowReactive({ bar: {} }) }) + expect(isShallow(r.foo)).toBe(true) + expect(isReactive(r.foo.bar)).toBe(false) + + r.foo = shallowReactive({ bar: {} }) + expect(isShallow(r.foo)).toBe(true) + expect(isReactive(r.foo.bar)).toBe(false) + }) + + test('should respect shallow/deep versions of same target on access', () => { + const original = {} + const shallow = shallowReactive(original) + const deep = reactive(original) + const r = reactive({ shallow, deep }) + expect(r.shallow).toBe(shallow) + expect(r.deep).toBe(deep) + }) + describe('collections', () => { test('should be reactive', () => { const shallowSet = shallowReactive(new Set()) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index 3d2ba661973..97acf063f67 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -8,7 +8,8 @@ import { reactiveMap, shallowReactiveMap, shallowReadonlyMap, - isReadonly + isReadonly, + isShallow } from './reactive' import { TrackOpTypes, TriggerOpTypes } from './operations' import { @@ -150,8 +151,10 @@ function createSetter(shallow = false) { ): boolean { let oldValue = (target as any)[key] if (!shallow && !isReadonly(value)) { - value = toRaw(value) - oldValue = toRaw(oldValue) + if (!isShallow(value)) { + value = toRaw(value) + oldValue = toRaw(oldValue) + } if (!isArray(target) && isRef(oldValue) && !isRef(value)) { oldValue.value = value return true