@feng3d/reactivity 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,298 +1,298 @@
1
- import { toReactive } from './reactive';
2
- import { ITERATE_KEY, MAP_KEY_ITERATE_KEY, ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './shared/constants';
3
- import { hasChanged, hasOwn, isMap, Target, toRaw, toRawType, warn } from './shared/general';
4
- import { PropertyReactivity } from './property';
5
-
6
- export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
7
- get: createInstrumentationGetter(),
8
- };
9
-
10
- function createInstrumentationGetter()
11
- {
12
- const instrumentations = createInstrumentations();
13
-
14
- return (
15
- target: CollectionTypes,
16
- key: string | symbol,
17
- receiver: CollectionTypes,
18
- ) =>
19
- {
20
- if (key === ReactiveFlags.IS_REACTIVE)
21
- {
22
- return true;
23
- }
24
- else if (key === ReactiveFlags.RAW)
25
- {
26
- return target;
27
- }
28
-
29
- return Reflect.get(
30
- hasOwn(instrumentations, key) && key in target
31
- ? instrumentations
32
- : target,
33
- key,
34
- receiver,
35
- );
36
- };
37
- }
38
-
39
- type Instrumentations = Record<string | symbol, Function | number>;
40
-
41
- function createInstrumentations(): Instrumentations
42
- {
43
- const instrumentations: Instrumentations = {
44
- get(this: MapTypes, key: unknown)
45
- {
46
- // #1772: readonly(reactive(Map)) should return readonly + reactive version
47
- // of the value
48
- const target = this[ReactiveFlags.RAW];
49
- const rawTarget = toRaw(target);
50
- const rawKey = toRaw(key);
51
-
52
- if (hasChanged(key, rawKey))
53
- {
54
- PropertyReactivity.track(rawTarget, TrackOpTypes.GET, key);
55
- }
56
- PropertyReactivity.track(rawTarget, TrackOpTypes.GET, rawKey);
57
-
58
- const { has } = getProto(rawTarget);
59
- const wrap = toReactive;
60
- if (has.call(rawTarget, key))
61
- {
62
- return wrap(target.get(key));
63
- }
64
- else if (has.call(rawTarget, rawKey))
65
- {
66
- return wrap(target.get(rawKey));
67
- }
68
- else if (target !== rawTarget)
69
- {
70
- // #3602 readonly(reactive(Map))
71
- // ensure that the nested reactive `Map` can do tracking for itself
72
- target.get(key);
73
- }
74
- },
75
- get size()
76
- {
77
- const target = (this as unknown as IterableCollections)[ReactiveFlags.RAW];
78
- PropertyReactivity.track(toRaw(target), TrackOpTypes.ITERATE, ITERATE_KEY);
79
-
80
- return Reflect.get(target, 'size', target);
81
- },
82
- has(this: CollectionTypes, key: unknown): boolean
83
- {
84
- const target = this[ReactiveFlags.RAW];
85
- const rawTarget = toRaw(target);
86
- const rawKey = toRaw(key);
87
-
88
- if (hasChanged(key, rawKey))
89
- {
90
- PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, key);
91
- }
92
- PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, rawKey);
93
-
94
- return key === rawKey
95
- ? target.has(key)
96
- : target.has(key) || target.has(rawKey);
97
- },
98
- forEach(this: IterableCollections, callback: Function, thisArg?: unknown)
99
- {
100
- const observed = this;
101
- const target = observed[ReactiveFlags.RAW];
102
- const rawTarget = toRaw(target);
103
- const wrap = toReactive;
104
- PropertyReactivity.track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY);
105
-
106
- return target.forEach((value: unknown, key: unknown) =>
107
-
108
- // important: make sure the callback is
109
- // 1. invoked with the reactive map as `this` and 3rd arg
110
- // 2. the value received should be a corresponding reactive/readonly.
111
- callback.call(thisArg, wrap(value), wrap(key), observed)
112
- );
113
- },
114
-
115
- add(this: SetTypes, value: unknown)
116
- {
117
- value = toRaw(value);
118
- const target = toRaw(this);
119
- const proto = getProto(target);
120
- const hadKey = proto.has.call(target, value);
121
- if (!hadKey)
122
- {
123
- target.add(value);
124
- PropertyReactivity.trigger(target, TriggerOpTypes.ADD, value, value);
125
- }
126
-
127
- return this;
128
- },
129
- set(this: MapTypes, key: unknown, value: unknown)
130
- {
131
- value = toRaw(value);
132
- const target = toRaw(this);
133
- const { has, get } = getProto(target);
134
-
135
- let hadKey = has.call(target, key);
136
- if (!hadKey)
137
- {
138
- key = toRaw(key);
139
- hadKey = has.call(target, key);
140
- }
141
- else if (__DEV__)
142
- {
143
- checkIdentityKeys(target, has, key);
144
- }
145
-
146
- const oldValue = get.call(target, key);
147
- target.set(key, value);
148
- if (!hadKey)
149
- {
150
- PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
151
- }
152
- else if (hasChanged(value, oldValue))
153
- {
154
- PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
155
- }
156
-
157
- return this;
158
- },
159
- delete(this: CollectionTypes, key: unknown)
160
- {
161
- const target = toRaw(this);
162
- const { has, get } = getProto(target);
163
- let hadKey = has.call(target, key);
164
- if (!hadKey)
165
- {
166
- key = toRaw(key);
167
- hadKey = has.call(target, key);
168
- }
169
- else if (__DEV__)
170
- {
171
- checkIdentityKeys(target, has, key);
172
- }
173
-
174
- const oldValue = get ? get.call(target, key) : undefined;
175
- // forward the operation before queueing reactions
176
- const result = target.delete(key);
177
- if (hadKey)
178
- {
179
- PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue);
180
- }
181
-
182
- return result;
183
- },
184
- clear(this: IterableCollections)
185
- {
186
- const target = toRaw(this);
187
- const hadItems = target.size !== 0;
188
- const oldTarget = __DEV__
189
- ? isMap(target)
190
- ? new Map(target)
191
- : new Set(target)
192
- : undefined;
193
- // forward the operation before queueing reactions
194
- const result = target.clear();
195
- if (hadItems)
196
- {
197
- PropertyReactivity.trigger(
198
- target,
199
- TriggerOpTypes.CLEAR,
200
- undefined,
201
- undefined,
202
- oldTarget,
203
- );
204
- }
205
-
206
- return result;
207
- },
208
- };
209
-
210
- const iteratorMethods = [
211
- 'keys',
212
- 'values',
213
- 'entries',
214
- Symbol.iterator,
215
- ] as const;
216
-
217
- iteratorMethods.forEach((method) =>
218
- {
219
- instrumentations[method] = createIterableMethod(method);
220
- });
221
-
222
- return instrumentations;
223
- }
224
-
225
- function createIterableMethod(method: string | symbol)
226
- {
227
- return function (
228
- this: IterableCollections,
229
- ...args: unknown[]
230
- ): Iterable<unknown> & Iterator<unknown>
231
- {
232
- const target = this[ReactiveFlags.RAW];
233
- const rawTarget = toRaw(target);
234
- const targetIsMap = isMap(rawTarget);
235
- const isPair
236
- = method === 'entries' || (method === Symbol.iterator && targetIsMap);
237
- const isKeyOnly = method === 'keys' && targetIsMap;
238
- const innerIterator = target[method](...args);
239
- const wrap = toReactive;
240
-
241
- PropertyReactivity.track(
242
- rawTarget,
243
- TrackOpTypes.ITERATE,
244
- isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY,
245
- );
246
-
247
- // return a wrapped iterator which returns observed versions of the
248
- // values emitted from the real iterator
249
- return {
250
- // iterator protocol
251
- next()
252
- {
253
- const { value, done } = innerIterator.next();
254
-
255
- return done
256
- ? { value, done }
257
- : {
258
- value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
259
- done,
260
- };
261
- },
262
- // iterable protocol
263
- [Symbol.iterator]()
264
- {
265
- return this;
266
- },
267
- };
268
- };
269
- }
270
-
271
- function checkIdentityKeys(
272
- target: CollectionTypes,
273
- has: (key: unknown) => boolean,
274
- key: unknown,
275
- )
276
- {
277
- const rawKey = toRaw(key);
278
- if (rawKey !== key && has.call(target, rawKey))
279
- {
280
- const type = toRawType(target);
281
- warn(
282
- `Reactive ${type} contains both the raw and reactive `
283
- + `versions of the same object${type === `Map` ? ` as keys` : ``}, `
284
- + `which can lead to inconsistencies. `
285
- + `Avoid differentiating between the raw and reactive versions `
286
- + `of an object and only use the reactive version if possible.`,
287
- );
288
- }
289
- }
290
-
291
- const getProto = <T extends CollectionTypes>(v: T): any => Reflect.getPrototypeOf(v);
292
-
293
- type CollectionTypes = IterableCollections | WeakCollections;
294
-
295
- type IterableCollections = (Map<any, any> | Set<any>) & Target;
296
- type WeakCollections = (WeakMap<any, any> | WeakSet<any>) & Target;
297
- type MapTypes = (Map<any, any> | WeakMap<any, any>) & Target;
298
- type SetTypes = (Set<any> | WeakSet<any>) & Target;
1
+ import { toReactive } from './reactive';
2
+ import { ITERATE_KEY, MAP_KEY_ITERATE_KEY, ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './shared/constants';
3
+ import { hasChanged, hasOwn, isMap, Target, toRaw, toRawType, warn } from './shared/general';
4
+ import { PropertyReactivity } from './property';
5
+
6
+ export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
7
+ get: createInstrumentationGetter(),
8
+ };
9
+
10
+ function createInstrumentationGetter()
11
+ {
12
+ const instrumentations = createInstrumentations();
13
+
14
+ return (
15
+ target: CollectionTypes,
16
+ key: string | symbol,
17
+ receiver: CollectionTypes,
18
+ ) =>
19
+ {
20
+ if (key === ReactiveFlags.IS_REACTIVE)
21
+ {
22
+ return true;
23
+ }
24
+ else if (key === ReactiveFlags.RAW)
25
+ {
26
+ return target;
27
+ }
28
+
29
+ return Reflect.get(
30
+ hasOwn(instrumentations, key) && key in target
31
+ ? instrumentations
32
+ : target,
33
+ key,
34
+ receiver,
35
+ );
36
+ };
37
+ }
38
+
39
+ type Instrumentations = Record<string | symbol, Function | number>;
40
+
41
+ function createInstrumentations(): Instrumentations
42
+ {
43
+ const instrumentations: Instrumentations = {
44
+ get(this: MapTypes, key: unknown)
45
+ {
46
+ // #1772: readonly(reactive(Map)) should return readonly + reactive version
47
+ // of the value
48
+ const target = this[ReactiveFlags.RAW];
49
+ const rawTarget = toRaw(target);
50
+ const rawKey = toRaw(key);
51
+
52
+ if (hasChanged(key, rawKey))
53
+ {
54
+ PropertyReactivity.track(rawTarget, TrackOpTypes.GET, key);
55
+ }
56
+ PropertyReactivity.track(rawTarget, TrackOpTypes.GET, rawKey);
57
+
58
+ const { has } = getProto(rawTarget);
59
+ const wrap = toReactive;
60
+ if (has.call(rawTarget, key))
61
+ {
62
+ return wrap(target.get(key));
63
+ }
64
+ else if (has.call(rawTarget, rawKey))
65
+ {
66
+ return wrap(target.get(rawKey));
67
+ }
68
+ else if (target !== rawTarget)
69
+ {
70
+ // #3602 readonly(reactive(Map))
71
+ // ensure that the nested reactive `Map` can do tracking for itself
72
+ target.get(key);
73
+ }
74
+ },
75
+ get size()
76
+ {
77
+ const target = (this as unknown as IterableCollections)[ReactiveFlags.RAW];
78
+ PropertyReactivity.track(toRaw(target), TrackOpTypes.ITERATE, ITERATE_KEY);
79
+
80
+ return Reflect.get(target, 'size', target);
81
+ },
82
+ has(this: CollectionTypes, key: unknown): boolean
83
+ {
84
+ const target = this[ReactiveFlags.RAW];
85
+ const rawTarget = toRaw(target);
86
+ const rawKey = toRaw(key);
87
+
88
+ if (hasChanged(key, rawKey))
89
+ {
90
+ PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, key);
91
+ }
92
+ PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, rawKey);
93
+
94
+ return key === rawKey
95
+ ? target.has(key)
96
+ : target.has(key) || target.has(rawKey);
97
+ },
98
+ forEach(this: IterableCollections, callback: Function, thisArg?: unknown)
99
+ {
100
+ const observed = this;
101
+ const target = observed[ReactiveFlags.RAW];
102
+ const rawTarget = toRaw(target);
103
+ const wrap = toReactive;
104
+ PropertyReactivity.track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY);
105
+
106
+ return target.forEach((value: unknown, key: unknown) =>
107
+
108
+ // important: make sure the callback is
109
+ // 1. invoked with the reactive map as `this` and 3rd arg
110
+ // 2. the value received should be a corresponding reactive/readonly.
111
+ callback.call(thisArg, wrap(value), wrap(key), observed)
112
+ );
113
+ },
114
+
115
+ add(this: SetTypes, value: unknown)
116
+ {
117
+ value = toRaw(value);
118
+ const target = toRaw(this);
119
+ const proto = getProto(target);
120
+ const hadKey = proto.has.call(target, value);
121
+ if (!hadKey)
122
+ {
123
+ target.add(value);
124
+ PropertyReactivity.trigger(target, TriggerOpTypes.ADD, value, value);
125
+ }
126
+
127
+ return this;
128
+ },
129
+ set(this: MapTypes, key: unknown, value: unknown)
130
+ {
131
+ value = toRaw(value);
132
+ const target = toRaw(this);
133
+ const { has, get } = getProto(target);
134
+
135
+ let hadKey = has.call(target, key);
136
+ if (!hadKey)
137
+ {
138
+ key = toRaw(key);
139
+ hadKey = has.call(target, key);
140
+ }
141
+ else if (__DEV__)
142
+ {
143
+ checkIdentityKeys(target, has, key);
144
+ }
145
+
146
+ const oldValue = get.call(target, key);
147
+ target.set(key, value);
148
+ if (!hadKey)
149
+ {
150
+ PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
151
+ }
152
+ else if (hasChanged(value, oldValue))
153
+ {
154
+ PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
155
+ }
156
+
157
+ return this;
158
+ },
159
+ delete(this: CollectionTypes, key: unknown)
160
+ {
161
+ const target = toRaw(this);
162
+ const { has, get } = getProto(target);
163
+ let hadKey = has.call(target, key);
164
+ if (!hadKey)
165
+ {
166
+ key = toRaw(key);
167
+ hadKey = has.call(target, key);
168
+ }
169
+ else if (__DEV__)
170
+ {
171
+ checkIdentityKeys(target, has, key);
172
+ }
173
+
174
+ const oldValue = get ? get.call(target, key) : undefined;
175
+ // forward the operation before queueing reactions
176
+ const result = target.delete(key);
177
+ if (hadKey)
178
+ {
179
+ PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue);
180
+ }
181
+
182
+ return result;
183
+ },
184
+ clear(this: IterableCollections)
185
+ {
186
+ const target = toRaw(this);
187
+ const hadItems = target.size !== 0;
188
+ const oldTarget = __DEV__
189
+ ? isMap(target)
190
+ ? new Map(target)
191
+ : new Set(target)
192
+ : undefined;
193
+ // forward the operation before queueing reactions
194
+ const result = target.clear();
195
+ if (hadItems)
196
+ {
197
+ PropertyReactivity.trigger(
198
+ target,
199
+ TriggerOpTypes.CLEAR,
200
+ undefined,
201
+ undefined,
202
+ oldTarget,
203
+ );
204
+ }
205
+
206
+ return result;
207
+ },
208
+ };
209
+
210
+ const iteratorMethods = [
211
+ 'keys',
212
+ 'values',
213
+ 'entries',
214
+ Symbol.iterator,
215
+ ] as const;
216
+
217
+ iteratorMethods.forEach((method) =>
218
+ {
219
+ instrumentations[method] = createIterableMethod(method);
220
+ });
221
+
222
+ return instrumentations;
223
+ }
224
+
225
+ function createIterableMethod(method: string | symbol)
226
+ {
227
+ return function (
228
+ this: IterableCollections,
229
+ ...args: unknown[]
230
+ ): Iterable<unknown> & Iterator<unknown>
231
+ {
232
+ const target = this[ReactiveFlags.RAW];
233
+ const rawTarget = toRaw(target);
234
+ const targetIsMap = isMap(rawTarget);
235
+ const isPair
236
+ = method === 'entries' || (method === Symbol.iterator && targetIsMap);
237
+ const isKeyOnly = method === 'keys' && targetIsMap;
238
+ const innerIterator = target[method](...args);
239
+ const wrap = toReactive;
240
+
241
+ PropertyReactivity.track(
242
+ rawTarget,
243
+ TrackOpTypes.ITERATE,
244
+ isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY,
245
+ );
246
+
247
+ // return a wrapped iterator which returns observed versions of the
248
+ // values emitted from the real iterator
249
+ return {
250
+ // iterator protocol
251
+ next()
252
+ {
253
+ const { value, done } = innerIterator.next();
254
+
255
+ return done
256
+ ? { value, done }
257
+ : {
258
+ value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
259
+ done,
260
+ };
261
+ },
262
+ // iterable protocol
263
+ [Symbol.iterator]()
264
+ {
265
+ return this;
266
+ },
267
+ };
268
+ };
269
+ }
270
+
271
+ function checkIdentityKeys(
272
+ target: CollectionTypes,
273
+ has: (key: unknown) => boolean,
274
+ key: unknown,
275
+ )
276
+ {
277
+ const rawKey = toRaw(key);
278
+ if (rawKey !== key && has.call(target, rawKey))
279
+ {
280
+ const type = toRawType(target);
281
+ warn(
282
+ `Reactive ${type} contains both the raw and reactive `
283
+ + `versions of the same object${type === `Map` ? ` as keys` : ``}, `
284
+ + `which can lead to inconsistencies. `
285
+ + `Avoid differentiating between the raw and reactive versions `
286
+ + `of an object and only use the reactive version if possible.`,
287
+ );
288
+ }
289
+ }
290
+
291
+ const getProto = <T extends CollectionTypes>(v: T): any => Reflect.getPrototypeOf(v);
292
+
293
+ type CollectionTypes = IterableCollections | WeakCollections;
294
+
295
+ type IterableCollections = (Map<any, any> | Set<any>) & Target;
296
+ type WeakCollections = (WeakMap<any, any> | WeakSet<any>) & Target;
297
+ type MapTypes = (Map<any, any> | WeakMap<any, any>) & Target;
298
+ type SetTypes = (Set<any> | WeakSet<any>) & Target;