@vue/reactivity 3.4.26 → 3.5.0-alpha.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @vue/reactivity v3.4.26
2
+ * @vue/reactivity v3.5.0-alpha.2
3
3
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
4
4
  * @license MIT
5
5
  **/
@@ -10,8 +10,6 @@ function makeMap(str, expectsLowerCase) {
10
10
  return (val) => set.has(val);
11
11
  }
12
12
 
13
- const NOOP = () => {
14
- };
15
13
  const extend = Object.assign;
16
14
  const hasOwnProperty$1 = Object.prototype.hasOwnProperty;
17
15
  const hasOwn = (val, key) => hasOwnProperty$1.call(val, key);
@@ -133,156 +131,296 @@ class EffectScope {
133
131
  function effectScope(detached) {
134
132
  return new EffectScope(detached);
135
133
  }
136
- function recordEffectScope(effect, scope = activeEffectScope) {
137
- if (scope && scope.active) {
138
- scope.effects.push(effect);
139
- }
140
- }
141
134
  function getCurrentScope() {
142
135
  return activeEffectScope;
143
136
  }
144
- function onScopeDispose(fn) {
137
+ function onScopeDispose(fn, failSilently = false) {
145
138
  if (activeEffectScope) {
146
139
  activeEffectScope.cleanups.push(fn);
147
- } else {
140
+ } else if (!failSilently) {
148
141
  warn(
149
142
  `onScopeDispose() is called when there is no active effect scope to be associated with.`
150
143
  );
151
144
  }
152
145
  }
153
146
 
154
- let activeEffect;
147
+ let activeSub;
148
+ const EffectFlags = {
149
+ "ACTIVE": 1,
150
+ "1": "ACTIVE",
151
+ "RUNNING": 2,
152
+ "2": "RUNNING",
153
+ "TRACKING": 4,
154
+ "4": "TRACKING",
155
+ "NOTIFIED": 8,
156
+ "8": "NOTIFIED",
157
+ "DIRTY": 16,
158
+ "16": "DIRTY",
159
+ "ALLOW_RECURSE": 32,
160
+ "32": "ALLOW_RECURSE",
161
+ "NO_BATCH": 64,
162
+ "64": "NO_BATCH"
163
+ };
155
164
  class ReactiveEffect {
156
- constructor(fn, trigger, scheduler, scope) {
165
+ constructor(fn) {
157
166
  this.fn = fn;
158
- this.trigger = trigger;
159
- this.scheduler = scheduler;
160
- this.active = true;
161
- this.deps = [];
162
167
  /**
163
168
  * @internal
164
169
  */
165
- this._dirtyLevel = 4;
170
+ this.deps = void 0;
166
171
  /**
167
172
  * @internal
168
173
  */
169
- this._trackId = 0;
174
+ this.depsTail = void 0;
170
175
  /**
171
176
  * @internal
172
177
  */
173
- this._runnings = 0;
178
+ this.flags = 1 | 4;
174
179
  /**
175
180
  * @internal
176
181
  */
177
- this._shouldSchedule = false;
182
+ this.nextEffect = void 0;
178
183
  /**
179
184
  * @internal
180
185
  */
181
- this._depsLength = 0;
182
- recordEffectScope(this, scope);
183
- }
184
- get dirty() {
185
- if (this._dirtyLevel === 2 || this._dirtyLevel === 3) {
186
- this._dirtyLevel = 1;
187
- pauseTracking();
188
- for (let i = 0; i < this._depsLength; i++) {
189
- const dep = this.deps[i];
190
- if (dep.computed) {
191
- triggerComputed(dep.computed);
192
- if (this._dirtyLevel >= 4) {
193
- break;
194
- }
195
- }
196
- }
197
- if (this._dirtyLevel === 1) {
198
- this._dirtyLevel = 0;
199
- }
200
- resetTracking();
186
+ this.cleanup = void 0;
187
+ this.scheduler = void 0;
188
+ if (activeEffectScope && activeEffectScope.active) {
189
+ activeEffectScope.effects.push(this);
201
190
  }
202
- return this._dirtyLevel >= 4;
203
191
  }
204
- set dirty(v) {
205
- this._dirtyLevel = v ? 4 : 0;
192
+ /**
193
+ * @internal
194
+ */
195
+ notify() {
196
+ if (this.flags & 2 && !(this.flags & 32)) {
197
+ return;
198
+ }
199
+ if (this.flags & 64) {
200
+ return this.trigger();
201
+ }
202
+ if (!(this.flags & 8)) {
203
+ this.flags |= 8;
204
+ this.nextEffect = batchedEffect;
205
+ batchedEffect = this;
206
+ }
206
207
  }
207
208
  run() {
208
- this._dirtyLevel = 0;
209
- if (!this.active) {
209
+ if (!(this.flags & 1)) {
210
210
  return this.fn();
211
211
  }
212
- let lastShouldTrack = shouldTrack;
213
- let lastEffect = activeEffect;
212
+ this.flags |= 2;
213
+ cleanupEffect(this);
214
+ prepareDeps(this);
215
+ const prevEffect = activeSub;
216
+ const prevShouldTrack = shouldTrack;
217
+ activeSub = this;
218
+ shouldTrack = true;
214
219
  try {
215
- shouldTrack = true;
216
- activeEffect = this;
217
- this._runnings++;
218
- preCleanupEffect(this);
219
220
  return this.fn();
220
221
  } finally {
221
- postCleanupEffect(this);
222
- this._runnings--;
223
- activeEffect = lastEffect;
224
- shouldTrack = lastShouldTrack;
222
+ if (activeSub !== this) {
223
+ warn(
224
+ "Active effect was not restored correctly - this is likely a Vue internal bug."
225
+ );
226
+ }
227
+ cleanupDeps(this);
228
+ activeSub = prevEffect;
229
+ shouldTrack = prevShouldTrack;
230
+ this.flags &= ~2;
225
231
  }
226
232
  }
227
233
  stop() {
228
- if (this.active) {
229
- preCleanupEffect(this);
230
- postCleanupEffect(this);
234
+ if (this.flags & 1) {
235
+ for (let link = this.deps; link; link = link.nextDep) {
236
+ removeSub(link);
237
+ }
238
+ this.deps = this.depsTail = void 0;
239
+ cleanupEffect(this);
231
240
  this.onStop && this.onStop();
232
- this.active = false;
241
+ this.flags &= ~1;
242
+ }
243
+ }
244
+ trigger() {
245
+ if (this.scheduler) {
246
+ this.scheduler();
247
+ } else {
248
+ this.runIfDirty();
249
+ }
250
+ }
251
+ /**
252
+ * @internal
253
+ */
254
+ runIfDirty() {
255
+ if (isDirty(this)) {
256
+ this.run();
233
257
  }
234
258
  }
259
+ get dirty() {
260
+ return isDirty(this);
261
+ }
235
262
  }
236
- function triggerComputed(computed) {
237
- return computed.value;
263
+ let batchDepth = 0;
264
+ let batchedEffect;
265
+ function startBatch() {
266
+ batchDepth++;
238
267
  }
239
- function preCleanupEffect(effect2) {
240
- effect2._trackId++;
241
- effect2._depsLength = 0;
268
+ function endBatch() {
269
+ if (batchDepth > 1) {
270
+ batchDepth--;
271
+ return;
272
+ }
273
+ let error;
274
+ while (batchedEffect) {
275
+ let e = batchedEffect;
276
+ batchedEffect = void 0;
277
+ while (e) {
278
+ const next = e.nextEffect;
279
+ e.nextEffect = void 0;
280
+ e.flags &= ~8;
281
+ if (e.flags & 1) {
282
+ try {
283
+ e.trigger();
284
+ } catch (err) {
285
+ if (!error)
286
+ error = err;
287
+ }
288
+ }
289
+ e = next;
290
+ }
291
+ }
292
+ batchDepth--;
293
+ if (error)
294
+ throw error;
295
+ }
296
+ function prepareDeps(sub) {
297
+ for (let link = sub.deps; link; link = link.nextDep) {
298
+ link.version = -1;
299
+ link.prevActiveLink = link.dep.activeLink;
300
+ link.dep.activeLink = link;
301
+ }
302
+ }
303
+ function cleanupDeps(sub) {
304
+ let head;
305
+ let tail = sub.depsTail;
306
+ for (let link = tail; link; link = link.prevDep) {
307
+ if (link.version === -1) {
308
+ if (link === tail)
309
+ tail = link.prevDep;
310
+ removeSub(link);
311
+ removeDep(link);
312
+ } else {
313
+ head = link;
314
+ }
315
+ link.dep.activeLink = link.prevActiveLink;
316
+ link.prevActiveLink = void 0;
317
+ }
318
+ sub.deps = head;
319
+ sub.depsTail = tail;
242
320
  }
243
- function postCleanupEffect(effect2) {
244
- if (effect2.deps.length > effect2._depsLength) {
245
- for (let i = effect2._depsLength; i < effect2.deps.length; i++) {
246
- cleanupDepEffect(effect2.deps[i], effect2);
321
+ function isDirty(sub) {
322
+ for (let link = sub.deps; link; link = link.nextDep) {
323
+ if (link.dep.version !== link.version || link.dep.computed && refreshComputed(link.dep.computed) === false || link.dep.version !== link.version) {
324
+ return true;
247
325
  }
248
- effect2.deps.length = effect2._depsLength;
249
326
  }
327
+ if (sub._dirty) {
328
+ return true;
329
+ }
330
+ return false;
250
331
  }
251
- function cleanupDepEffect(dep, effect2) {
252
- const trackId = dep.get(effect2);
253
- if (trackId !== void 0 && effect2._trackId !== trackId) {
254
- dep.delete(effect2);
255
- if (dep.size === 0) {
256
- dep.cleanup();
332
+ function refreshComputed(computed) {
333
+ if (computed.flags & 2) {
334
+ return false;
335
+ }
336
+ if (computed.flags & 4 && !(computed.flags & 16)) {
337
+ return;
338
+ }
339
+ computed.flags &= ~16;
340
+ if (computed.globalVersion === globalVersion) {
341
+ return;
342
+ }
343
+ computed.globalVersion = globalVersion;
344
+ const dep = computed.dep;
345
+ computed.flags |= 2;
346
+ if (dep.version > 0 && !computed.isSSR && !isDirty(computed)) {
347
+ computed.flags &= ~2;
348
+ return;
349
+ }
350
+ const prevSub = activeSub;
351
+ const prevShouldTrack = shouldTrack;
352
+ activeSub = computed;
353
+ shouldTrack = true;
354
+ try {
355
+ prepareDeps(computed);
356
+ const value = computed.fn();
357
+ if (dep.version === 0 || hasChanged(value, computed._value)) {
358
+ computed._value = value;
359
+ dep.version++;
257
360
  }
361
+ } catch (err) {
362
+ dep.version++;
363
+ throw err;
364
+ } finally {
365
+ activeSub = prevSub;
366
+ shouldTrack = prevShouldTrack;
367
+ cleanupDeps(computed);
368
+ computed.flags &= ~2;
369
+ }
370
+ }
371
+ function removeSub(link) {
372
+ const { dep, prevSub, nextSub } = link;
373
+ if (prevSub) {
374
+ prevSub.nextSub = nextSub;
375
+ link.prevSub = void 0;
376
+ }
377
+ if (nextSub) {
378
+ nextSub.prevSub = prevSub;
379
+ link.nextSub = void 0;
380
+ }
381
+ if (dep.subs === link) {
382
+ dep.subs = prevSub;
383
+ }
384
+ if (!dep.subs && dep.computed) {
385
+ dep.computed.flags &= ~4;
386
+ for (let l = dep.computed.deps; l; l = l.nextDep) {
387
+ removeSub(l);
388
+ }
389
+ }
390
+ }
391
+ function removeDep(link) {
392
+ const { prevDep, nextDep } = link;
393
+ if (prevDep) {
394
+ prevDep.nextDep = nextDep;
395
+ link.prevDep = void 0;
396
+ }
397
+ if (nextDep) {
398
+ nextDep.prevDep = prevDep;
399
+ link.nextDep = void 0;
258
400
  }
259
401
  }
260
402
  function effect(fn, options) {
261
403
  if (fn.effect instanceof ReactiveEffect) {
262
404
  fn = fn.effect.fn;
263
405
  }
264
- const _effect = new ReactiveEffect(fn, NOOP, () => {
265
- if (_effect.dirty) {
266
- _effect.run();
267
- }
268
- });
406
+ const e = new ReactiveEffect(fn);
269
407
  if (options) {
270
- extend(_effect, options);
271
- if (options.scope)
272
- recordEffectScope(_effect, options.scope);
408
+ extend(e, options);
273
409
  }
274
- if (!options || !options.lazy) {
275
- _effect.run();
410
+ try {
411
+ e.run();
412
+ } catch (err) {
413
+ e.stop();
414
+ throw err;
276
415
  }
277
- const runner = _effect.run.bind(_effect);
278
- runner.effect = _effect;
416
+ const runner = e.run.bind(e);
417
+ runner.effect = e;
279
418
  return runner;
280
419
  }
281
420
  function stop(runner) {
282
421
  runner.effect.stop();
283
422
  }
284
423
  let shouldTrack = true;
285
- let pauseScheduleStack = 0;
286
424
  const trackStack = [];
287
425
  function pauseTracking() {
288
426
  trackStack.push(shouldTrack);
@@ -296,192 +434,423 @@ function resetTracking() {
296
434
  const last = trackStack.pop();
297
435
  shouldTrack = last === void 0 ? true : last;
298
436
  }
299
- function pauseScheduling() {
300
- pauseScheduleStack++;
301
- }
302
- function resetScheduling() {
303
- pauseScheduleStack--;
304
- while (!pauseScheduleStack && queueEffectSchedulers.length) {
305
- queueEffectSchedulers.shift()();
437
+ function onEffectCleanup(fn, failSilently = false) {
438
+ if (activeSub instanceof ReactiveEffect) {
439
+ activeSub.cleanup = fn;
440
+ } else if (!failSilently) {
441
+ warn(
442
+ `onEffectCleanup() was called when there was no active effect to associate with.`
443
+ );
306
444
  }
307
445
  }
308
- function trackEffect(effect2, dep, debuggerEventExtraInfo) {
309
- var _a;
310
- if (dep.get(effect2) !== effect2._trackId) {
311
- dep.set(effect2, effect2._trackId);
312
- const oldDep = effect2.deps[effect2._depsLength];
313
- if (oldDep !== dep) {
314
- if (oldDep) {
315
- cleanupDepEffect(oldDep, effect2);
316
- }
317
- effect2.deps[effect2._depsLength++] = dep;
318
- } else {
319
- effect2._depsLength++;
446
+ function cleanupEffect(e) {
447
+ const { cleanup } = e;
448
+ e.cleanup = void 0;
449
+ if (cleanup) {
450
+ const prevSub = activeSub;
451
+ activeSub = void 0;
452
+ try {
453
+ cleanup();
454
+ } finally {
455
+ activeSub = prevSub;
320
456
  }
457
+ }
458
+ }
459
+
460
+ let globalVersion = 0;
461
+ class Dep {
462
+ constructor(computed) {
463
+ this.computed = computed;
464
+ this.version = 0;
465
+ /**
466
+ * Link between this dep and the current active effect
467
+ */
468
+ this.activeLink = void 0;
469
+ /**
470
+ * Doubly linked list representing the subscribing effects (tail)
471
+ */
472
+ this.subs = void 0;
321
473
  {
322
- (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));
474
+ this.subsHead = void 0;
323
475
  }
324
476
  }
325
- }
326
- const queueEffectSchedulers = [];
327
- function triggerEffects(dep, dirtyLevel, debuggerEventExtraInfo) {
328
- var _a;
329
- pauseScheduling();
330
- for (const effect2 of dep.keys()) {
331
- let tracking;
332
- if (effect2._dirtyLevel < dirtyLevel && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {
333
- effect2._shouldSchedule || (effect2._shouldSchedule = effect2._dirtyLevel === 0);
334
- effect2._dirtyLevel = dirtyLevel;
477
+ track(debugInfo) {
478
+ if (!activeSub || !shouldTrack) {
479
+ return;
335
480
  }
336
- if (effect2._shouldSchedule && (tracking != null ? tracking : tracking = dep.get(effect2) === effect2._trackId)) {
337
- {
338
- (_a = effect2.onTrigger) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));
481
+ let link = this.activeLink;
482
+ if (link === void 0 || link.sub !== activeSub) {
483
+ link = this.activeLink = {
484
+ dep: this,
485
+ sub: activeSub,
486
+ version: this.version,
487
+ nextDep: void 0,
488
+ prevDep: void 0,
489
+ nextSub: void 0,
490
+ prevSub: void 0,
491
+ prevActiveLink: void 0
492
+ };
493
+ if (!activeSub.deps) {
494
+ activeSub.deps = activeSub.depsTail = link;
495
+ } else {
496
+ link.prevDep = activeSub.depsTail;
497
+ activeSub.depsTail.nextDep = link;
498
+ activeSub.depsTail = link;
499
+ }
500
+ if (activeSub.flags & 4) {
501
+ addSub(link);
502
+ }
503
+ } else if (link.version === -1) {
504
+ link.version = this.version;
505
+ if (link.nextDep) {
506
+ const next = link.nextDep;
507
+ next.prevDep = link.prevDep;
508
+ if (link.prevDep) {
509
+ link.prevDep.nextDep = next;
510
+ }
511
+ link.prevDep = activeSub.depsTail;
512
+ link.nextDep = void 0;
513
+ activeSub.depsTail.nextDep = link;
514
+ activeSub.depsTail = link;
515
+ if (activeSub.deps === link) {
516
+ activeSub.deps = next;
517
+ }
339
518
  }
340
- effect2.trigger();
341
- if ((!effect2._runnings || effect2.allowRecurse) && effect2._dirtyLevel !== 2) {
342
- effect2._shouldSchedule = false;
343
- if (effect2.scheduler) {
344
- queueEffectSchedulers.push(effect2.scheduler);
519
+ }
520
+ if (activeSub.onTrack) {
521
+ activeSub.onTrack(
522
+ extend(
523
+ {
524
+ effect: activeSub
525
+ },
526
+ debugInfo
527
+ )
528
+ );
529
+ }
530
+ return link;
531
+ }
532
+ trigger(debugInfo) {
533
+ this.version++;
534
+ globalVersion++;
535
+ this.notify(debugInfo);
536
+ }
537
+ notify(debugInfo) {
538
+ startBatch();
539
+ try {
540
+ if (true) {
541
+ for (let head = this.subsHead; head; head = head.nextSub) {
542
+ if (head.sub.onTrigger && !(head.sub.flags & 8)) {
543
+ head.sub.onTrigger(
544
+ extend(
545
+ {
546
+ effect: head.sub
547
+ },
548
+ debugInfo
549
+ )
550
+ );
551
+ }
345
552
  }
346
553
  }
554
+ for (let link = this.subs; link; link = link.prevSub) {
555
+ link.sub.notify();
556
+ }
557
+ } finally {
558
+ endBatch();
347
559
  }
348
560
  }
349
- resetScheduling();
350
561
  }
351
-
352
- const createDep = (cleanup, computed) => {
353
- const dep = /* @__PURE__ */ new Map();
354
- dep.cleanup = cleanup;
355
- dep.computed = computed;
356
- return dep;
357
- };
358
-
562
+ function addSub(link) {
563
+ const computed = link.dep.computed;
564
+ if (computed && !link.dep.subs) {
565
+ computed.flags |= 4 | 16;
566
+ for (let l = computed.deps; l; l = l.nextDep) {
567
+ addSub(l);
568
+ }
569
+ }
570
+ const currentTail = link.dep.subs;
571
+ if (currentTail !== link) {
572
+ link.prevSub = currentTail;
573
+ if (currentTail)
574
+ currentTail.nextSub = link;
575
+ }
576
+ if (link.dep.subsHead === void 0) {
577
+ link.dep.subsHead = link;
578
+ }
579
+ link.dep.subs = link;
580
+ }
359
581
  const targetMap = /* @__PURE__ */ new WeakMap();
360
- const ITERATE_KEY = Symbol("iterate" );
361
- const MAP_KEY_ITERATE_KEY = Symbol("Map key iterate" );
582
+ const ITERATE_KEY = Symbol("Object iterate" );
583
+ const MAP_KEY_ITERATE_KEY = Symbol("Map keys iterate" );
584
+ const ARRAY_ITERATE_KEY = Symbol("Array iterate" );
362
585
  function track(target, type, key) {
363
- if (shouldTrack && activeEffect) {
586
+ if (shouldTrack && activeSub) {
364
587
  let depsMap = targetMap.get(target);
365
588
  if (!depsMap) {
366
589
  targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
367
590
  }
368
591
  let dep = depsMap.get(key);
369
592
  if (!dep) {
370
- depsMap.set(key, dep = createDep(() => depsMap.delete(key)));
593
+ depsMap.set(key, dep = new Dep());
371
594
  }
372
- trackEffect(
373
- activeEffect,
374
- dep,
375
- {
595
+ {
596
+ dep.track({
376
597
  target,
377
598
  type,
378
599
  key
379
- }
380
- );
600
+ });
601
+ }
381
602
  }
382
603
  }
383
604
  function trigger(target, type, key, newValue, oldValue, oldTarget) {
384
605
  const depsMap = targetMap.get(target);
385
606
  if (!depsMap) {
607
+ globalVersion++;
386
608
  return;
387
609
  }
388
610
  let deps = [];
389
611
  if (type === "clear") {
390
612
  deps = [...depsMap.values()];
391
- } else if (key === "length" && isArray(target)) {
392
- const newLength = Number(newValue);
393
- depsMap.forEach((dep, key2) => {
394
- if (key2 === "length" || !isSymbol(key2) && key2 >= newLength) {
395
- deps.push(dep);
396
- }
397
- });
398
613
  } else {
399
- if (key !== void 0) {
400
- deps.push(depsMap.get(key));
401
- }
402
- switch (type) {
403
- case "add":
404
- if (!isArray(target)) {
405
- deps.push(depsMap.get(ITERATE_KEY));
406
- if (isMap(target)) {
407
- deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
408
- }
409
- } else if (isIntegerKey(key)) {
410
- deps.push(depsMap.get("length"));
614
+ const targetIsArray = isArray(target);
615
+ const isArrayIndex = targetIsArray && isIntegerKey(key);
616
+ if (targetIsArray && key === "length") {
617
+ const newLength = Number(newValue);
618
+ depsMap.forEach((dep, key2) => {
619
+ if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) {
620
+ deps.push(dep);
411
621
  }
412
- break;
413
- case "delete":
414
- if (!isArray(target)) {
415
- deps.push(depsMap.get(ITERATE_KEY));
622
+ });
623
+ } else {
624
+ const push = (dep) => dep && deps.push(dep);
625
+ if (key !== void 0) {
626
+ push(depsMap.get(key));
627
+ }
628
+ if (isArrayIndex) {
629
+ push(depsMap.get(ARRAY_ITERATE_KEY));
630
+ }
631
+ switch (type) {
632
+ case "add":
633
+ if (!targetIsArray) {
634
+ push(depsMap.get(ITERATE_KEY));
635
+ if (isMap(target)) {
636
+ push(depsMap.get(MAP_KEY_ITERATE_KEY));
637
+ }
638
+ } else if (isArrayIndex) {
639
+ push(depsMap.get("length"));
640
+ }
641
+ break;
642
+ case "delete":
643
+ if (!targetIsArray) {
644
+ push(depsMap.get(ITERATE_KEY));
645
+ if (isMap(target)) {
646
+ push(depsMap.get(MAP_KEY_ITERATE_KEY));
647
+ }
648
+ }
649
+ break;
650
+ case "set":
416
651
  if (isMap(target)) {
417
- deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
652
+ push(depsMap.get(ITERATE_KEY));
418
653
  }
419
- }
420
- break;
421
- case "set":
422
- if (isMap(target)) {
423
- deps.push(depsMap.get(ITERATE_KEY));
424
- }
425
- break;
654
+ break;
655
+ }
426
656
  }
427
657
  }
428
- pauseScheduling();
658
+ startBatch();
429
659
  for (const dep of deps) {
430
- if (dep) {
431
- triggerEffects(
432
- dep,
433
- 4,
434
- {
435
- target,
436
- type,
437
- key,
438
- newValue,
439
- oldValue,
440
- oldTarget
441
- }
442
- );
660
+ {
661
+ dep.trigger({
662
+ target,
663
+ type,
664
+ key,
665
+ newValue,
666
+ oldValue,
667
+ oldTarget
668
+ });
443
669
  }
444
670
  }
445
- resetScheduling();
671
+ endBatch();
446
672
  }
447
673
  function getDepFromReactive(object, key) {
448
- const depsMap = targetMap.get(object);
449
- return depsMap && depsMap.get(key);
674
+ var _a;
675
+ return (_a = targetMap.get(object)) == null ? void 0 : _a.get(key);
676
+ }
677
+
678
+ function reactiveReadArray(array) {
679
+ const raw = toRaw(array);
680
+ if (raw === array)
681
+ return raw;
682
+ track(raw, "iterate", ARRAY_ITERATE_KEY);
683
+ return isShallow(array) ? raw : raw.map(toReactive);
684
+ }
685
+ function shallowReadArray(arr) {
686
+ track(arr = toRaw(arr), "iterate", ARRAY_ITERATE_KEY);
687
+ return arr;
688
+ }
689
+ const arrayInstrumentations = {
690
+ __proto__: null,
691
+ [Symbol.iterator]() {
692
+ return iterator(this, Symbol.iterator, toReactive);
693
+ },
694
+ concat(...args) {
695
+ return reactiveReadArray(this).concat(
696
+ ...args.map((x) => reactiveReadArray(x))
697
+ );
698
+ },
699
+ entries() {
700
+ return iterator(this, "entries", (value) => {
701
+ value[1] = toReactive(value[1]);
702
+ return value;
703
+ });
704
+ },
705
+ every(fn, thisArg) {
706
+ return apply(this, "every", fn, thisArg);
707
+ },
708
+ filter(fn, thisArg) {
709
+ const result = apply(this, "filter", fn, thisArg);
710
+ return isProxy(this) && !isShallow(this) ? result.map(toReactive) : result;
711
+ },
712
+ find(fn, thisArg) {
713
+ const result = apply(this, "find", fn, thisArg);
714
+ return isProxy(this) && !isShallow(this) ? toReactive(result) : result;
715
+ },
716
+ findIndex(fn, thisArg) {
717
+ return apply(this, "findIndex", fn, thisArg);
718
+ },
719
+ findLast(fn, thisArg) {
720
+ const result = apply(this, "findLast", fn, thisArg);
721
+ return isProxy(this) && !isShallow(this) ? toReactive(result) : result;
722
+ },
723
+ findLastIndex(fn, thisArg) {
724
+ return apply(this, "findLastIndex", fn, thisArg);
725
+ },
726
+ // flat, flatMap could benefit from ARRAY_ITERATE but are not straight-forward to implement
727
+ forEach(fn, thisArg) {
728
+ return apply(this, "forEach", fn, thisArg);
729
+ },
730
+ includes(...args) {
731
+ return searchProxy(this, "includes", args);
732
+ },
733
+ indexOf(...args) {
734
+ return searchProxy(this, "indexOf", args);
735
+ },
736
+ join(separator) {
737
+ return reactiveReadArray(this).join(separator);
738
+ },
739
+ // keys() iterator only reads `length`, no optimisation required
740
+ lastIndexOf(...args) {
741
+ return searchProxy(this, "lastIndexOf", args);
742
+ },
743
+ map(fn, thisArg) {
744
+ return apply(this, "map", fn, thisArg);
745
+ },
746
+ pop() {
747
+ return noTracking(this, "pop");
748
+ },
749
+ push(...args) {
750
+ return noTracking(this, "push", args);
751
+ },
752
+ reduce(fn, ...args) {
753
+ return reduce(this, "reduce", fn, args);
754
+ },
755
+ reduceRight(fn, ...args) {
756
+ return reduce(this, "reduceRight", fn, args);
757
+ },
758
+ shift() {
759
+ return noTracking(this, "shift");
760
+ },
761
+ // slice could use ARRAY_ITERATE but also seems to beg for range tracking
762
+ some(fn, thisArg) {
763
+ return apply(this, "some", fn, thisArg);
764
+ },
765
+ splice(...args) {
766
+ return noTracking(this, "splice", args);
767
+ },
768
+ toReversed() {
769
+ return reactiveReadArray(this).toReversed();
770
+ },
771
+ toSorted(comparer) {
772
+ return reactiveReadArray(this).toSorted(comparer);
773
+ },
774
+ toSpliced(...args) {
775
+ return reactiveReadArray(this).toSpliced(...args);
776
+ },
777
+ unshift(...args) {
778
+ return noTracking(this, "unshift", args);
779
+ },
780
+ values() {
781
+ return iterator(this, "values", toReactive);
782
+ }
783
+ };
784
+ function iterator(self, method, wrapValue) {
785
+ const arr = shallowReadArray(self);
786
+ const iter = arr[method]();
787
+ if (arr !== self && !isShallow(self)) {
788
+ iter._next = iter.next;
789
+ iter.next = () => {
790
+ const result = iter._next();
791
+ if (result.value) {
792
+ result.value = wrapValue(result.value);
793
+ }
794
+ return result;
795
+ };
796
+ }
797
+ return iter;
798
+ }
799
+ function apply(self, method, fn, thisArg) {
800
+ const arr = shallowReadArray(self);
801
+ let wrappedFn = fn;
802
+ if (arr !== self) {
803
+ if (!isShallow(self)) {
804
+ wrappedFn = function(item, index) {
805
+ return fn.call(this, toReactive(item), index, self);
806
+ };
807
+ } else if (fn.length > 2) {
808
+ wrappedFn = function(item, index) {
809
+ return fn.call(this, item, index, self);
810
+ };
811
+ }
812
+ }
813
+ return arr[method](wrappedFn, thisArg);
814
+ }
815
+ function reduce(self, method, fn, args) {
816
+ const arr = shallowReadArray(self);
817
+ let wrappedFn = fn;
818
+ if (arr !== self) {
819
+ if (!isShallow(self)) {
820
+ wrappedFn = function(acc, item, index) {
821
+ return fn.call(this, acc, toReactive(item), index, self);
822
+ };
823
+ } else if (fn.length > 3) {
824
+ wrappedFn = function(acc, item, index) {
825
+ return fn.call(this, acc, item, index, self);
826
+ };
827
+ }
828
+ }
829
+ return arr[method](wrappedFn, ...args);
830
+ }
831
+ function searchProxy(self, method, args) {
832
+ const arr = toRaw(self);
833
+ track(arr, "iterate", ARRAY_ITERATE_KEY);
834
+ const res = arr[method](...args);
835
+ if ((res === -1 || res === false) && isProxy(args[0])) {
836
+ args[0] = toRaw(args[0]);
837
+ return arr[method](...args);
838
+ }
839
+ return res;
840
+ }
841
+ function noTracking(self, method, args = []) {
842
+ pauseTracking();
843
+ startBatch();
844
+ const res = toRaw(self)[method].apply(self, args);
845
+ endBatch();
846
+ resetTracking();
847
+ return res;
450
848
  }
451
849
 
452
850
  const isNonTrackableKeys = /* @__PURE__ */ makeMap(`__proto__,__v_isRef,__isVue`);
453
851
  const builtInSymbols = new Set(
454
852
  /* @__PURE__ */ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol)
455
853
  );
456
- const arrayInstrumentations = /* @__PURE__ */ createArrayInstrumentations();
457
- function createArrayInstrumentations() {
458
- const instrumentations = {};
459
- ["includes", "indexOf", "lastIndexOf"].forEach((key) => {
460
- instrumentations[key] = function(...args) {
461
- const arr = toRaw(this);
462
- for (let i = 0, l = this.length; i < l; i++) {
463
- track(arr, "get", i + "");
464
- }
465
- const res = arr[key](...args);
466
- if (res === -1 || res === false) {
467
- return arr[key](...args.map(toRaw));
468
- } else {
469
- return res;
470
- }
471
- };
472
- });
473
- ["push", "pop", "shift", "unshift", "splice"].forEach((key) => {
474
- instrumentations[key] = function(...args) {
475
- pauseTracking();
476
- pauseScheduling();
477
- const res = toRaw(this)[key].apply(this, args);
478
- resetScheduling();
479
- resetTracking();
480
- return res;
481
- };
482
- });
483
- return instrumentations;
484
- }
485
854
  function hasOwnProperty(key) {
486
855
  if (!isSymbol(key))
487
856
  key = String(key);
@@ -512,14 +881,22 @@ class BaseReactiveHandler {
512
881
  }
513
882
  const targetIsArray = isArray(target);
514
883
  if (!isReadonly2) {
515
- if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
516
- return Reflect.get(arrayInstrumentations, key, receiver);
884
+ let fn;
885
+ if (targetIsArray && (fn = arrayInstrumentations[key])) {
886
+ return fn;
517
887
  }
518
888
  if (key === "hasOwnProperty") {
519
889
  return hasOwnProperty;
520
890
  }
521
891
  }
522
- const res = Reflect.get(target, key, receiver);
892
+ const res = Reflect.get(
893
+ target,
894
+ key,
895
+ // if this is a proxy wrapping a ref, return methods using the raw ref
896
+ // as receiver so that we don't have to call `toRaw` on the ref in all
897
+ // its class methods
898
+ isRef(target) ? target : receiver
899
+ );
523
900
  if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
524
901
  return res;
525
902
  }
@@ -1018,110 +1395,8 @@ function markRaw(value) {
1018
1395
  const toReactive = (value) => isObject(value) ? reactive(value) : value;
1019
1396
  const toReadonly = (value) => isObject(value) ? readonly(value) : value;
1020
1397
 
1021
- 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`;
1022
- class ComputedRefImpl {
1023
- constructor(getter, _setter, isReadonly, isSSR) {
1024
- this.getter = getter;
1025
- this._setter = _setter;
1026
- this.dep = void 0;
1027
- this.__v_isRef = true;
1028
- this["__v_isReadonly"] = false;
1029
- this.effect = new ReactiveEffect(
1030
- () => getter(this._value),
1031
- () => triggerRefValue(
1032
- this,
1033
- this.effect._dirtyLevel === 2 ? 2 : 3
1034
- )
1035
- );
1036
- this.effect.computed = this;
1037
- this.effect.active = this._cacheable = !isSSR;
1038
- this["__v_isReadonly"] = isReadonly;
1039
- }
1040
- get value() {
1041
- const self = toRaw(this);
1042
- if ((!self._cacheable || self.effect.dirty) && hasChanged(self._value, self._value = self.effect.run())) {
1043
- triggerRefValue(self, 4);
1044
- }
1045
- trackRefValue(self);
1046
- if (self.effect._dirtyLevel >= 2) {
1047
- if (this._warnRecursive) {
1048
- warn(COMPUTED_SIDE_EFFECT_WARN, `
1049
-
1050
- getter: `, this.getter);
1051
- }
1052
- triggerRefValue(self, 2);
1053
- }
1054
- return self._value;
1055
- }
1056
- set value(newValue) {
1057
- this._setter(newValue);
1058
- }
1059
- // #region polyfill _dirty for backward compatibility third party code for Vue <= 3.3.x
1060
- get _dirty() {
1061
- return this.effect.dirty;
1062
- }
1063
- set _dirty(v) {
1064
- this.effect.dirty = v;
1065
- }
1066
- // #endregion
1067
- }
1068
- function computed(getterOrOptions, debugOptions, isSSR = false) {
1069
- let getter;
1070
- let setter;
1071
- const onlyGetter = isFunction(getterOrOptions);
1072
- if (onlyGetter) {
1073
- getter = getterOrOptions;
1074
- setter = () => {
1075
- warn("Write operation failed: computed value is readonly");
1076
- } ;
1077
- } else {
1078
- getter = getterOrOptions.get;
1079
- setter = getterOrOptions.set;
1080
- }
1081
- const cRef = new ComputedRefImpl(getter, setter, onlyGetter || !setter, isSSR);
1082
- if (debugOptions && !isSSR) {
1083
- cRef.effect.onTrack = debugOptions.onTrack;
1084
- cRef.effect.onTrigger = debugOptions.onTrigger;
1085
- }
1086
- return cRef;
1087
- }
1088
-
1089
- function trackRefValue(ref2) {
1090
- var _a;
1091
- if (shouldTrack && activeEffect) {
1092
- ref2 = toRaw(ref2);
1093
- trackEffect(
1094
- activeEffect,
1095
- (_a = ref2.dep) != null ? _a : ref2.dep = createDep(
1096
- () => ref2.dep = void 0,
1097
- ref2 instanceof ComputedRefImpl ? ref2 : void 0
1098
- ),
1099
- {
1100
- target: ref2,
1101
- type: "get",
1102
- key: "value"
1103
- }
1104
- );
1105
- }
1106
- }
1107
- function triggerRefValue(ref2, dirtyLevel = 4, newVal) {
1108
- ref2 = toRaw(ref2);
1109
- const dep = ref2.dep;
1110
- if (dep) {
1111
- triggerEffects(
1112
- dep,
1113
- dirtyLevel,
1114
- {
1115
- target: ref2,
1116
- type: "set",
1117
- key: "value",
1118
- newValue: newVal
1119
- }
1120
- );
1121
- }
1122
- }
1123
1398
  function isRef(r) {
1124
- return !!(r && r.__v_isRef === true);
1399
+ return r ? r.__v_isRef === true : false;
1125
1400
  }
1126
1401
  function ref(value) {
1127
1402
  return createRef(value, false);
@@ -1138,27 +1413,49 @@ function createRef(rawValue, shallow) {
1138
1413
  class RefImpl {
1139
1414
  constructor(value, __v_isShallow) {
1140
1415
  this.__v_isShallow = __v_isShallow;
1141
- this.dep = void 0;
1416
+ this.dep = new Dep();
1142
1417
  this.__v_isRef = true;
1143
1418
  this._rawValue = __v_isShallow ? value : toRaw(value);
1144
1419
  this._value = __v_isShallow ? value : toReactive(value);
1145
1420
  }
1146
1421
  get value() {
1147
- trackRefValue(this);
1422
+ {
1423
+ this.dep.track({
1424
+ target: this,
1425
+ type: "get",
1426
+ key: "value"
1427
+ });
1428
+ }
1148
1429
  return this._value;
1149
1430
  }
1150
- set value(newVal) {
1151
- const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
1152
- newVal = useDirectValue ? newVal : toRaw(newVal);
1153
- if (hasChanged(newVal, this._rawValue)) {
1154
- this._rawValue = newVal;
1155
- this._value = useDirectValue ? newVal : toReactive(newVal);
1156
- triggerRefValue(this, 4, newVal);
1431
+ set value(newValue) {
1432
+ const oldValue = this._rawValue;
1433
+ const useDirectValue = this.__v_isShallow || isShallow(newValue) || isReadonly(newValue);
1434
+ newValue = useDirectValue ? newValue : toRaw(newValue);
1435
+ if (hasChanged(newValue, oldValue)) {
1436
+ this._rawValue = newValue;
1437
+ this._value = useDirectValue ? newValue : toReactive(newValue);
1438
+ {
1439
+ this.dep.trigger({
1440
+ target: this,
1441
+ type: "set",
1442
+ key: "value",
1443
+ newValue,
1444
+ oldValue
1445
+ });
1446
+ }
1157
1447
  }
1158
1448
  }
1159
1449
  }
1160
1450
  function triggerRef(ref2) {
1161
- triggerRefValue(ref2, 4, ref2.value );
1451
+ {
1452
+ ref2.dep.trigger({
1453
+ target: ref2,
1454
+ type: "set",
1455
+ key: "value",
1456
+ newValue: ref2._value
1457
+ });
1458
+ }
1162
1459
  }
1163
1460
  function unref(ref2) {
1164
1461
  return isRef(ref2) ? ref2.value : ref2;
@@ -1183,12 +1480,9 @@ function proxyRefs(objectWithRefs) {
1183
1480
  }
1184
1481
  class CustomRefImpl {
1185
1482
  constructor(factory) {
1186
- this.dep = void 0;
1187
1483
  this.__v_isRef = true;
1188
- const { get, set } = factory(
1189
- () => trackRefValue(this),
1190
- () => triggerRefValue(this)
1191
- );
1484
+ const dep = this.dep = new Dep();
1485
+ const { get, set } = factory(dep.track.bind(dep), dep.trigger.bind(dep));
1192
1486
  this._get = get;
1193
1487
  this._set = set;
1194
1488
  }
@@ -1256,7 +1550,89 @@ function propertyToRef(source, key, defaultValue) {
1256
1550
  return isRef(val) ? val : new ObjectRefImpl(source, key, defaultValue);
1257
1551
  }
1258
1552
 
1259
- const deferredComputed = computed;
1553
+ class ComputedRefImpl {
1554
+ constructor(fn, setter, isSSR) {
1555
+ this.fn = fn;
1556
+ this.setter = setter;
1557
+ /**
1558
+ * @internal
1559
+ */
1560
+ this._value = void 0;
1561
+ /**
1562
+ * @internal
1563
+ */
1564
+ this.dep = new Dep(this);
1565
+ /**
1566
+ * @internal
1567
+ */
1568
+ this.__v_isRef = true;
1569
+ // A computed is also a subscriber that tracks other deps
1570
+ /**
1571
+ * @internal
1572
+ */
1573
+ this.deps = void 0;
1574
+ /**
1575
+ * @internal
1576
+ */
1577
+ this.depsTail = void 0;
1578
+ /**
1579
+ * @internal
1580
+ */
1581
+ this.flags = 16;
1582
+ /**
1583
+ * @internal
1584
+ */
1585
+ this.globalVersion = globalVersion - 1;
1586
+ // for backwards compat
1587
+ this.effect = this;
1588
+ this.__v_isReadonly = !setter;
1589
+ this.isSSR = isSSR;
1590
+ }
1591
+ /**
1592
+ * @internal
1593
+ */
1594
+ notify() {
1595
+ if (activeSub !== this) {
1596
+ this.flags |= 16;
1597
+ this.dep.notify();
1598
+ }
1599
+ }
1600
+ get value() {
1601
+ const link = this.dep.track({
1602
+ target: this,
1603
+ type: "get",
1604
+ key: "value"
1605
+ }) ;
1606
+ refreshComputed(this);
1607
+ if (link) {
1608
+ link.version = this.dep.version;
1609
+ }
1610
+ return this._value;
1611
+ }
1612
+ set value(newValue) {
1613
+ if (this.setter) {
1614
+ this.setter(newValue);
1615
+ } else {
1616
+ warn("Write operation failed: computed value is readonly");
1617
+ }
1618
+ }
1619
+ }
1620
+ function computed(getterOrOptions, debugOptions, isSSR = false) {
1621
+ let getter;
1622
+ let setter;
1623
+ if (isFunction(getterOrOptions)) {
1624
+ getter = getterOrOptions;
1625
+ } else {
1626
+ getter = getterOrOptions.get;
1627
+ setter = getterOrOptions.set;
1628
+ }
1629
+ const cRef = new ComputedRefImpl(getter, setter, isSSR);
1630
+ if (debugOptions && !isSSR) {
1631
+ cRef.onTrack = debugOptions.onTrack;
1632
+ cRef.onTrigger = debugOptions.onTrigger;
1633
+ }
1634
+ return cRef;
1635
+ }
1260
1636
 
1261
1637
  const TrackOpTypes = {
1262
1638
  "GET": "get",
@@ -1277,4 +1653,4 @@ const ReactiveFlags = {
1277
1653
  "RAW": "__v_raw"
1278
1654
  };
1279
1655
 
1280
- 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 };
1656
+ 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 };