mobx-state-tree 7.0.2 → 7.1.0

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.
@@ -791,7 +791,7 @@ function addDisposer(target, disposer) {
791
791
  }
792
792
  /**
793
793
  * Returns the environment of the current state tree, or throws. For more info on environments,
794
- * see [Dependency injection](https://github.com/mobxjs/mobx-state-tree#dependency-injection)
794
+ * see [Dependency injection](/concepts/dependency-injection)
795
795
  *
796
796
  * Please note that in child nodes access to the root is only possible
797
797
  * once the `afterAttach` hook has fired
@@ -2165,6 +2165,17 @@ var ObjectNode = /** @class */ (function (_super) {
2165
2165
  return this._internalEventsRegister(InternalEvents.Patch, handler);
2166
2166
  }
2167
2167
  });
2168
+ Object.defineProperty(ObjectNode.prototype, "hasPatchSubscribers", {
2169
+ enumerable: false,
2170
+ configurable: true,
2171
+ writable: true,
2172
+ value: function () {
2173
+ if (this._internalEventsHasSubscribers(InternalEvents.Patch)) {
2174
+ return true;
2175
+ }
2176
+ return this.parent ? this.parent.hasPatchSubscribers() : false;
2177
+ }
2178
+ });
2168
2179
  Object.defineProperty(ObjectNode.prototype, "emitPatch", {
2169
2180
  enumerable: false,
2170
2181
  configurable: true,
@@ -2377,6 +2388,7 @@ var TypeFlags;
2377
2388
  TypeFlags[TypeFlags["Lazy"] = 1048576] = "Lazy";
2378
2389
  TypeFlags[TypeFlags["Finite"] = 2097152] = "Finite";
2379
2390
  TypeFlags[TypeFlags["Float"] = 4194304] = "Float";
2391
+ TypeFlags[TypeFlags["BigInt"] = 8388608] = "BigInt";
2380
2392
  })(TypeFlags || (TypeFlags = {}));
2381
2393
  /**
2382
2394
  * @internal
@@ -2693,6 +2705,38 @@ var SimpleType = /** @class */ (function (_super) {
2693
2705
  });
2694
2706
  return SimpleType;
2695
2707
  }(BaseType));
