@@ -2,7 +2,13 @@ import { toRaw, reactive, readonly } from './reactive'
2
2
import { track , trigger , ITERATE_KEY , MAP_KEY_ITERATE_KEY } from './effect'
3
3
import { TrackOpTypes , TriggerOpTypes } from './operations'
4
4
import { LOCKED } from './lock'
5
- import { isObject , capitalize , hasOwn , hasChanged } from '@vue/shared'
5
+ import {
6
+ isObject ,
7
+ capitalize ,
8
+ hasOwn ,
9
+ hasChanged ,
10
+ toRawType
11
+ } from '@vue/shared'
6
12
7
13
export type CollectionTypes = IterableCollections | WeakCollections
8
14
@@ -27,6 +33,9 @@ function get(
27
33
) {
28
34
target = toRaw ( target )
29
35
const rawKey = toRaw ( key )
36
+ if ( key !== rawKey ) {
37
+ track ( target , TrackOpTypes . GET , key )
38
+ }
30
39
track ( target , TrackOpTypes . GET , rawKey )
31
40
const { has, get } = getProto ( target )
32
41
if ( has . call ( target , key ) ) {
@@ -39,6 +48,9 @@ function get(
39
48
function has ( this : CollectionTypes , key : unknown ) : boolean {
40
49
const target = toRaw ( this )
41
50
const rawKey = toRaw ( key )
51
+ if ( key !== rawKey ) {
52
+ track ( target , TrackOpTypes . HAS , key )
53
+ }
42
54
track ( target , TrackOpTypes . HAS , rawKey )
43
55
const has = getProto ( target ) . has
44
56
return has . call ( target , key ) || has . call ( target , rawKey )
@@ -64,12 +76,19 @@ function add(this: SetTypes, value: unknown) {
64
76
65
77
function set ( this : MapTypes , key : unknown , value : unknown ) {
66
78
value = toRaw ( value )
67
- key = toRaw ( key )
68
79
const target = toRaw ( this )
69
- const proto = getProto ( target )
70
- const hadKey = proto . has . call ( target , key )
71
- const oldValue = proto . get . call ( target , key )
72
- const result = proto . set . call ( target , key , value )
80
+ const { has, get, set } = getProto ( target )
81
+
82
+ let hadKey = has . call ( target , key )
83
+ if ( ! hadKey ) {
84
+ key = toRaw ( key )
85
+ hadKey = has . call ( target , key )
86
+ } else if ( __DEV__ ) {
87
+ checkIdentitiyKeys ( target , has , key )
88
+ }
89
+
90
+ const oldValue = get . call ( target , key )
91
+ const result = set . call ( target , key , value )
73
92
if ( ! hadKey ) {
74
93
trigger ( target , TriggerOpTypes . ADD , key , value )
75
94
} else if ( hasChanged ( value , oldValue ) ) {
@@ -85,7 +104,10 @@ function deleteEntry(this: CollectionTypes, key: unknown) {
85
104
if ( ! hadKey ) {
86
105
key = toRaw ( key )
87
106
hadKey = has . call ( target , key )
107
+ } else if ( __DEV__ ) {
108
+ checkIdentitiyKeys ( target , has , key )
88
109
}
110
+
89
111
const oldValue = get ? get . call ( target , key ) : undefined
90
112
// forward the operation before queueing reactions
91
113
const result = del . call ( target , key )
@@ -251,3 +273,21 @@ export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
251
273
export const readonlyCollectionHandlers : ProxyHandler < CollectionTypes > = {
252
274
get : createInstrumentationGetter ( readonlyInstrumentations )
253
275
}
276
+
277
+ function checkIdentitiyKeys (
278
+ target : CollectionTypes ,
279
+ has : ( key : unknown ) => boolean ,
280
+ key : unknown
281
+ ) {
282
+ const rawKey = toRaw ( key )
283
+ if ( rawKey !== key && has . call ( target , rawKey ) ) {
284
+ const type = toRawType ( target )
285
+ console . warn (
286
+ `Reactive ${ type } contains both the raw and reactive ` +
287
+ `versions of the same object${ type === `Map` ? `as keys` : `` } , ` +
288
+ `which can lead to inconsistencies. ` +
289
+ `Avoid differentiating between the raw and reactive versions ` +
290
+ `of an object and only use the reactive version if possible.`
291
+ )
292
+ }
293
+ }
0 commit comments