From d3c456a7f45e7d7953d792b0b5767ed1452e0d3c Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Fri, 10 Sep 2021 04:37:04 +0800 Subject: [PATCH] fix: improve `isReadonly` behaviour, close #811, close #812 --- src/reactivity/readonly.ts | 2 + src/reactivity/ref.ts | 3 +- test/v3/reactivity/readonly.spec.ts | 72 ++++++++++++++++++----------- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/reactivity/readonly.ts b/src/reactivity/readonly.ts index 532fe14c..537e8e74 100644 --- a/src/reactivity/readonly.ts +++ b/src/reactivity/readonly.ts @@ -46,6 +46,8 @@ export function readonly( ): DeepReadonly> { if (__DEV__ && !isObject(target)) { warn(`value cannot be made reactive: ${String(target)}`) + } else { + readonlySet.set(target, true) } return target as any } diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts index b251f693..bf49d1c7 100644 --- a/src/reactivity/ref.ts +++ b/src/reactivity/ref.ts @@ -65,7 +65,8 @@ export function createRef(options: RefOption, readonly = false) { // related issues: #79 const sealed = Object.seal(r) - readonlySet.set(sealed, true) + if (readonly) readonlySet.set(sealed, true) + return sealed } diff --git a/test/v3/reactivity/readonly.spec.ts b/test/v3/reactivity/readonly.spec.ts index ebb513a3..8aa29ba6 100644 --- a/test/v3/reactivity/readonly.spec.ts +++ b/test/v3/reactivity/readonly.spec.ts @@ -7,6 +7,9 @@ import { watch, nextTick, readonly, + isReadonly, + toRaw, + computed, } from '../../../src' const Vue = require('vue/dist/vue.common.js') @@ -292,21 +295,21 @@ describe('reactivity/readonly', () => { // }) // }) - // test('calling reactive on an readonly should return readonly', () => { - // const a = readonly({}) - // const b = reactive(a) - // expect(isReadonly(b)).toBe(true) - // // should point to same original - // expect(toRaw(a)).toBe(toRaw(b)) - // }) + test('calling reactive on an readonly should return readonly', () => { + const a = readonly({}) + const b = reactive(a) + expect(isReadonly(b)).toBe(true) + // should point to same original + expect(toRaw(a)).toBe(toRaw(b)) + }) - // test('calling readonly on a reactive object should return readonly', () => { - // const a = reactive({}) - // const b = readonly(a) - // expect(isReadonly(b)).toBe(true) - // // should point to same original - // expect(toRaw(a)).toBe(toRaw(b)) - // }) + test('calling readonly on a reactive object should return readonly', () => { + const a = reactive({}) + const b = readonly(a) + expect(isReadonly(b)).toBe(true) + // should point to same original + expect(toRaw(a)).toBe(toRaw(b)) + }) // test('readonly should track and trigger if wrapping reactive original', () => { // const a = reactive({ n: 1 }) @@ -324,19 +327,19 @@ describe('reactivity/readonly', () => { // expect(dummy).toBe(2) // }) - // test('wrapping already wrapped value should return same Proxy', () => { - // const original = { foo: 1 } - // const wrapped = readonly(original) - // const wrapped2 = readonly(wrapped) - // expect(wrapped2).toBe(wrapped) - // }) + test('wrapping already wrapped value should return same Proxy', () => { + const original = { foo: 1 } + const wrapped = readonly(original) + const wrapped2 = readonly(wrapped) + expect(wrapped2).toBe(wrapped) + }) - // test('wrapping the same value multiple times should return same Proxy', () => { - // const original = { foo: 1 } - // const wrapped = readonly(original) - // const wrapped2 = readonly(original) - // expect(wrapped2).toBe(wrapped) - // }) + test('wrapping the same value multiple times should return same Proxy', () => { + const original = { foo: 1 } + const wrapped = readonly(original) + const wrapped2 = readonly(original) + expect(wrapped2).toBe(wrapped) + }) // test('markRaw', () => { // const obj = readonly({ @@ -474,5 +477,22 @@ describe('reactivity/readonly', () => { ).toHaveBeenWarned() expect(vm.$el.textContent).toBe(`1`) }) + + it('should mark computed as readonly', () => { + expect(isReadonly(computed(() => {}))).toBe(true) + expect( + isReadonly( + computed({ + get: () => {}, + set: () => {}, + }) + ) + ).toBe(false) + }) + + // #811 + it('should not mark ref as readonly', () => { + expect(isReadonly(ref([]))).toBe(false) + }) }) })