2708
+ function canApplyDirectSnapshot(childType, childNode, newValue) {
2709
+ var reconciliationType = childNode.getReconciliationType();
2710
+ var expectedReconciliationType = resolveDirectApplyType(childType);
2711
+ // Only types that reconcile as the same transparent-wrapper-adjusted type can safely reuse
2712
+ // the existing child node. Wrappers with their own validation or snapshot semantics
2713
+ // intentionally keep a distinct reconciliation type so they fall back to the validated path.
2714
+ var hasMatchingReconciliationType = reconciliationType === expectedReconciliationType;
2715
+ return (childNode instanceof ObjectNode &&
2716
+ hasMatchingReconciliationType &&
2717
+ reconciliationType instanceof ComplexType &&
2718
+ isMutable(newValue) &&
2719
+ !isStateTreeNode(newValue) &&
2720
+ reconciliationType.isMatchingSnapshotId(childNode, newValue));
2721
+ }
2722
+ function resolveDirectApplyType(type) {
2723
+ var subTypes = type.getSubTypes();
2724
+ if (!subTypes ||
2725
+ Array.isArray(subTypes) ||
2726
+ subTypes === cannotDetermineSubtype ||
2727
+ !canUnwrapDirectApplyType(type)) {
2728
+ return type;
2729
+ }
2730
+ // Only unwrap wrappers that are transparent for direct apply. Wrappers with their own
2731
+ // validation or snapshot processing must keep their wrapper identity here.
2732
+ return resolveDirectApplyType(subTypes);
2733
+ }
2734
+ function canUnwrapDirectApplyType(type) {
2735
+ var transparentWrapperFlags = TypeFlags.Optional | TypeFlags.Late;
2736
+ var nonTransparentWrapperFlags = TypeFlags.Refinement | TypeFlags.SnapshotProcessor | TypeFlags.Union;
2737
+ return ((type.flags & transparentWrapperFlags) > 0 &&
2738
+ (type.flags & nonTransparentWrapperFlags) === 0);
2739
+ }
2696
2740
  /**
2697
2741
  * Returns if a given value represents a type.
2698
2742
  *
@@ -4042,6 +4086,7 @@ function isPrimitive(value, includeDate) {
4042
4086
  typeof value === "string" ||
4043
4087
  typeof value === "number" ||
4044
4088
  typeof value === "boolean" ||
4089
+ typeof value === "bigint" ||
4045
4090
  (includeDate && value instanceof Date));
4046
4091
  }
4047
4092
  /**
@@ -4926,6 +4971,8 @@ function proxyNodeTypeMethods(nodeType, snapshotProcessorType) {
4926
4971
  /**
4927
4972
  * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
4928
4973
  *
4974
+ * [See known issue with `applySnapshot` and `preProcessSnapshot`](https://github.com/mobxjs/mobx-state-tree/issues/1317)
4975
+ *
4929
4976
  * Example:
4930
4977
  * ```ts
4931
4978
  * const Todo1 = types.model({ text: types.string })
@@ -5376,23 +5423,33 @@ var MapType = /** @class */ (function (_super) {
5376
5423
  configurable: true,
5377
5424
  writable: true,
5378
5425
  value: function (node, snapshot) {
5379
- typecheckInternal(this, snapshot);
5426
+ if (!isPlainObject(snapshot)) {
5427
+ typecheckInternal(this, snapshot);
5428
+ return;
5429
+ }
5380
5430
  var target = node.storedValue;
5381
- var currentKeys = {};
5431
+ var childType = this.getChildType();
5382
5432
  Array.from(target.keys()).forEach(function (key) {
5383
- currentKeys[key] = false;
5384
- });
5385
- if (snapshot) {
5386
- // Don't use target.replace, as it will throw away all existing items first
5387
- for (var key in snapshot) {
5388
- target.set(key, snapshot[key]);
5389
- currentKeys["" + key] = true;
5390
- }
5391
- }
5392
- Object.keys(currentKeys).forEach(function (key) {
5393
- if (currentKeys[key] === false)
5433
+ if (!Object.prototype.hasOwnProperty.call(snapshot, key)) {
5394
5434
  target.delete(key);
5435
+ return;
5436
+ }
5437
+ var childNode = node.getChildNode(key);
5438
+ var newValue = snapshot[key];
5439
+ if (childNode.snapshot === newValue)
5440
+ return;
5441
+ if (canApplyDirectSnapshot(childType, childNode, newValue)) {
5442
+ childNode.applySnapshot(newValue);
5443
+ }
5444
+ else {
5445
+ target.set(key, newValue);
5446
+ }
5395
5447
  });
5448
+ for (var key in snapshot) {
5449
+ if (!Object.prototype.hasOwnProperty.call(snapshot, key) || target.has(key))
5450
+ continue;
5451
+ target.set(key, snapshot[key]);
5452
+ }
5396
5453
  }
5397
5454
  });
