mirror of
https://github.com/vuejs/vue.git
synced 2024-11-21 20:28:54 +00:00
fix(reactivity): fix shallowReactive nested ref setting edge cases
ref #12688
This commit is contained in:
parent
ba7dd2c4ed
commit
2af751b6ef
@ -191,7 +191,7 @@ export function defineReactive(
|
||||
} else if (getter) {
|
||||
// #7981: for accessor properties without setter
|
||||
return
|
||||
} else if (isRef(value) && !isRef(newVal)) {
|
||||
} else if (!shallow && isRef(value) && !isRef(newVal)) {
|
||||
value.value = newVal
|
||||
return
|
||||
} else {
|
||||
|
@ -483,7 +483,6 @@ describe('reactivity/readonly', () => {
|
||||
const ror = readonly(r)
|
||||
const obj = reactive({ ror })
|
||||
obj.ror = true
|
||||
|
||||
expect(obj.ror).toBe(false)
|
||||
expect(`Set operation on key "value" failed`).toHaveBeenWarned()
|
||||
})
|
||||
@ -492,14 +491,20 @@ describe('reactivity/readonly', () => {
|
||||
const r = ref(false)
|
||||
const ror = readonly(r)
|
||||
const obj = reactive({ ror })
|
||||
try {
|
||||
obj.ror = ref(true) as unknown as boolean
|
||||
} catch (e) {}
|
||||
|
||||
obj.ror = ref(true) as unknown as boolean
|
||||
expect(obj.ror).toBe(true)
|
||||
expect(toRaw(obj).ror).not.toBe(ror) // ref successfully replaced
|
||||
})
|
||||
|
||||
test('setting readonly object to writable nested ref', () => {
|
||||
const r = ref<any>()
|
||||
const obj = reactive({ r })
|
||||
const ro = readonly({})
|
||||
obj.r = ro
|
||||
expect(obj.r).toBe(ro)
|
||||
expect(r.value).toBe(ro)
|
||||
})
|
||||
|
||||
test('compatiblity with classes', () => {
|
||||
const spy = vi.fn()
|
||||
class Foo {
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
isReactive,
|
||||
isShallow,
|
||||
reactive,
|
||||
computed
|
||||
computed,
|
||||
readonly
|
||||
} from 'v3'
|
||||
import { effect } from 'v3/reactivity/effect'
|
||||
|
||||
@ -404,4 +405,17 @@ describe('reactivity/ref', () => {
|
||||
b.value = obj
|
||||
expect(spy2).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
test('ref should preserve value readonly-ness', () => {
|
||||
const original = {}
|
||||
const r = reactive(original)
|
||||
const rr = readonly(original)
|
||||
const a = ref(original)
|
||||
|
||||
expect(a.value).toBe(r)
|
||||
|
||||
a.value = rr
|
||||
expect(a.value).toBe(rr)
|
||||
expect(a.value).not.toBe(r)
|
||||
})
|
||||
})
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
isRef,
|
||||
isShallow,
|
||||
reactive,
|
||||
Ref,
|
||||
ref,
|
||||
shallowReactive,
|
||||
shallowReadonly
|
||||
@ -45,6 +46,18 @@ describe('shallowReactive', () => {
|
||||
expect(foo.bar.value).toBe(123)
|
||||
})
|
||||
|
||||
// #12688
|
||||
test('should not mutate refs', () => {
|
||||
const original = ref(123)
|
||||
const foo = shallowReactive<{ bar: Ref<number> | number }>({
|
||||
bar: original
|
||||
})
|
||||
expect(foo.bar).toBe(original)
|
||||
foo.bar = 234
|
||||
expect(foo.bar).toBe(234)
|
||||
expect(original.value).toBe(123)
|
||||
})
|
||||
|
||||
// @discrepancy no shallow/non-shallow versions from the same source -
|
||||
// cannot support this without real proxies
|
||||
// #2843
|
||||
|
Loading…
Reference in New Issue
Block a user