mirror of https://github.com/vuejs/core.git
fix(reactivity): fix mutation on user proxy of reactive Array
close #9742 close #9751 close #9750
This commit is contained in:
parent
983d45d4f8
commit
6ecbd5ce2a
|
|
@ -158,6 +158,21 @@ describe('reactivity/reactive', () => {
|
|||
expect(original.bar).toBe(original2)
|
||||
})
|
||||
|
||||
// #1246
|
||||
test('mutation on objects using reactive as prototype should not trigger', () => {
|
||||
const observed = reactive({ foo: 1 })
|
||||
const original = Object.create(observed)
|
||||
let dummy
|
||||
effect(() => (dummy = original.foo))
|
||||
expect(dummy).toBe(1)
|
||||
observed.foo = 2
|
||||
expect(dummy).toBe(2)
|
||||
original.foo = 3
|
||||
expect(dummy).toBe(2)
|
||||
original.foo = 4
|
||||
expect(dummy).toBe(2)
|
||||
})
|
||||
|
||||
test('toRaw', () => {
|
||||
const original = { foo: 1 }
|
||||
const observed = reactive(original)
|
||||
|
|
@ -166,11 +181,18 @@ describe('reactivity/reactive', () => {
|
|||
})
|
||||
|
||||
test('toRaw on object using reactive as prototype', () => {
|
||||
const original = reactive({})
|
||||
const obj = Object.create(original)
|
||||
const original = { foo: 1 }
|
||||
const observed = reactive(original)
|
||||
const inherted = Object.create(observed)
|
||||
expect(toRaw(inherted)).toBe(inherted)
|
||||
})
|
||||
|
||||
test('toRaw on user Proxy wrapping reactive', () => {
|
||||
const original = {}
|
||||
const re = reactive(original)
|
||||
const obj = new Proxy(re, {})
|
||||
const raw = toRaw(obj)
|
||||
expect(raw).toBe(obj)
|
||||
expect(raw).not.toBe(toRaw(original))
|
||||
expect(raw).toBe(original)
|
||||
})
|
||||
|
||||
test('should not unwrap Ref<T>', () => {
|
||||
|
|
|
|||
|
|
@ -142,6 +142,15 @@ describe('reactivity/reactive/Array', () => {
|
|||
expect(length).toBe('01')
|
||||
})
|
||||
|
||||
// #9742
|
||||
test('mutation on user proxy of reactive Array', () => {
|
||||
const array = reactive<number[]>([])
|
||||
const proxy = new Proxy(array, {})
|
||||
proxy.push(1)
|
||||
expect(array).toHaveLength(1)
|
||||
expect(proxy).toHaveLength(1)
|
||||
})
|
||||
|
||||
describe('Array methods w/ refs', () => {
|
||||
let original: any[]
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -100,19 +100,25 @@ class BaseReactiveHandler implements ProxyHandler<Target> {
|
|||
return isReadonly
|
||||
} else if (key === ReactiveFlags.IS_SHALLOW) {
|
||||
return shallow
|
||||
} else if (
|
||||
key === ReactiveFlags.RAW &&
|
||||
receiver ===
|
||||
(isReadonly
|
||||
? shallow
|
||||
? shallowReadonlyMap
|
||||
: readonlyMap
|
||||
: shallow
|
||||
? shallowReactiveMap
|
||||
: reactiveMap
|
||||
).get(target)
|
||||
) {
|
||||
return target
|
||||
} else if (key === ReactiveFlags.RAW) {
|
||||
if (
|
||||
receiver ===
|
||||
(isReadonly
|
||||
? shallow
|
||||
? shallowReadonlyMap
|
||||
: readonlyMap
|
||||
: shallow
|
||||
? shallowReactiveMap
|
||||
: reactiveMap
|
||||
).get(target) ||
|
||||
// receiver is not the reactive proxy, but has the same prototype
|
||||
// this means the reciever is a user proxy of the reactive proxy
|
||||
Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)
|
||||
) {
|
||||
return target
|
||||
}
|
||||
// early return undefined
|
||||
return
|
||||
}
|
||||
|
||||
const targetIsArray = isArray(target)
|
||||
|
|
|
|||
Loading…
Reference in New Issue