5398
5455
  Object.defineProperty(MapType.prototype, "getChildType", {
@@ -5718,9 +5775,52 @@ var ArrayType = /** @class */ (function (_super) {
5718
5775
  configurable: true,
5719
5776
  writable: true,
5720
5777
  value: function (node, snapshot) {
5721
- typecheckInternal(this, snapshot);
5778
+ if (!isArray(snapshot)) {
5779
+ typecheckInternal(this, snapshot);
5780
+ return;
5781
+ }
5722
5782
  var target = node.storedValue;
5723
- target.replace(snapshot);
5783
+ var childNodes = node.getChildren();
5784
+ var oldLength = childNodes.length;
5785
+ var newLength = snapshot.length;
5786
+ var childType = this.getChildType();
5787
+ var minLength = Math.min(oldLength, newLength);
5788
+ var firstChangedIndex = findFirstChangedIndex(childNodes, snapshot, minLength);
5789
+ // If all array items are the same and the length did not change, there is nothing to do.
5790
+ if (firstChangedIndex === oldLength && firstChangedIndex === newLength) {
5791
+ return;
5792
+ }
5793
+ // Preserve the old "always replace" behavior for length changes and when patches are being
5794
+ // observed, since those cases are more sensitive to patch shape (for example, splice
5795
+ // would otherwise emit add/remove patch sequences) and benchmark variance.
5796
+ if (oldLength !== newLength || node.hasPatchSubscribers()) {
5797
+ target.replace(snapshot);
5798
+ return;
5799
+ }
5800
+ // When every changed entry can reuse its existing child node, update them in place
5801
+ // instead of going through array replacement/splice.
5802
+ if (canApplyDirectSnapshotsInRange(childType, childNodes, snapshot, firstChangedIndex)) {
5803
+ applyDirectSnapshotsInRange(childNodes, snapshot, firstChangedIndex);
5804
+ return;
5805
+ }
5806
+ var oldEnd = oldLength - 1;
5807
+ var newEnd = newLength - 1;
5808
+ while (oldEnd >= firstChangedIndex &&
5809
+ newEnd >= firstChangedIndex &&
5810
+ childNodes[oldEnd].snapshot === snapshot[newEnd]) {
5811
+ oldEnd--;
5812
+ newEnd--;
5813
+ }
5814
+ // Trim the unchanged suffix too, so we only replace the minimal changed window.
5815
+ var replacedCount = oldEnd >= firstChangedIndex ? oldEnd - firstChangedIndex + 1 : 0;
5816
+ var replacementSnapshots = newEnd >= firstChangedIndex
5817
+ ? snapshot.slice(firstChangedIndex, newEnd + 1)
5818
+ : EMPTY_ARRAY;
5819
+ if (replacedCount === 1 && replacementSnapshots.length === 1) {
5820
+ target[firstChangedIndex] = replacementSnapshots[0];
5821
+ return;
5822
+ }
5823
+ target.splice.apply(target, __spreadArray([firstChangedIndex, replacedCount], __read(replacementSnapshots), false));
5724
5824
  }
5725
5825
  });
5726
5826
  Object.defineProperty(ArrayType.prototype, "getChildType", {
@@ -5792,6 +5892,31 @@ function array(subtype) {
5792
5892
  assertIsType(subtype, 1);
5793
5893
  return new ArrayType("".concat(subtype.name, "[]"), subtype);
5794
5894
  }
5895
+ function findFirstChangedIndex(childNodes, snapshot, length) {
5896
+ var index = 0;
5897
+ while (index < length && childNodes[index].snapshot === snapshot[index]) {
5898
+ index++;
5899
+ }
5900
+ return index;
5901
+ }
5902
+ function canApplyDirectSnapshotsInRange(childType, childNodes, snapshot, startIndex) {
5903
+ for (var i = startIndex; i < childNodes.length; i++) {
5904
+ if (childNodes[i].snapshot === snapshot[i])
5905
+ continue;
5906
+ if (!canApplyDirectSnapshot(childType, childNodes[i], snapshot[i])) {
5907
+ return false;
5908
+ }
5909
+ }
5910
+ return true;
5911
+ }
5912
+ function applyDirectSnapshotsInRange(childNodes, snapshot, startIndex) {
5913
+ for (var i = startIndex; i < childNodes.length; i++) {
5914
+ var childNode = childNodes[i];
5915
+ if (childNode.snapshot === snapshot[i])
5916
+ continue;
5917
+ childNode.applySnapshot(snapshot[i]);
5918
+ }
5919
+ }
5795
5920
  function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths) {
5796
5921
  var nothingChanged = true;
5797
5922
  for (var i = 0;; i++) {
@@ -6437,10 +6562,25 @@ var ModelType = /** @class */ (function (_super) {
6437
6562
  configurable: true,
6438
6563
  writable: true,
6439
6564
  value: function (node, snapshot) {
6440
- typecheckInternal(this, snapshot);
6441
6565
  var preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
6442
- this.forAllProps(function (name) {
6443
- node.storedValue[name] = preProcessedSnapshot[name];
6566
+ var isPreProcessedSnapshotNonPlain = !isPlainObject(preProcessedSnapshot);
6567
+ // Fast-path plain-object snapshots, but still validate when preprocessing is required
6568
+ // or when preprocessing produces an invalid model snapshot.
6569
+ if (!isPlainObject(snapshot) || isPreProcessedSnapshotNonPlain) {
6570
+ typecheckInternal(this, snapshot);
6571
+ if (isPreProcessedSnapshotNonPlain)
6572
+ return;
6573
+ }
6574
+ this.forAllProps(function (name, childType) {
6575
+ var childNode = node.getChildNode(name);
6576
+ var newValue = preProcessedSnapshot[name];
6577
+ if (childNode.snapshot === newValue)
6578
+ return;
6579
+ if (canApplyDirectSnapshot(childType, childNode, newValue)) {
6580
+ childNode.applySnapshot(newValue);
6581
+ return;
6582
+ }
6583
+ node.storedValue[name] = newValue;
6444
6584
  });
6445
6585
  }
6446
6586
  });
@@ -6731,6 +6871,37 @@ var float = new CoreType("float", TypeFlags.Float, function (v) { return isFloat
6731
6871
  */
6732
6872
  // tslint:disable-next-line:variable-name
6733
6873
  var finite = new CoreType("finite", TypeFlags.Finite, function (v) { return isFinite(v); });
6874
+ var _BigIntPrimitive = new CoreType("bigint", TypeFlags.BigInt, function (v) {
6875
+ if (typeof v === "bigint") {
6876
+ return true;
6877
+ }
6878
+ if (typeof v === "string" || typeof v === "number") {
6879
+ try {
6880
+ // BigInt primitive constructor verifies whether the value is a valid integer
6881
+ BigInt(v);
6882
+ return true;
6883
+ }
6884
+ catch (_a) { }
6885
+ }
6886
+ return false;
6887
+ }, function (v) { return (typeof v === "bigint" ? v : BigInt(v)); });
6888
+ _BigIntPrimitive.getSnapshot = function (node) {
6889
+ return String(node.storedValue);
6890
+ };
6891
+ /**
6892
+ * `types.bigint` - Creates a type that can only contain a bigint value.
6893
+ * Snapshots serialize to string (JSON-safe) and deserialize from string, number or bigint.
6894
+ *
6895
+ * Example:
6896
+ * ```ts
6897
+ * const BigId = types.model({
6898
+ * id: types.identifier,
6899
+ * value: types.bigint
6900
+ * })
6901
+ * getSnapshot(store).value // "0" (string, JSON-safe)
6902
+ * ```
6903
+ */
6904
+ var bigint = _BigIntPrimitive;
6734
6905
  /**
6735
6906
  * `types.boolean` - Creates a type that can only contain a boolean value.
6736
6907
  * This type is used for boolean values by default
@@ -6782,6 +6953,8 @@ function getPrimitiveFactoryFromValue(value) {
6782
6953
  return number; // In the future, isInteger(value) ? integer : number would be interesting, but would be too breaking for now
6783
6954
  case "boolean":
6784
6955
  return boolean;
6956
+ case "bigint":
6957
+ return bigint;
6785
6958
  case "object":
6786
6959
  if (value instanceof Date)
6787
6960
  return DatePrimitive;
@@ -6801,7 +6974,8 @@ function isPrimitiveType(type) {
6801
6974
  TypeFlags.Number |
6802
6975
  TypeFlags.Integer |
6803
6976
  TypeFlags.Boolean |
6804
- TypeFlags.Date)) >
6977
+ TypeFlags.Date |
6978
+ TypeFlags.BigInt)) >
6805
6979
  0);
6806
6980
  }
6807
6981
 
@@ -8632,6 +8806,7 @@ var types = {
8632
8806
  integer: integer,
8633
8807
  float: float,
8634
8808
  finite: finite,
8809
+ bigint: bigint,
8635
8810
  Date: DatePrimitive,
8636
8811
  map: map,
8637
8812
  array: array,
@@ -795,7 +795,7 @@
795
795
  }
796
796
  /**
797
797
  * Returns the environment of the current state tree, or throws. For more info on environments,
798
- * see [Dependency injection](https://github.com/mobxjs/mobx-state-tree#dependency-injection)
798
+ * see [Dependency injection](/concepts/dependency-injection)
799
799
  *
800
800
  * Please note that in child nodes access to the root is only possible
801
801
  * once the `afterAttach` hook has fired
@@ -2169,6 +2169,17 @@
2169
2169
  return this._internalEventsRegister(InternalEvents.Patch, handler);
2170
2170
  }
2171
2171
  });
2172
+ Object.defineProperty(ObjectNode.prototype, "hasPatchSubscribers", {
2173
+ enumerable: false,
2174
+ configurable: true,
2175
+ writable: true,
2176
+ value: function () {
2177
+ if (this._internalEventsHasSubscribers(InternalEvents.Patch)) {
2178
+ return true;
2179
+ }
2180
+ return this.parent ? this.parent.hasPatchSubscribers() : false;
2181
+ }
2182
+ });
2172
2183
  Object.defineProperty(ObjectNode.prototype, "emitPatch", {
2173
2184
  enumerable: false,
2174
2185
  configurable: true,
@@ -2381,6 +2392,7 @@
2381
2392
  TypeFlags[TypeFlags["Lazy"] = 1048576] = "Lazy";
2382
2393
  TypeFlags[TypeFlags["Finite"] = 2097152] = "Finite";
2383
2394
  TypeFlags[TypeFlags["Float"] = 4194304] = "Float";
2395
+ TypeFlags[TypeFlags["BigInt"] = 8388608] = "BigInt";
2384
2396
  })(TypeFlags || (TypeFlags = {}));
2385
2397
  /**
2386
2398
  * @internal
@@ -2697,6 +2709,38 @@
2697
2709
  });
2698
2710
  return SimpleType;
2699
2711
  }(BaseType));
2712
+ function canApplyDirectSnapshot(childType, childNode, newValue) {
2713
+ var reconciliationType = childNode.getReconciliationType();
2714
+ var expectedReconciliationType = resolveDirectApplyType(childType);
2715
+ // Only types that reconcile as the same transparent-wrapper-adjusted type can safely reuse
2716
+ // the existing child node. Wrappers with their own validation or snapshot semantics
2717
+ // intentionally keep a distinct reconciliation type so they fall back to the validated path.
2718
+ var hasMatchingReconciliationType = reconciliationType === expectedReconciliationType;
2719
+ return (childNode instanceof ObjectNode &&
2720
+ hasMatchingReconciliationType &&
2721
+ reconciliationType instanceof ComplexType &&
2722
+ isMutable(newValue) &&
2723
+ !isStateTreeNode(newValue) &&
2724
+ reconciliationType.isMatchingSnapshotId(childNode, newValue));
2725
+ }
2726
+ function resolveDirectApplyType(type) {
2727
+ var subTypes = type.getSubTypes();
2728
+ if (!subTypes ||
2729
+ Array.isArray(subTypes) ||
2730
+ subTypes === cannotDetermineSubtype ||
2731
+ !canUnwrapDirectApplyType(type)) {
2732
+ return type;
2733
+ }
2734
+ // Only unwrap wrappers that are transparent for direct apply. Wrappers with their own
2735
+ // validation or snapshot processing must keep their wrapper identity here.
2736
+ return resolveDirectApplyType(subTypes);
2737
+ }
2738
+ function canUnwrapDirectApplyType(type) {
2739
+ var transparentWrapperFlags = TypeFlags.Optional | TypeFlags.Late;
2740
+ var nonTransparentWrapperFlags = TypeFlags.Refinement | TypeFlags.SnapshotProcessor | TypeFlags.Union;
2741
+ return ((type.flags & transparentWrapperFlags) > 0 &&
2742
+ (type.flags & nonTransparentWrapperFlags) === 0);
2743
+ }
2700
2744
  /**
2701
2745
  * Returns if a given value represents a type.
2702
2746
  *
@@ -4046,6 +4090,7 @@
4046
4090
  typeof value === "string" ||
4047
4091
  typeof value === "number" ||
4048
4092
  typeof value === "boolean" ||
4093
+ typeof value === "bigint" ||
4049
4094
  (includeDate && value instanceof Date));
4050
4095
  }
4051
4096
  /**
@@ -4908,6 +4953,8 @@
4908
4953
  /**
4909
4954
  * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
4910
4955
  *
4956
+ * [See known issue with `applySnapshot` and `preProcessSnapshot`](https://github.com/mobxjs/mobx-state-tree/issues/1317)
4957
+ *
4911
4958
  * Example:
4912
4959
  * ```ts
4913
4960
  * const Todo1 = types.model({ text: types.string })
@@ -5358,23 +5405,33 @@
5358
5405
  configurable: true,
5359
5406
  writable: true,
5360
5407
  value: function (node, snapshot) {
5361
- typecheckInternal(this, snapshot);
5408
+ if (!isPlainObject(snapshot)) {
5409
+ typecheckInternal(this, snapshot);
5410
+ return;
5411
+ }
5362
5412
  var target = node.storedValue;
5363
- var currentKeys = {};
5413
+ var childType = this.getChildType();
5364
5414
  Array.from(target.keys()).forEach(function (key) {
5365
- currentKeys[key] = false;
5366
- });
5367
- if (snapshot) {
5368
- // Don't use target.replace, as it will throw away all existing items first
5369
- for (var key in snapshot) {
5370
- target.set(key, snapshot[key]);
5371
- currentKeys["" + key] = true;
5372
- }
5373
- }
5374
- Object.keys(currentKeys).forEach(function (key) {
5375
- if (currentKeys[key] === false)
5415
+ if (!Object.prototype.hasOwnProperty.call(snapshot, key)) {
5376
5416
  target.delete(key);
5417
+ return;
5418
+ }
5419
+ var childNode = node.getChildNode(key);
5420
+ var newValue = snapshot[key];
5421
+ if (childNode.snapshot === newValue)
5422
+ return;
5423
+ if (canApplyDirectSnapshot(childType, childNode, newValue)) {
5424
+ childNode.applySnapshot(newValue);
5425
+ }
5426
+ else {
5427
+ target.set(key, newValue);
5428
+ }
5377
5429
  });
5430
+ for (var key in snapshot) {
5431
+ if (!Object.prototype.hasOwnProperty.call(snapshot, key) || target.has(key))
5432
+ continue;
5433
+ target.set(key, snapshot[key]);
5434
+ }
5378
5435
  }
5379
5436
  });
5380
5437
  Object.defineProperty(MapType.prototype, "getChildType", {
@@ -5700,9 +5757,52 @@
5700
5757
  configurable: true,
5701
5758
  writable: true,
5702
5759
  value: function (node, snapshot) {
5703
- typecheckInternal(this, snapshot);
5760
+ if (!isArray(snapshot)) {
5761
+ typecheckInternal(this, snapshot);
5762
+ return;
5763
+ }
5704
5764
  var target = node.storedValue;
5705
- target.replace(snapshot);
5765
+ var childNodes = node.getChildren();
5766
+ var oldLength = childNodes.length;
5767
+ var newLength = snapshot.length;
5768
+ var childType = this.getChildType();
5769
+ var minLength = Math.min(oldLength, newLength);
5770
+ var firstChangedIndex = findFirstChangedIndex(childNodes, snapshot, minLength);
5771
+ // If all array items are the same and the length did not change, there is nothing to do.
5772
+ if (firstChangedIndex === oldLength && firstChangedIndex === newLength) {
5773
+ return;
5774
+ }
5775
+ // Preserve the old "always replace" behavior for length changes and when patches are being
5776
+ // observed, since those cases are more sensitive to patch shape (for example, splice
5777
+ // would otherwise emit add/remove patch sequences) and benchmark variance.
5778
+ if (oldLength !== newLength || node.hasPatchSubscribers()) {
5779
+ target.replace(snapshot);
5780
+ return;
5781
+ }
5782
+ // When every changed entry can reuse its existing child node, update them in place
5783
+ // instead of going through array replacement/splice.
5784
+ if (canApplyDirectSnapshotsInRange(childType, childNodes, snapshot, firstChangedIndex)) {
5785
+ applyDirectSnapshotsInRange(childNodes, snapshot, firstChangedIndex);
5786
+ return;
5787
+ }
5788
+ var oldEnd = oldLength - 1;
5789
+ var newEnd = newLength - 1;
5790
+ while (oldEnd >= firstChangedIndex &&
5791
+ newEnd >= firstChangedIndex &&
5792
+ childNodes[oldEnd].snapshot === snapshot[newEnd]) {
5793
+ oldEnd--;
5794
+ newEnd--;
5795
+ }
5796
+ // Trim the unchanged suffix too, so we only replace the minimal changed window.
5797
+ var replacedCount = oldEnd >= firstChangedIndex ? oldEnd - firstChangedIndex + 1 : 0;
5798
+ var replacementSnapshots = newEnd >= firstChangedIndex
5799
+ ? snapshot.slice(firstChangedIndex, newEnd + 1)
5800
+ : EMPTY_ARRAY;
5801
+ if (replacedCount === 1 && replacementSnapshots.length === 1) {
5802
+ target[firstChangedIndex] = replacementSnapshots[0];
5803
+ return;
5804
+ }
5805
+ target.splice.apply(target, __spreadArray([firstChangedIndex, replacedCount], __read(replacementSnapshots), false));
5706
5806
  }
5707
5807
  });
5708
5808
  Object.defineProperty(ArrayType.prototype, "getChildType", {
@@ -5774,6 +5874,31 @@
5774
5874
  assertIsType(subtype, 1);
5775
5875
  return new ArrayType("".concat(subtype.name, "[]"), subtype);
5776
5876
  }
5877
+ function findFirstChangedIndex(childNodes, snapshot, length) {
5878
+ var index = 0;
5879
+ while (index < length && childNodes[index].snapshot === snapshot[index]) {
5880
+ index++;
5881
+ }
5882
+ return index;
5883
+ }
5884
+ function canApplyDirectSnapshotsInRange(childType, childNodes, snapshot, startIndex) {
5885
+ for (var i = startIndex; i < childNodes.length; i++) {
5886
+ if (childNodes[i].snapshot === snapshot[i])
5887
+ continue;
5888
+ if (!canApplyDirectSnapshot(childType, childNodes[i], snapshot[i])) {
5889
+ return false;
5890
+ }
5891
+ }
5892
+ return true;
5893
+ }
5894
+ function applyDirectSnapshotsInRange(childNodes, snapshot, startIndex) {
5895
+ for (var i = startIndex; i < childNodes.length; i++) {
5896
+ var childNode = childNodes[i];
5897
+ if (childNode.snapshot === snapshot[i])
5898
+ continue;
5899
+ childNode.applySnapshot(snapshot[i]);
5900
+ }
5901
+ }
5777
5902
  function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths) {
5778
5903
  var nothingChanged = true;
5779
5904
  for (var i = 0;; i++) {
@@ -6419,10 +6544,25 @@
6419
6544
  configurable: true,
6420
6545
  writable: true,
6421
6546
  value: function (node, snapshot) {
6422
- typecheckInternal(this, snapshot);
6423
6547
  var preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
6424
- this.forAllProps(function (name) {
6425
- node.storedValue[name] = preProcessedSnapshot[name];
6548
+ var isPreProcessedSnapshotNonPlain = !isPlainObject(preProcessedSnapshot);
6549
+ // Fast-path plain-object snapshots, but still validate when preprocessing is required
6550
+ // or when preprocessing produces an invalid model snapshot.
6551
+ if (!isPlainObject(snapshot) || isPreProcessedSnapshotNonPlain) {
6552
+ typecheckInternal(this, snapshot);
6553
+ if (isPreProcessedSnapshotNonPlain)
6554
+ return;
6555
+ }
6556
+ this.forAllProps(function (name, childType) {
6557
+ var childNode = node.getChildNode(name);
6558
+ var newValue = preProcessedSnapshot[name];
6559
+ if (childNode.snapshot === newValue)
6560
+ return;
6561
+ if (canApplyDirectSnapshot(childType, childNode, newValue)) {
6562
+ childNode.applySnapshot(newValue);
6563
+ return;
6564
+ }
6565
+ node.storedValue[name] = newValue;
6426
6566
  });
6427
6567
  }
6428
6568
  });
@@ -6713,6 +6853,37 @@
6713
6853
  */
6714
6854
  // tslint:disable-next-line:variable-name
6715
6855
  var finite = new CoreType("finite", TypeFlags.Finite, function (v) { return isFinite(v); });
6856
+ var _BigIntPrimitive = new CoreType("bigint", TypeFlags.BigInt, function (v) {
6857
+ if (typeof v === "bigint") {
6858
+ return true;
6859
+ }
6860
+ if (typeof v === "string" || typeof v === "number") {
6861
+ try {
6862
+ // BigInt primitive constructor verifies whether the value is a valid integer
6863
+ BigInt(v);
6864
+ return true;
6865
+ }
6866
+ catch (_a) { }
6867
+ }
6868
+ return false;
6869
+ }, function (v) { return (typeof v === "bigint" ? v : BigInt(v)); });
6870
+ _BigIntPrimitive.getSnapshot = function (node) {
6871
+ return String(node.storedValue);
6872
+ };
6873
+ /**
6874
+ * `types.bigint` - Creates a type that can only contain a bigint value.
6875
+ * Snapshots serialize to string (JSON-safe) and deserialize from string, number or bigint.
6876
+ *
6877
+ * Example:
6878
+ * ```ts
6879
+ * const BigId = types.model({
6880
+ * id: types.identifier,
6881
+ * value: types.bigint
6882
+ * })
6883
+ * getSnapshot(store).value // "0" (string, JSON-safe)
6884
+ * ```
6885
+ */
6886
+ var bigint = _BigIntPrimitive;
6716
6887
  /**
6717
6888
  * `types.boolean` - Creates a type that can only contain a boolean value.
6718
6889
  * This type is used for boolean values by default
@@ -6764,6 +6935,8 @@
6764
6935
  return number; // In the future, isInteger(value) ? integer : number would be interesting, but would be too breaking for now
6765
6936
  case "boolean":
6766
6937
  return boolean;
6938
+ case "bigint":
6939
+ return bigint;
6767
6940
  case "object":
6768
6941
  if (value instanceof Date)
6769
6942
  return DatePrimitive;
@@ -6783,7 +6956,8 @@
6783
6956
  TypeFlags.Number |
6784
6957
  TypeFlags.Integer |
6785
6958
  TypeFlags.Boolean |
6786
- TypeFlags.Date)) >
6959
+ TypeFlags.Date |
6960
+ TypeFlags.BigInt)) >
6787
6961
  0);
6788
6962
  }
6789
6963
 
@@ -8614,6 +8788,7 @@
8614
8788
  integer: integer,
8615
8789
  float: float,
8616
8790
  finite: finite,
8791
+ bigint: bigint,
8617
8792
  Date: DatePrimitive,
8618
8793
  map: map,
8619
8794
  array: array,