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.
@@ -822,6 +822,19 @@
822
822
  extend_
823
823
  };
824
824
  }
825
+ // The auto annotation only depends on `deep` and `autoBind`, so share one instance per combination
826
+ // instead of allocating one for every object created with options
827
+ const autoAnnotations = [autoAnnotation];
828
+ function getAutoAnnotation(options) {
829
+ var _autoAnnotations$idx;
830
+ const deep = options.deep !== false;
831
+ const autoBind = !!options.autoBind;
832
+ const idx = (deep ? 0 : 1) | (autoBind ? 2 : 0);
833
+ return (_autoAnnotations$idx = autoAnnotations[idx]) != null ? _autoAnnotations$idx : autoAnnotations[idx] = createAutoAnnotation({
834
+ deep,
835
+ autoBind
836
+ });
837
+ }
825
838
  function make_$1(adm, key, descriptor, source) {
826
839
  var _this$options_3, _this$options_4;
827
840
  // getter -> computed
@@ -938,7 +951,7 @@
938
951
  }
939
952
  function getAnnotationFromOptions(options) {
940
953
  var _options$defaultDecor;
941
- return options ? (_options$defaultDecor = options.defaultDecorator) != null ? _options$defaultDecor : createAutoAnnotation(options) : undefined;
954
+ return options ? (_options$defaultDecor = options.defaultDecorator) != null ? _options$defaultDecor : getAutoAnnotation(options) : undefined;
942
955
  }
943
956
  function getEnhancerFromAnnotation(annotation) {
944
957
  var _annotation$options_$, _annotation$options_;
@@ -1184,14 +1197,13 @@
1184
1197
  this.equals_ = equals_;
1185
1198
  this.value_ = enhancer_(value, undefined, name_);
1186
1199
  if (notifySpy && isSpyEnabled()) {
1187
- var _this$value_;
1188
1200
  // only notify spy if this is a stand-alone observable
1189
1201
  spyReport({
1190
1202
  type: CREATE,
1191
1203
  object: this,
1192
1204
  observableKind: "value",
1193
1205
  debugObjectName: this.name_,
1194
- newValue: "" + ((_this$value_ = this.value_) == null ? void 0 : _this$value_.toString())
1206
+ newValue: this.value_
1195
1207
  });
1196
1208
  }
1197
1209
  }
@@ -1990,34 +2002,41 @@
1990
2002
  // the nested call instead of recursing; the outer loop re-reads list.length on
1991
2003
  // every iteration, so it picks up anything the nested dispose() pushes onto the
1992
2004
  // same pendingUnobservations array.
