mobx 7.0.1 → 7.0.3

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.
@@ -4401,17 +4401,40 @@
4401
4401
  if (isObservableSet(other)) {
4402
4402
  other = new Set(other);
4403
4403
  }
4404
- transaction(() => {
4405
- if (Array.isArray(other)) {
4406
- this.clear();
4407
- other.forEach(value => this.add(value));
4408
- } else if (isES6Set(other)) {
4409
- this.clear();
4410
- other.forEach(value => this.add(value));
4411
- } else if (other !== null && other !== undefined) {
4412
- die(41, other);
4413
- }
4414
- });
4404
+ if (Array.isArray(other) || isES6Set(other)) {
4405
+ // Only emit `delete`/`add` events (and `reportChanged`) for values that
4406
+ // actually change, instead of clearing and re-adding everything. `add` and
4407
+ // `delete` are already no-ops for values that are respectively already
4408
+ // present or already absent, so we just need to avoid deleting values that
4409
+ // are part of the replacement. See #3761.
4410
+ transaction(() => {
4411
+ // Collect the desired values for quick lookup. `other` is already a Set
4412
+ // here when it was passed (or snapshotted from an observable set) as one,
4413
+ // so reuse it rather than allocating another; arrays are wrapped (which
4414
+ // also dedupes them).
4415
+ const replacementValues = isES6Set(other) ? other : new Set(other);
4416
+ // Short-circuit the trivial cases: an empty replacement is just a clear,
4417
+ // and replacing into an empty set only needs the adds.
4418
+ if (replacementValues.size === 0) {
4419
+ this.clear();
4420
+ return;
4421
+ }
4422
+ if (this.data_.size === 0) {
4423
+ replacementValues.forEach(value => this.add(value));
4424
+ return;
4425
+ }
4426
+ // Delete values that are not part of the replacement.
4427
+ for (const value of this.data_.values()) {
4428
+ if (!replacementValues.has(this.dehanceValue_(value))) {
4429
+ this.delete(value);
4430
+ }
4431
+ }
4432
+ // Add new values; values that are already present are a no-op.
4433
+ replacementValues.forEach(value => this.add(value));
4434
+ });
4435
+ } else if (other !== null && other !== undefined) {
4436
+ die(41, other);
4437
+ }
4415
4438
  return this;
4416
4439
  }
4417
4440
  toJSON() {