@@ -8,7 +8,14 @@ import {
8
8
} from './reactive'
9
9
import { ITERATE_KEY , MAP_KEY_ITERATE_KEY , track , trigger } from './dep'
10
10
import { ReactiveFlags , TrackOpTypes , TriggerOpTypes } from './constants'
11
- import { capitalize , hasChanged , hasOwn , isMap , toRawType } from '@vue/shared'
11
+ import {
12
+ capitalize ,
13
+ extend ,
14
+ hasChanged ,
15
+ hasOwn ,
16
+ isMap ,
17
+ toRawType ,
18
+ } from '@vue/shared'
12
19
import { warn } from './warning'
13
20
14
21
type CollectionTypes = IterableCollections | WeakCollections
@@ -23,152 +30,6 @@ const toShallow = <T extends unknown>(value: T): T => value
23
30
const getProto = < T extends CollectionTypes > ( v : T ) : any =>
24
31
Reflect . getPrototypeOf ( v )
25
32
26
- function get (
27
- target : MapTypes ,
28
- key : unknown ,
29
- isReadonly = false ,
30
- isShallow = false ,
31
- ) {
32
- // #1772: readonly(reactive(Map)) should return readonly + reactive version
33
- // of the value
34
- target = target [ ReactiveFlags . RAW ]
35
- const rawTarget = toRaw ( target )
36
- const rawKey = toRaw ( key )
37
- if ( ! isReadonly ) {
38
- if ( hasChanged ( key , rawKey ) ) {
39
- track ( rawTarget , TrackOpTypes . GET , key )
40
- }
41
- track ( rawTarget , TrackOpTypes . GET , rawKey )
42
- }
43
- const { has } = getProto ( rawTarget )
44
- const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive
45
- if ( has . call ( rawTarget , key ) ) {
46
- return wrap ( target . get ( key ) )
47
- } else if ( has . call ( rawTarget , rawKey ) ) {
48
- return wrap ( target . get ( rawKey ) )
49
- } else if ( target !== rawTarget ) {
50
- // #3602 readonly(reactive(Map))
51
- // ensure that the nested reactive `Map` can do tracking for itself
52
- target . get ( key )
53
- }
54
- }
55
-
56
- function has ( this : CollectionTypes , key : unknown , isReadonly = false ) : boolean {
57
- const target = this [ ReactiveFlags . RAW ]
58
- const rawTarget = toRaw ( target )
59
- const rawKey = toRaw ( key )
60
- if ( ! isReadonly ) {
61
- if ( hasChanged ( key , rawKey ) ) {
62
- track ( rawTarget , TrackOpTypes . HAS , key )
63
- }
64
- track ( rawTarget , TrackOpTypes . HAS , rawKey )
65
- }
66
- return key === rawKey
67
- ? target . has ( key )
68
- : target . has ( key ) || target . has ( rawKey )
69
- }
70
-
71
- function size ( target : IterableCollections , isReadonly = false ) {
72
- target = target [ ReactiveFlags . RAW ]
73
- ! isReadonly && track ( toRaw ( target ) , TrackOpTypes . ITERATE , ITERATE_KEY )
74
- return Reflect . get ( target , 'size' , target )
75
- }
76
-
77
- function add ( this : SetTypes , value : unknown , _isShallow = false ) {
78
- if ( ! _isShallow && ! isShallow ( value ) && ! isReadonly ( value ) ) {
79
- value = toRaw ( value )
80
- }
81
- const target = toRaw ( this )
82
- const proto = getProto ( target )
83
- const hadKey = proto . has . call ( target , value )
84
- if ( ! hadKey ) {
85
- target . add ( value )
86
- trigger ( target , TriggerOpTypes . ADD , value , value )
87
- }
88
- return this
89
- }
90
-
91
- function set ( this : MapTypes , key : unknown , value : unknown , _isShallow = false ) {
92
- if ( ! _isShallow && ! isShallow ( value ) && ! isReadonly ( value ) ) {
93
- value = toRaw ( value )
94
- }
95
- const target = toRaw ( this )
96
- const { has, get } = getProto ( target )
97
-
98
- let hadKey = has . call ( target , key )
99
- if ( ! hadKey ) {
100
- key = toRaw ( key )
101
- hadKey = has . call ( target , key )
102
- } else if ( __DEV__ ) {
103
- checkIdentityKeys ( target , has , key )
104
- }
105
-
106
- const oldValue = get . call ( target , key )
107
- target . set ( key , value )
108
- if ( ! hadKey ) {
109
- trigger ( target , TriggerOpTypes . ADD , key , value )
110
- } else if ( hasChanged ( value , oldValue ) ) {
111
- trigger ( target , TriggerOpTypes . SET , key , value , oldValue )
112
- }
113
- return this
114
- }
115
-
116
- function deleteEntry ( this : CollectionTypes , key : unknown ) {
117
- const target = toRaw ( this )
118
- const { has, get } = getProto ( target )
119
- let hadKey = has . call ( target , key )
120
- if ( ! hadKey ) {
121
- key = toRaw ( key )
122
- hadKey = has . call ( target , key )
123
- } else if ( __DEV__ ) {
124
- checkIdentityKeys ( target , has , key )
125
- }
126
-
127
- const oldValue = get ? get . call ( target , key ) : undefined
128
- // forward the operation before queueing reactions
129
- const result = target . delete ( key )
130
- if ( hadKey ) {
131
- trigger ( target , TriggerOpTypes . DELETE , key , undefined , oldValue )
132
- }
133
- return result
134
- }
135
-
136
- function clear ( this : IterableCollections ) {
137
- const target = toRaw ( this )
138
- const hadItems = target . size !== 0
139
- const oldTarget = __DEV__
140
- ? isMap ( target )
141
- ? new Map ( target )
142
- : new Set ( target )
143
- : undefined
144
- // forward the operation before queueing reactions
145
- const result = target . clear ( )
146
- if ( hadItems ) {
147
- trigger ( target , TriggerOpTypes . CLEAR , undefined , undefined , oldTarget )
148
- }
149
- return result
150
- }
151
-
152
- function createForEach ( isReadonly : boolean , isShallow : boolean ) {
153
- return function forEach (
154
- this : IterableCollections ,
155
- callback : Function ,
156
- thisArg ?: unknown ,
157
- ) {
158
- const observed = this
159
- const target = observed [ ReactiveFlags . RAW ]
160
- const rawTarget = toRaw ( target )
161
- const wrap = isShallow ? toShallow : isReadonly ? toReadonly : toReactive
162
- ! isReadonly && track ( rawTarget , TrackOpTypes . ITERATE , ITERATE_KEY )
163
- return target . forEach ( ( value : unknown , key : unknown ) => {
164
- // important: make sure the callback is
165
- // 1. invoked with the reactive map as `this` and 3rd arg
166
- // 2. the value received should be a corresponding reactive/readonly.
167
- return callback . call ( thisArg , wrap ( value ) , wrap ( key ) , observed )
168
- } )
169
- }
170
- }
171
-
172
33
function createIterableMethod (
173
34
method : string | symbol ,
174
35
isReadonly : boolean ,
@@ -232,74 +93,158 @@ function createReadonlyMethod(type: TriggerOpTypes): Function {
232
93
233
94
type Instrumentations = Record < string | symbol , Function | number >
234
95
235
- function createInstrumentations ( ) {
236
- const mutableInstrumentations : Instrumentations = {
237
- get ( this : MapTypes , key : unknown ) {
238
- return get ( this , key )
239
- } ,
240
- get size ( ) {
241
- return size ( this as unknown as IterableCollections )
242
- } ,
243
- has,
244
- add,
245
- set,
246
- delete : deleteEntry ,
247
- clear,
248
- forEach : createForEach ( false , false ) ,
249
- }
250
-
251
- const shallowInstrumentations : Instrumentations = {
96
+ function createInstrumentations (
97
+ readonly : boolean ,
98
+ shallow : boolean ,
99
+ ) : Instrumentations {
100
+ const instrumentations : Instrumentations = {
252
101
get ( this : MapTypes , key : unknown ) {
253
- return get ( this , key , false , true )
102
+ // #1772: readonly(reactive(Map)) should return readonly + reactive version
103
+ // of the value
104
+ const target = this [ ReactiveFlags . RAW ]
105
+ const rawTarget = toRaw ( target )
106
+ const rawKey = toRaw ( key )
107
+ if ( ! readonly ) {
108
+ if ( hasChanged ( key , rawKey ) ) {
109
+ track ( rawTarget , TrackOpTypes . GET , key )
110
+ }
111
+ track ( rawTarget , TrackOpTypes . GET , rawKey )
112
+ }
113
+ const { has } = getProto ( rawTarget )
114
+ const wrap = shallow ? toShallow : readonly ? toReadonly : toReactive
115
+ if ( has . call ( rawTarget , key ) ) {
116
+ return wrap ( target . get ( key ) )
117
+ } else if ( has . call ( rawTarget , rawKey ) ) {
118
+ return wrap ( target . get ( rawKey ) )
119
+ } else if ( target !== rawTarget ) {
120
+ // #3602 readonly(reactive(Map))
121
+ // ensure that the nested reactive `Map` can do tracking for itself
122
+ target . get ( key )
123
+ }
254
124
} ,
255
125
get size ( ) {
256
- return size ( this as unknown as IterableCollections )
126
+ const target = ( this as unknown as IterableCollections ) [ ReactiveFlags . RAW ]
127
+ ! readonly && track ( toRaw ( target ) , TrackOpTypes . ITERATE , ITERATE_KEY )
128
+ return Reflect . get ( target , 'size' , target )
257
129
} ,
258
- has,
259
- add ( this : SetTypes , value : unknown ) {
260
- return add . call ( this , value , true )
130
+ has ( this : CollectionTypes , key : unknown ) : boolean {
131
+ const target = this [ ReactiveFlags . RAW ]
132
+ const rawTarget = toRaw ( target )
133
+ const rawKey = toRaw ( key )
134
+ if ( ! readonly ) {
135
+ if ( hasChanged ( key , rawKey ) ) {
136
+ track ( rawTarget , TrackOpTypes . HAS , key )
137
+ }
138
+ track ( rawTarget , TrackOpTypes . HAS , rawKey )
139
+ }
140
+ return key === rawKey
141
+ ? target . has ( key )
142
+ : target . has ( key ) || target . has ( rawKey )
261
143
} ,
262
- set ( this : MapTypes , key : unknown , value : unknown ) {
263
- return set . call ( this , key , value , true )
144
+ forEach ( this : IterableCollections , callback : Function , thisArg ?: unknown ) {
145
+ const observed = this
146
+ const target = observed [ ReactiveFlags . RAW ]
147
+ const rawTarget = toRaw ( target )
148
+ const wrap = shallow ? toShallow : readonly ? toReadonly : toReactive
149
+ ! readonly && track ( rawTarget , TrackOpTypes . ITERATE , ITERATE_KEY )
150
+ return target . forEach ( ( value : unknown , key : unknown ) => {
151
+ // important: make sure the callback is
152
+ // 1. invoked with the reactive map as `this` and 3rd arg
153
+ // 2. the value received should be a corresponding reactive/readonly.
154
+ return callback . call ( thisArg , wrap ( value ) , wrap ( key ) , observed )
155
+ } )
264
156
} ,
265
- delete : deleteEntry ,
266
- clear,
267
- forEach : createForEach ( false , true ) ,
268
157
}
269
158
270
- const readonlyInstrumentations : Instrumentations = {
271
- get ( this : MapTypes , key : unknown ) {
272
- return get ( this , key , true )
273
- } ,
274
- get size ( ) {
275
- return size ( this as unknown as IterableCollections , true )
276
- } ,
277
- has ( this : MapTypes , key : unknown ) {
278
- return has . call ( this , key , true )
279
- } ,
280
- add : createReadonlyMethod ( TriggerOpTypes . ADD ) ,
281
- set : createReadonlyMethod ( TriggerOpTypes . SET ) ,
282
- delete : createReadonlyMethod ( TriggerOpTypes . DELETE ) ,
283
- clear : createReadonlyMethod ( TriggerOpTypes . CLEAR ) ,
284
- forEach : createForEach ( true , false ) ,
285
- }
159
+ extend (
160
+ instrumentations ,
161
+ readonly
162
+ ? {
163
+ add : createReadonlyMethod ( TriggerOpTypes . ADD ) ,
164
+ set : createReadonlyMethod ( TriggerOpTypes . SET ) ,
165
+ delete : createReadonlyMethod ( TriggerOpTypes . DELETE ) ,
166
+ clear : createReadonlyMethod ( TriggerOpTypes . CLEAR ) ,
167
+ }
168
+ : {
169
+ add ( this : SetTypes , value : unknown ) {
170
+ if ( ! shallow && ! isShallow ( value ) && ! isReadonly ( value ) ) {
171
+ value = toRaw ( value )
172
+ }
173
+ const target = toRaw ( this )
174
+ const proto = getProto ( target )
175
+ const hadKey = proto . has . call ( target , value )
176
+ if ( ! hadKey ) {
177
+ target . add ( value )
178
+ trigger ( target , TriggerOpTypes . ADD , value , value )
179
+ }
180
+ return this
181
+ } ,
182
+ set ( this : MapTypes , key : unknown , value : unknown ) {
183
+ if ( ! shallow && ! isShallow ( value ) && ! isReadonly ( value ) ) {
184
+ value = toRaw ( value )
185
+ }
186
+ const target = toRaw ( this )
187
+ const { has, get } = getProto ( target )
188
+
189
+ let hadKey = has . call ( target , key )
190
+ if ( ! hadKey ) {
191
+ key = toRaw ( key )
192
+ hadKey = has . call ( target , key )
193
+ } else if ( __DEV__ ) {
194
+ checkIdentityKeys ( target , has , key )
195
+ }
286
196
287
- const shallowReadonlyInstrumentations : Instrumentations = {
288
- get ( this : MapTypes , key : unknown ) {
289
- return get ( this , key , true , true )
290
- } ,
291
- get size ( ) {
292
- return size ( this as unknown as IterableCollections , true )
293
- } ,
294
- has ( this : MapTypes , key : unknown ) {
295
- return has . call ( this , key , true )
296
- } ,
297
- add : createReadonlyMethod ( TriggerOpTypes . ADD ) ,
298
- set : createReadonlyMethod ( TriggerOpTypes . SET ) ,
299
- delete : createReadonlyMethod ( TriggerOpTypes . DELETE ) ,
300
- clear : createReadonlyMethod ( TriggerOpTypes . CLEAR ) ,
301
- forEach : createForEach ( true , true ) ,
302
- }
197
+ const oldValue = get . call ( target , key )
198
+ target . set ( key , value )
199
+ if ( ! hadKey ) {
200
+ trigger ( target , TriggerOpTypes . ADD , key , value )
201
+ } else if ( hasChanged ( value , oldValue ) ) {
202
+ trigger ( target , TriggerOpTypes . SET , key , value , oldValue )
203
+ }
204
+ return this
205
+ } ,
206
+ delete ( this : CollectionTypes , key : unknown ) {
207
+ const target = toRaw ( this )
208
+ const { has, get } = getProto ( target )
209
+ let hadKey = has . call ( target , key )
210
+ if ( ! hadKey ) {
211
+ key = toRaw ( key )
212
+ hadKey = has . call ( target , key )
213
+ } else if ( __DEV__ ) {
214
+ checkIdentityKeys ( target , has , key )
215
+ }
216
+
217
+ const oldValue = get ? get . call ( target , key ) : undefined
218
+ // forward the operation before queueing reactions
219
+ const result = target . delete ( key )
220
+ if ( hadKey ) {
221
+ trigger ( target , TriggerOpTypes . DELETE , key , undefined , oldValue )
222
+ }
223
+ return result
224
+ } ,
225
+ clear ( this : IterableCollections ) {
226
+ const target = toRaw ( this )
227
+ const hadItems = target . size !== 0
228
+ const oldTarget = __DEV__
229
+ ? isMap ( target )
230
+ ? new Map ( target )
231
+ : new Set ( target )
232
+ : undefined
233
+ // forward the operation before queueing reactions
234
+ const result = target . clear ( )
235
+ if ( hadItems ) {
236
+ trigger (
237
+ target ,
238
+ TriggerOpTypes . CLEAR ,
239
+ undefined ,
240
+ undefined ,
241
+ oldTarget ,
242
+ )
243
+ }
244
+ return result
245
+ } ,
246
+ } ,
247
+ )
303
248
304
249
const iteratorMethods = [
305
250
'keys' ,
@@ -309,39 +254,14 @@ function createInstrumentations() {
309
254
] as const
310
255
311
256
iteratorMethods . forEach ( method => {
312
- mutableInstrumentations [ method ] = createIterableMethod ( method , false , false )
313
- readonlyInstrumentations [ method ] = createIterableMethod ( method , true , false )
314
- shallowInstrumentations [ method ] = createIterableMethod ( method , false , true )
315
- shallowReadonlyInstrumentations [ method ] = createIterableMethod (
316
- method ,
317
- true ,
318
- true ,
319
- )
257
+ instrumentations [ method ] = createIterableMethod ( method , readonly , shallow )
320
258
} )
321
259
322
- return [
323
- mutableInstrumentations ,
324
- readonlyInstrumentations ,
325
- shallowInstrumentations ,
326
- shallowReadonlyInstrumentations ,
327
- ]
260
+ return instrumentations
328
261
}
329
262
330
- const [
331
- mutableInstrumentations ,
332
- readonlyInstrumentations ,
333
- shallowInstrumentations ,
334
- shallowReadonlyInstrumentations ,
335
- ] = /* @__PURE__ */ createInstrumentations ( )
336
-
337
263
function createInstrumentationGetter ( isReadonly : boolean , shallow : boolean ) {
338
- const instrumentations = shallow
339
- ? isReadonly
340
- ? shallowReadonlyInstrumentations
341
- : shallowInstrumentations
342
- : isReadonly
343
- ? readonlyInstrumentations
344
- : mutableInstrumentations
264
+ const instrumentations = createInstrumentations ( isReadonly , shallow )
345
265
346
266
return (
347
267
target : CollectionTypes ,
0 commit comments