mobx 7.0.4 → 7.0.6

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.
@@ -816,6 +816,19 @@ function createAutoAnnotation(options) {
816
816
  extend_
817
817
  };
818
818
  }
819
+ // The auto annotation only depends on `deep` and `autoBind`, so share one instance per combination
820
+ // instead of allocating one for every object created with options
821
+ const autoAnnotations = [autoAnnotation];
822
+ function getAutoAnnotation(options) {
823
+ var _autoAnnotations$idx;
824
+ const deep = options.deep !== false;
825
+ const autoBind = !!options.autoBind;
826
+ const idx = (deep ? 0 : 1) | (autoBind ? 2 : 0);
827
+ return (_autoAnnotations$idx = autoAnnotations[idx]) != null ? _autoAnnotations$idx : autoAnnotations[idx] = createAutoAnnotation({
828
+ deep,
829
+ autoBind
830
+ });
831
+ }
819
832
  function make_$1(adm, key, descriptor, source) {
820
833
  var _this$options_3, _this$options_4;
821
834
  // getter -> computed
@@ -932,7 +945,7 @@ function getEnhancerFromOptions(options) {
932
945
  }
933
946
  function getAnnotationFromOptions(options) {
934
947
  var _options$defaultDecor;
935
- return options ? (_options$defaultDecor = options.defaultDecorator) != null ? _options$defaultDecor : createAutoAnnotation(options) : undefined;
948
+ return options ? (_options$defaultDecor = options.defaultDecorator) != null ? _options$defaultDecor : getAutoAnnotation(options) : undefined;
936
949
  }
937
950
  function getEnhancerFromAnnotation(annotation) {
938
951
  var _annotation$options_$, _annotation$options_;
@@ -1178,14 +1191,13 @@ class ObservableValue extends Atom {
1178
1191
  this.equals_ = equals_;
1179
1192
  this.value_ = enhancer_(value, undefined, name_);
1180
1193
  if (notifySpy && isSpyEnabled()) {
1181
- var _this$value_;
1182
1194
  // only notify spy if this is a stand-alone observable
1183
1195
  spyReport({
1184
1196
  type: CREATE,
1185
1197
  object: this,
1186
1198
  observableKind: "value",
1187
1199
  debugObjectName: this.name_,
1188
- newValue: "" + ((_this$value_ = this.value_) == null ? void 0 : _this$value_.toString())
1200
+ newValue: this.value_
1189
1201
  });
1190
1202
  }
1191
1203
  }
@@ -1984,34 +1996,41 @@ function endBatch() {
1984
1996
  // the nested call instead of recursing; the outer loop re-reads list.length on
1985
1997
  // every iteration, so it picks up anything the nested dispose() pushes onto the
1986
1998
  // same pendingUnobservations array.
1987
- if (!globalState.isRunningUnobservations) {
1988
- globalState.isRunningUnobservations = true;
1989
- try {
1990
- const list = globalState.pendingUnobservations;
1991
- for (let i = 0; i < list.length; i++) {
1992
- const observable = list[i];
1993
- observable.isPendingUnobservation = false;
1994
- if (!observable.observers_ || observable.observers_.size === 0) {
1995
- if (observable.isBeingObserved) {
1996
- // if this observable had reactive observers, trigger the hooks
1997
- observable.isBeingObserved = false;
1998
- observable.onBUO();
1999
- }
2000
- if (observable instanceof ComputedValue) {
2001
- // computed values are automatically teared down when the last observer leaves
2002
- // this process happens recursively, this computed might be the last observabe of another, etc..
2003
- observable.suspend_();
2004
- }
2005
- }
1999
+ if (!globalState.isRunningUnobservations && globalState.pendingUnobservations.length > 0) {
2000
+ runPendingUnobservations();
2001
+ }
2002
+ }
2003
+ }
2004
+ // Only called when there is something to unobserve, so the common endBatch() skips the
2005
+ // try/finally and the pendingUnobservations reallocation entirely
2006
+ function runPendingUnobservations() {
2007
+ globalState.isRunningUnobservations = true;
2008
+ try {
2009
+ const list = globalState.pendingUnobservations;
2010
+ for (let i = 0; i < list.length; i++) {
2011
+ const observable = list[i];
2012
+ observable.isPendingUnobservation = false;
2013
+ if (!observable.observers_ || observable.observers_.size === 0) {
2014
+ // release the empty Set so unobserved atoms don't keep paying for it
2015
+ observable.observers_ = null;
2016
+ if (observable.isBeingObserved) {
2017
+ // if this observable had reactive observers, trigger the hooks
2018
+ observable.isBeingObserved = false;
2019
+ observable.onBUO();
2020
+ }
2021
+ if (observable instanceof ComputedValue) {
2022
+ // computed values are automatically teared down when the last observer leaves
2023
+ // this process happens recursively, this computed might be the last observabe of another, etc..
2024
+ observable.suspend_();
2006
2025
  }
2007
- globalState.pendingUnobservations = [];
2008
- } finally {
2009
- // Always release the guard, even if an onBUO handler (user code) threw,
2010
- // otherwise every future endBatch() would see isRunningUnobservations
2011
- // stuck true and silently stop draining pendingUnobservations forever.
2012
- globalState.isRunningUnobservations = false;
2013
2026
  }
2014
2027
  }
2028
+ globalState.pendingUnobservations = [];
2029
+ } finally {
2030
+ // Always release the guard, even if an onBUO handler (user code) threw,
2031
+ // otherwise every future endBatch() would see isRunningUnobservations
2032
+ // stuck true and silently stop draining pendingUnobservations forever.
2033
+ globalState.isRunningUnobservations = false;
2015
2034
  }
2016
2035
  }
2017
2036
  /**
@@ -2141,6 +2160,7 @@ class Reaction {
2141
2160
  this.runId_ = 0;
2142
2161
  this.unboundDepsCount_ = 0;
2143
2162
  this.flags_ = 0b00000;
2163
+ this.removeAbortListener_ = undefined;
2144
2164
  this.name_ = name_;
2145
2165
  this.onInvalidate_ = onInvalidate_;
2146
2166
  this.errorHandler_ = errorHandler_;
@@ -2277,7 +2297,10 @@ class Reaction {
2277
2297
  }
2278
2298
  dispose() {
2279
2299
  if (!this.isDisposed) {
2300
+ var _this$removeAbortList;
2280
2301
  this.isDisposed = true;
2302
+ // also covers self-disposal (`r.dispose()`, `when`), which bypasses the disposer
2303
+ (_this$removeAbortList = this.removeAbortListener_) == null || _this$removeAbortList.call(this);
2281
2304
  if (!this.isRunning) {
2282
2305
  // if disposed while running, clean up later. Maybe not optimal, but rare case
2283
2306
  startBatch();
@@ -2287,11 +2310,11 @@ class Reaction {
2287
2310
  }
2288
2311
  }
2289
2312
  getDisposer_(abortSignal) {
2290
- const dispose = () => {
2291
- this.dispose();
2292
- abortSignal == null || abortSignal.removeEventListener == null || abortSignal.removeEventListener("abort", dispose);
2293
- };
2294
- abortSignal == null || abortSignal.addEventListener == null || abortSignal.addEventListener("abort", dispose);
2313
+ const dispose = () => this.dispose();
2314
+ if (abortSignal != null && abortSignal.addEventListener && !this.isDisposed) {
2315
+ abortSignal.addEventListener("abort", dispose);
2316
+ this.removeAbortListener_ = () => abortSignal.removeEventListener == null ? void 0 : abortSignal.removeEventListener("abort", dispose);
2317
+ }
2295
2318
  dispose[$mobx] = this;
2296
2319
  if ("dispose" in Symbol && typeof Symbol.dispose === "symbol") {
2297
2320
  dispose[Symbol.dispose] = dispose;
@@ -3290,8 +3313,13 @@ function hasInterceptors(interceptable) {
3290
3313
  return interceptable.interceptors_ !== undefined && interceptable.interceptors_.length > 0;
3291
3314
  }
3292
3315
  function registerInterceptor(interceptable, handler) {
3293
- const interceptors = interceptable.interceptors_ || (interceptable.interceptors_ = []);
3294
- interceptors.push(handler);
3316
+ let interceptors = interceptable.interceptors_;
3317
+ if (interceptors) {
3318
+ interceptors.push(handler);
3319
+ } else {
3320
+ // Allocate at the exact size: pushing onto an empty array over-allocates its backing store
3321
+ interceptors = interceptable.interceptors_ = [handler];
3322
+ }
3295
3323
  return once(() => {
3296
3324
  const idx = interceptors.indexOf(handler);
3297
3325
  if (idx !== -1) {
@@ -3323,8 +3351,13 @@ function hasListeners(listenable) {
3323
3351
  return listenable.changeListeners_ !== undefined && listenable.changeListeners_.length > 0;
3324
3352
  }
3325
3353
  function registerListener(listenable, handler) {
3326
- const listeners = listenable.changeListeners_ || (listenable.changeListeners_ = []);
3327
- listeners.push(handler);
3354
+ let listeners = listenable.changeListeners_;
3355
+ if (listeners) {
3356
+ listeners.push(handler);
3357
+ } else {
3358
+ // Allocate at the exact size: pushing onto an empty array over-allocates its backing store
3359
+ listeners = listenable.changeListeners_ = [handler];
3360
+ }
3328
3361
  return once(() => {
3329
3362
  const idx = listeners.indexOf(handler);
3330
3363
  if (idx !== -1) {
@@ -3438,8 +3471,7 @@ const arrayTraps = {
3438
3471
  const adm = target[$mobx];
3439
3472
  if (name === "length") {
3440
3473
  adm.setArrayLength_(value);
3441
- }
3442
- if (typeof name === "symbol" || isNaN(name)) {
3474
+ } else if (typeof name === "symbol" || isNaN(name)) {
3443
3475
  target[name] = value;
3444
3476
  } else {
3445
3477
  // numeric string
@@ -3484,7 +3516,7 @@ class ObservableArrayAdministration {
3484
3516
  return this.values_.length;
3485
3517
  }
3486
3518
  setArrayLength_(newLength) {
3487
- if (typeof newLength !== "number" || isNaN(newLength) || newLength < 0) {
3519
+ if (!Number.isInteger(newLength) || newLength < 0) {
3488
3520
  die(40, newLength);
3489
3521
  }
3490
3522
  let currentLength = this.values_.length;
@@ -4266,7 +4298,8 @@ class ObservableSet {
4266
4298
  }
4267
4299
  if (!this.has(value)) {
4268
4300
  transaction(() => {
4269
- this.data_.add(this.enhancer_(value, undefined));
4301
+ value = this.enhancer_(value, undefined); // report the stored value, like map and array
4302
+ this.data_.add(value);
4270
4303
  this.atom_.reportChanged();
4271
4304
  });
4272
4305
  const notifySpy = isSpyEnabled();