Skip to content

Commit 41e02f0

Browse files
committed
fix(reactivity): ensure computed can be wrapped by readonly
fix #3376
1 parent e4b5fcc commit 41e02f0

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

packages/reactivity/__tests__/readonly.spec.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
effect,
99
ref,
1010
shallowReadonly,
11-
isProxy
11+
isProxy,
12+
computed
1213
} from '../src'
1314

1415
/**
@@ -435,6 +436,26 @@ describe('reactivity/readonly', () => {
435436
).toHaveBeenWarned()
436437
})
437438

439+
// https://github.com/vuejs/vue-next/issues/3376
440+
test('calling readonly on computed should allow computed to set its private properties', () => {
441+
const r = ref<boolean>(false)
442+
const c = computed(() => r.value)
443+
const rC = readonly(c)
444+
445+
r.value = true
446+
447+
expect(rC.value).toBe(true)
448+
expect(
449+
'Set operation on key "_dirty" failed: target is readonly.'
450+
).not.toHaveBeenWarned()
451+
// @ts-expect-error - non-existant property
452+
rC.randomProperty = true
453+
454+
expect(
455+
'Set operation on key "randomProperty" failed: target is readonly.'
456+
).toHaveBeenWarned()
457+
})
458+
438459
describe('shallowReadonly', () => {
439460
test('should not make non-reactive properties reactive', () => {
440461
const props = shallowReadonly({ n: { foo: 1 } })

packages/reactivity/src/computed.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ class ComputedRefImpl<T> {
4848
}
4949

5050
get value() {
51-
if (this._dirty) {
52-
this._value = this.effect()
53-
this._dirty = false
51+
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
52+
const self = toRaw(this)
53+
if (self._dirty) {
54+
self._value = this.effect()
55+
self._dirty = false
5456
}
55-
track(toRaw(this), TrackOpTypes.GET, 'value')
56-
return this._value
57+
track(self, TrackOpTypes.GET, 'value')
58+
return self._value
5759
}
5860

5961
set value(newValue: T) {

0 commit comments

Comments
 (0)