diff --git a/packages/reactivity/__tests__/readonly.spec.ts b/packages/reactivity/__tests__/readonly.spec.ts index b9edb440fb7..5219c224d97 100644 --- a/packages/reactivity/__tests__/readonly.spec.ts +++ b/packages/reactivity/__tests__/readonly.spec.ts @@ -8,7 +8,8 @@ import { effect, ref, shallowReadonly, - isProxy + isProxy, + computed } from '../src' /** @@ -435,6 +436,21 @@ describe('reactivity/readonly', () => { ).toHaveBeenWarned() }) + // https://github.com/vuejs/vue-next/issues/3376 + test('calling readonly on computed should allow computed to set its private properties', () => { + const r = ref(false) + const c = computed(() => r.value) + const rC = readonly(c) + + r.value = true + + expect(rC.value).toBe(true) + ;(rC as any).randomProperty = true + + expect( + 'Set operation on key "randomProperty" failed: target is readonly.' + ).toHaveBeenWarned() + }) describe('shallowReadonly', () => { test('should not make non-reactive properties reactive', () => { const props = shallowReadonly({ n: { foo: 1 } }) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index d1b0dfc2b02..11eb7f70e43 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -197,7 +197,14 @@ export const mutableHandlers: ProxyHandler = { export const readonlyHandlers: ProxyHandler = { get: readonlyGet, - set(target, key) { + set(target, key, value, receiver) { + // is computed() + if ((target as any).__v_isRef && (target as any).effect) { + // computed should be able to set its own private properties + if (key === '_dirty' || key === '_value') { + return set(target, key, value, receiver) + } + } if (__DEV__) { console.warn( `Set operation on key "${String(key)}" failed: target is readonly.`,