From 4be1037f31e169d667059c44364fc3e43803accb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20L=C3=BCnborg?= Date: Sun, 23 Jan 2022 14:08:27 +0100 Subject: [PATCH] fix(reactivity): ensure readonly refs can be replaced with new refs in reactive objects (#5310) fix #5307 --- packages/reactivity/__tests__/readonly.spec.ts | 13 ++++++++++++- packages/reactivity/src/baseHandlers.ts | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/reactivity/__tests__/readonly.spec.ts b/packages/reactivity/__tests__/readonly.spec.ts index 4462061b..73030c5b 100644 --- a/packages/reactivity/__tests__/readonly.spec.ts +++ b/packages/reactivity/__tests__/readonly.spec.ts @@ -476,7 +476,7 @@ describe('reactivity/readonly', () => { expect(isReadonly(rr.foo)).toBe(true) }) - test('attemptingt to write to a readonly ref nested in a reactive object should fail', () => { + test('attemptingt to write plain value to a readonly ref nested in a reactive object should fail', () => { const r = ref(false) const ror = readonly(r) const obj = reactive({ ror }) @@ -486,4 +486,15 @@ describe('reactivity/readonly', () => { expect(obj.ror).toBe(false) }) + test('replacing a readonly ref nested in a reactive object with a new ref', () => { + const r = ref(false) + const ror = readonly(r) + const obj = reactive({ ror }) + try { + obj.ror = ref(true) as unknown as boolean + } catch (e) {} + + expect(obj.ror).toBe(true) + expect(toRaw(obj).ror).not.toBe(ror) // ref successfully replaced + }) }) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index eed9dc85..8ad8e571 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -150,7 +150,7 @@ function createSetter(shallow = false) { receiver: object ): boolean { let oldValue = (target as any)[key] - if (isReadonly(oldValue) && isRef(oldValue)) { + if (isReadonly(oldValue) && isRef(oldValue) && !isRef(value)) { return false } if (!shallow && !isReadonly(value)) {