@@ -4,54 +4,67 @@ import { OperationTypes } from './operations'
4
4
import { LOCKED } from './lock'
5
5
import { isObject , capitalize , hasOwn } from '@vue/shared'
6
6
7
- const toReactive = ( value : any ) => ( isObject ( value ) ? reactive ( value ) : value )
8
- const toReadonly = ( value : any ) => ( isObject ( value ) ? readonly ( value ) : value )
7
+ export type CollectionTypes = IterableCollections | WeakCollections
9
8
10
- function get ( target : any , key : any , wrap : ( t : any ) => any ) : any {
9
+ type IterableCollections = Map < any , any > | Set < any >
10
+ type WeakCollections = WeakMap < any , any > | WeakSet < any >
11
+ type MapTypes = Map < any , any > | WeakMap < any , any >
12
+ type SetTypes = Set < any > | WeakSet < any >
13
+
14
+ const toReactive = < T extends unknown > ( value : T ) : T =>
15
+ isObject ( value ) ? reactive ( value ) : value
16
+
17
+ const toReadonly = < T extends unknown > ( value : T ) : T =>
18
+ isObject ( value ) ? readonly ( value ) : value
19
+
20
+ const getProto = < T extends CollectionTypes > ( v : T ) : any =>
21
+ Reflect . getPrototypeOf ( v )
22
+
23
+ function get (
24
+ target : MapTypes ,
25
+ key : unknown ,
26
+ wrap : typeof toReactive | typeof toReadonly
27
+ ) {
11
28
target = toRaw ( target )
12
29
key = toRaw ( key )
13
- const proto : any = Reflect . getPrototypeOf ( target )
14
30
track ( target , OperationTypes . GET , key )
15
- const res = proto . get . call ( target , key )
16
- return wrap ( res )
31
+ return wrap ( getProto ( target ) . get . call ( target , key ) )
17
32
}
18
33
19
- function has ( this : any , key : any ) : boolean {
34
+ function has ( this : CollectionTypes , key : unknown ) : boolean {
20
35
const target = toRaw ( this )
21
36
key = toRaw ( key )
22
- const proto : any = Reflect . getPrototypeOf ( target )
23
37
track ( target , OperationTypes . HAS , key )
24
- return proto . has . call ( target , key )
38
+ return getProto ( target ) . has . call ( target , key )
25
39
}
26
40
27
- function size ( target : any ) {
41
+ function size ( target : IterableCollections ) {
28
42
target = toRaw ( target )
29
- const proto = Reflect . getPrototypeOf ( target )
30
43
track ( target , OperationTypes . ITERATE )
31
- return Reflect . get ( proto , 'size' , target )
44
+ return Reflect . get ( getProto ( target ) , 'size' , target )
32
45
}
33
46
34
- function add ( this : any , value : any ) {
47
+ function add ( this : SetTypes , value : unknown ) {
35
48
value = toRaw ( value )
36
49
const target = toRaw ( this )
37
- const proto : any = Reflect . getPrototypeOf ( this )
50
+ const proto = getProto ( target )
38
51
const hadKey = proto . has . call ( target , value )
39
52
const result = proto . add . call ( target , value )
40
53
if ( ! hadKey ) {
41
54
/* istanbul ignore else */
42
55
if ( __DEV__ ) {
43
- trigger ( target , OperationTypes . ADD , value , { value } )
56
+ trigger ( target , OperationTypes . ADD , value , { newValue : value } )
44
57
} else {
45
58
trigger ( target , OperationTypes . ADD , value )
46
59
}
47
60
}
48
61
return result
49
62
}
50
63
51
- function set ( this : any , key : any , value : any ) {
64
+ function set ( this : MapTypes , key : unknown , value : unknown ) {
52
65
value = toRaw ( value )
53
66
const target = toRaw ( this )
54
- const proto : any = Reflect . getPrototypeOf ( this )
67
+ const proto = getProto ( target )
55
68
const hadKey = proto . has . call ( target , key )
56
69
const oldValue = proto . get . call ( target , key )
57
70
const result = proto . set . call ( target , key , value )
@@ -75,9 +88,9 @@ function set(this: any, key: any, value: any) {
75
88
return result
76
89
}
77
90
78
- function deleteEntry ( this : any , key : any ) {
91
+ function deleteEntry ( this : CollectionTypes , key : unknown ) {
79
92
const target = toRaw ( this )
80
- const proto : any = Reflect . getPrototypeOf ( this )
93
+ const proto = getProto ( target )
81
94
const hadKey = proto . has . call ( target , key )
82
95
const oldValue = proto . get ? proto . get . call ( target , key ) : undefined
83
96
// forward the operation before queueing reactions
@@ -93,13 +106,16 @@ function deleteEntry(this: any, key: any) {
93
106
return result
94
107
}
95
108
96
- function clear ( this : any ) {
109
+ function clear ( this : IterableCollections ) {
97
110
const target = toRaw ( this )
98
- const proto : any = Reflect . getPrototypeOf ( this )
99
111
const hadItems = target . size !== 0
100
- const oldTarget = target instanceof Map ? new Map ( target ) : new Set ( target )
112
+ const oldTarget = __DEV__
113
+ ? target instanceof Map
114
+ ? new Map ( target )
115
+ : new Set ( target )
116
+ : undefined
101
117
// forward the operation before queueing reactions
102
- const result = proto . clear . call ( target )
118
+ const result = getProto ( target ) . clear . call ( target )
103
119
if ( hadItems ) {
104
120
/* istanbul ignore else */
105
121
if ( __DEV__ ) {
@@ -112,30 +128,32 @@ function clear(this: any) {
112
128
}
113
129
114
130
function createForEach ( isReadonly : boolean ) {
115
- return function forEach ( this : any , callback : Function , thisArg ?: any ) {
131
+ return function forEach (
132
+ this : IterableCollections ,
133
+ callback : Function ,
134
+ thisArg ?: unknown
135
+ ) {
116
136
const observed = this
117
137
const target = toRaw ( observed )
118
- const proto : any = Reflect . getPrototypeOf ( target )
119
138
const wrap = isReadonly ? toReadonly : toReactive
120
139
track ( target , OperationTypes . ITERATE )
121
140
// important: create sure the callback is
122
141
// 1. invoked with the reactive map as `this` and 3rd arg
123
142
// 2. the value received should be a corresponding reactive/readonly.
124
- function wrappedCallback ( value : any , key : any ) {
143
+ function wrappedCallback ( value : unknown , key : unknown ) {
125
144
return callback . call ( observed , wrap ( value ) , wrap ( key ) , observed )
126
145
}
127
- return proto . forEach . call ( target , wrappedCallback , thisArg )
146
+ return getProto ( target ) . forEach . call ( target , wrappedCallback , thisArg )
128
147
}
129
148
}
130
149
131
150
function createIterableMethod ( method : string | symbol , isReadonly : boolean ) {
132
- return function ( this : any , ...args : any [ ] ) {
151
+ return function ( this : IterableCollections , ...args : unknown [ ] ) {
133
152
const target = toRaw ( this )
134
- const proto : any = Reflect . getPrototypeOf ( target )
135
153
const isPair =
136
154
method === 'entries' ||
137
155
( method === Symbol . iterator && target instanceof Map )
138
- const innerIterator = proto [ method ] . apply ( target , args )
156
+ const innerIterator = getProto ( target ) [ method ] . apply ( target , args )
139
157
const wrap = isReadonly ? toReadonly : toReactive
140
158
track ( target , OperationTypes . ITERATE )
141
159
// return a wrapped iterator which returns observed versions of the
@@ -163,7 +181,7 @@ function createReadonlyMethod(
163
181
method : Function ,
164
182
type : OperationTypes
165
183
) : Function {
166
- return function ( this : any , ...args : any [ ] ) {
184
+ return function ( this : CollectionTypes , ...args : unknown [ ] ) {
167
185
if ( LOCKED ) {
168
186
if ( __DEV__ ) {
169
187
const key = args [ 0 ] ? `on key "${ args [ 0 ] } " ` : ``
@@ -179,11 +197,11 @@ function createReadonlyMethod(
179
197
}
180
198
}
181
199
182
- const mutableInstrumentations : any = {
183
- get ( key : any ) {
200
+ const mutableInstrumentations : Record < string , Function > = {
201
+ get ( this : MapTypes , key : unknown ) {
184
202
return get ( this , key , toReactive )
185
203
} ,
186
- get size ( ) {
204
+ get size ( this : IterableCollections ) {
187
205
return size ( this )
188
206
} ,
189
207
has,
@@ -194,11 +212,11 @@ const mutableInstrumentations: any = {
194
212
forEach : createForEach ( false )
195
213
}
196
214
197
- const readonlyInstrumentations : any = {
198
- get ( key : any ) {
215
+ const readonlyInstrumentations : Record < string , Function > = {
216
+ get ( this : MapTypes , key : unknown ) {
199
217
return get ( this , key , toReadonly )
200
218
} ,
201
- get size ( ) {
219
+ get size ( this : IterableCollections ) {
202
220
return size ( this )
203
221
} ,
204
222
has,
@@ -211,26 +229,37 @@ const readonlyInstrumentations: any = {
211
229
212
230
const iteratorMethods = [ 'keys' , 'values' , 'entries' , Symbol . iterator ]
213
231
iteratorMethods . forEach ( method => {
214
- mutableInstrumentations [ method ] = createIterableMethod ( method , false )
215
- readonlyInstrumentations [ method ] = createIterableMethod ( method , true )
232
+ mutableInstrumentations [ method as string ] = createIterableMethod (
233
+ method ,
234
+ false
235
+ )
236
+ readonlyInstrumentations [ method as string ] = createIterableMethod (
237
+ method ,
238
+ true
239
+ )
216
240
} )
217
241
218
- function createInstrumentationGetter ( instrumentations : any ) {
219
- return function getInstrumented (
220
- target : any ,
242
+ function createInstrumentationGetter (
243
+ instrumentations : Record < string , Function >
244
+ ) {
245
+ return (
246
+ target : CollectionTypes ,
221
247
key : string | symbol ,
222
- receiver : any
223
- ) {
224
- target =
225
- hasOwn ( instrumentations , key ) && key in target ? instrumentations : target
226
- return Reflect . get ( target , key , receiver )
227
- }
248
+ receiver : CollectionTypes
249
+ ) =>
250
+ Reflect . get (
251
+ hasOwn ( instrumentations , key ) && key in target
252
+ ? instrumentations
253
+ : target ,
254
+ key ,
255
+ receiver
256
+ )
228
257
}
229
258
230
- export const mutableCollectionHandlers : ProxyHandler < any > = {
259
+ export const mutableCollectionHandlers : ProxyHandler < CollectionTypes > = {
231
260
get : createInstrumentationGetter ( mutableInstrumentations )
232
261
}
233
262
234
- export const readonlyCollectionHandlers : ProxyHandler < any > = {
263
+ export const readonlyCollectionHandlers : ProxyHandler < CollectionTypes > = {
235
264
get : createInstrumentationGetter ( readonlyInstrumentations )
236
265
}
0 commit comments