1993
- if (!globalState.isRunningUnobservations) {
1994
- globalState.isRunningUnobservations = true;
1995
- try {
1996
- const list = globalState.pendingUnobservations;
1997
- for (let i = 0; i < list.length; i++) {
1998
- const observable = list[i];
1999
- observable.isPendingUnobservation = false;
2000
- if (!observable.observers_ || observable.observers_.size === 0) {
2001
- if (observable.isBeingObserved) {
2002
- // if this observable had reactive observers, trigger the hooks
2003
- observable.isBeingObserved = false;
2004
- observable.onBUO();
2005
- }
2006
- if (observable instanceof ComputedValue) {
2007
- // computed values are automatically teared down when the last observer leaves
2008
- // this process happens recursively, this computed might be the last observabe of another, etc..
2009
- observable.suspend_();
2010
- }
2011
- }
2005
+ if (!globalState.isRunningUnobservations && globalState.pendingUnobservations.length > 0) {
2006
+ runPendingUnobservations();
2007
+ }
2008
+ }
2009
+ }
2010
+ // Only called when there is something to unobserve, so the common endBatch() skips the
2011
+ // try/finally and the pendingUnobservations reallocation entirely
2012
+ function runPendingUnobservations() {
2013
+ globalState.isRunningUnobservations = true;
2014
+ try {
2015
+ const list = globalState.pendingUnobservations;
2016
+ for (let i = 0; i < list.length; i++) {
2017
+ const observable = list[i];
2018
+ observable.isPendingUnobservation = false;
2019
+ if (!observable.observers_ || observable.observers_.size === 0) {
2020
+ // release the empty Set so unobserved atoms don't keep paying for it
2021
+ observable.observers_ = null;
2022
+ if (observable.isBeingObserved) {
2023
+ // if this observable had reactive observers, trigger the hooks
2024
+ observable.isBeingObserved = false;
2025
+ observable.onBUO();
2026
+ }
2027
+ if (observable instanceof ComputedValue) {
2028
+ // computed values are automatically teared down when the last observer leaves
2029
+ // this process happens recursively, this computed might be the last observabe of another, etc..
2030
+ observable.suspend_();
2012
2031
  }
2013
- globalState.pendingUnobservations = [];
2014
- } finally {
2015
- // Always release the guard, even if an onBUO handler (user code) threw,
2016
- // otherwise every future endBatch() would see isRunningUnobservations
2017
- // stuck true and silently stop draining pendingUnobservations forever.
2018
- globalState.isRunningUnobservations = false;
2019
2032
  }
2020
2033
  }
2034
+ globalState.pendingUnobservations = [];
2035
+ } finally {
2036
+ // Always release the guard, even if an onBUO handler (user code) threw,
2037
+ // otherwise every future endBatch() would see isRunningUnobservations
2038
+ // stuck true and silently stop draining pendingUnobservations forever.
2039
+ globalState.isRunningUnobservations = false;
2021
2040
  }
2022
2041
  }
2023
2042
  /**
@@ -2147,6 +2166,7 @@
2147
2166
  this.runId_ = 0;
2148
2167
  this.unboundDepsCount_ = 0;
2149
2168
  this.flags_ = 0b00000;
2169
+ this.removeAbortListener_ = undefined;
2150
2170
  this.name_ = name_;
2151
2171
  this.onInvalidate_ = onInvalidate_;
2152
2172
  this.errorHandler_ = errorHandler_;
@@ -2283,7 +2303,10 @@
2283
2303
  }
2284
2304
  dispose() {
2285
2305
  if (!this.isDisposed) {
2306
+ var _this$removeAbortList;
2286
2307
  this.isDisposed = true;
2308
+ // also covers self-disposal (`r.dispose()`, `when`), which bypasses the disposer
2309
+ (_this$removeAbortList = this.removeAbortListener_) == null || _this$removeAbortList.call(this);
2287
2310
  if (!this.isRunning) {
2288
2311
  // if disposed while running, clean up later. Maybe not optimal, but rare case
2289
2312
  startBatch();
@@ -2293,11 +2316,11 @@
2293
2316
  }
2294
2317
  }
2295
2318
  getDisposer_(abortSignal) {
2296
- const dispose = () => {
2297
- this.dispose();
2298
- abortSignal == null || abortSignal.removeEventListener == null || abortSignal.removeEventListener("abort", dispose);
2299
- };
2300
- abortSignal == null || abortSignal.addEventListener == null || abortSignal.addEventListener("abort", dispose);
2319
+ const dispose = () => this.dispose();
2320
+ if (abortSignal != null && abortSignal.addEventListener && !this.isDisposed) {
2321
+ abortSignal.addEventListener("abort", dispose);
2322
+ this.removeAbortListener_ = () => abortSignal.removeEventListener == null ? void 0 : abortSignal.removeEventListener("abort", dispose);
2323
+ }
2301
2324
  dispose[$mobx] = this;
2302
2325
  if ("dispose" in Symbol && typeof Symbol.dispose === "symbol") {
2303
2326
  dispose[Symbol.dispose] = dispose;
@@ -3296,8 +3319,13 @@
3296
3319
  return interceptable.interceptors_ !== undefined && interceptable.interceptors_.length > 0;
3297
3320
  }
3298
3321
  function registerInterceptor(interceptable, handler) {
3299
- const interceptors = interceptable.interceptors_ || (interceptable.interceptors_ = []);
3300
- interceptors.push(handler);
3322
+ let interceptors = interceptable.interceptors_;
3323
+ if (interceptors) {
3324
+ interceptors.push(handler);
3325
+ } else {
3326
+ // Allocate at the exact size: pushing onto an empty array over-allocates its backing store
3327
+ interceptors = interceptable.interceptors_ = [handler];
3328
+ }
3301
3329
  return once(() => {
3302
3330
  const idx = interceptors.indexOf(handler);
3303
3331
  if (idx !== -1) {
@@ -3329,8 +3357,13 @@
3329
3357
  return listenable.changeListeners_ !== undefined && listenable.changeListeners_.length > 0;
3330
3358
  }
3331
3359
  function registerListener(listenable, handler) {
3332
- const listeners = listenable.changeListeners_ || (listenable.changeListeners_ = []);
3333
- listeners.push(handler);
3360
+ let listeners = listenable.changeListeners_;
3361
+ if (listeners) {
3362
+ listeners.push(handler);
3363
+ } else {
3364
+ // Allocate at the exact size: pushing onto an empty array over-allocates its backing store
3365
+ listeners = listenable.changeListeners_ = [handler];
3366
+ }
3334
3367
  return once(() => {
3335
3368
  const idx = listeners.indexOf(handler);
3336
3369
  if (idx !== -1) {
@@ -3444,8 +3477,7 @@
3444
3477
  const adm = target[$mobx];
3445
3478
  if (name === "length") {
3446
3479
  adm.setArrayLength_(value);
3447
- }
3448
- if (typeof name === "symbol" || isNaN(name)) {
3480
+ } else if (typeof name === "symbol" || isNaN(name)) {
3449
3481
  target[name] = value;
3450
3482
  } else {
3451
3483
  // numeric string
@@ -3490,7 +3522,7 @@
3490
3522
  return this.values_.length;
3491
3523
  }
3492
3524
  setArrayLength_(newLength) {
3493
- if (typeof newLength !== "number" || isNaN(newLength) || newLength < 0) {
3525
+ if (!Number.isInteger(newLength) || newLength < 0) {
3494
3526
  die(40, newLength);
3495
3527
  }
3496
3528
  let currentLength = this.values_.length;
@@ -4272,7 +4304,8 @@
4272
4304
  }
4273
4305
  if (!this.has(value)) {
4274
4306
  transaction(() => {
4275
- this.data_.add(this.enhancer_(value, undefined));
4307
+ value = this.enhancer_(value, undefined); // report the stored value, like map and array
4308
+ this.data_.add(value);
4276
4309
  this.atom_.reportChanged();
4277
4310
  });
4278
4311
  const notifySpy = isSpyEnabled();