@feng3d/reactivity 0.0.1 → 1.0.2

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.
Files changed (45) hide show
  1. package/README.md +124 -26
  2. package/dist/index.js +1018 -58
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +1017 -57
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/lib/Reactivity.d.ts +69 -0
  7. package/lib/Reactivity.d.ts.map +1 -0
  8. package/lib/arrayInstrumentations.d.ts +2 -0
  9. package/lib/arrayInstrumentations.d.ts.map +1 -0
  10. package/lib/baseHandlers.d.ts +5 -0
  11. package/lib/baseHandlers.d.ts.map +1 -0
  12. package/lib/batch.d.ts +23 -0
  13. package/lib/batch.d.ts.map +1 -0
  14. package/lib/collectionHandlers.d.ts +7 -0
  15. package/lib/collectionHandlers.d.ts.map +1 -0
  16. package/lib/computed.d.ts +94 -0
  17. package/lib/computed.d.ts.map +1 -0
  18. package/lib/effect.d.ts +52 -0
  19. package/lib/effect.d.ts.map +1 -0
  20. package/lib/index.d.ts +7 -18
  21. package/lib/index.d.ts.map +1 -1
  22. package/lib/property.d.ts +44 -0
  23. package/lib/property.d.ts.map +1 -0
  24. package/lib/reactive.d.ts +66 -0
  25. package/lib/reactive.d.ts.map +1 -0
  26. package/lib/ref.d.ts +41 -0
  27. package/lib/ref.d.ts.map +1 -0
  28. package/lib/shared/constants.d.ts +34 -0
  29. package/lib/shared/constants.d.ts.map +1 -0
  30. package/lib/shared/general.d.ts +36 -0
  31. package/lib/shared/general.d.ts.map +1 -0
  32. package/package.json +3 -2
  33. package/src/Reactivity.ts +126 -0
  34. package/src/arrayInstrumentations.ts +448 -0
  35. package/src/baseHandlers.ts +220 -0
  36. package/src/batch.ts +91 -0
  37. package/src/collectionHandlers.ts +298 -0
  38. package/src/computed.ts +201 -0
  39. package/src/effect.ts +108 -0
  40. package/src/index.ts +7 -200
  41. package/src/property.ts +223 -0
  42. package/src/reactive.ts +130 -0
  43. package/src/ref.ts +88 -0
  44. package/src/shared/constants.ts +41 -0
  45. package/src/shared/general.ts +109 -0
@@ -2,102 +2,1062 @@
2
2
  typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.feng3d = {}));
