mobx 6.10.0 → 6.10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # mobx
2
2
 
3
+ ## 6.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`3ceeb865`](https://github.com/mobxjs/mobx/commit/3ceeb8651e328c4c7211c875696b3f5269fea834) [#3732](https://github.com/mobxjs/mobx/pull/3732) Thanks [@urugator](https://github.com/urugator)! - - fix: #3728: Observable initialization updates state version.
8
+ - fix: Observable set initialization violates `enforceActions: "always"`.
9
+ - fix: Changing keys of observable object does not respect `enforceActions`.
10
+
3
11
  ## 6.10.0
4
12
 
5
13
  ### Minor Changes
@@ -2,13 +2,14 @@ import { IDerivationState_, IObservable, IDerivation, Lambda } from "../internal
2
2
  export declare const $mobx: unique symbol;
3
3
  export interface IAtom extends IObservable {
4
4
  reportObserved(): boolean;
5
- reportChanged(): any;
5
+ reportChanged(): void;
6
6
  }
7
7
  export declare class Atom implements IAtom {
8
8
  name_: string;
9
9
  isPendingUnobservation_: boolean;
10
10
  isBeingObserved_: boolean;
11
11
  observers_: Set<IDerivation>;
12
+ batchId_: number;
12
13
  diffValue_: number;
13
14
  lastAccessedBy_: number;
14
15
  lowestObserverState_: IDerivationState_;
@@ -37,6 +37,11 @@ export declare class MobXGlobals {
37
37
  * Are we in a batch block? (and how many of them)
38
38
  */
39
39
  inBatch: number;
40
+ /**
41
+ * ID of the latest batch. Used to suppress reportChanged of newly created atoms.
42
+ * Note the value persists even after batch ended.
43
+ */
44
+ batchId: number;
40
45
  /**
41
46
  * Observables that don't have observers anymore, and are about to be
42
47
  * suspended, unless somebody else accesses it in the same batch
@@ -426,12 +426,14 @@ var Atom = /*#__PURE__*/function () {
426
426
  this.isPendingUnobservation_ = false;
427
427
  this.isBeingObserved_ = false;
428
428
  this.observers_ = new Set();
429
+ this.batchId_ = void 0;
429
430
  this.diffValue_ = 0;
430
431
  this.lastAccessedBy_ = 0;
431
432
  this.lowestObserverState_ = IDerivationState_.NOT_TRACKING_;
432
433
  this.onBOL = void 0;
433
434
  this.onBUOL = void 0;
434
435
  this.name_ = name_;
436
+ this.batchId_ = globalState.inBatch ? globalState.batchId : NaN;
435
437
  }
436
438
  // onBecomeObservedListeners
437
439
  var _proto = Atom.prototype;
@@ -460,6 +462,12 @@ var Atom = /*#__PURE__*/function () {
460
462
  * Invoke this method _after_ this method has changed to signal mobx that all its observers should invalidate.
461
463
  */;
462
464
  _proto.reportChanged = function reportChanged() {
465
+ if (globalState.inBatch && this.batchId_ === globalState.batchId) {
466
+ // Called from the same batch this atom was created in.
467
+ return;
468
+ }
469
+ // Avoids the possibility of hitting the same globalState.batchId when it cycled through all integers (necessary?)
470
+ this.batchId_ = NaN;
463
471
  startBatch();
464
472
  propagateChanged(this);
465
473
  // We could update state version only at the end of batch,
@@ -993,7 +1001,9 @@ var observableFactories = {
993
1001
  return new ObservableSet(initialValues, getEnhancerFromOptions(o), o.name);
994
1002
  },
995
1003
  object: function object(props, decorators, options) {
996
- return extendObservable(globalState.useProxies === false || (options == null ? void 0 : options.proxy) === false ? asObservableObject({}, options) : asDynamicObservableObject({}, options), props, decorators);
1004
+ return initObservable(function () {
1005
+ return extendObservable(globalState.useProxies === false || (options == null ? void 0 : options.proxy) === false ? asObservableObject({}, options) : asDynamicObservableObject({}, options), props, decorators);
1006
+ });
997
1007
  },
998
1008
  ref: /*#__PURE__*/createDecoratorAnnotation(observableRefAnnotation),
999
1009
  shallow: /*#__PURE__*/createDecoratorAnnotation(observableShallowAnnotation),
@@ -1815,6 +1825,7 @@ var MobXGlobals = function MobXGlobals() {
1815
1825
  this.runId = 0;
1816
1826
  this.mobxGuid = 0;
1817
1827
  this.inBatch = 0;
1828
+ this.batchId = Number.MIN_SAFE_INTEGER;
1818
1829
  this.pendingUnobservations = [];
1819
1830
  this.pendingReactions = [];
1820
1831
  this.isRunningReactions = false;
@@ -1954,6 +1965,9 @@ function queueForUnobservation(observable) {
1954
1965
  * Avoids unnecessary recalculations.
1955
1966
  */
1956
1967
  function startBatch() {
1968
+ if (globalState.inBatch === 0) {
1969
+ globalState.batchId = globalState.batchId < Number.MAX_SAFE_INTEGER ? globalState.batchId + 1 : Number.MIN_SAFE_INTEGER;
1970
+ }
1957
1971
  globalState.inBatch++;
1958
1972
  }
1959
1973
  function endBatch() {
@@ -2629,17 +2643,14 @@ function extendObservable(target, properties, annotations, options) {
2629
2643
  }
2630
2644
  // Pull descriptors first, so we don't have to deal with props added by administration ($mobx)
2631
2645
  var descriptors = getOwnPropertyDescriptors(properties);
2632
- var adm = asObservableObject(target, options)[$mobx];
2633
- startBatch();
2634
- try {
2646
+ initObservable(function () {
2647
+ var adm = asObservableObject(target, options)[$mobx];
2635
2648
  ownKeys(descriptors).forEach(function (key) {
2636
2649
  adm.extend_(key, descriptors[key],
2637
2650
  // must pass "undefined" for { key: undefined }
2638
2651
  !annotations ? true : key in annotations ? annotations[key] : true);
2639
2652
  });
2640
- } finally {
2641
- endBatch();
2642
- }
2653
+ });
2643
2654
  return target;
2644
2655
  }
2645
2656
 
@@ -3325,10 +3336,9 @@ function notifyListeners(listenable, change) {
3325
3336
  }
3326
3337
 
3327
3338
  function makeObservable(target, annotations, options) {
3328
- var adm = asObservableObject(target, options)[$mobx];
3329
- startBatch();
3330
- try {
3339
+ initObservable(function () {
3331
3340
  var _annotations;
3341
+ var adm = asObservableObject(target, options)[$mobx];
3332
3342
  if ("development" !== "production" && annotations && target[storedAnnotationsSymbol]) {
3333
3343
  die("makeObservable second arg must be nullish when using decorators. Mixing @decorator syntax with annotations is not supported.");
3334
3344
  }
@@ -3338,9 +3348,7 @@ function makeObservable(target, annotations, options) {
3338
3348
  ownKeys(annotations).forEach(function (key) {
3339
3349
  return adm.make_(key, annotations[key]);
3340
3350
  });
3341
- } finally {
3342
- endBatch();
3343
- }
3351
+ });
3344
3352
  return target;
3345
3353
  }
3346
3354
  // proto[keysSymbol] = new Set<PropertyKey>()
@@ -3359,26 +3367,23 @@ function makeAutoObservable(target, overrides, options) {
3359
3367
  if (isPlainObject(target)) {
3360
3368
  return extendObservable(target, target, overrides, options);
3361
3369
  }
3362
- var adm = asObservableObject(target, options)[$mobx];
3363
- // Optimization: cache keys on proto
3364
- // Assumes makeAutoObservable can be called only once per object and can't be used in subclass
3365
- if (!target[keysSymbol]) {
3366
- var proto = Object.getPrototypeOf(target);
3367
- var keys = new Set([].concat(ownKeys(target), ownKeys(proto)));
3368
- keys["delete"]("constructor");
3369
- keys["delete"]($mobx);
3370
- addHiddenProp(proto, keysSymbol, keys);
3371
- }
3372
- startBatch();
3373
- try {
3370
+ initObservable(function () {
3371
+ var adm = asObservableObject(target, options)[$mobx];
3372
+ // Optimization: cache keys on proto
3373
+ // Assumes makeAutoObservable can be called only once per object and can't be used in subclass
3374
+ if (!target[keysSymbol]) {
3375
+ var proto = Object.getPrototypeOf(target);
3376
+ var keys = new Set([].concat(ownKeys(target), ownKeys(proto)));
3377
+ keys["delete"]("constructor");
3378
+ keys["delete"]($mobx);
3379
+ addHiddenProp(proto, keysSymbol, keys);
3380
+ }
3374
3381
  target[keysSymbol].forEach(function (key) {
3375
3382
  return adm.make_(key,
3376
3383
  // must pass "undefined" for { key: undefined }
3377
3384
  !overrides ? true : key in overrides ? overrides[key] : true);
3378
3385
  });
3379
- } finally {
3380
- endBatch();
3381
- }
3386
+ });
3382
3387
  return target;
3383
3388
  }
3384
3389
 
@@ -3686,16 +3691,16 @@ function createObservableArray(initialValues, enhancer, name, owned) {
3686
3691
  owned = false;
3687
3692
  }
3688
3693
  assertProxies();
3689
- var adm = new ObservableArrayAdministration(name, enhancer, owned, false);
3690
- addHiddenFinalProp(adm.values_, $mobx, adm);
3691
- var proxy = new Proxy(adm.values_, arrayTraps);
3692
- adm.proxy_ = proxy;
3693
- if (initialValues && initialValues.length) {
3694
- var prev = allowStateChangesStart(true);
3695
- adm.spliceWithArray_(0, 0, initialValues);
3696
- allowStateChangesEnd(prev);
3697
- }
3698
- return proxy;
3694
+ return initObservable(function () {
3695
+ var adm = new ObservableArrayAdministration(name, enhancer, owned, false);
3696
+ addHiddenFinalProp(adm.values_, $mobx, adm);
3697
+ var proxy = new Proxy(adm.values_, arrayTraps);
3698
+ adm.proxy_ = proxy;
3699
+ if (initialValues && initialValues.length) {
3700
+ adm.spliceWithArray_(0, 0, initialValues);
3701
+ }
3702
+ return proxy;
3703
+ });
3699
3704
  }
3700
3705
  // eslint-disable-next-line
3701
3706
  var arrayExtensions = {
@@ -3891,11 +3896,13 @@ var ObservableMap = /*#__PURE__*/function () {
3891
3896
  if (!isFunction(Map)) {
3892
3897
  die(18);
3893
3898
  }
3894
- this.keysAtom_ = createAtom( this.name_ + ".keys()" );
3895
- this.data_ = new Map();
3896
- this.hasMap_ = new Map();
3897
- allowStateChanges(true, function () {
3898
- _this.merge(initialData);
3899
+ initObservable(function () {
3900
+ _this.keysAtom_ = createAtom("development" !== "production" ? _this.name_ + ".keys()" : "ObservableMap.keys()");
3901
+ _this.data_ = new Map();
3902
+ _this.hasMap_ = new Map();
3903
+ if (initialData) {
3904
+ _this.merge(initialData);
3905
+ }
3899
3906
  });
3900
3907
  }
3901
3908
  var _proto = ObservableMap.prototype;
@@ -4279,6 +4286,7 @@ _Symbol$iterator$1 = Symbol.iterator;
4279
4286
  _Symbol$toStringTag$1 = Symbol.toStringTag;
4280
4287
  var ObservableSet = /*#__PURE__*/function () {
4281
4288
  function ObservableSet(initialData, enhancer, name_) {
4289
+ var _this = this;
4282
4290
  if (enhancer === void 0) {
4283
4291
  enhancer = deepEnhancer;
4284
4292
  }
@@ -4297,13 +4305,15 @@ var ObservableSet = /*#__PURE__*/function () {
4297
4305
  if (!isFunction(Set)) {
4298
4306
  die(22);
4299
4307
  }
4300
- this.atom_ = createAtom(this.name_);
4301
4308
  this.enhancer_ = function (newV, oldV) {
4302
4309
  return enhancer(newV, oldV, name_);
4303
4310
  };
4304
- if (initialData) {
4305
- this.replace(initialData);
4306
- }
4311
+ initObservable(function () {
4312
+ _this.atom_ = createAtom(_this.name_);
4313
+ if (initialData) {
4314
+ _this.replace(initialData);
4315
+ }
4316
+ });
4307
4317
  }
4308
4318
  var _proto = ObservableSet.prototype;
4309
4319
  _proto.dehanceValue_ = function dehanceValue_(value) {
@@ -4313,12 +4323,12 @@ var ObservableSet = /*#__PURE__*/function () {
4313
4323
  return value;
4314
4324
  };
4315
4325
  _proto.clear = function clear() {
4316
- var _this = this;
4326
+ var _this2 = this;
4317
4327
  transaction(function () {
4318
4328
  untracked(function () {
4319
- for (var _iterator = _createForOfIteratorHelperLoose(_this.data_.values()), _step; !(_step = _iterator()).done;) {
4329
+ for (var _iterator = _createForOfIteratorHelperLoose(_this2.data_.values()), _step; !(_step = _iterator()).done;) {
4320
4330
  var value = _step.value;
4321
- _this["delete"](value);
4331
+ _this2["delete"](value);
4322
4332
  }
4323
4333
  });
4324
4334
  });
@@ -4330,7 +4340,7 @@ var ObservableSet = /*#__PURE__*/function () {
4330
4340
  }
4331
4341
  };
4332
4342
  _proto.add = function add(value) {
4333
- var _this2 = this;
4343
+ var _this3 = this;
4334
4344
  checkIfStateModificationsAreAllowed(this.atom_);
4335
4345
  if (hasInterceptors(this)) {
4336
4346
  var change = interceptChange(this, {
@@ -4347,8 +4357,8 @@ var ObservableSet = /*#__PURE__*/function () {
4347
4357
 
4348
4358
  if (!this.has(value)) {
4349
4359
  transaction(function () {
4350
- _this2.data_.add(_this2.enhancer_(value, undefined));
4351
- _this2.atom_.reportChanged();
4360
+ _this3.data_.add(_this3.enhancer_(value, undefined));
4361
+ _this3.atom_.reportChanged();
4352
4362
  });
4353
4363
  var notifySpy = isSpyEnabled();
4354
4364
  var notify = hasListeners(this);
@@ -4372,7 +4382,7 @@ var ObservableSet = /*#__PURE__*/function () {
4372
4382
  return this;
4373
4383
  };
4374
4384
  _proto["delete"] = function _delete(value) {
4375
- var _this3 = this;
4385
+ var _this4 = this;
4376
4386
  if (hasInterceptors(this)) {
4377
4387
  var change = interceptChange(this, {
4378
4388
  type: DELETE,
@@ -4397,8 +4407,8 @@ var ObservableSet = /*#__PURE__*/function () {
4397
4407
  spyReportStart(_change2);
4398
4408
  }
4399
4409
  transaction(function () {
4400
- _this3.atom_.reportChanged();
4401
- _this3.data_["delete"](value);
4410
+ _this4.atom_.reportChanged();
4411
+ _this4.data_["delete"](value);
4402
4412
  });
4403
4413
  if (notify) {
4404
4414
  notifyListeners(this, _change2);
@@ -4451,20 +4461,20 @@ var ObservableSet = /*#__PURE__*/function () {
4451
4461
  });
4452
4462
  };
4453
4463
  _proto.replace = function replace(other) {
4454
- var _this4 = this;
4464
+ var _this5 = this;
4455
4465
  if (isObservableSet(other)) {
4456
4466
  other = new Set(other);
4457
4467
  }
4458
4468
  transaction(function () {
4459
4469
  if (Array.isArray(other)) {
4460
- _this4.clear();
4470
+ _this5.clear();
4461
4471
  other.forEach(function (value) {
4462
- return _this4.add(value);
4472
+ return _this5.add(value);
4463
4473
  });
4464
4474
  } else if (isES6Set(other)) {
4465
- _this4.clear();
4475
+ _this5.clear();
4466
4476
  other.forEach(function (value) {
4467
- return _this4.add(value);
4477
+ return _this5.add(value);
4468
4478
  });
4469
4479
  } else if (other !== null && other !== undefined) {
4470
4480
  die("Cannot initialize set from " + other);
@@ -4728,6 +4738,7 @@ var ObservableObjectAdministration = /*#__PURE__*/function () {
4728
4738
  if (proxyTrap === void 0) {
4729
4739
  proxyTrap = false;
4730
4740
  }
4741
+ checkIfStateModificationsAreAllowed(this.keysAtom_);
4731
4742
  try {
4732
4743
  startBatch();
4733
4744
  // Delete
@@ -4775,6 +4786,7 @@ var ObservableObjectAdministration = /*#__PURE__*/function () {
4775
4786
  if (proxyTrap === void 0) {
4776
4787
  proxyTrap = false;
4777
4788
  }
4789
+ checkIfStateModificationsAreAllowed(this.keysAtom_);
4778
4790
  try {
4779
4791
  startBatch();
4780
4792
  // Delete
@@ -4826,6 +4838,7 @@ var ObservableObjectAdministration = /*#__PURE__*/function () {
4826
4838
  if (proxyTrap === void 0) {
4827
4839
  proxyTrap = false;
4828
4840
  }
4841
+ checkIfStateModificationsAreAllowed(this.keysAtom_);
4829
4842
  try {
4830
4843
  startBatch();
4831
4844
  // Delete
@@ -4881,6 +4894,7 @@ var ObservableObjectAdministration = /*#__PURE__*/function () {
4881
4894
  if (proxyTrap === void 0) {
4882
4895
  proxyTrap = false;
4883
4896
  }
4897
+ checkIfStateModificationsAreAllowed(this.keysAtom_);
4884
4898
  // No such prop
4885
4899
  if (!hasProp(this.target_, key)) {
4886
4900
  return true;
@@ -5110,6 +5124,17 @@ function assertAnnotable(adm, annotation, key) {
5110
5124
 
5111
5125
  // Bug in safari 9.* (or iOS 9 safari mobile). See #364
5112
5126
  var ENTRY_0 = /*#__PURE__*/createArrayEntryDescriptor(0);
5127
+ var safariPrototypeSetterInheritanceBug = /*#__PURE__*/function () {
5128
+ var v = false;
5129
+ var p = {};
5130
+ Object.defineProperty(p, "0", {
5131
+ set: function set() {
5132
+ v = true;
5133
+ }
5134
+ });
5135
+ /*#__PURE__*/Object.create(p)["0"] = 1;
5136
+ return v === false;
5137
+ }();
5113
5138
  /**
5114
5139
  * This array buffer contains two lists of properties, so that all arrays
5115
5140
  * can recycle their property definitions, which significantly improves performance of creating
@@ -5142,20 +5167,20 @@ var LegacyObservableArray = /*#__PURE__*/function (_StubArray, _Symbol$toStringT
5142
5167
  owned = false;
5143
5168
  }
5144
5169
  _this = _StubArray.call(this) || this;
5145
- var adm = new ObservableArrayAdministration(name, enhancer, owned, true);
5146
- adm.proxy_ = _assertThisInitialized(_this);
5147
- addHiddenFinalProp(_assertThisInitialized(_this), $mobx, adm);
5148
- if (initialValues && initialValues.length) {
5149
- var prev = allowStateChangesStart(true);
5150
- // @ts-ignore
5151
- _this.spliceWithArray(0, 0, initialValues);
5152
- allowStateChangesEnd(prev);
5153
- }
5154
- {
5155
- // Seems that Safari won't use numeric prototype setter untill any * numeric property is
5156
- // defined on the instance. After that it works fine, even if this property is deleted.
5157
- Object.defineProperty(_assertThisInitialized(_this), "0", ENTRY_0);
5158
- }
5170
+ initObservable(function () {
5171
+ var adm = new ObservableArrayAdministration(name, enhancer, owned, true);
5172
+ adm.proxy_ = _assertThisInitialized(_this);
5173
+ addHiddenFinalProp(_assertThisInitialized(_this), $mobx, adm);
5174
+ if (initialValues && initialValues.length) {
5175
+ // @ts-ignore
5176
+ _this.spliceWithArray(0, 0, initialValues);
5177
+ }
5178
+ if (safariPrototypeSetterInheritanceBug) {
5179
+ // Seems that Safari won't use numeric prototype setter untill any * numeric property is
5180
+ // defined on the instance. After that it works fine, even if this property is deleted.
5181
+ Object.defineProperty(_assertThisInitialized(_this), "0", ENTRY_0);
5182
+ }
5183
+ });
5159
5184
  return _this;
5160
5185
  }
5161
5186
  var _proto = LegacyObservableArray.prototype;
@@ -5310,6 +5335,24 @@ function getDebugName(thing, property) {
5310
5335
  }
5311
5336
  return named.name_;
5312
5337
  }
5338
+ /**
5339
+ * Helper function for initializing observable structures, it applies:
5340
+ * 1. allowStateChanges so we don't violate enforceActions.
5341
+ * 2. untracked so we don't accidentaly subscribe to anything observable accessed during init in case the observable is created inside derivation.
5342
+ * 3. batch to avoid state version updates
5343
+ */
5344
+ function initObservable(cb) {
5345
+ var derivation = untrackedStart();
5346
+ var allowStateChanges = allowStateChangesStart(true);
5347
+ startBatch();
5348
+ try {
5349
+ return cb();
5350
+ } finally {
5351
+ endBatch();
5352
+ allowStateChangesEnd(allowStateChanges);
5353
+ untrackedEnd(derivation);
5354
+ }
5355
+ }
5313
5356
 
5314
5357
  var toString = objectPrototype.toString;
5315
5358
  function deepEqual(a, b, depth) {