fix(reactivity): ensure that shallow and normal proxies are tracked seperately (close #2843) (#2851)
fix #2843
This commit is contained in:
parent
68de9f408a
commit
22cc4a7659
@ -1,4 +1,5 @@
|
|||||||
import { shallowReactive, isReactive, reactive } from '../src/reactive'
|
import { isReactive, reactive, shallowReactive } from '../src/reactive'
|
||||||
|
|
||||||
import { effect } from '../src/effect'
|
import { effect } from '../src/effect'
|
||||||
|
|
||||||
describe('shallowReactive', () => {
|
describe('shallowReactive', () => {
|
||||||
@ -13,6 +14,16 @@ describe('shallowReactive', () => {
|
|||||||
expect(isReactive(props.n)).toBe(true)
|
expect(isReactive(props.n)).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #2843
|
||||||
|
test('should allow shallow und normal reactive for same target', async () => {
|
||||||
|
const original = { foo: {} }
|
||||||
|
const shallowProxy = shallowReactive(original)
|
||||||
|
const reactiveProxy = reactive(original)
|
||||||
|
expect(shallowProxy).not.toBe(reactiveProxy)
|
||||||
|
expect(isReactive(shallowProxy.foo)).toBe(false)
|
||||||
|
expect(isReactive(reactiveProxy.foo)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
describe('collections', () => {
|
describe('collections', () => {
|
||||||
test('should be reactive', () => {
|
test('should be reactive', () => {
|
||||||
const shallowSet = shallowReactive(new Set())
|
const shallowSet = shallowReactive(new Set())
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isReactive, isReadonly, shallowReadonly } from '../src'
|
import { isReactive, isReadonly, readonly, shallowReadonly } from '../src'
|
||||||
|
|
||||||
describe('reactivity/shallowReadonly', () => {
|
describe('reactivity/shallowReadonly', () => {
|
||||||
test('should not make non-reactive properties reactive', () => {
|
test('should not make non-reactive properties reactive', () => {
|
||||||
@ -27,6 +27,16 @@ describe('reactivity/shallowReadonly', () => {
|
|||||||
).not.toHaveBeenWarned()
|
).not.toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #2843
|
||||||
|
test('should differentiate from normal readonly calls', async () => {
|
||||||
|
const original = { foo: {} }
|
||||||
|
const shallowProxy = shallowReadonly(original)
|
||||||
|
const reactiveProxy = readonly(original)
|
||||||
|
expect(shallowProxy).not.toBe(reactiveProxy)
|
||||||
|
expect(isReadonly(shallowProxy.foo)).toBe(false)
|
||||||
|
expect(isReadonly(reactiveProxy.foo)).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
describe('collection/Map', () => {
|
describe('collection/Map', () => {
|
||||||
;[Map, WeakMap].forEach(Collection => {
|
;[Map, WeakMap].forEach(Collection => {
|
||||||
test('should make the map/weak-map readonly', () => {
|
test('should make the map/weak-map readonly', () => {
|
||||||
|
@ -5,7 +5,9 @@ import {
|
|||||||
ReactiveFlags,
|
ReactiveFlags,
|
||||||
Target,
|
Target,
|
||||||
readonlyMap,
|
readonlyMap,
|
||||||
reactiveMap
|
reactiveMap,
|
||||||
|
shallowReactiveMap,
|
||||||
|
shallowReadonlyMap
|
||||||
} from './reactive'
|
} from './reactive'
|
||||||
import { TrackOpTypes, TriggerOpTypes } from './operations'
|
import { TrackOpTypes, TriggerOpTypes } from './operations'
|
||||||
import {
|
import {
|
||||||
@ -80,7 +82,15 @@ function createGetter(isReadonly = false, shallow = false) {
|
|||||||
return isReadonly
|
return isReadonly
|
||||||
} else if (
|
} else if (
|
||||||
key === ReactiveFlags.RAW &&
|
key === ReactiveFlags.RAW &&
|
||||||
receiver === (isReadonly ? readonlyMap : reactiveMap).get(target)
|
receiver ===
|
||||||
|
(isReadonly
|
||||||
|
? shallow
|
||||||
|
? shallowReadonlyMap
|
||||||
|
: readonlyMap
|
||||||
|
: shallow
|
||||||
|
? shallowReactiveMap
|
||||||
|
: reactiveMap
|
||||||
|
).get(target)
|
||||||
) {
|
) {
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,9 @@ export interface Target {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const reactiveMap = new WeakMap<Target, any>()
|
export const reactiveMap = new WeakMap<Target, any>()
|
||||||
|
export const shallowReactiveMap = new WeakMap<Target, any>()
|
||||||
export const readonlyMap = new WeakMap<Target, any>()
|
export const readonlyMap = new WeakMap<Target, any>()
|
||||||
|
export const shallowReadonlyMap = new WeakMap<Target, any>()
|
||||||
|
|
||||||
const enum TargetType {
|
const enum TargetType {
|
||||||
INVALID = 0,
|
INVALID = 0,
|
||||||
@ -92,7 +94,8 @@ export function reactive(target: object) {
|
|||||||
target,
|
target,
|
||||||
false,
|
false,
|
||||||
mutableHandlers,
|
mutableHandlers,
|
||||||
mutableCollectionHandlers
|
mutableCollectionHandlers,
|
||||||
|
reactiveMap
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +109,8 @@ export function shallowReactive<T extends object>(target: T): T {
|
|||||||
target,
|
target,
|
||||||
false,
|
false,
|
||||||
shallowReactiveHandlers,
|
shallowReactiveHandlers,
|
||||||
shallowCollectionHandlers
|
shallowCollectionHandlers,
|
||||||
|
shallowReactiveMap
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +147,8 @@ export function readonly<T extends object>(
|
|||||||
target,
|
target,
|
||||||
true,
|
true,
|
||||||
readonlyHandlers,
|
readonlyHandlers,
|
||||||
readonlyCollectionHandlers
|
readonlyCollectionHandlers,
|
||||||
|
readonlyMap
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +165,8 @@ export function shallowReadonly<T extends object>(
|
|||||||
target,
|
target,
|
||||||
true,
|
true,
|
||||||
shallowReadonlyHandlers,
|
shallowReadonlyHandlers,
|
||||||
shallowReadonlyCollectionHandlers
|
shallowReadonlyCollectionHandlers,
|
||||||
|
shallowReadonlyMap
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +174,8 @@ function createReactiveObject(
|
|||||||
target: Target,
|
target: Target,
|
||||||
isReadonly: boolean,
|
isReadonly: boolean,
|
||||||
baseHandlers: ProxyHandler<any>,
|
baseHandlers: ProxyHandler<any>,
|
||||||
collectionHandlers: ProxyHandler<any>
|
collectionHandlers: ProxyHandler<any>,
|
||||||
|
proxyMap: WeakMap<Target, any>
|
||||||
) {
|
) {
|
||||||
if (!isObject(target)) {
|
if (!isObject(target)) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
@ -185,7 +192,6 @@ function createReactiveObject(
|
|||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
// target already has corresponding Proxy
|
// target already has corresponding Proxy
|
||||||
const proxyMap = isReadonly ? readonlyMap : reactiveMap
|
|
||||||
const existingProxy = proxyMap.get(target)
|
const existingProxy = proxyMap.get(target)
|
||||||
if (existingProxy) {
|
if (existingProxy) {
|
||||||
return existingProxy
|
return existingProxy
|
||||||
|
Loading…
Reference in New Issue
Block a user