3
3
  })(this, function(exports2) {
4
4
  "use strict";
5
- function ref(value) {
6
- return new ValueReactiveNode(value);
7
- }
8
- function computed(func) {
9
- return new FunctionReactiveNode(func);
10
- }
11
- let activeReactiveNode;
12
- class ReactiveNode {
5
+ class Reactivity {
13
6
  constructor() {
14
- this.parents = /* @__PURE__ */ new Set();
15
- this.dirty = true;
7
+ this._parents = /* @__PURE__ */ new Map();
16
8
  }
17
9
  /**
18
- * 当前节点值。
10
+ * 获取当前节点值。
11
+ *
12
+ * 取值时将会建立与父节点的依赖关系。
19
13
  */
20
14
  get value() {
21
- this.run();
15
+ this.track();
22
16
  return this._value;
23
17
  }
24
18
  /**
25
- * 执行当前节点。
19
+ * 捕捉。
20
+ *
21
+ * 建立与父节点的依赖关系。
26
22
  */
27
- run() {
28
- const parentReactiveNode = activeReactiveNode;
29
- activeReactiveNode = this;
30
- let node = this.invalidChildren;
31
- while (node) {
32
- if (node.value !== node.node.value) {
33
- this.markDirty();
34
- }
35
- node = node.next;
23
+ track() {
24
+ if (!_shouldTrack)
25
+ return;
26
+ const parent = Reactivity.activeReactivity;
27
+ if (parent) {
28
+ this._parents.set(parent, parent._version);
36
29
  }
37
- this.invalidChildren = void 0;
38
- if (this.dirty) {
39
- this._value = this._runSelf();
40
- if (parentReactiveNode) {
41
- this.parents.add(parentReactiveNode);
42
- }
43
- this.dirty = false;
30
+ }
31
+ /**
32
+ * 触发。
33
+ *
34
+ * 冒泡到所有父节点,设置失效子节点字典。
35
+ */
36
+ trigger() {
37
+ this._parents.forEach((version, parent) => {
38
+ if (parent._version !== version)
39
+ return;
40
+ parent.trigger();
41
+ parent._children.set(this, this._value);
42
+ });
43
+ this._parents.clear();
44
+ }
45
+ }
46
+ function forceTrack(fn) {
47
+ const preShouldTrack = _shouldTrack;
48
+ _shouldTrack = true;
49
+ const result = fn();
50
+ _shouldTrack = preShouldTrack;
51
+ return result;
52
+ }
53
+ function noTrack(fn) {
54
+ const preShouldTrack = _shouldTrack;
55
+ _shouldTrack = false;
56
+ const result = fn();
57
+ _shouldTrack = preShouldTrack;
58
+ return result;
59
+ }
60
+ let _shouldTrack = true;
61
+ function batch(dep, isRunning) {
62
+ if (isRunning) {
63
+ _isRunedDeps.push(dep);
64
+ } else {
65
+ _needEffectDeps.push(dep);
66
+ }
67
+ }
68
+ function batchRun(fn) {
69
+ _batchDepth++;
70
+ const result = fn();
71
+ if (--_batchDepth > 0) {
72
+ return;
73
+ }
74
+ if (_isRunedDeps.length > 0) {
75
+ _isRunedDeps.forEach((dep) => {
76
+ dep._children.forEach((version, node) => {
77
+ node._parents.set(dep, dep._version);
78
+ });
79
+ dep._children.clear();
80
+ });
81
+ _isRunedDeps.length = 0;
82
+ }
83
+ if (_needEffectDeps.length > 0) {
84
+ _needEffectDeps.forEach((dep) => {
85
+ const pre = Reactivity.activeReactivity;
86
+ Reactivity.activeReactivity = null;
87
+ dep.runIfDirty();
88
+ Reactivity.activeReactivity = pre;
89
+ });
90
+ _needEffectDeps.length = 0;
91
+ }
92
+ return result;
93
+ }
94
+ let _batchDepth = 0;
95
+ const _needEffectDeps = [];
96
+ const _isRunedDeps = [];
97
+ function computed(func) {
98
+ return new ComputedReactivity(func);
99
+ }
100
+ class ComputedReactivity extends Reactivity {
101
+ /**
102
+ * 创建计算依赖。
103
+ * @param func 检测的可能包含响应式的函数。
104
+ */
105
+ constructor(func) {
106
+ super();
107
+ this.__v_isRef = true;
108
+ this._children = /* @__PURE__ */ new Map();
109
+ this._isDirty = true;
110
+ this._version = -1;
111
+ this._func = func;
112
+ }
113
+ /**
114
+ * 捕捉。
115
+ *
116
+ * 建立与父节点的依赖关系。
117
+ */
118
+ track() {
119
+ this.runIfDirty();
120
+ super.track();
121
+ }
122
+ /**
123
+ * 触发。
124
+ *
125
+ * 冒泡到所有父节点,设置失效子节点字典。
126
+ *
127
+ * 把触发节点添加到失效子节点字典队列中。
128
+ */
129
+ trigger() {
130
+ if (Reactivity.activeReactivity === this) {
131
+ batch(this, Reactivity.activeReactivity === this);
44
132
  }
45
- activeReactiveNode = parentReactiveNode;
133
+ super.trigger();
46
134
  }
47
135
  /**
48
- * 标记为脏,触发更新。
136
+ * 执行当前节点。
49
137
  */
50
- markDirty() {
51
- if (this.dirty) {
52
- return;
138
+ run() {
139
+ forceTrack(() => {
140
+ const parentReactiveNode = Reactivity.activeReactivity;
141
+ Reactivity.activeReactivity = this;
142
+ this._version++;
143
+ this._value = this._func(this._value);
144
+ Reactivity.activeReactivity = parentReactiveNode;
145
+ });
146
+ }
147
+ /**
148
+ * 检查当前节点是否脏。
149
+ *
150
+ * 如果脏,则执行计算。
151
+ */
152
+ runIfDirty() {
153
+ this._isDirty = this._isDirty || this.isChildrenChanged();
154
+ if (this._isDirty) {
155
+ this._isDirty = false;
156
+ this.run();
53
157
  }
54
- this.dirty = true;
55
- this.invalidate();
56
- this.parents.clear();
57
158
  }
58
- invalidate() {
59
- if (this.parents.size > 0) {
60
- this.parents.forEach((parent) => {
61
- const node = { node: this, value: this._value, next: parent.invalidChildren };
62
- parent.invalidChildren = node;
63
- parent.invalidate();
159
+ /**
160
+ * 判断子节点是否发生变化。
161
+ */
162
+ isChildrenChanged() {
163
+ if (this._children.size === 0)
164
+ return false;
165
+ let isChanged = false;
166
+ const preReactiveNode = Reactivity.activeReactivity;
167
+ Reactivity.activeReactivity = null;
168
+ this._children.forEach((value, node) => {
169
+ if (isChanged)
170
+ return;
171
+ if (node.value !== value) {
172
+ isChanged = true;
173
+ return;
174
+ }
175
+ });
176
+ Reactivity.activeReactivity = preReactiveNode;
177
+ if (!isChanged) {
178
+ this._children.forEach((version, node) => {
179
+ node._parents.set(this, this._version);
64
180
  });
65
181
  }
182
+ this._children.clear();
183
+ return isChanged;
184
+ }
185
+ }
186
+ function effect(fn) {
187
+ return new EffectReactivity(fn);
188
+ }
189
+ const _EffectReactivity = class _EffectReactivity2 extends ComputedReactivity {
190
+ constructor(func) {
191
+ super(func);
192
+ this._isEnable = true;
193
+ this.runIfDirty();
194
+ }
195
+ pause() {
196
+ this._isEnable = false;
197
+ }
198
+ resume() {
199
+ if (this._isEnable)
200
+ return;
201
+ this._isEnable = true;
202
+ if (_EffectReactivity2.pausedQueueEffects.has(this)) {
203
+ _EffectReactivity2.pausedQueueEffects.delete(this);
204
+ this.trigger();
205
+ }
206
+ }
207
+ trigger() {
208
+ batchRun(() => {
209
+ super.trigger();
210
+ if (this._isEnable) {
211
+ batch(this, Reactivity.activeReactivity === this);
212
+ } else {
213
+ _EffectReactivity2.pausedQueueEffects.add(this);
214
+ }
215
+ });
66
216
  }
67
217
  /**
68
- * 执行当前节点自身。
218
+ * 执行当前节点。
219
+ *
220
+ * 当暂停时将会直接执行被包装的函数。
69
221
  */
70
- _runSelf() {
71
- return this._value;
222
+ run() {
223
+ if (this._isEnable) {
224
+ super.run();
225
+ } else {
226
+ this._func(this._value);
227
+ }
228
+ }
229
+ };
230
+ _EffectReactivity.pausedQueueEffects = /* @__PURE__ */ new WeakSet();
231
+ let EffectReactivity = _EffectReactivity;
232
+ var ReactiveFlags = /* @__PURE__ */ ((ReactiveFlags2) => {
233
+ ReactiveFlags2["IS_REACTIVE"] = "__v_isReactive";
234
+ ReactiveFlags2["RAW"] = "__v_raw";
235
+ ReactiveFlags2["IS_REF"] = "__v_isRef";
236
+ return ReactiveFlags2;
237
+ })(ReactiveFlags || {});
238
+ var TargetType = /* @__PURE__ */ ((TargetType2) => {
239
+ TargetType2[TargetType2["INVALID"] = 0] = "INVALID";
240
+ TargetType2[TargetType2["COMMON"] = 1] = "COMMON";
241
+ TargetType2[TargetType2["COLLECTION"] = 2] = "COLLECTION";
242
+ return TargetType2;
243
+ })(TargetType || {});
244
+ var TrackOpTypes = /* @__PURE__ */ ((TrackOpTypes2) => {
245
+ TrackOpTypes2["GET"] = "get";
246
+ TrackOpTypes2["HAS"] = "has";
247
+ TrackOpTypes2["ITERATE"] = "iterate";
248
+ return TrackOpTypes2;
249
+ })(TrackOpTypes || {});
250
+ var TriggerOpTypes = /* @__PURE__ */ ((TriggerOpTypes2) => {
251
+ TriggerOpTypes2["SET"] = "set";
252
+ TriggerOpTypes2["ADD"] = "add";
253
+ TriggerOpTypes2["DELETE"] = "delete";
254
+ TriggerOpTypes2["CLEAR"] = "clear";
255
+ return TriggerOpTypes2;
256
+ })(TriggerOpTypes || {});
257
+ const ITERATE_KEY = Symbol("");
258
+ const MAP_KEY_ITERATE_KEY = Symbol("");
259
+ const ARRAY_ITERATE_KEY = Symbol("");
260
+ globalThis.__DEV__ ?? (globalThis.__DEV__ = true);
261
+ const isObject = (val) => val !== null && typeof val === "object";
262
+ const isArray = Array.isArray;
263
+ const isSymbol = (val) => typeof val === "symbol";
264
+ const isString = (val) => typeof val === "string";
265
+ const isIntegerKey = (key) => isString(key) && key !== "NaN" && key[0] !== "-" && `${parseInt(key, 10)}` === key;
266
+ const isMap = (val) => toTypeString(val) === "[object Map]";
267
+ const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);
268
+ const hasChanged = (value, oldValue) => !Object.is(value, oldValue);
269
+ function targetTypeMap(rawType) {
270
+ switch (rawType) {
271
+ case "Object":
272
+ case "Array":
273
+ return TargetType.COMMON;
274
+ case "Map":
275
+ case "Set":
276
+ case "WeakMap":
277
+ case "WeakSet":
278
+ return TargetType.COLLECTION;
279
+ default:
280
+ return TargetType.COMMON;
72
281
  }
73
282
  }
74
- class FunctionReactiveNode extends ReactiveNode {
75
- constructor(func) {
76
- super();
77
- this.func = func;
283
+ function getTargetType(value) {
284
+ if (!Object.isExtensible(value))
285
+ return TargetType.INVALID;
286
+ return targetTypeMap(toRawType(value));
287
+ }
288
+ const toTypeString = (value) => Object.prototype.toString.call(value);
289
+ const toRawType = (value) => (
290
+ // 从类似 "[object RawType]" 的字符串中提取 "RawType"
291
+ toTypeString(value).slice(8, -1)
292
+ );
293
+ function toRaw(observed) {
294
+ const raw = observed && observed[ReactiveFlags.RAW];
295
+ return raw ? toRaw(raw) : observed;
296
+ }
297
+ // @__NO_SIDE_EFFECTS__
298
+ function makeMap(str) {
299
+ const map = /* @__PURE__ */ Object.create(null);
300
+ for (const key of str.split(","))
301
+ map[key] = 1;
302
+ return (val) => val in map;
303
+ }
304
+ function property(target, key) {
305
+ let depsMap = PropertyReactivity._targetMap.get(target);
306
+ if (!depsMap) {
307
+ depsMap = /* @__PURE__ */ new Map();
308
+ PropertyReactivity._targetMap.set(target, depsMap);
78
309
  }
79
- _runSelf() {
80
- return this.func();
310
+ let dep = depsMap.get(key);
311
+ if (!dep) {
312
+ dep = new PropertyReactivity(target, key);
313
+ depsMap.set(key, dep);
81
314
  }
315
+ return dep;
82
316
  }
83
- class ValueReactiveNode extends ReactiveNode {
317
+ class PropertyReactivity extends Reactivity {
318
+ constructor(target, key) {
319
+ super();
320
+ this._target = target;
321
+ this._key = key;
322
+ if (target instanceof Map || target instanceof WeakMap) {
323
+ this._value = target.get(key);
324
+ } else if (target instanceof Set || target instanceof WeakSet) {
325
+ this._value = target.has(key);
326
+ } else {
327
+ this._value = target[key];
328
+ }
329
+ }
330
+ /**
331
+ * 获取当前节点值。
332
+ *
333
+ * 取值时将会建立与父节点的依赖关系。
334
+ */
84
335
  get value() {
85
- this.run();
336
+ this.track();
86
337
  return this._value;
87
338
  }
88
339
  set value(v) {
89
- if (this._value === v)
340
+ if (this._key === "length") {
341
+ v = this._target["length"];
342
+ } else if (isSymbol(this._key)) {
343
+ v = ~~this._value + 1;
344
+ }
345
+ if (v === this._value)
90
346
  return;
91
- this.markDirty();
347
+ this.trigger();
92
348
  this._value = v;
93
349
  }
350
+ triggerIfChanged() {
351
+ }
352
+ /**
353
+ * 追踪属性的变化。
354
+ *
355
+ * 当属性被访问时,将会追踪属性的变化。
356
+ *
357
+ * @param target 目标对象。
358
+ * @param key 属性名。
359
+ * @returns
360
+ */
361
+ static track(target, type, key) {
362
+ const dep = property(target, key);
363
+ dep.track();
364
+ }
365
+ /**
366
+ * 触发属性的变化。
367
+ *
368
+ * @param target 目标对象。
369
+ * @param type 操作类型。
370
+ * @param key 属性名。
371
+ * @param newValue 新值。
372
+ * @param oldValue 旧值。
373
+ * @returns
374
+ */
375
+ static trigger(target, type, key, newValue, oldValue) {
376
+ const depsMap = this._targetMap.get(target);
377
+ if (!depsMap)
378
+ return;
379
+ const run = (dep) => {
380
+ if (dep) {
381
+ dep.value = newValue;
382
+ }
383
+ };
384
+ batchRun(() => {
385
+ if (type === TriggerOpTypes.CLEAR) {
386
+ depsMap.forEach(run);
387
+ } else {
388
+ const targetIsArray = isArray(target);
389
+ const isArrayIndex = targetIsArray && isIntegerKey(key);
390
+ if (targetIsArray && key === "length") {
391
+ const newLength = Number(newValue);
392
+ depsMap.forEach((dep, key2) => {
393
+ if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) {
394
+ run(dep);
395
+ }
396
+ });
397
+ } else {
398
+ if (key !== void 0 || depsMap.has(void 0)) {
399
+ run(depsMap.get(key));
400
+ }
401
+ if (isArrayIndex) {
402
+ run(depsMap.get(ARRAY_ITERATE_KEY));
403
+ }
404
+ switch (type) {
405
+ case TriggerOpTypes.ADD:
406
+ if (!targetIsArray) {
407
+ run(depsMap.get(ITERATE_KEY));
408
+ if (isMap(target)) {
409
+ run(depsMap.get(MAP_KEY_ITERATE_KEY));
410
+ }
411
+ } else if (isArrayIndex) {
412
+ run(depsMap.get("length"));
413
+ }
414
+ break;
415
+ case TriggerOpTypes.DELETE:
416
+ if (!targetIsArray) {
417
+ run(depsMap.get(ITERATE_KEY));
418
+ if (isMap(target)) {
419
+ run(depsMap.get(MAP_KEY_ITERATE_KEY));
420
+ }
421
+ }
422
+ break;
423
+ case TriggerOpTypes.SET:
424
+ if (isMap(target)) {
425
+ run(depsMap.get(ITERATE_KEY));
426
+ }
427
+ break;
428
+ }
429
+ }
430
+ }
431
+ });
432
+ }
433
+ }
434
+ PropertyReactivity._targetMap = /* @__PURE__ */ new WeakMap();
435
+ const arrayInstrumentations = {
436
+ __proto__: null,
437
+ /**
438
+ * 返回一个迭代器,用于遍历数组的响应式值
439
+ */
440
+ [Symbol.iterator]() {
441
+ return iterator(this, Symbol.iterator, toReactive);
442
+ },
443
+ /**
444
+ * 连接数组并返回新数组,处理响应式数组
445
+ */
446
+ concat(...args) {
447
+ return reactiveReadArray(this).concat(
448
+ ...args.map((x) => isArray(x) ? reactiveReadArray(x) : x)
449
+ );
450
+ },
451
+ /**
452
+ * 返回一个迭代器,用于遍历数组的键值对,并将值转换为响应式
453
+ */
454
+ entries() {
455
+ return iterator(this, "entries", (value) => {
456
+ value[1] = toReactive(value[1]);
457
+ return value;
458
+ });
459
+ },
460
+ /**
461
+ * 测试数组中的所有元素是否都通过了指定函数的测试
462
+ */
463
+ every(fn, thisArg) {
464
+ return apply(this, "every", fn, thisArg, void 0, arguments);
465
+ },
466
+ /**
467
+ * 创建一个新数组,包含通过指定函数测试的所有元素
468
+ */
469
+ filter(fn, thisArg) {
470
+ return apply(this, "filter", fn, thisArg, (v) => v.map(toReactive), arguments);
471
+ },
472
+ /**
473
+ * 返回数组中满足指定测试函数的第一个元素
474
+ */
475
+ find(fn, thisArg) {
476
+ return apply(this, "find", fn, thisArg, toReactive, arguments);
477
+ },
478
+ /**
479
+ * 返回数组中满足指定测试函数的第一个元素的索引
480
+ */
481
+ findIndex(fn, thisArg) {
482
+ return apply(this, "findIndex", fn, thisArg, void 0, arguments);
483
+ },
484
+ /**
485
+ * 返回数组中满足指定测试函数的最后一个元素
486
+ */
487
+ findLast(fn, thisArg) {
488
+ return apply(this, "findLast", fn, thisArg, toReactive, arguments);
489
+ },
490
+ /**
491
+ * 返回数组中满足指定测试函数的最后一个元素的索引
492
+ */
493
+ findLastIndex(fn, thisArg) {
494
+ return apply(this, "findLastIndex", fn, thisArg, void 0, arguments);
495
+ },
496
+ // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement
497
+ /**
498
+ * 对数组中的每个元素执行指定函数
499
+ */
500
+ forEach(fn, thisArg) {
501
+ return apply(this, "forEach", fn, thisArg, void 0, arguments);
502
+ },
503
+ /**
504
+ * 判断数组是否包含指定元素,处理响应式值
505
+ */
506
+ includes(...args) {
507
+ return searchProxy(this, "includes", args);
508
+ },
509
+ /**
510
+ * 返回数组中指定元素第一次出现的索引,处理响应式值
511
+ */
512
+ indexOf(...args) {
513
+ return searchProxy(this, "indexOf", args);
514
+ },
515
+ /**
516
+ * 将数组的所有元素连接成一个字符串
517
+ */
518
+ join(separator) {
519
+ return reactiveReadArray(this).join(separator);
520
+ },
521
+ // keys() iterator only reads `length`, no optimisation required
522
+ /**
523
+ * 返回数组中指定元素最后一次出现的索引,处理响应式值
524
+ */
525
+ lastIndexOf(...args) {
526
+ return searchProxy(this, "lastIndexOf", args);
527
+ },
528
+ /**
529
+ * 创建一个新数组,包含对原数组每个元素调用指定函数的结果
530
+ */
531
+ map(fn, thisArg) {
532
+ return apply(this, "map", fn, thisArg, void 0, arguments);
533
+ },
534
+ /**
535
+ * 移除数组的最后一个元素并返回该元素,避免跟踪长度变化
536
+ */
537
+ pop() {
538
+ return noTracking(this, "pop");
539
+ },
540
+ /**
541
+ * 向数组末尾添加一个或多个元素,并返回新的长度,避免跟踪长度变化
542
+ */
543
+ push(...args) {
544
+ return noTracking(this, "push", args);
545
+ },
546
+ /**
547
+ * 对数组中的每个元素执行累加器函数,并返回最终结果
548
+ */
549
+ reduce(fn, ...args) {
550
+ return reduce(this, "reduce", fn, args);
551
+ },
552
+ /**
553
+ * 从右到左对数组中的每个元素执行累加器函数,并返回最终结果
554
+ */
555
+ reduceRight(fn, ...args) {
556
+ return reduce(this, "reduceRight", fn, args);
557
+ },
558
+ /**
559
+ * 移除数组的第一个元素并返回该元素,避免跟踪长度变化
560
+ */
561
+ shift() {
562
+ return noTracking(this, "shift");
563
+ },
564
+ // slice could use ARRAY_ITERATE but also seems to beg for range tracking
565
+ /**
566
+ * 测试数组中的某些元素是否通过了指定函数的测试
567
+ */
568
+ some(fn, thisArg) {
569
+ return apply(this, "some", fn, thisArg, void 0, arguments);
570
+ },
571
+ /**
572
+ * 通过删除或替换现有元素或添加新元素来修改数组,避免跟踪长度变化
573
+ */
574
+ splice(...args) {
575
+ return noTracking(this, "splice", args);
576
+ },
577
+ /**
578
+ * 返回一个新数组,包含原数组的反转副本
579
+ */
580
+ toReversed() {
581
+ return reactiveReadArray(this).toReversed();
582
+ },
583
+ /**
584
+ * 返回一个新数组,包含原数组的排序副本
585
+ */
586
+ toSorted(comparer) {
587
+ return reactiveReadArray(this).toSorted(comparer);
588
+ },
589
+ /**
590
+ * 返回一个新数组,包含原数组的切片副本
591
+ */
592
+ toSpliced(...args) {
593
+ return reactiveReadArray(this).toSpliced(...args);
594
+ },
595
+ /**
596
+ * 向数组开头添加一个或多个元素,并返回新的长度,避免跟踪长度变化
597
+ */
598
+ unshift(...args) {
599
+ return noTracking(this, "unshift", args);
600
+ },
601
+ /**
602
+ * 返回一个迭代器,用于遍历数组的响应式值
603
+ */
604
+ values() {
605
+ return iterator(this, "values", toReactive);
606
+ }
607
+ };
608
+ function iterator(self2, method, wrapValue) {
609
+ const arr = shallowReadArray(self2);
610
+ const iter = arr[method]();
611
+ if (arr !== self2) {
612
+ iter._next = iter.next;
613
+ iter.next = () => {
614
+ const result = iter._next();
615
+ if (result.value) {
616
+ result.value = wrapValue(result.value);
617
+ }
618
+ return result;
619
+ };
620
+ }
621
+ return iter;
622
+ }
623
+ function shallowReadArray(arr) {
624
+ PropertyReactivity.track(arr = toRaw(arr), TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY);
625
+ return arr;
626
+ }
627
+ function reactiveReadArray(array) {
628
+ const raw = toRaw(array);
629
+ if (raw === array)
630
+ return raw;
631
+ PropertyReactivity.track(raw, TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY);
632
+ return raw.map(toReactive);
633
+ }
634
+ function apply(self2, method, fn, thisArg, wrappedRetFn, args) {
635
+ const arr = shallowReadArray(self2);
636
+ const needsWrap = arr !== self2;
637
+ const methodFn = arr[method];
638
+ if (methodFn !== Array.prototype[method]) {
639
+ const result2 = methodFn.apply(self2, args);
640
+ return needsWrap ? toReactive(result2) : result2;
641
+ }
642
+ let wrappedFn = fn;
643
+ if (arr !== self2) {
644
+ if (needsWrap) {
645
+ wrappedFn = function(item, index) {
646
+ return fn.call(this, toReactive(item), index, self2);
647
+ };
648
+ } else if (fn.length > 2) {
649
+ wrappedFn = function(item, index) {
650
+ return fn.call(this, item, index, self2);
651
+ };
652
+ }
653
+ }
654
+ const result = methodFn.call(arr, wrappedFn, thisArg);
655
+ return needsWrap && wrappedRetFn ? wrappedRetFn(result) : result;
656
+ }
657
+ function reduce(self2, method, fn, args) {
658
+ const arr = shallowReadArray(self2);
659
+ let wrappedFn = fn;
660
+ if (arr !== self2) {
661
+ wrappedFn = function(acc, item, index) {
662
+ return fn.call(this, acc, toReactive(item), index, self2);
663
+ };
664
+ }
665
+ return arr[method](wrappedFn, ...args);
666
+ }
667
+ function searchProxy(self2, method, args) {
668
+ const arr = toRaw(self2);
669
+ PropertyReactivity.track(arr, TrackOpTypes.ITERATE, ARRAY_ITERATE_KEY);
670
+ const res = arr[method](...args);
671
+ if ((res === -1 || res === false) && isProxy(args[0])) {
672
+ args[0] = toRaw(args[0]);
673
+ return arr[method](...args);
674
+ }
675
+ return res;
676
+ }
677
+ function noTracking(self2, method, args = []) {
678
+ const res = batchRun(
679
+ () => noTrack(
680
+ () => toRaw(self2)[method].apply(self2, args)
681
+ )
682
+ );
683
+ return res;
684
+ }
685
+ var _a;
686
+ function ref(value) {
687
+ if (isRef(value)) {
688
+ return value;
689
+ }
690
+ return new RefReactivity(value);
691
+ }
692
+ function isRef(r) {
693
+ return r ? r[ReactiveFlags.IS_REF] === true : false;
694
+ }
695
+ class RefReactivity extends Reactivity {
94
696
  constructor(value) {
95
697
  super();
96
- this._value = value;
698
+ this[_a] = true;
699
+ this._rawValue = toRaw(value);
700
+ this._value = toReactive(value);
701
+ }
702
+ get value() {
703
+ this.track();
704
+ return this._value;
705
+ }
706
+ set value(v) {
707
+ const oldValue = this._rawValue;
708
+ const newValue = toRaw(v);
709
+ if (!hasChanged(oldValue, newValue))
710
+ return;
711
+ batchRun(() => {
712
+ this.trigger();
713
+ this._rawValue = newValue;
714
+ this._value = toReactive(newValue);
715
+ });
716
+ }
717
+ }
718
+ _a = ReactiveFlags.IS_REF;
719
+ class BaseReactiveHandler {
720
+ /**
721
+ * 获取对象的属性值。
722
+ *
723
+ * @param target 对象本身
724
+ * @param key 属性名
725
+ * @param receiver 代理对象
726
+ * @returns
727
+ */
728
+ get(target, key, receiver) {
729
+ if (key === ReactiveFlags.IS_REACTIVE) {
730
+ return true;
731
+ } else if (key === ReactiveFlags.RAW) {
732
+ if (receiver === reactiveMap.get(target) || Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)) {
733
+ return target;
734
+ }
735
+ return;
736
+ }
737
+ const targetIsArray = isArray(target);
738
+ let fn;
739
+ if (targetIsArray && (fn = arrayInstrumentations[key])) {
740
+ return fn;
741
+ }
742
+ if (key === "hasOwnProperty") {
743
+ return hasOwnProperty;
744
+ }
745
+ const res = Reflect.get(
746
+ target,
747
+ key,
748
+ isRef(target) ? target : receiver
749
+ );
750
+ if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
751
+ return res;
752
+ }
753
+ PropertyReactivity.track(target, TrackOpTypes.GET, key);
754
+ if (isRef(res)) {
755
+ return targetIsArray && isIntegerKey(key) ? res : res.value;
756
+ }
757
+ if (isObject(res)) {
758
+ return reactive(res);
759
+ }
760
+ return res;
761
+ }
762
+ }
763
+ class MutableReactiveHandler extends BaseReactiveHandler {
764
+ /**
765
+ * 设置对象的属性值。
766
+ * @param target 被代理的对象。
767
+ * @param key 属性名。
768
+ * @param value 新值。
769
+ * @param receiver 代理对象。
770
+ * @returns 设置是否成功。
771
+ */
772
+ set(target, key, value, receiver) {
773
+ let oldValue = target[key];
774
+ oldValue = toRaw(oldValue);
775
+ value = toRaw(value);
776
+ if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
777
+ oldValue.value = value;
778
+ return true;
779
+ }
780
+ const hadKey = isArray(target) && isIntegerKey(key) ? Number(key) < target.length : hasOwn(target, key);
781
+ const result = Reflect.set(
782
+ target,
783
+ key,
784
+ value,
785
+ isRef(target) ? target : receiver
786
+ );
787
+ if (target === toRaw(receiver)) {
788
+ if (!hadKey) {
789
+ PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
790
+ } else if (hasChanged(value, oldValue)) {
791
+ PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
792
+ }
793
+ }
794
+ return result;
795
+ }
796
+ /**
797
+ * 删除对象的属性。
798
+ *
799
+ * @param target 被代理的对象。
800
+ * @param key 属性名。
801
+ * @returns 删除是否成功。
802
+ */
803
+ deleteProperty(target, key) {
804
+ const hadKey = hasOwn(target, key);
805
+ const oldValue = target[key];
806
+ const result = Reflect.deleteProperty(target, key);
807
+ if (result && hadKey) {
808
+ PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, void 0, oldValue);
809
+ }
810
+ return result;
811
+ }
812
+ has(target, key) {
813
+ const result = Reflect.has(target, key);
814
+ if (!isSymbol(key) || !builtInSymbols.has(key)) {
815
+ PropertyReactivity.track(target, TrackOpTypes.HAS, key);
816
+ }
817
+ return result;
818
+ }
819
+ ownKeys(target) {
820
+ PropertyReactivity.track(
821
+ target,
822
+ TrackOpTypes.ITERATE,
823
+ isArray(target) ? "length" : ITERATE_KEY
824
+ );
825
+ return Reflect.ownKeys(target);
826
+ }
827
+ }
828
+ const mutableHandlers = new MutableReactiveHandler();
829
+ function hasOwnProperty(key) {
830
+ if (!isSymbol(key))
831
+ key = String(key);
832
+ const obj = toRaw(this);
833
+ PropertyReactivity.track(obj, TrackOpTypes.HAS, key);
834
+ return obj.hasOwnProperty(key);
835
+ }
836
+ const builtInSymbols = new Set(
837
+ /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol)
838
+ );
839
+ const isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);
840
+ const mutableCollectionHandlers = {
841
+ get: createInstrumentationGetter()
842
+ };
843
+ function createInstrumentationGetter() {
844
+ const instrumentations = createInstrumentations();
845
+ return (target, key, receiver) => {
846
+ if (key === ReactiveFlags.IS_REACTIVE) {
847
+ return true;
848
+ } else if (key === ReactiveFlags.RAW) {
849
+ return target;
850
+ }
851
+ return Reflect.get(
852
+ hasOwn(instrumentations, key) && key in target ? instrumentations : target,
853
+ key,
854
+ receiver
855
+ );
856
+ };
857
+ }
858
+ function createInstrumentations() {
859
+ const instrumentations = {
860
+ get(key) {
861
+ const target = this[ReactiveFlags.RAW];
862
+ const rawTarget = toRaw(target);
863
+ const rawKey = toRaw(key);
864
+ if (hasChanged(key, rawKey)) {
865
+ PropertyReactivity.track(rawTarget, TrackOpTypes.GET, key);
866
+ }
867
+ PropertyReactivity.track(rawTarget, TrackOpTypes.GET, rawKey);
868
+ const { has } = getProto(rawTarget);
869
+ const wrap = toReactive;
870
+ if (has.call(rawTarget, key)) {
871
+ return wrap(target.get(key));
872
+ } else if (has.call(rawTarget, rawKey)) {
873
+ return wrap(target.get(rawKey));
874
+ } else if (target !== rawTarget) {
875
+ target.get(key);
876
+ }
877
+ },
878
+ get size() {
879
+ const target = this[ReactiveFlags.RAW];
880
+ PropertyReactivity.track(toRaw(target), TrackOpTypes.ITERATE, ITERATE_KEY);
881
+ return Reflect.get(target, "size", target);
882
+ },
883
+ has(key) {
884
+ const target = this[ReactiveFlags.RAW];
885
+ const rawTarget = toRaw(target);
886
+ const rawKey = toRaw(key);
887
+ if (hasChanged(key, rawKey)) {
888
+ PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, key);
889
+ }
890
+ PropertyReactivity.track(rawTarget, TrackOpTypes.HAS, rawKey);
891
+ return key === rawKey ? target.has(key) : target.has(key) || target.has(rawKey);
892
+ },
893
+ forEach(callback, thisArg) {
894
+ const observed = this;
895
+ const target = observed[ReactiveFlags.RAW];
896
+ const rawTarget = toRaw(target);
897
+ const wrap = toReactive;
898
+ PropertyReactivity.track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY);
899
+ return target.forEach(
900
+ (value, key) => (
901
+ // important: make sure the callback is
902
+ // 1. invoked with the reactive map as `this` and 3rd arg
903
+ // 2. the value received should be a corresponding reactive/readonly.
904
+ callback.call(thisArg, wrap(value), wrap(key), observed)
905
+ )
906
+ );
907
+ },
908
+ add(value) {
909
+ value = toRaw(value);
910
+ const target = toRaw(this);
911
+ const proto = getProto(target);
912
+ const hadKey = proto.has.call(target, value);
913
+ if (!hadKey) {
914
+ target.add(value);
915
+ PropertyReactivity.trigger(target, TriggerOpTypes.ADD, value, value);
916
+ }
917
+ return this;
918
+ },
919
+ set(key, value) {
920
+ value = toRaw(value);
921
+ const target = toRaw(this);
922
+ const { has, get } = getProto(target);
923
+ let hadKey = has.call(target, key);
924
+ if (!hadKey) {
925
+ key = toRaw(key);
926
+ hadKey = has.call(target, key);
927
+ }
928
+ const oldValue = get.call(target, key);
929
+ target.set(key, value);
930
+ if (!hadKey) {
931
+ PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
932
+ } else if (hasChanged(value, oldValue)) {
933
+ PropertyReactivity.trigger(target, TriggerOpTypes.SET, key, value, oldValue);
934
+ }
935
+ return this;
936
+ },
937
+ delete(key) {
938
+ const target = toRaw(this);
939
+ const { has, get } = getProto(target);
940
+ let hadKey = has.call(target, key);
941
+ if (!hadKey) {
942
+ key = toRaw(key);
943
+ hadKey = has.call(target, key);
944
+ }
945
+ const oldValue = get ? get.call(target, key) : void 0;
946
+ const result = target.delete(key);
947
+ if (hadKey) {
948
+ PropertyReactivity.trigger(target, TriggerOpTypes.DELETE, key, void 0, oldValue);
949
+ }
950
+ return result;
951
+ },
952
+ clear() {
953
+ const target = toRaw(this);
954
+ const hadItems = target.size !== 0;
955
+ const oldTarget = void 0;
956
+ const result = target.clear();
957
+ if (hadItems) {
958
+ PropertyReactivity.trigger(
959
+ target,
960
+ TriggerOpTypes.CLEAR,
961
+ void 0,
962
+ void 0,
963
+ oldTarget
964
+ );
965
+ }
966
+ return result;
967
+ }
968
+ };
969
+ const iteratorMethods = [
970
+ "keys",
971
+ "values",
972
+ "entries",
973
+ Symbol.iterator
974
+ ];
975
+ iteratorMethods.forEach((method) => {
976
+ instrumentations[method] = createIterableMethod(method);
977
+ });
978
+ return instrumentations;
979
+ }
980
+ function createIterableMethod(method) {
981
+ return function(...args) {
982
+ const target = this[ReactiveFlags.RAW];
983
+ const rawTarget = toRaw(target);
984
+ const targetIsMap = isMap(rawTarget);
985
+ const isPair = method === "entries" || method === Symbol.iterator && targetIsMap;
986
+ const isKeyOnly = method === "keys" && targetIsMap;
987
+ const innerIterator = target[method](...args);
988
+ const wrap = toReactive;
989
+ PropertyReactivity.track(
990
+ rawTarget,
991
+ TrackOpTypes.ITERATE,
992
+ isKeyOnly ? MAP_KEY_ITERATE_KEY : ITERATE_KEY
993
+ );
994
+ return {
995
+ // iterator protocol
996
+ next() {
997
+ const { value, done } = innerIterator.next();
998
+ return done ? { value, done } : {
999
+ value: isPair ? [wrap(value[0]), wrap(value[1])] : wrap(value),
1000
+ done
1001
+ };
1002
+ },
1003
+ // iterable protocol
1004
+ [Symbol.iterator]() {
1005
+ return this;
1006
+ }
1007
+ };
1008
+ };
1009
+ }
1010
+ const getProto = (v) => Reflect.getPrototypeOf(v);
1011
+ function reactive(target) {
1012
+ if (!isObject(target)) {
1013
+ return target;
1014
+ }
1015
+ if (target[ReactiveFlags.RAW]) {
1016
+ return target;
1017
+ }
1018
+ const targetType = getTargetType(target);
1019
+ if (targetType === TargetType.INVALID) {
1020
+ return target;
1021
+ }
1022
+ const existingProxy = reactiveMap.get(target);
1023
+ if (existingProxy) {
1024
+ return existingProxy;
1025
+ }
1026
+ const proxy = new Proxy(
1027
+ target,
1028
+ targetType === TargetType.COLLECTION ? mutableCollectionHandlers : mutableHandlers
1029
+ );
1030
+ reactiveMap.set(target, proxy);
1031
+ return proxy;
1032
+ }
1033
+ const reactiveMap = /* @__PURE__ */ new WeakMap();
1034
+ function isReactive(value) {
1035
+ return !!(value && value[ReactiveFlags.IS_REACTIVE]);
1036
+ }
1037
+ const toReactive = (value) => {
1038
+ if (isObject(value)) {
1039
+ return reactive(value);
97
1040
  }
1041
+ return value;
1042
+ };
1043
+ function isProxy(value) {
1044
+ return value ? !!value[ReactiveFlags.RAW] : false;
98
1045
  }
1046
+ exports2.ComputedDep = ComputedReactivity;
1047
+ exports2.Dep = Reactivity;
1048
+ exports2.EffectDep = EffectReactivity;
1049
+ exports2.RefReactivity = RefReactivity;
1050
+ exports2.batchRun = batchRun;
99
1051
  exports2.computed = computed;
1052
+ exports2.effect = effect;
1053
+ exports2.forceTrack = forceTrack;
1054
+ exports2.isProxy = isProxy;
1055
+ exports2.isReactive = isReactive;
1056
+ exports2.isRef = isRef;
1057
+ exports2.noTrack = noTrack;
1058
+ exports2.reactive = reactive;
100
1059
  exports2.ref = ref;
1060
+ exports2.toRaw = toRaw;
101
1061
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
102
1062
  });
103
1063
  //# sourceMappingURL=index.umd.cjs.map