@vue/reactivity 3.4.25 → 3.5.0-alpha.1

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,9 +1,9 @@
1
1
  /**
2
- * @vue/reactivity v3.4.25
2
+ * @vue/reactivity v3.5.0-alpha.1
3
3
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
4
4
  * @license MIT
5
5
  **/
6
- import { NOOP, extend, isArray, isSymbol, isMap, isIntegerKey, hasOwn, hasChanged, isObject, makeMap, capitalize, toRawType, def, isFunction } from '@vue/shared';
6
+ import { hasChanged, extend, isArray, isIntegerKey, isSymbol, isMap, hasOwn, isObject, makeMap, capitalize, toRawType, def, isFunction } from '@vue/shared';
7
7
 
8
8
  function warn(msg, ...args) {
9
9
  console.warn(`[Vue warn] ${msg}`, ...args);
@@ -91,157 +91,296 @@ class EffectScope {
91
91
  function effectScope(detached) {
92
92
  return new EffectScope(detached);
93
93
  }
94
- function recordEffectScope(effect, scope = activeEffectScope) {
95
- if (scope && scope.active) {
96
- scope.effects.push(effect);
97
- }
98
- }
99
94
  function getCurrentScope() {
100
95
  return activeEffectScope;
101
96
  }
102
- function onScopeDispose(fn) {
97
+ function onScopeDispose(fn, failSilently = false) {
103
98
  if (activeEffectScope) {
104
99
  activeEffectScope.cleanups.push(fn);
105
- } else if (!!(process.env.NODE_ENV !== "production")) {
100
+ } else if (!!(process.env.NODE_ENV !== "production") && !failSilently) {
106
101
  warn(
107
102
  `onScopeDispose() is called when there is no active effect scope to be associated with.`
108
103
  );
109
104
  }
110
105
  }
111
106
 
112
- let activeEffect;
107
+ let activeSub;
108
+ const EffectFlags = {
109
+ "ACTIVE": 1,
110
+ "1": "ACTIVE",
111
+ "RUNNING": 2,
112
+ "2": "RUNNING",
113
+ "TRACKING": 4,
114
+ "4": "TRACKING",
115
+ "NOTIFIED": 8,
116
+ "8": "NOTIFIED",
117
+ "DIRTY": 16,
118
+ "16": "DIRTY",
119
+ "ALLOW_RECURSE": 32,
120
+ "32": "ALLOW_RECURSE",
121
+ "NO_BATCH": 64,
122
+ "64": "NO_BATCH"
123
+ };
113
124
  class ReactiveEffect {
114
- constructor(fn, trigger, scheduler, scope) {
125
+ constructor(fn) {
115
126
  this.fn = fn;
116
- this.trigger = trigger;
117
- this.scheduler = scheduler;
118
- this.active = true;
119
- this.deps = [];
120
127
  /**
121
128
  * @internal
122
129
  */
123
- this._dirtyLevel = 4;
130
+ this.deps = void 0;
124
131
  /**
125
132
  * @internal
126
133
  */
127
- this._trackId = 0;
134
+ this.depsTail = void 0;
128
135
  /**
129
136
  * @internal
130
137
  */
131
- this._runnings = 0;
138
+ this.flags = 1 | 4;
132
139
  /**
133
140
  * @internal
134
141
  */
135
- this._shouldSchedule = false;
142
+ this.nextEffect = void 0;
136
143
  /**
137
144
  * @internal
138
145
  */
139
- this._depsLength = 0;
140
- recordEffectScope(this, scope);
141
- }
142
- get dirty() {
143
- if (this._dirtyLevel === 2 || this._dirtyLevel === 3) {
144
- this._dirtyLevel = 1;
145
- pauseTracking();
146
- for (let i = 0; i < this._depsLength; i++) {
147
- const dep = this.deps[i];
148
- if (dep.computed) {
149
- triggerComputed(dep.computed);
150
- if (this._dirtyLevel >= 4) {
151
- break;
152
- }
153
- }
154
- }
155
- if (this._dirtyLevel === 1) {
156
- this._dirtyLevel = 0;
157
- }
158
- resetTracking();
146
+ this.cleanup = void 0;
147
+ this.scheduler = void 0;
148
+ if (activeEffectScope && activeEffectScope.active) {
149
+ activeEffectScope.effects.push(this);
159
150
  }
160
- return this._dirtyLevel >= 4;
161
151
  }
162
- set dirty(v) {
163
- this._dirtyLevel = v ? 4 : 0;
152
+ /**
153
+ * @internal
154
+ */
155
+ notify() {
156
+ if (this.flags & 2 && !(this.flags & 32)) {
157
+ return;
158
+ }
159
+ if (this.flags & 64) {
160
+ return this.trigger();
161
+ }
162
+ if (!(this.flags & 8)) {
163
+ this.flags |= 8;
164
+ this.nextEffect = batchedEffect;
165
+ batchedEffect = this;
166
+ }
164
167
  }
165
168
  run() {
166
- this._dirtyLevel = 0;
167
- if (!this.active) {
169
+ if (!(this.flags & 1)) {
168
170
  return this.fn();
169
171
  }
170
- let lastShouldTrack = shouldTrack;
171
- let lastEffect = activeEffect;
172
+ this.flags |= 2;
173
+ cleanupEffect(this);
174
+ prepareDeps(this);
175
+ const prevEffect = activeSub;
176
+ const prevShouldTrack = shouldTrack;
177
+ activeSub = this;
178
+ shouldTrack = true;
172
179
  try {
173
- shouldTrack = true;
174
- activeEffect = this;
175
- this._runnings++;
176
- preCleanupEffect(this);
177
180
  return this.fn();
178
181
  } finally {
179
- postCleanupEffect(this);
180
- this._runnings--;
181
- activeEffect = lastEffect;
182
- shouldTrack = lastShouldTrack;
182
+ if (!!(process.env.NODE_ENV !== "production") && activeSub !== this) {
183
+ warn(
184
+ "Active effect was not restored correctly - this is likely a Vue internal bug."
185
+ );
186
+ }
187
+ cleanupDeps(this);
188
+ activeSub = prevEffect;
189
+ shouldTrack = prevShouldTrack;
190
+ this.flags &= ~2;
183
191
  }
184
192
  }
185
193
  stop() {
186
- var _a;
187
- if (this.active) {
188
- preCleanupEffect(this);
189
- postCleanupEffect(this);
190
- (_a = this.onStop) == null ? void 0 : _a.call(this);
191
- this.active = false;
194
+ if (this.flags & 1) {
195
+ for (let link = this.deps; link; link = link.nextDep) {
196
+ removeSub(link);
197
+ }
198
+ this.deps = this.depsTail = void 0;
199
+ cleanupEffect(this);
200
+ this.onStop && this.onStop();
201
+ this.flags &= ~1;
202
+ }
203
+ }
204
+ trigger() {
205
+ if (this.scheduler) {
206
+ this.scheduler();
207
+ } else {
208
+ this.runIfDirty();
209
+ }
210
+ }
211
+ /**
212
+ * @internal
213
+ */
214
+ runIfDirty() {
215
+ if (isDirty(this)) {
216
+ this.run();
192
217
  }
193
218
  }
219
+ get dirty() {
220
+ return isDirty(this);
221
+ }
194
222
  }
195
- function triggerComputed(computed) {
196
- return computed.value;
223
+ let batchDepth = 0;
224
+ let batchedEffect;
225
+ function startBatch() {
226
+ batchDepth++;
197
227
  }
198
- function preCleanupEffect(effect2) {
199
- effect2._trackId++;
200
- effect2._depsLength = 0;
228
+ function endBatch() {
229
+ if (batchDepth > 1) {
230
+ batchDepth--;
231
+ return;
232
+ }
233
+ let error;
234
+ while (batchedEffect) {
235
+ let e = batchedEffect;
236
+ batchedEffect = void 0;
237
+ while (e) {
238
+ const next = e.nextEffect;
239
+ e.nextEffect = void 0;
240
+ e.flags &= ~8;
241
+ if (e.flags & 1) {
242
+ try {
243
+ e.trigger();
244
+ } catch (err) {
245
+ if (!error)
246
+ error = err;
247
+ }
248
+ }
249
+ e = next;
250
+ }
251
+ }
252
+ batchDepth--;
253
+ if (error)
254
+ throw error;
255
+ }
256
+ function prepareDeps(sub) {
257
+ for (let link = sub.deps; link; link = link.nextDep) {
258
+ link.version = -1;
259
+ link.prevActiveLink = link.dep.activeLink;
260
+ link.dep.activeLink = link;
261
+ }
262
+ }
263
+ function cleanupDeps(sub) {
264
+ let head;
265
+ let tail = sub.depsTail;
266
+ for (let link = tail; link; link = link.prevDep) {
267
+ if (link.version === -1) {
268
+ if (link === tail)
269
+ tail = link.prevDep;
270
+ removeSub(link);
271
+ removeDep(link);
272
+ } else {
273
+ head = link;
274
+ }
275
+ link.dep.activeLink = link.prevActiveLink;
276
+ link.prevActiveLink = void 0;
277
+ }
278
+ sub.deps = head;
279
+ sub.depsTail = tail;
201
280
  }
202
- function postCleanupEffect(effect2) {
203
- if (effect2.deps.length > effect2._depsLength) {
204
- for (let i = effect2._depsLength; i < effect2.deps.length; i++) {
205
- cleanupDepEffect(effect2.deps[i], effect2);
281
+ function isDirty(sub) {
282
+ for (let link = sub.deps; link; link = link.nextDep) {
283
+ if (link.dep.version !== link.version || link.dep.computed && refreshComputed(link.dep.computed) === false || link.dep.version !== link.version) {
284
+ return true;
206
285
  }
207
- effect2.deps.length = effect2._depsLength;
208
286
  }
287
+ if (sub._dirty) {
288
+ return true;
289
+ }
290
+ return false;
209
291
  }
210
- function cleanupDepEffect(dep, effect2) {
211
- const trackId = dep.get(effect2);
212
- if (trackId !== void 0 && effect2._trackId !== trackId) {
213
- dep.delete(effect2);
214
- if (dep.size === 0) {
215
- dep.cleanup();
292
+ function refreshComputed(computed) {
293
+ if (computed.flags & 2) {
294
+ return false;
295
+ }
296
+ if (computed.flags & 4 && !(computed.flags & 16)) {
297
+ return;
298
+ }
299
+ computed.flags &= ~16;
300
+ if (computed.globalVersion === globalVersion) {
301
+ return;
302
+ }
303
+ computed.globalVersion = globalVersion;
304
+ const dep = computed.dep;
305
+ computed.flags |= 2;
306
+ if (dep.version > 0 && !computed.isSSR && !isDirty(computed)) {
307
+ computed.flags &= ~2;
308
+ return;
309
+ }
310
+ const prevSub = activeSub;
311
+ const prevShouldTrack = shouldTrack;
312
+ activeSub = computed;
313
+ shouldTrack = true;
314
+ try {
315
+ prepareDeps(computed);
316
+ const value = computed.fn();
317
+ if (dep.version === 0 || hasChanged(value, computed._value)) {
318
+ computed._value = value;
319
+ dep.version++;
320
+ }
321
+ } catch (err) {
322
+ dep.version++;
323
+ throw err;
324
+ } finally {
325
+ activeSub = prevSub;
326
+ shouldTrack = prevShouldTrack;
327
+ cleanupDeps(computed);
328
+ computed.flags &= ~2;
329
+ }
330
+ }
331
+ function removeSub(link) {
332
+ const { dep, prevSub, nextSub } = link;
333
+ if (prevSub) {
334
+ prevSub.nextSub = nextSub;
335
+ link.prevSub = void 0;
336
+ }
337
+ if (nextSub) {
338
+ nextSub.prevSub = prevSub;
339
+ link.nextSub = void 0;
340
+ }
341
+ if (dep.subs === link) {
342
+ dep.subs = prevSub;
343
+ }
344
+ if (!dep.subs && dep.computed) {
345
+ dep.computed.flags &= ~4;
346
+ for (let l = dep.computed.deps; l; l = l.nextDep) {
347
+ removeSub(l);
216
348
  }
217
349
  }
218
350
  }
351
+ function removeDep(link) {
352
+ const { prevDep, nextDep } = link;
353
+ if (prevDep) {
354
+ prevDep.nextDep = nextDep;
355
+ link.prevDep = void 0;
356
+ }
357
+ if (nextDep) {
358
+ nextDep.prevDep = prevDep;
359
+ link.nextDep = void 0;
360
+ }
361
+ }
219
362
  function effect(fn, options) {
220
363
  if (fn.effect instanceof ReactiveEffect) {
221
364
  fn = fn.effect.fn;
222
365
  }
223
- const _effect = new ReactiveEffect(fn, NOOP, () => {
224
- if (_effect.dirty) {
225
- _effect.run();
226
- }
227
- });
366
+ const e = new ReactiveEffect(fn);
228
367
  if (options) {
229
- extend(_effect, options);
230
- if (options.scope)
231
- recordEffectScope(_effect, options.scope);
368
+ extend(e, options);
232
369
  }
233
- if (!options || !options.lazy) {
234
- _effect.run();
370
+ try {
371
+ e.run();
372
+ } catch (err) {
373
+ e.stop();
374
+ throw err;
235
375
  }
236
- const runner = _effect.run.bind(_effect);
237
- runner.effect = _effect;
376
+ const runner = e.run.bind(e);
377
+ runner.effect = e;
238
378
  return runner;
239
379
  }
240
380
  function stop(runner) {
241
381
  runner.effect.stop();
242
382
  }
243
383
  let shouldTrack = true;
244
- let pauseScheduleStack = 0;
245
384
  const trackStack = [];
246
385
  function pauseTracking() {
247
386
  trackStack.push(shouldTrack);
@@ -255,192 +394,427 @@ function resetTracking() {
255
394
  const last = trackStack.pop();
256
395
  shouldTrack = last === void 0 ? true : last;
257
396
  }
258
- function pauseScheduling() {
259
- pauseScheduleStack++;
260
- }
261
- function resetScheduling() {
262
- pauseScheduleStack--;
263
- while (!pauseScheduleStack && queueEffectSchedulers.length) {
264
- queueEffectSchedulers.shift()();
397
+ function onEffectCleanup(fn, failSilently = false) {
398
+ if (activeSub instanceof ReactiveEffect) {
399
+ activeSub.cleanup = fn;
400
+ } else if (!!(process.env.NODE_ENV !== "production") && !failSilently) {
401
+ warn(
402
+ `onEffectCleanup() was called when there was no active effect to associate with.`
403
+ );
265
404
  }
266
405
  }
267
- function trackEffect(effect2, dep, debuggerEventExtraInfo) {
268
- var _a;
269
- if (dep.get(effect2) !== effect2._trackId) {
270
- dep.set(effect2, effect2._trackId);
271
- const oldDep = effect2.deps[effect2._depsLength];
272
- if (oldDep !== dep) {
273
- if (oldDep) {
274
- cleanupDepEffect(oldDep, effect2);
275
- }
276
- effect2.deps[effect2._depsLength++] = dep;
277
- } else {
278
- effect2._depsLength++;
406
+ function cleanupEffect(e) {
407
+ const { cleanup } = e;
408
+ e.cleanup = void 0;
409
+ if (cleanup) {
410
+ const prevSub = activeSub;
411
+ activeSub = void 0;
412
+ try {
413
+ cleanup();
414
+ } finally {
415
+ activeSub = prevSub;
279
416
  }
417
+ }
418
+ }
419
+
420
+ let globalVersion = 0;
421
+ class Dep {
422
+ constructor(computed) {
423
+ this.computed = computed;
424
+ this.version = 0;
425
+ /**
426
+ * Link between this dep and the current active effect
427
+ */
428
+ this.activeLink = void 0;
429
+ /**
430
+ * Doubly linked list representing the subscribing effects (tail)
431
+ */
432
+ this.subs = void 0;
280
433
  if (!!(process.env.NODE_ENV !== "production")) {
281
- (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));
434
+ this.subsHead = void 0;
282
435
  }
283
436
  }
284
- }
285
- const queueEffectSchedulers = [];
286
- function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) {
287
- var _a;
288
- pauseScheduling();
289
- for (const effect2 of dep.keys()) {
290
- let tracking;
291
- if (effect2._dirtyLevel < dirtyLevel && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {
292
- effect2._shouldSchedule || (effect2._shouldSchedule = effect2._dirtyLevel === 0);
293
- effect2._dirtyLevel = dirtyLevel;
437
+ track(debugInfo) {
438
+ if (!activeSub || !shouldTrack) {
439
+ return;
294
440
  }
295
- if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {
296
- if (!!(process.env.NODE_ENV !== "production")) {
297
- (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));
441
+ let link = this.activeLink;
442
+ if (link === void 0 || link.sub !== activeSub) {
443
+ link = this.activeLink = {
444
+ dep: this,
445
+ sub: activeSub,
446
+ version: this.version,
447
+ nextDep: void 0,
448
+ prevDep: void 0,
449
+ nextSub: void 0,
450
+ prevSub: void 0,
451
+ prevActiveLink: void 0
452
+ };
453
+ if (!activeSub.deps) {
454
+ activeSub.deps = activeSub.depsTail = link;
455
+ } else {
456
+ link.prevDep = activeSub.depsTail;
457
+ activeSub.depsTail.nextDep = link;
458
+ activeSub.depsTail = link;
459
+ }
460
+ if (activeSub.flags & 4) {
461
+ addSub(link);
298
462
  }
299
- effect2.trigger();
300
- if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) {
301
- effect2._shouldSchedule = false;
302
- if (effect2.scheduler) {
303
- queueEffectSchedulers.push(effect2.scheduler);
463
+ } else if (link.version === -1) {
464
+ link.version = this.version;
465
+ if (link.nextDep) {
466
+ const next = link.nextDep;
467
+ next.prevDep = link.prevDep;
468
+ if (link.prevDep) {
469
+ link.prevDep.nextDep = next;
470
+ }
471
+ link.prevDep = activeSub.depsTail;
472
+ link.nextDep = void 0;
473
+ activeSub.depsTail.nextDep = link;
474
+ activeSub.depsTail = link;
475
+ if (activeSub.deps === link) {
476
+ activeSub.deps = next;
477
+ }
478
+ }
479
+ }
480
+ if (!!(process.env.NODE_ENV !== "production") && activeSub.onTrack) {
481
+ activeSub.onTrack(
482
+ extend(
483
+ {
484
+ effect: activeSub
485
+ },
486
+ debugInfo
487
+ )
488
+ );
489
+ }
490
+ return link;
491
+ }
492
+ trigger(debugInfo) {
493
+ this.version++;
494
+ globalVersion++;
495
+ this.notify(debugInfo);
496
+ }
497
+ notify(debugInfo) {
498
+ startBatch();
499
+ try {
500
+ if (!!(process.env.NODE_ENV !== "production")) {
501
+ for (let head = this.subsHead; head; head = head.nextSub) {
502
+ if (!!(process.env.NODE_ENV !== "production") && head.sub.onTrigger && !(head.sub.flags & 8)) {
503
+ head.sub.onTrigger(
504
+ extend(
505
+ {
506
+ effect: head.sub
507
+ },
508
+ debugInfo
509
+ )
510
+ );
511
+ }
304
512
  }
305
513
  }
514
+ for (let link = this.subs; link; link = link.prevSub) {
515
+ link.sub.notify();
516
+ }
517
+ } finally {
518
+ endBatch();
306
519
  }
307
520
  }
308
- resetScheduling();
309
521
  }
310
-
311
- const createDep = (cleanup, computed) => {
312
- const dep = /* @__PURE__ */ new Map();
313
- dep.cleanup = cleanup;
314
- dep.computed = computed;
315
- return dep;
316
- };
317
-
522
+ function addSub(link) {
523
+ const computed = link.dep.computed;
524
+ if (computed && !link.dep.subs) {
525
+ computed.flags |= 4 | 16;
526
+ for (let l = computed.deps; l; l = l.nextDep) {
527
+ addSub(l);
528
+ }
529
+ }
530
+ const currentTail = link.dep.subs;
531
+ if (currentTail !== link) {
532
+ link.prevSub = currentTail;
533
+ if (currentTail)
534
+ currentTail.nextSub = link;
535
+ }
536
+ if (!!(process.env.NODE_ENV !== "production") && link.dep.subsHead === void 0) {
537
+ link.dep.subsHead = link;
538
+ }
539
+ link.dep.subs = link;
540
+ }
318
541
  const targetMap = /* @__PURE__ */ new WeakMap();
319
- const ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== "production") ? "iterate" : "");
320
- const MAP_KEY_ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== "production") ? "Map key iterate" : "");
542
+ const ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== "production") ? "Object iterate" : "");
543
+ const MAP_KEY_ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== "production") ? "Map keys iterate" : "");
544
+ const ARRAY_ITERATE_KEY = Symbol(!!(process.env.NODE_ENV !== "production") ? "Array iterate" : "");
321
545
  function track(target, type, key) {
322
- if (shouldTrack && activeEffect) {
546
+ if (shouldTrack && activeSub) {
323
547
  let depsMap = targetMap.get(target);
324
548
  if (!depsMap) {
325
549
  targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
326
550
  }
327
551
  let dep = depsMap.get(key);
328
552
  if (!dep) {
329
- depsMap.set(key, dep = createDep(() => depsMap.delete(key)));
553
+ depsMap.set(key, dep = new Dep());
330
554
  }
331
- trackEffect(
332
- activeEffect,
333
- dep,
334
- !!(process.env.NODE_ENV !== "production") ? {
555
+ if (!!(process.env.NODE_ENV !== "production")) {
556
+ dep.track({
335
557
  target,
336
558
  type,
337
559
  key
338
- } : void 0
339
- );
560
+ });
561
+ } else {
562
+ dep.track();
563
+ }
340
564
  }
341
565
  }
342
566
  function trigger(target, type, key, newValue, oldValue, oldTarget) {
343
567
  const depsMap = targetMap.get(target);
344
568
  if (!depsMap) {
569
+ globalVersion++;
345
570
  return;
346
571
  }
347
572
  let deps = [];
348
573
  if (type === "clear") {
349
574
  deps = [...depsMap.values()];
350
- } else if (key === "length" && isArray(target)) {
351
- const newLength = Number(newValue);
352
- depsMap.forEach((dep, key2) => {
353
- if (key2 === "length" || !isSymbol(key2) && key2 >= newLength) {
354
- deps.push(dep);
355
- }
356
- });
357
575
  } else {
358
- if (key !== void 0) {
359
- deps.push(depsMap.get(key));
360
- }
361
- switch (type) {
362
- case "add":
363
- if (!isArray(target)) {
364
- deps.push(depsMap.get(ITERATE_KEY));
365
- if (isMap(target)) {
366
- deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
367
- }
368
- } else if (isIntegerKey(key)) {
369
- deps.push(depsMap.get("length"));
576
+ const targetIsArray = isArray(target);
577
+ const isArrayIndex = targetIsArray && isIntegerKey(key);
578
+ if (targetIsArray && key === "length") {
579
+ const newLength = Number(newValue);
580
+ depsMap.forEach((dep, key2) => {
581
+ if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) {
582
+ deps.push(dep);
370
583
  }
371
- break;
372
- case "delete":
373
- if (!isArray(target)) {
374
- deps.push(depsMap.get(ITERATE_KEY));
584
+ });
585
+ } else {
586
+ const push = (dep) => dep && deps.push(dep);
587
+ if (key !== void 0) {
588
+ push(depsMap.get(key));
589
+ }
590
+ if (isArrayIndex) {
591
+ push(depsMap.get(ARRAY_ITERATE_KEY));
592
+ }
593
+ switch (type) {
594
+ case "add":
595
+ if (!targetIsArray) {
596
+ push(depsMap.get(ITERATE_KEY));
597
+ if (isMap(target)) {
598
+ push(depsMap.get(MAP_KEY_ITERATE_KEY));
599
+ }
600
+ } else if (isArrayIndex) {
601
+ push(depsMap.get("length"));
602
+ }
603
+ break;
604
+ case "delete":
605
+ if (!targetIsArray) {
606
+ push(depsMap.get(ITERATE_KEY));
607
+ if (isMap(target)) {
608
+ push(depsMap.get(MAP_KEY_ITERATE_KEY));
609
+ }
610
+ }
611
+ break;
612
+ case "set":
375
613
  if (isMap(target)) {
376
- deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
614
+ push(depsMap.get(ITERATE_KEY));
377
615
  }
378
- }
379
- break;
380
- case "set":
381
- if (isMap(target)) {
382
- deps.push(depsMap.get(ITERATE_KEY));
383
- }
384
- break;
616
+ break;
617
+ }
385
618
  }
386
619
  }
387
- pauseScheduling();
620
+ startBatch();
388
621
  for (const dep of deps) {
389
- if (dep) {
390
- triggerEffects(
391
- dep,
392
- 4,
393
- !!(process.env.NODE_ENV !== "production") ? {
394
- target,
395
- type,
396
- key,
397
- newValue,
398
- oldValue,
399
- oldTarget
400
- } : void 0
401
- );
622
+ if (!!(process.env.NODE_ENV !== "production")) {
623
+ dep.trigger({
624
+ target,
625
+ type,
626
+ key,
627
+ newValue,
628
+ oldValue,
629
+ oldTarget
630
+ });
631
+ } else {
632
+ dep.trigger();
402
633
  }
403
634
  }
404
- resetScheduling();
635
+ endBatch();
405
636
  }
406
637
  function getDepFromReactive(object, key) {
407
638
  var _a;
408
639
  return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key);
409
640
  }
410
641
 
642
+ function reactiveReadArray(array) {
643
+ const raw = toRaw(array);
644
+ if (raw === array)
645
+ return raw;
646
+ track(raw, "iterate", ARRAY_ITERATE_KEY);
647
+ return isShallow(array) ? raw : raw.map(toReactive);
648
+ }
649
+ function shallowReadArray(arr) {
650
+ track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY);
651
+ return arr;
652
+ }
653
+ const arrayInstrumentations = {
654
+ __proto__: null,
655
+ [Symbol.iterator]() {
656
+ return iterator(this, Symbol.iterator, toReactive);
657
+ },
658
+ concat(...args) {
659
+ return reactiveReadArray(this).concat(
660
+ ...args.map((x) => reactiveReadArray(x))
661
+ );
662
+ },
663
+ entries() {
664
+ return iterator(this, "entries", (value) => {
665
+ value[1] = toReactive(value[1]);
666
+ return value;
667
+ });
668
+ },
669
+ every(fn, thisArg) {
670
+ return apply(this, "every", fn, thisArg);
671
+ },
672
+ filter(fn, thisArg) {
673
+ const result = apply(this, "filter", fn, thisArg);
674
+ return isProxy(this) && !isShallow(this) ? result.map(toReactive) : result;
675
+ },
676
+ find(fn, thisArg) {
677
+ const result = apply(this, "find", fn, thisArg);
678
+ return isProxy(this) && !isShallow(this) ? toReactive(result) : result;
679
+ },
680
+ findIndex(fn, thisArg) {
681
+ return apply(this, "findIndex", fn, thisArg);
682
+ },
683
+ findLast(fn, thisArg) {
684
+ const result = apply(this, "findLast", fn, thisArg);
685
+ return isProxy(this) && !isShallow(this) ? toReactive(result) : result;
686
+ },
687
+ findLastIndex(fn, thisArg) {
688
+ return apply(this, "findLastIndex", fn, thisArg);
689
+ },
690
+ // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement
691
+ forEach(fn, thisArg) {
692
+ return apply(this, "forEach", fn, thisArg);
693
+ },
694
+ includes(...args) {
695
+ return searchProxy(this, "includes", args);
696
+ },
697
+ indexOf(...args) {
698
+ return searchProxy(this, "indexOf", args);
699
+ },
700
+ join(separator) {
701
+ return reactiveReadArray(this).join(separator);
702
+ },
703
+ // keys() iterator only reads `length`, no optimisation required
704
+ lastIndexOf(...args) {
705
+ return searchProxy(this, "lastIndexOf", args);
706
+ },
707
+ map(fn, thisArg) {
708
+ return apply(this, "map", fn, thisArg);
709
+ },
710
+ pop() {
711
+ return noTracking(this, "pop");
712
+ },
713
+ push(...args) {
714
+ return noTracking(this, "push", args);
715
+ },
716
+ reduce(fn, ...args) {
717
+ return reduce(this, "reduce", fn, args);
718
+ },
719
+ reduceRight(fn, ...args) {
720
+ return reduce(this, "reduceRight", fn, args);
721
+ },
722
+ shift() {
723
+ return noTracking(this, "shift");
724
+ },
725
+ // slice could use ARRAY_ITERATE but also seems to beg for range tracking
726
+ some(fn, thisArg) {
727
+ return apply(this, "some", fn, thisArg);
728
+ },
729
+ splice(...args) {
730
+ return noTracking(this, "splice", args);
731
+ },
732
+ toReversed() {
733
+ return reactiveReadArray(this).toReversed();
734
+ },
735
+ toSorted(comparer) {
736
+ return reactiveReadArray(this).toSorted(comparer);
737
+ },
738
+ toSpliced(...args) {
739
+ return reactiveReadArray(this).toSpliced(...args);
740
+ },
741
+ unshift(...args) {
742
+ return noTracking(this, "unshift", args);
743
+ },
744
+ values() {
745
+ return iterator(this, "values", toReactive);
746
+ }
747
+ };
748
+ function iterator(self, method, wrapValue) {
749
+ const arr = shallowReadArray(self);
750
+ const iter = arr[method]();
751
+ if (arr !== self && !isShallow(self)) {
752
+ iter._next = iter.next;
753
+ iter.next = () => {
754
+ const result = iter._next();
755
+ if (result.value) {
756
+ result.value = wrapValue(result.value);
757
+ }
758
+ return result;
759
+ };
760
+ }
761
+ return iter;
762
+ }
763
+ function apply(self, method, fn, thisArg) {
764
+ const arr = shallowReadArray(self);
765
+ let wrappedFn = fn;
766
+ if (arr !== self) {
767
+ if (!isShallow(self)) {
768
+ wrappedFn = function(item, index) {
769
+ return fn.call(this, toReactive(item), index, self);
770
+ };
771
+ } else if (fn.length > 2) {
772
+ wrappedFn = function(item, index) {
773
+ return fn.call(this, item, index, self);
774
+ };
775
+ }
776
+ }
777
+ return arr[method](wrappedFn, thisArg);
778
+ }
779
+ function reduce(self, method, fn, args) {
780
+ const arr = shallowReadArray(self);
781
+ let wrappedFn = fn;
782
+ if (arr !== self) {
783
+ if (!isShallow(self)) {
784
+ wrappedFn = function(acc, item, index) {
785
+ return fn.call(this, acc, toReactive(item), index, self);
786
+ };
787
+ } else if (fn.length > 3) {
788
+ wrappedFn = function(acc, item, index) {
789
+ return fn.call(this, acc, item, index, self);
790
+ };
791
+ }
792
+ }
793
+ return arr[method](wrappedFn, ...args);
794
+ }
795
+ function searchProxy(self, method, args) {
796
+ const arr = toRaw(self);
797
+ track(arr, "iterate", ARRAY_ITERATE_KEY);
798
+ const res = arr[method](...args);
799
+ if ((res === -1 || res === false) && isProxy(args[0])) {
800
+ args[0] = toRaw(args[0]);
801
+ return arr[method](...args);
802
+ }
803
+ return res;
804
+ }
805
+ function noTracking(self, method, args = []) {
806
+ pauseTracking();
807
+ startBatch();
808
+ const res = toRaw(self)[method].apply(self, args);
809
+ endBatch();
810
+ resetTracking();
811
+ return res;
812
+ }
813
+
411
814
  const isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);
412
815
  const builtInSymbols = new Set(
413
816
  /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol)
414
817
  );
415
- const arrayInstrumentations = /* @__PURE__ */ createArrayInstrumentations();
416
- function createArrayInstrumentations() {
417
- const instrumentations = {};
418
- ["includes", "indexOf", "lastIndexOf"].forEach((key) => {
419
- instrumentations[key] = function(...args) {
420
- const arr = toRaw(this);
421
- for (let i = 0, l = this.length; i < l; i++) {
422
- track(arr, "get", i + "");
423
- }
424
- const res = arr[key](...args);
425
- if (res === -1 || res === false) {
426
- return arr[key](...args.map(toRaw));
427
- } else {
428
- return res;
429
- }
430
- };
431
- });
432
- ["push", "pop", "shift", "unshift", "splice"].forEach((key) => {
433
- instrumentations[key] = function(...args) {
434
- pauseTracking();
435
- pauseScheduling();
436
- const res = toRaw(this)[key].apply(this, args);
437
- resetScheduling();
438
- resetTracking();
439
- return res;
440
- };
441
- });
442
- return instrumentations;
443
- }
444
818
  function hasOwnProperty(key) {
445
819
  if (!isSymbol(key))
446
820
  key = String(key);
@@ -471,14 +845,22 @@ class BaseReactiveHandler {
471
845
  }
472
846
  const targetIsArray = isArray(target);
473
847
  if (!isReadonly2) {
474
- if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
475
- return Reflect.get(arrayInstrumentations, key, receiver);
848
+ let fn;
849
+ if (targetIsArray && (fn = arrayInstrumentations[key])) {
850
+ return fn;
476
851
  }
477
852
  if (key === "hasOwnProperty") {
478
853
  return hasOwnProperty;
479
854
  }
480
855
  }
481
- const res = Reflect.get(target, key, receiver);
856
+ const res = Reflect.get(
857
+ target,
858
+ key,
859
+ // if this is a proxy wrapping a ref, return methods using the raw ref
860
+ // as receiver so that we don't have to call `toRaw` on the ref in all
861
+ // its class methods
862
+ isRef(target) ? target : receiver
863
+ );
482
864
  if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
483
865
  return res;
484
866
  }
@@ -977,110 +1359,8 @@ function markRaw(value) {
977
1359
  const toReactive = (value) => isObject(value) ? reactive(value) : value;
978
1360
  const toReadonly = (value) => isObject(value) ? readonly(value) : value;
979
1361
 
980
- const COMPUTED_SIDE_EFFECT_WARN = `Computed is still dirty after getter evaluation, likely because a computed is mutating its own dependency in its getter. State mutations in computed getters should be avoided. Check the docs for more details: https://vuejs.org/guide/essentials/computed.html#getters-should-be-side-effect-free`;
981
- class ComputedRefImpl {
982
- constructor(getter, _setter, isReadonly, isSSR) {
983
- this.getter = getter;
984
- this._setter = _setter;
985
- this.dep = void 0;
986
- this.__v_isRef = true;
987
- this["__v_isReadonly"] = false;
988
- this.effect = new ReactiveEffect(
989
- () => getter(this._value),
990
- () => triggerRefValue(
991
- this,
992
- this.effect._dirtyLevel === 2 ? 2 : 3
993
- )
994
- );
995
- this.effect.computed = this;
996
- this.effect.active = this._cacheable = !isSSR;
997
- this["__v_isReadonly"] = isReadonly;
998
- }
999
- get value() {
1000
- const self = toRaw(this);
1001
- if ((!self._cacheable || self.effect.dirty) && hasChanged(self._value, self._value = self.effect.run())) {
1002
- triggerRefValue(self, 4);
1003
- }
1004
- trackRefValue(self);
1005
- if (self.effect._dirtyLevel >= 2) {
1006
- if (!!(process.env.NODE_ENV !== "production") && this._warnRecursive) {
1007
- warn(COMPUTED_SIDE_EFFECT_WARN, `
1008
-
1009
- getter: `, this.getter);
1010
- }
1011
- triggerRefValue(self, 2);
1012
- }
1013
- return self._value;
1014
- }
1015
- set value(newValue) {
1016
- this._setter(newValue);
1017
- }
1018
- // #region polyfill _dirty for backward compatibility third party code for Vue <= 3.3.x
1019
- get _dirty() {
1020
- return this.effect.dirty;
1021
- }
1022
- set _dirty(v) {
1023
- this.effect.dirty = v;
1024
- }
1025
- // #endregion
1026
- }
1027
- function computed(getterOrOptions, debugOptions, isSSR = false) {
1028
- let getter;
1029
- let setter;
1030
- const onlyGetter = isFunction(getterOrOptions);
1031
- if (onlyGetter) {
1032
- getter = getterOrOptions;
1033
- setter = !!(process.env.NODE_ENV !== "production") ? () => {
1034
- warn("Write operation failed: computed value is readonly");
1035
- } : NOOP;
1036
- } else {
1037
- getter = getterOrOptions.get;
1038
- setter = getterOrOptions.set;
1039
- }
1040
- const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR);
1041
- if (!!(process.env.NODE_ENV !== "production") && debugOptions && !isSSR) {
1042
- cRef.effect.onTrack = debugOptions.onTrack;
1043
- cRef.effect.onTrigger = debugOptions.onTrigger;
1044
- }
1045
- return cRef;
1046
- }
1047
-
1048
- function trackRefValue(ref2) {
1049
- var _a;
1050
- if (shouldTrack && activeEffect) {
1051
- ref2 = toRaw(ref2);
1052
- trackEffect(
1053
- activeEffect,
1054
- (_a = ref2.dep) != null ? _a : ref2.dep = createDep(
1055
- () => ref2.dep = void 0,
1056
- ref2 instanceof ComputedRefImpl ? ref2 : void 0
1057
- ),
1058
- !!(process.env.NODE_ENV !== "production") ? {
1059
- target: ref2,
1060
- type: "get",
1061
- key: "value"
1062
- } : void 0
1063
- );
1064
- }
1065
- }
1066
- function triggerRefValue(ref2, dirtyLevel = 4, newVal) {
1067
- ref2 = toRaw(ref2);
1068
- const dep = ref2.dep;
1069
- if (dep) {
1070
- triggerEffects(
1071
- dep,
1072
- dirtyLevel,
1073
- !!(process.env.NODE_ENV !== "production") ? {
1074
- target: ref2,
1075
- type: "set",
1076
- key: "value",
1077
- newValue: newVal
1078
- } : void 0
1079
- );
1080
- }
1081
- }
1082
1362
  function isRef(r) {
1083
- return !!(r && r.__v_isRef === true);
1363
+ return r ? r.__v_isRef === true : false;
1084
1364
  }
1085
1365
  function ref(value) {
1086
1366
  return createRef(value, false);
@@ -1097,27 +1377,55 @@ function createRef(rawValue, shallow) {
1097
1377
  class RefImpl {
1098
1378
  constructor(value, __v_isShallow) {
1099
1379
  this.__v_isShallow = __v_isShallow;
1100
- this.dep = void 0;
1380
+ this.dep = new Dep();
1101
1381
  this.__v_isRef = true;
1102
1382
  this._rawValue = __v_isShallow ? value : toRaw(value);
1103
1383
  this._value = __v_isShallow ? value : toReactive(value);
1104
1384
  }
1105
1385
  get value() {
1106
- trackRefValue(this);
1386
+ if (!!(process.env.NODE_ENV !== "production")) {
1387
+ this.dep.track({
1388
+ target: this,
1389
+ type: "get",
1390
+ key: "value"
1391
+ });
1392
+ } else {
1393
+ this.dep.track();
1394
+ }
1107
1395
  return this._value;
1108
1396
  }
1109
- set value(newVal) {
1110
- const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
1111
- newVal = useDirectValue ? newVal : toRaw(newVal);
1112
- if (hasChanged(newVal, this._rawValue)) {
1113
- this._rawValue = newVal;
1114
- this._value = useDirectValue ? newVal : toReactive(newVal);
1115
- triggerRefValue(this, 4, newVal);
1397
+ set value(newValue) {
1398
+ const oldValue = this._rawValue;
1399
+ const useDirectValue = this.__v_isShallow || isShallow(newValue) || isReadonly(newValue);
1400
+ newValue = useDirectValue ? newValue : toRaw(newValue);
1401
+ if (hasChanged(newValue, oldValue)) {
1402
+ this._rawValue = newValue;
1403
+ this._value = useDirectValue ? newValue : toReactive(newValue);
1404
+ if (!!(process.env.NODE_ENV !== "production")) {
1405
+ this.dep.trigger({
1406
+ target: this,
1407
+ type: "set",
1408
+ key: "value",
1409
+ newValue,
1410
+ oldValue
1411
+ });
1412
+ } else {
1413
+ this.dep.trigger();
1414
+ }
1116
1415
  }
1117
1416
  }
1118
1417
  }
1119
1418
  function triggerRef(ref2) {
1120
- triggerRefValue(ref2, 4, !!(process.env.NODE_ENV !== "production") ? ref2.value : void 0);
1419
+ if (!!(process.env.NODE_ENV !== "production")) {
1420
+ ref2.dep.trigger({
1421
+ target: ref2,
1422
+ type: "set",
1423
+ key: "value",
1424
+ newValue: ref2._value
1425
+ });
1426
+ } else {
1427
+ ref2.dep.trigger();
1428
+ }
1121
1429
  }
1122
1430
  function unref(ref2) {
1123
1431
  return isRef(ref2) ? ref2.value : ref2;
@@ -1142,12 +1450,9 @@ function proxyRefs(objectWithRefs) {
1142
1450
  }
1143
1451
  class CustomRefImpl {
1144
1452
  constructor(factory) {
1145
- this.dep = void 0;
1146
1453
  this.__v_isRef = true;
1147
- const { get, set } = factory(
1148
- () => trackRefValue(this),
1149
- () => triggerRefValue(this)
1150
- );
1454
+ const dep = this.dep = new Dep();
1455
+ const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep));
1151
1456
  this._get = get;
1152
1457
  this._set = set;
1153
1458
  }
@@ -1215,7 +1520,89 @@ function propertyToRef(source, key, defaultValue) {
1215
1520
  return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue);
1216
1521
  }
1217
1522
 
1218
- const deferredComputed = computed;
1523
+ class ComputedRefImpl {
1524
+ constructor(fn, setter, isSSR) {
1525
+ this.fn = fn;
1526
+ this.setter = setter;
1527
+ /**
1528
+ * @internal
1529
+ */
1530
+ this._value = void 0;
1531
+ /**
1532
+ * @internal
1533
+ */
1534
+ this.dep = new Dep(this);
1535
+ /**
1536
+ * @internal
1537
+ */
1538
+ this.__v_isRef = true;
1539
+ // A computed is also a subscriber that tracks other deps
1540
+ /**
1541
+ * @internal
1542
+ */
1543
+ this.deps = void 0;
1544
+ /**
1545
+ * @internal
1546
+ */
1547
+ this.depsTail = void 0;
1548
+ /**
1549
+ * @internal
1550
+ */
1551
+ this.flags = 16;
1552
+ /**
1553
+ * @internal
1554
+ */
1555
+ this.globalVersion = globalVersion - 1;
1556
+ // for backwards compat
1557
+ this.effect = this;
1558
+ this.__v_isReadonly = !setter;
1559
+ this.isSSR = isSSR;
1560
+ }
1561
+ /**
1562
+ * @internal
1563
+ */
1564
+ notify() {
1565
+ if (activeSub !== this) {
1566
+ this.flags |= 16;
1567
+ this.dep.notify();
1568
+ } else if (!!(process.env.NODE_ENV !== "production")) ;
1569
+ }
1570
+ get value() {
1571
+ const link = !!(process.env.NODE_ENV !== "production") ? this.dep.track({
1572
+ target: this,
1573
+ type: "get",
1574
+ key: "value"
1575
+ }) : this.dep.track();
1576
+ refreshComputed(this);
1577
+ if (link) {
1578
+ link.version = this.dep.version;
1579
+ }
1580
+ return this._value;
1581
+ }
1582
+ set value(newValue) {
1583
+ if (this.setter) {
1584
+ this.setter(newValue);
1585
+ } else if (!!(process.env.NODE_ENV !== "production")) {
1586
+ warn("Write operation failed: computed value is readonly");
1587
+ }
1588
+ }
1589
+ }
1590
+ function computed(getterOrOptions, debugOptions, isSSR = false) {
1591
+ let getter;
1592
+ let setter;
1593
+ if (isFunction(getterOrOptions)) {
1594
+ getter = getterOrOptions;
1595
+ } else {
1596
+ getter = getterOrOptions.get;
1597
+ setter = getterOrOptions.set;
1598
+ }
1599
+ const cRef = new ComputedRefImpl(getter, setter, isSSR);
1600
+ if (!!(process.env.NODE_ENV !== "production") && debugOptions && !isSSR) {
1601
+ cRef.onTrack = debugOptions.onTrack;
1602
+ cRef.onTrigger = debugOptions.onTrigger;
1603
+ }
1604
+ return cRef;
1605
+ }
1219
1606
 
1220
1607
  const TrackOpTypes = {
1221
1608
  "GET": "get",
@@ -1236,4 +1623,4 @@ const ReactiveFlags = {
1236
1623
  "RAW": "__v_raw"
1237
1624
  };
1238
1625
 
1239
- export { EffectScope, ITERATE_KEY, ReactiveEffect, ReactiveFlags, TrackOpTypes, TriggerOpTypes, computed, customRef, deferredComputed, effect, effectScope, enableTracking, getCurrentScope, isProxy, isReactive, isReadonly, isRef, isShallow, markRaw, onScopeDispose, pauseScheduling, pauseTracking, proxyRefs, reactive, readonly, ref, resetScheduling, resetTracking, shallowReactive, shallowReadonly, shallowRef, stop, toRaw, toRef, toRefs, toValue, track, trigger, triggerRef, unref };
1626
+ export { ARRAY_ITERATE_KEY, EffectFlags, EffectScope, ITERATE_KEY, MAP_KEY_ITERATE_KEY, ReactiveEffect, ReactiveFlags, TrackOpTypes, TriggerOpTypes, computed, customRef, effect, effectScope, enableTracking, getCurrentScope, isProxy, isReactive, isReadonly, isRef, isShallow, markRaw, onEffectCleanup, onScopeDispose, pauseTracking, proxyRefs, reactive, reactiveReadArray, readonly, ref, resetTracking, shallowReactive, shallowReadArray, shallowReadonly, shallowRef, stop, toRaw, toReactive, toReadonly, toRef, toRefs, toValue, track, trigger, triggerRef, unref };