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.
- package/dist/core/mst-operations.d.ts +1 -1
- package/dist/core/type/type.d.ts +3 -1
- package/dist/mobx-state-tree.js +195 -20
- package/dist/mobx-state-tree.min.js +1 -1
- package/dist/mobx-state-tree.module.js +195 -20
- package/dist/mobx-state-tree.umd.js +195 -20
- package/dist/mobx-state-tree.umd.min.js +1 -1
- package/dist/types/complex-types/model.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/primitives.d.ts +15 -1
- package/dist/types/utility-types/snapshotProcessor.d.ts +2 -0
- package/package.json +2 -2
|
@@ -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](
|
|
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
|
-
|
|
5426
|
+
if (!isPlainObject(snapshot)) {
|
|
5427
|
+
typecheckInternal(this, snapshot);
|
|
5428
|
+
return;
|
|
5429
|
+
}
|
|
5380
5430
|
var target = node.storedValue;
|
|
5381
|
-
var
|
|
5431
|
+
var childType = this.getChildType();
|
|
5382
5432
|
Array.from(target.keys()).forEach(function (key) {
|
|
5383
|
-
|
|
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
|
-
|
|
5778
|
+
if (!isArray(snapshot)) {
|
|
5779
|
+
typecheckInternal(this, snapshot);
|
|
5780
|
+
return;
|
|
5781
|
+
}
|
|
5722
5782
|
var target = node.storedValue;
|
|
5723
|
-
|
|
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
|
-
|
|
6443
|
-
|
|
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](
|
|
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
|
-
|
|
5408
|
+
if (!isPlainObject(snapshot)) {
|
|
5409
|
+
typecheckInternal(this, snapshot);
|
|
5410
|
+
return;
|
|
5411
|
+
}
|
|
5362
5412
|
var target = node.storedValue;
|
|
5363
|
-
var
|
|
5413
|
+
var childType = this.getChildType();
|
|
5364
5414
|
Array.from(target.keys()).forEach(function (key) {
|
|
5365
|
-
|
|
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
|
-
|
|
5760
|
+
if (!isArray(snapshot)) {
|
|
5761
|
+
typecheckInternal(this, snapshot);
|
|
5762
|
+
return;
|
|
5763
|
+
}
|
|
5704
5764
|
var target = node.storedValue;
|
|
5705
|
-
|
|
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
|
-
|
|
6425
|
-
|
|
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,
|