@jbrowse/mobx-state-tree 6.5.2 → 6.6.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/CHANGELOG.md +23 -0
- package/dist/index.d.ts +151 -116
- package/dist/mobx-state-tree.cjs +272 -318
- package/dist/mobx-state-tree.cjs.map +1 -1
- package/dist/mobx-state-tree.mjs +269 -320
- package/dist/mobx-state-tree.mjs.map +1 -1
- package/package.json +1 -1
package/dist/mobx-state-tree.cjs
CHANGED
|
@@ -567,7 +567,9 @@ function getRelativePath(base, target) {
|
|
|
567
567
|
}
|
|
568
568
|
/**
|
|
569
569
|
* Returns a deep copy of the given state tree node as new tree.
|
|
570
|
-
*
|
|
570
|
+
* Like `getType(x).create(getSnapshot(x))`, except that a node wrapped in a
|
|
571
|
+
* `types.snapshotProcessor` is recreated through the processor, which
|
|
572
|
+
* `getType(x)` (the wrapped type) would skip.
|
|
571
573
|
*
|
|
572
574
|
* _Tip: clone will create a literal copy, including the same identifiers. To modify identifiers etc. during cloning, don't use clone but take a snapshot of the tree, modify it, and create new instance_
|
|
573
575
|
*
|
|
@@ -579,11 +581,11 @@ function clone(source, keepEnvironment = true) {
|
|
|
579
581
|
// check all arguments
|
|
580
582
|
assertIsStateTreeNode(source, 1);
|
|
581
583
|
const node = getStateTreeNode(source);
|
|
582
|
-
return node.type.create(node.snapshot, keepEnvironment === true
|
|
584
|
+
return (node.snapshotProcessorType ?? node.type).create(node.snapshot, keepEnvironment === true
|
|
583
585
|
? node.root.environment
|
|
584
586
|
: keepEnvironment === false
|
|
585
587
|
? undefined
|
|
586
|
-
: keepEnvironment);
|
|
588
|
+
: keepEnvironment);
|
|
587
589
|
}
|
|
588
590
|
/**
|
|
589
591
|
* Removes a model element from the state tree, and let it live on as a new state tree
|
|
@@ -702,17 +704,15 @@ function walk(target, processor) {
|
|
|
702
704
|
* @returns
|
|
703
705
|
*/
|
|
704
706
|
function getPropertyMembers(typeOrNode) {
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
}
|
|
712
|
-
assertArg(type, t => isModelType(t), "model type or model instance", 1);
|
|
707
|
+
const type = isStateTreeNode(typeOrNode)
|
|
708
|
+
? getType(typeOrNode)
|
|
709
|
+
: typeOrNode;
|
|
710
|
+
assertArg(type, isModelType, "model type or model instance", 1);
|
|
711
|
+
// a wrapped model reports the model's properties; a union of models has no
|
|
712
|
+
// single set and reports none
|
|
713
713
|
return {
|
|
714
714
|
name: type.name,
|
|
715
|
-
properties: { ...type
|
|
715
|
+
properties: { ...asModelType(type)?.properties }
|
|
716
716
|
};
|
|
717
717
|
}
|
|
718
718
|
/**
|
|
@@ -914,16 +914,28 @@ class BaseNode {
|
|
|
914
914
|
}
|
|
915
915
|
}
|
|
916
916
|
_hookSubscribers;
|
|
917
|
-
fireInternalHook(name) {
|
|
918
|
-
|
|
919
|
-
|
|
917
|
+
fireInternalHook(name, subject = this) {
|
|
918
|
+
this._hookSubscribers?.emit(name, subject, name);
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Detaching a node takes its whole subtree out of the tree, but only the
|
|
922
|
+
* detached node's parent changes, so only it fires `beforeDetach` for real.
|
|
923
|
+
* Internal subscribers below it (reference watchers on a target) still need
|
|
924
|
+
* to know their node is leaving.
|
|
925
|
+
*/
|
|
926
|
+
notifyDetachOf(subject) {
|
|
927
|
+
this.fireInternalHook(Hook.beforeDetach, subject);
|
|
928
|
+
}
|
|
929
|
+
isWithin(ancestor) {
|
|
930
|
+
for (let node = this.parent; node; node = node.parent) {
|
|
931
|
+
if (node === ancestor) {
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
920
934
|
}
|
|
935
|
+
return false;
|
|
921
936
|
}
|
|
922
937
|
registerHook(hook, hookHandler) {
|
|
923
|
-
|
|
924
|
-
this._hookSubscribers = new EventHandlers();
|
|
925
|
-
}
|
|
926
|
-
return this._hookSubscribers.register(hook, hookHandler);
|
|
938
|
+
return (this._hookSubscribers ??= new EventHandlers()).register(hook, hookHandler);
|
|
927
939
|
}
|
|
928
940
|
_parent;
|
|
929
941
|
get parent() {
|
|
@@ -984,6 +996,13 @@ class BaseNode {
|
|
|
984
996
|
this.aliveAtom.reportObserved();
|
|
985
997
|
return this.isAlive;
|
|
986
998
|
}
|
|
999
|
+
die() {
|
|
1000
|
+
if (!this.isAlive || this.isDetaching) {
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
this.aboutToDie();
|
|
1004
|
+
this.finalizeDeath();
|
|
1005
|
+
}
|
|
987
1006
|
baseFinalizeCreation(whenFinalized) {
|
|
988
1007
|
if (devMode()) {
|
|
989
1008
|
if (!this.isAlive) {
|
|
@@ -1019,6 +1038,7 @@ class BaseNode {
|
|
|
1019
1038
|
this.fireHook(Hook.beforeDestroy);
|
|
1020
1039
|
}
|
|
1021
1040
|
}
|
|
1041
|
+
BaseNode.prototype.die = mobx.action(BaseNode.prototype.die);
|
|
1022
1042
|
|
|
1023
1043
|
/**
|
|
1024
1044
|
* @internal
|
|
@@ -1036,9 +1056,6 @@ class ScalarNode extends BaseNode {
|
|
|
1036
1056
|
throw e;
|
|
1037
1057
|
}
|
|
1038
1058
|
this.state = NodeLifeCycle.CREATED;
|
|
1039
|
-
// for scalar nodes there's no point in firing this event since it would fire on the constructor, before
|
|
1040
|
-
// anybody can actually register for/listen to it
|
|
1041
|
-
// this.fireHook(Hook.AfterCreate)
|
|
1042
1059
|
this.finalizeCreation();
|
|
1043
1060
|
}
|
|
1044
1061
|
get root() {
|
|
@@ -1081,13 +1098,6 @@ class ScalarNode extends BaseNode {
|
|
|
1081
1098
|
const path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
|
|
1082
1099
|
return `${this.type.name}@${path}${this.isAlive ? "" : " [dead]"}`;
|
|
1083
1100
|
}
|
|
1084
|
-
die() {
|
|
1085
|
-
if (!this.isAlive || this.state === NodeLifeCycle.DETACHING) {
|
|
1086
|
-
return;
|
|
1087
|
-
}
|
|
1088
|
-
this.aboutToDie();
|
|
1089
|
-
this.finalizeDeath();
|
|
1090
|
-
}
|
|
1091
1101
|
finalizeCreation() {
|
|
1092
1102
|
this.baseFinalizeCreation();
|
|
1093
1103
|
}
|
|
@@ -1101,7 +1111,6 @@ class ScalarNode extends BaseNode {
|
|
|
1101
1111
|
this.fireInternalHook(name);
|
|
1102
1112
|
}
|
|
1103
1113
|
}
|
|
1104
|
-
ScalarNode.prototype.die = mobx.action(ScalarNode.prototype.die);
|
|
1105
1114
|
|
|
1106
1115
|
let nextNodeId = 1;
|
|
1107
1116
|
var ObservableInstanceLifecycle;
|
|
@@ -1289,8 +1298,8 @@ class ObjectNode extends BaseNode {
|
|
|
1289
1298
|
if (!this.parent) {
|
|
1290
1299
|
return;
|
|
1291
1300
|
}
|
|
1292
|
-
// detach if attached
|
|
1293
1301
|
this.fireHook(Hook.beforeDetach);
|
|
1302
|
+
this.notifyChildrenOfDetach(this);
|
|
1294
1303
|
const previousState = this.state;
|
|
1295
1304
|
this.state = NodeLifeCycle.DETACHING;
|
|
1296
1305
|
const root = this.root;
|
|
@@ -1306,6 +1315,21 @@ class ObjectNode extends BaseNode {
|
|
|
1306
1315
|
this.state = previousState;
|
|
1307
1316
|
}
|
|
1308
1317
|
}
|
|
1318
|
+
notifyDetachOf(subject) {
|
|
1319
|
+
super.notifyDetachOf(subject);
|
|
1320
|
+
this.notifyChildrenOfDetach(subject);
|
|
1321
|
+
}
|
|
1322
|
+
notifyChildrenOfDetach(subject) {
|
|
1323
|
+
// a handler notified earlier in the walk may have destroyed this node.
|
|
1324
|
+
// A node never read still has to be walked: an instance created elsewhere
|
|
1325
|
+
// can have been moved under it, subscribers and all.
|
|
1326
|
+
if (!this.isAlive) {
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
for (const child of this.getChildren()) {
|
|
1330
|
+
child.notifyDetachOf(subject);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1309
1333
|
setParent(newParent, subpath) {
|
|
1310
1334
|
const parentChanged = newParent !== this.parent;
|
|
1311
1335
|
const subpathChanged = subpath !== this.subpath;
|
|
@@ -1510,37 +1534,27 @@ class ObjectNode extends BaseNode {
|
|
|
1510
1534
|
this.clearParent();
|
|
1511
1535
|
}
|
|
1512
1536
|
preboot() {
|
|
1513
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1514
|
-
const self = this;
|
|
1515
1537
|
this._applyPatches = createActionInvoker(this.storedValue, "@APPLY_PATCHES", (patches) => {
|
|
1516
1538
|
patches.forEach(patch => {
|
|
1517
1539
|
if (!patch.path) {
|
|
1518
|
-
|
|
1540
|
+
this.type.applySnapshot(this, patch.value);
|
|
1519
1541
|
return;
|
|
1520
1542
|
}
|
|
1521
1543
|
const parts = splitJsonPath(patch.path);
|
|
1522
|
-
const node = resolveNodeByPathParts(
|
|
1544
|
+
const node = resolveNodeByPathParts(this, parts.slice(0, -1));
|
|
1523
1545
|
node.applyPatchLocally(parts[parts.length - 1], patch);
|
|
1524
1546
|
});
|
|
1525
1547
|
});
|
|
1526
1548
|
this._applySnapshot = createActionInvoker(this.storedValue, "@APPLY_SNAPSHOT", (snapshot) => {
|
|
1527
|
-
//
|
|
1528
|
-
if (snapshot ===
|
|
1549
|
+
// the current snapshot needs no reconcile
|
|
1550
|
+
if (snapshot === this.snapshot) {
|
|
1529
1551
|
return;
|
|
1530
1552
|
}
|
|
1531
|
-
|
|
1532
|
-
return self.type.applySnapshot(self, snapshot);
|
|
1553
|
+
this.type.applySnapshot(this, snapshot);
|
|
1533
1554
|
});
|
|
1534
1555
|
addHiddenFinalProp(this.storedValue, "$treenode", this);
|
|
1535
1556
|
addHiddenFinalProp(this.storedValue, "toJSON", toJSON);
|
|
1536
1557
|
}
|
|
1537
|
-
die() {
|
|
1538
|
-
if (!this.isAlive || this.state === NodeLifeCycle.DETACHING) {
|
|
1539
|
-
return;
|
|
1540
|
-
}
|
|
1541
|
-
this.aboutToDie();
|
|
1542
|
-
this.finalizeDeath();
|
|
1543
|
-
}
|
|
1544
1558
|
aboutToDie() {
|
|
1545
1559
|
if (this._observableInstanceState ===
|
|
1546
1560
|
ObservableInstanceLifecycle.UNINITIALIZED) {
|
|
@@ -1552,8 +1566,8 @@ class ObjectNode extends BaseNode {
|
|
|
1552
1566
|
// beforeDestroy should run before the disposers since else we could end up in a situation where
|
|
1553
1567
|
// a disposer added with addDisposer at this stage (beforeDestroy) is actually never released
|
|
1554
1568
|
this.baseAboutToDie();
|
|
1555
|
-
this.
|
|
1556
|
-
this.
|
|
1569
|
+
this._internalEvents?.emit(InternalEvents.Dispose);
|
|
1570
|
+
this._internalEvents?.clear(InternalEvents.Dispose);
|
|
1557
1571
|
}
|
|
1558
1572
|
finalizeDeath() {
|
|
1559
1573
|
// invariant: not called directly but from "die"
|
|
@@ -1564,57 +1578,57 @@ class ObjectNode extends BaseNode {
|
|
|
1564
1578
|
// "kill" the computed prop and just store the last snapshot
|
|
1565
1579
|
const snapshot = this.snapshot;
|
|
1566
1580
|
this._snapshotUponDeath = snapshot;
|
|
1567
|
-
this.
|
|
1581
|
+
this._internalEvents?.clearAll();
|
|
1568
1582
|
this.baseFinalizeDeath();
|
|
1569
1583
|
}
|
|
1570
1584
|
onSnapshot(onChange) {
|
|
1571
1585
|
this._addSnapshotReaction();
|
|
1572
|
-
const unregister = this.
|
|
1586
|
+
const unregister = this.internalEvents().register(InternalEvents.Snapshot, onChange);
|
|
1573
1587
|
return () => {
|
|
1574
1588
|
unregister();
|
|
1575
1589
|
// The reaction re-serializes the whole subtree on every change, so leaving
|
|
1576
1590
|
// it running once the last listener is gone would keep charging the node
|
|
1577
1591
|
// for a snapshot nobody receives. Referential stability of getSnapshot()
|
|
1578
1592
|
// does not depend on it — that comes from keepAlive on _snapshotComputed.
|
|
1579
|
-
if (!this.
|
|
1593
|
+
if (!this._internalEvents?.hasSubscribers(InternalEvents.Snapshot)) {
|
|
1580
1594
|
this._removeSnapshotReaction();
|
|
1581
1595
|
}
|
|
1582
1596
|
};
|
|
1583
1597
|
}
|
|
1584
1598
|
emitSnapshot(snapshot) {
|
|
1585
|
-
this.
|
|
1599
|
+
this._internalEvents?.emit(InternalEvents.Snapshot, snapshot);
|
|
1586
1600
|
}
|
|
1587
1601
|
onPatch(handler) {
|
|
1588
|
-
return this.
|
|
1602
|
+
return this.internalEvents().register(InternalEvents.Patch, handler);
|
|
1589
1603
|
}
|
|
1590
1604
|
emitPatch(basePatch, source) {
|
|
1591
|
-
if (this.
|
|
1605
|
+
if (this._internalEvents?.hasSubscribers(InternalEvents.Patch)) {
|
|
1592
1606
|
const localizedPatch = {
|
|
1593
1607
|
...basePatch,
|
|
1594
1608
|
path: `${source.path.slice(this.path.length)}/${basePatch.path}` // calculate the relative path of the patch
|
|
1595
1609
|
};
|
|
1596
1610
|
const [patch, reversePatch] = splitPatch(localizedPatch);
|
|
1597
|
-
this.
|
|
1611
|
+
this._internalEvents?.emit(InternalEvents.Patch, patch, reversePatch);
|
|
1598
1612
|
}
|
|
1599
1613
|
if (this.parent) {
|
|
1600
1614
|
this.parent.emitPatch(basePatch, source);
|
|
1601
1615
|
}
|
|
1602
1616
|
}
|
|
1603
1617
|
hasDisposer(disposer) {
|
|
1604
|
-
return this.
|
|
1618
|
+
return !!this._internalEvents?.has(InternalEvents.Dispose, disposer);
|
|
1605
1619
|
}
|
|
1606
1620
|
addDisposer(disposer) {
|
|
1607
1621
|
if (!this.hasDisposer(disposer)) {
|
|
1608
|
-
this.
|
|
1622
|
+
this.internalEvents().register(InternalEvents.Dispose, disposer, true);
|
|
1609
1623
|
return;
|
|
1610
1624
|
}
|
|
1611
1625
|
throw fail("cannot add a disposer when it is already registered for execution");
|
|
1612
1626
|
}
|
|
1613
1627
|
removeDisposer(disposer) {
|
|
1614
|
-
if (!this.
|
|
1628
|
+
if (!this._internalEvents?.has(InternalEvents.Dispose, disposer)) {
|
|
1615
1629
|
throw fail("cannot remove a disposer which was never registered for execution");
|
|
1616
1630
|
}
|
|
1617
|
-
this.
|
|
1631
|
+
this._internalEvents?.unregister(InternalEvents.Dispose, disposer);
|
|
1618
1632
|
}
|
|
1619
1633
|
removeMiddleware(middleware) {
|
|
1620
1634
|
if (this.middlewares) {
|
|
@@ -1659,48 +1673,17 @@ class ObjectNode extends BaseNode {
|
|
|
1659
1673
|
// not removeDisposer(), which throws when the registration is already gone —
|
|
1660
1674
|
// the last listener can be disposed from within a disposer, i.e. after
|
|
1661
1675
|
// aboutToDie has cleared them
|
|
1662
|
-
this.
|
|
1676
|
+
this._internalEvents?.unregister(InternalEvents.Dispose, disposer);
|
|
1663
1677
|
disposer();
|
|
1664
1678
|
}
|
|
1665
|
-
//
|
|
1679
|
+
// created on first registration: most nodes never get a listener
|
|
1666
1680
|
_internalEvents;
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
return !!this._internalEvents && this._internalEvents.hasSubscribers(event);
|
|
1670
|
-
}
|
|
1671
|
-
_internalEventsRegister(event, eventHandler, atTheBeginning = false) {
|
|
1672
|
-
if (!this._internalEvents) {
|
|
1673
|
-
this._internalEvents = new EventHandlers();
|
|
1674
|
-
}
|
|
1675
|
-
return this._internalEvents.register(event, eventHandler, atTheBeginning);
|
|
1676
|
-
}
|
|
1677
|
-
_internalEventsHas(event, eventHandler) {
|
|
1678
|
-
return (!!this._internalEvents && this._internalEvents.has(event, eventHandler));
|
|
1679
|
-
}
|
|
1680
|
-
_internalEventsUnregister(event, eventHandler) {
|
|
1681
|
-
if (this._internalEvents) {
|
|
1682
|
-
this._internalEvents.unregister(event, eventHandler);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
_internalEventsEmit(event, ...args) {
|
|
1686
|
-
if (this._internalEvents) {
|
|
1687
|
-
this._internalEvents.emit(event, ...args);
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
_internalEventsClear(event) {
|
|
1691
|
-
if (this._internalEvents) {
|
|
1692
|
-
this._internalEvents.clear(event);
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
_internalEventsClearAll() {
|
|
1696
|
-
if (this._internalEvents) {
|
|
1697
|
-
this._internalEvents.clearAll();
|
|
1698
|
-
}
|
|
1681
|
+
internalEvents() {
|
|
1682
|
+
return (this._internalEvents ??= new EventHandlers());
|
|
1699
1683
|
}
|
|
1700
1684
|
}
|
|
1701
1685
|
ObjectNode.prototype.createObservableInstance = mobx.action(ObjectNode.prototype.createObservableInstance);
|
|
1702
1686
|
ObjectNode.prototype.detach = mobx.action(ObjectNode.prototype.detach);
|
|
1703
|
-
ObjectNode.prototype.die = mobx.action(ObjectNode.prototype.die);
|
|
1704
1687
|
|
|
1705
1688
|
/**
|
|
1706
1689
|
* @internal
|
|
@@ -1892,7 +1875,6 @@ class ComplexType extends BaseType {
|
|
|
1892
1875
|
return null;
|
|
1893
1876
|
}
|
|
1894
1877
|
}
|
|
1895
|
-
ComplexType.prototype.create = mobx.action(ComplexType.prototype.create);
|
|
1896
1878
|
/**
|
|
1897
1879
|
* @internal
|
|
1898
1880
|
* @hidden
|
|
@@ -1902,11 +1884,6 @@ class SimpleType extends BaseType {
|
|
|
1902
1884
|
return snapshot;
|
|
1903
1885
|
}
|
|
1904
1886
|
getValue(node) {
|
|
1905
|
-
// if we ever find a case where scalar nodes can be accessed without iterating through its parent
|
|
1906
|
-
// uncomment this to make sure the parent chain is created when this is accessed
|
|
1907
|
-
// if (node.parent) {
|
|
1908
|
-
// node.parent.createObservableInstanceIfNeeded()
|
|
1909
|
-
// }
|
|
1910
1887
|
return node.storedValue;
|
|
1911
1888
|
}
|
|
1912
1889
|
getSnapshot(node) {
|
|
@@ -1936,6 +1913,30 @@ class SimpleType extends BaseType {
|
|
|
1936
1913
|
function isType(value) {
|
|
1937
1914
|
return (typeof value === "object" && value?.isType === true);
|
|
1938
1915
|
}
|
|
1916
|
+
/**
|
|
1917
|
+
* The one type a wrapper hands everything to: what an `optional`,
|
|
1918
|
+
* `stripDefault`, `refinement`, `snapshotProcessor` or (resolved) `late`
|
|
1919
|
+
* wraps. `undefined` for any other type, including a union or a `resilient`,
|
|
1920
|
+
* which pick a type per value.
|
|
1921
|
+
*
|
|
1922
|
+
* Resolves a `late` type's definition if it has not been read yet.
|
|
1923
|
+
*/
|
|
1924
|
+
function getWrappedType(type) {
|
|
1925
|
+
const subtype = type.getSubTypes();
|
|
1926
|
+
return isType(subtype) ? subtype : undefined;
|
|
1927
|
+
}
|
|
1928
|
+
/**
|
|
1929
|
+
* Strips every wrapper {@link getWrappedType} sees through, down to the type
|
|
1930
|
+
* that actually builds the value: for a complex type `T`,
|
|
1931
|
+
* `getType(T.create(snapshot)) === unwrapType(T)`.
|
|
1932
|
+
*
|
|
1933
|
+
* `types.model({ xs: types.array(X) }).properties.xs`, for instance, is an
|
|
1934
|
+
* `optional` whose unwrapped type is the array type.
|
|
1935
|
+
*/
|
|
1936
|
+
function unwrapType(type) {
|
|
1937
|
+
const wrapped = getWrappedType(type);
|
|
1938
|
+
return wrapped ? unwrapType(wrapped) : type;
|
|
1939
|
+
}
|
|
1939
1940
|
/**
|
|
1940
1941
|
* @internal
|
|
1941
1942
|
* @hidden
|
|
@@ -2934,7 +2935,7 @@ function createScalarNode(type, parent, subpath, environment, initialValue) {
|
|
|
2934
2935
|
* @hidden
|
|
2935
2936
|
*/
|
|
2936
2937
|
function isNode(value) {
|
|
2937
|
-
return value instanceof
|
|
2938
|
+
return value instanceof BaseNode;
|
|
2938
2939
|
}
|
|
2939
2940
|
|
|
2940
2941
|
/**
|
|
@@ -3113,25 +3114,6 @@ function fail(message = "Illegal state") {
|
|
|
3113
3114
|
function identity(_) {
|
|
3114
3115
|
return _;
|
|
3115
3116
|
}
|
|
3116
|
-
/**
|
|
3117
|
-
* @internal
|
|
3118
|
-
* @hidden
|
|
3119
|
-
*/
|
|
3120
|
-
const isInteger = Number.isInteger;
|
|
3121
|
-
/**
|
|
3122
|
-
* @internal
|
|
3123
|
-
* @hidden
|
|
3124
|
-
*/
|
|
3125
|
-
function isFloat(val) {
|
|
3126
|
-
return Number(val) === val && val % 1 !== 0;
|
|
3127
|
-
}
|
|
3128
|
-
/**
|
|
3129
|
-
* @internal
|
|
3130
|
-
* @hidden
|
|
3131
|
-
*/
|
|
3132
|
-
function isFinite(val) {
|
|
3133
|
-
return Number.isFinite(val);
|
|
3134
|
-
}
|
|
3135
3117
|
/**
|
|
3136
3118
|
* @internal
|
|
3137
3119
|
* @hidden
|
|
@@ -3779,11 +3761,8 @@ class SnapshotProcessor extends BaseType {
|
|
|
3779
3761
|
return sn;
|
|
3780
3762
|
}
|
|
3781
3763
|
_fixNode(node) {
|
|
3782
|
-
// the node's type is the *inner* type, so `getType(instance).create(...)`
|
|
3783
|
-
// would bypass the processors — point it at ours instead
|
|
3784
|
-
const nodeType = node.type;
|
|
3785
|
-
nodeType.create = this.create.bind(this);
|
|
3786
3764
|
if (node instanceof ObjectNode) {
|
|
3765
|
+
node.snapshotProcessorType = this;
|
|
3787
3766
|
node.hasSnapshotPostProcessor = !!this._processors.postProcessor;
|
|
3788
3767
|
}
|
|
3789
3768
|
const oldGetSnapshot = node.getSnapshot;
|
|
@@ -4267,14 +4246,20 @@ function map(subtype) {
|
|
|
4267
4246
|
return new MapType(subtype);
|
|
4268
4247
|
}
|
|
4269
4248
|
/**
|
|
4270
|
-
* Returns if a
|
|
4271
|
-
*
|
|
4272
|
-
* @param type
|
|
4273
|
-
* @returns `true` if it is a map type.
|
|
4249
|
+
* Returns if a type is a map type, or wraps or unions one. For the map type
|
|
4250
|
+
* itself, use {@link asMapType}.
|
|
4274
4251
|
*/
|
|
4275
4252
|
function isMapType(type) {
|
|
4276
4253
|
return isType(type) && (type.flags & TypeFlags.Map) > 0;
|
|
4277
4254
|
}
|
|
4255
|
+
/**
|
|
4256
|
+
* The map type `type` builds its values with, seeing through the wrappers
|
|
4257
|
+
* {@link unwrapType} does, or `undefined` if that is not a map type.
|
|
4258
|
+
*/
|
|
4259
|
+
function asMapType(type) {
|
|
4260
|
+
const unwrapped = unwrapType(type);
|
|
4261
|
+
return unwrapped instanceof MapType ? unwrapped : undefined;
|
|
4262
|
+
}
|
|
4278
4263
|
|
|
4279
4264
|
/**
|
|
4280
4265
|
* @internal
|
|
@@ -4644,14 +4629,20 @@ function areSame(oldNode, newValue) {
|
|
|
4644
4629
|
oldNodeType.isMatchingSnapshotId(oldNode, newValue));
|
|
4645
4630
|
}
|
|
4646
4631
|
/**
|
|
4647
|
-
* Returns if a
|
|
4648
|
-
*
|
|
4649
|
-
* @param type
|
|
4650
|
-
* @returns `true` if the type is an array type.
|
|
4632
|
+
* Returns if a type is an array type, or wraps or unions one. For the array
|
|
4633
|
+
* type itself, use {@link asArrayType}.
|
|
4651
4634
|
*/
|
|
4652
4635
|
function isArrayType(type) {
|
|
4653
4636
|
return isType(type) && (type.flags & TypeFlags.Array) > 0;
|
|
4654
4637
|
}
|
|
4638
|
+
/**
|
|
4639
|
+
* The array type `type` builds its values with, seeing through the wrappers
|
|
4640
|
+
* {@link unwrapType} does, or `undefined` if that is not an array type.
|
|
4641
|
+
*/
|
|
4642
|
+
function asArrayType(type) {
|
|
4643
|
+
const unwrapped = unwrapType(type);
|
|
4644
|
+
return unwrapped instanceof ArrayType ? unwrapped : undefined;
|
|
4645
|
+
}
|
|
4655
4646
|
|
|
4656
4647
|
const PRE_PROCESS_SNAPSHOT = "preProcessSnapshot";
|
|
4657
4648
|
const POST_PROCESS_SNAPSHOT = "postProcessSnapshot";
|
|
@@ -4686,6 +4677,12 @@ function getPropObservables(storedValue) {
|
|
|
4686
4677
|
function objectTypeToString() {
|
|
4687
4678
|
return getStateTreeNode(this).toString();
|
|
4688
4679
|
}
|
|
4680
|
+
/** `second` applied to `first`'s result, allocating only when both exist */
|
|
4681
|
+
function chainProcessors(first, second) {
|
|
4682
|
+
return first && second
|
|
4683
|
+
? snapshot => second(first(snapshot))
|
|
4684
|
+
: (first ?? second);
|
|
4685
|
+
}
|
|
4689
4686
|
const ANONYMOUS_MODEL_NAME = "AnonymousModel";
|
|
4690
4687
|
/**
|
|
4691
4688
|
* A plain loop rather than a callback per property, which allocated a closure
|
|
@@ -4974,8 +4971,6 @@ class ModelType extends ComplexType {
|
|
|
4974
4971
|
? initialValue
|
|
4975
4972
|
: this.applySnapshotPreProcessor(initialValue);
|
|
4976
4973
|
return createObjectNode(this, parent, subpath, environment, value);
|
|
4977
|
-
// Optimization: record all prop- view- and action names after first construction, and generate an optimal base class
|
|
4978
|
-
// that pre-reserves all these fields for fast object-member lookups
|
|
4979
4974
|
}
|
|
4980
4975
|
initializeChildNodes(objNode, initialSnapshot = {}) {
|
|
4981
4976
|
const type = objNode.type;
|
|
@@ -5139,15 +5134,12 @@ class ModelType extends ComplexType {
|
|
|
5139
5134
|
}
|
|
5140
5135
|
}
|
|
5141
5136
|
applySnapshotPreProcessor(snapshot) {
|
|
5142
|
-
const
|
|
5143
|
-
return
|
|
5137
|
+
const preProcessor = this.preProcessor;
|
|
5138
|
+
return preProcessor ? preProcessor(snapshot) : snapshot;
|
|
5144
5139
|
}
|
|
5145
5140
|
applySnapshotPostProcessor(snapshot) {
|
|
5146
5141
|
const postProcessor = this.postProcessor;
|
|
5147
|
-
|
|
5148
|
-
return postProcessor.call(null, snapshot);
|
|
5149
|
-
}
|
|
5150
|
-
return snapshot;
|
|
5142
|
+
return postProcessor ? postProcessor(snapshot) : snapshot;
|
|
5151
5143
|
}
|
|
5152
5144
|
getChildType(propertyName) {
|
|
5153
5145
|
assertIsString(propertyName, 1);
|
|
@@ -5170,7 +5162,6 @@ class ModelType extends ComplexType {
|
|
|
5170
5162
|
return typeCheckSuccess();
|
|
5171
5163
|
}
|
|
5172
5164
|
describe() {
|
|
5173
|
-
// optimization: cache
|
|
5174
5165
|
return `{ ${this.propertyNames
|
|
5175
5166
|
.map(key => `${key}: ${this.properties[key].describe()}`)
|
|
5176
5167
|
.join("; ")} }`;
|
|
@@ -5192,27 +5183,17 @@ Object.assign(ModelType.prototype, {
|
|
|
5192
5183
|
props(properties) {
|
|
5193
5184
|
return this.cloneAndEnhance({ properties });
|
|
5194
5185
|
},
|
|
5186
|
+
// a newly added pre-processor sees the raw snapshot first; a newly added
|
|
5187
|
+
// post-processor sees what the existing one produced
|
|
5195
5188
|
preProcessSnapshot(preProcessor) {
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
}
|
|
5200
|
-
else {
|
|
5201
|
-
return this.cloneAndEnhance({
|
|
5202
|
-
preProcessor: snapshot => currentPreprocessor(preProcessor(snapshot))
|
|
5203
|
-
});
|
|
5204
|
-
}
|
|
5189
|
+
return this.cloneAndEnhance({
|
|
5190
|
+
preProcessor: chainProcessors(preProcessor, this.preProcessor)
|
|
5191
|
+
});
|
|
5205
5192
|
},
|
|
5206
5193
|
postProcessSnapshot(postProcessor) {
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
}
|
|
5211
|
-
else {
|
|
5212
|
-
return this.cloneAndEnhance({
|
|
5213
|
-
postProcessor: snapshot => postProcessor(currentPostprocessor(snapshot))
|
|
5214
|
-
});
|
|
5215
|
-
}
|
|
5194
|
+
return this.cloneAndEnhance({
|
|
5195
|
+
postProcessor: chainProcessors(this.postProcessor, postProcessor)
|
|
5196
|
+
});
|
|
5216
5197
|
}
|
|
5217
5198
|
});
|
|
5218
5199
|
/**
|
|
@@ -5236,39 +5217,44 @@ function model(...args) {
|
|
|
5236
5217
|
* the types are composed into a new Type with the given name
|
|
5237
5218
|
*/
|
|
5238
5219
|
function compose(...args) {
|
|
5239
|
-
// TODO: just join the base type names if no name is provided
|
|
5240
5220
|
const hasTypename = typeof args[0] === "string";
|
|
5241
5221
|
const typeName = hasTypename ? args[0] : ANONYMOUS_MODEL_NAME;
|
|
5242
5222
|
if (hasTypename) {
|
|
5243
5223
|
args.shift();
|
|
5244
5224
|
}
|
|
5245
|
-
//
|
|
5225
|
+
// exactly a model type: each part's own properties and initializers are
|
|
5226
|
+
// read below, and a wrapper around a model has neither
|
|
5246
5227
|
if (devMode()) {
|
|
5247
5228
|
args.forEach((type, i) => {
|
|
5248
|
-
assertArg(type,
|
|
5229
|
+
assertArg(type, t => t instanceof ModelType, "mobx-state-tree model type", hasTypename ? i + 2 : i + 1);
|
|
5249
5230
|
});
|
|
5250
5231
|
}
|
|
5251
5232
|
return args
|
|
5252
5233
|
.reduce((prev, cur) => prev.cloneAndEnhance({
|
|
5253
|
-
name: `${prev.name}_${cur.name}`,
|
|
5254
5234
|
properties: cur.properties,
|
|
5255
5235
|
// cur.properties is another ModelType's already-converted+frozen bag
|
|
5256
5236
|
propertiesAreConverted: true,
|
|
5257
5237
|
initializers: cur.initializers,
|
|
5258
|
-
preProcessor: (
|
|
5259
|
-
postProcessor: (
|
|
5238
|
+
preProcessor: chainProcessors(prev.preProcessor, cur.preProcessor),
|
|
5239
|
+
postProcessor: chainProcessors(prev.postProcessor, cur.postProcessor)
|
|
5260
5240
|
}))
|
|
5261
5241
|
.named(typeName);
|
|
5262
5242
|
}
|
|
5263
5243
|
/**
|
|
5264
|
-
* Returns if a
|
|
5265
|
-
*
|
|
5266
|
-
* @param type
|
|
5267
|
-
* @returns
|
|
5244
|
+
* Returns if a type is a model type, or wraps or unions one. For the model
|
|
5245
|
+
* type itself, use {@link asModelType}.
|
|
5268
5246
|
*/
|
|
5269
5247
|
function isModelType(type) {
|
|
5270
5248
|
return isType(type) && (type.flags & TypeFlags.Object) > 0;
|
|
5271
5249
|
}
|
|
5250
|
+
/**
|
|
5251
|
+
* The model type `type` builds its values with, seeing through the wrappers
|
|
5252
|
+
* {@link unwrapType} does, or `undefined` if that is not a model type.
|
|
5253
|
+
*/
|
|
5254
|
+
function asModelType(type) {
|
|
5255
|
+
const unwrapped = unwrapType(type);
|
|
5256
|
+
return unwrapped instanceof ModelType ? unwrapped : undefined;
|
|
5257
|
+
}
|
|
5272
5258
|
/**
|
|
5273
5259
|
* `extendInstance` - attaches additional actions, views and volatile state to an
|
|
5274
5260
|
* already-created model instance, using the same instantiation machinery as
|
|
@@ -5294,7 +5280,7 @@ function extendInstance(instance, fn) {
|
|
|
5294
5280
|
throw fail("extendInstance expects a mobx-state-tree node");
|
|
5295
5281
|
}
|
|
5296
5282
|
const type = getStateTreeNode(instance).type;
|
|
5297
|
-
if (!
|
|
5283
|
+
if (!(type instanceof ModelType)) {
|
|
5298
5284
|
throw fail("extendInstance can only be used on model instances");
|
|
5299
5285
|
}
|
|
5300
5286
|
// Views/actions/volatile are installed via defineProperty + makeObservable — the
|
|
@@ -5302,9 +5288,8 @@ function extendInstance(instance, fn) {
|
|
|
5302
5288
|
// write-protection interceptor is attached (see finalizeNewInstance). On a live
|
|
5303
5289
|
// instance that interceptor is already active, so run the attach inside an action
|
|
5304
5290
|
// context: isRunningAction() then short-circuits assertWritable.
|
|
5305
|
-
const modelType = type;
|
|
5306
5291
|
const attach = createActionInvoker(instance, "@@extendInstance", (() => {
|
|
5307
|
-
|
|
5292
|
+
type.applyExtensionToInstance(instance, fn(instance));
|
|
5308
5293
|
}));
|
|
5309
5294
|
attach();
|
|
5310
5295
|
return instance;
|
|
@@ -5376,7 +5361,7 @@ const number = new CoreType("number", TypeFlags.Number, v => typeof v === "numbe
|
|
|
5376
5361
|
* })
|
|
5377
5362
|
* ```
|
|
5378
5363
|
*/
|
|
5379
|
-
const integer = new CoreType("integer", TypeFlags.Integer,
|
|
5364
|
+
const integer = new CoreType("integer", TypeFlags.Integer, Number.isInteger);
|
|
5380
5365
|
/**
|
|
5381
5366
|
* `types.float` - Creates a type that can only contain an float value.
|
|
5382
5367
|
*
|
|
@@ -5388,7 +5373,7 @@ const integer = new CoreType("integer", TypeFlags.Integer, v => isInteger(v));
|
|
|
5388
5373
|
* })
|
|
5389
5374
|
* ```
|
|
5390
5375
|
*/
|
|
5391
|
-
const float = new CoreType("float", TypeFlags.Float, v =>
|
|
5376
|
+
const float = new CoreType("float", TypeFlags.Float, v => Number(v) === v && v % 1 !== 0);
|
|
5392
5377
|
/**
|
|
5393
5378
|
* `types.finite` - Creates a type that can only contain an finite value.
|
|
5394
5379
|
*
|
|
@@ -5400,7 +5385,7 @@ const float = new CoreType("float", TypeFlags.Float, v => isFloat(v));
|
|
|
5400
5385
|
* })
|
|
5401
5386
|
* ```
|
|
5402
5387
|
*/
|
|
5403
|
-
const finite = new CoreType("finite", TypeFlags.Finite,
|
|
5388
|
+
const finite = new CoreType("finite", TypeFlags.Finite, Number.isFinite);
|
|
5404
5389
|
/**
|
|
5405
5390
|
* `types.boolean` - Creates a type that can only contain a boolean value.
|
|
5406
5391
|
* This type is used for boolean values by default
|
|
@@ -5461,11 +5446,9 @@ function getPrimitiveFactoryFromValue(value) {
|
|
|
5461
5446
|
/**
|
|
5462
5447
|
* Returns if a given value represents a primitive type.
|
|
5463
5448
|
*
|
|
5464
|
-
*
|
|
5465
|
-
*
|
|
5466
|
-
*
|
|
5467
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
5468
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
5449
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
5450
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
5451
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
5469
5452
|
*
|
|
5470
5453
|
* @param type
|
|
5471
5454
|
* @returns
|
|
@@ -5531,11 +5514,9 @@ function literal(value) {
|
|
|
5531
5514
|
/**
|
|
5532
5515
|
* Returns if a given value represents a literal type.
|
|
5533
5516
|
*
|
|
5534
|
-
*
|
|
5535
|
-
*
|
|
5536
|
-
*
|
|
5537
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
5538
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
5517
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
5518
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
5519
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
5539
5520
|
*
|
|
5540
5521
|
* @param type
|
|
5541
5522
|
* @returns
|
|
@@ -5613,11 +5594,9 @@ function refinement(...args) {
|
|
|
5613
5594
|
/**
|
|
5614
5595
|
* Returns if a given value is a refinement type.
|
|
5615
5596
|
*
|
|
5616
|
-
*
|
|
5617
|
-
*
|
|
5618
|
-
*
|
|
5619
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
5620
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
5597
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
5598
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
5599
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
5621
5600
|
*
|
|
5622
5601
|
* @param type
|
|
5623
5602
|
* @returns
|
|
@@ -5630,6 +5609,10 @@ function isRefinementType(type) {
|
|
|
5630
5609
|
* `types.enumeration` - Can be used to create an string based enumeration.
|
|
5631
5610
|
* (note: this methods is just sugar for a union of string literals)
|
|
5632
5611
|
*
|
|
5612
|
+
* The member type is inferred from the options, so a literal array, an
|
|
5613
|
+
* `as const` array and `Object.values(SomeStringEnum)` all produce the exact
|
|
5614
|
+
* union; only an array already typed `string[]` falls back to `string`.
|
|
5615
|
+
*
|
|
5633
5616
|
* Example:
|
|
5634
5617
|
* ```ts
|
|
5635
5618
|
* const TrafficLight = types.model({
|
|
@@ -5641,52 +5624,47 @@ function isRefinementType(type) {
|
|
|
5641
5624
|
* @param options possible values this enumeration can have
|
|
5642
5625
|
* @returns
|
|
5643
5626
|
*/
|
|
5644
|
-
function enumeration(
|
|
5645
|
-
const
|
|
5646
|
-
|
|
5627
|
+
function enumeration(nameOrOptions, maybeOptions) {
|
|
5628
|
+
const name = typeof nameOrOptions === "string" ? nameOrOptions : undefined;
|
|
5629
|
+
const options = typeof nameOrOptions === "string" ? maybeOptions : nameOrOptions;
|
|
5647
5630
|
if (devMode()) {
|
|
5648
|
-
|
|
5631
|
+
options.forEach((option, i) => {
|
|
5649
5632
|
assertIsString(option, i + 1);
|
|
5650
5633
|
});
|
|
5651
5634
|
}
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
}
|
|
5656
|
-
return type;
|
|
5635
|
+
// built directly rather than through union(): its members are fresh
|
|
5636
|
+
// literals, so interning could never share it, and the name belongs to this
|
|
5637
|
+
// union alone
|
|
5638
|
+
return new Union(options.map(option => literal(`${option}`)), name === undefined ? undefined : { name });
|
|
5657
5639
|
}
|
|
5658
5640
|
|
|
5659
|
-
//
|
|
5660
|
-
//
|
|
5661
|
-
//
|
|
5662
|
-
// members are rarely bare models (jbrowse config schemas
|
|
5663
|
-
// always optional(model) or optional(snapshotProcessor(model))).
|
|
5664
|
-
//
|
|
5665
|
-
//
|
|
5666
|
-
|
|
5667
|
-
// Only *successful* resolutions are cached. A wrapper chain's shape is fixed at
|
|
5668
|
-
// construction, so once a member resolves to a ModelType it always will; but a
|
|
5669
|
-
// `late` member reports no subtype until its definition evaluates, and that
|
|
5670
|
-
// miss must stay retryable.
|
|
5671
|
-
const resolvedModelTypes = new WeakMap();
|
|
5641
|
+
// The model a member is meant for: the one under its wrappers, and for a
|
|
5642
|
+
// `resilient` member the one it tries first. Matching a snapshot to a member
|
|
5643
|
+
// (quick-match dispatch, discriminator scoping) keys on that model's props,
|
|
5644
|
+
// and real-world members are rarely bare models (jbrowse config schemas are
|
|
5645
|
+
// always optional(model) or optional(snapshotProcessor(model))).
|
|
5646
|
+
// Misses are cached too, unless the member holds a `late` type: that has no
|
|
5647
|
+
// subtype until its definition evaluates, so its miss must stay retryable.
|
|
5648
|
+
const intendedModelTypes = new WeakMap();
|
|
5672
5649
|
function resolveModelType(type) {
|
|
5673
|
-
|
|
5674
|
-
|
|
5650
|
+
const cached = intendedModelTypes.get(type);
|
|
5651
|
+
if (cached !== undefined) {
|
|
5652
|
+
return cached ?? undefined;
|
|
5675
5653
|
}
|
|
5676
|
-
const
|
|
5677
|
-
if (
|
|
5678
|
-
|
|
5654
|
+
const model = findIntendedModelType(type);
|
|
5655
|
+
if (model || !(type.flags & TypeFlags.Late)) {
|
|
5656
|
+
intendedModelTypes.set(type, model ?? null);
|
|
5679
5657
|
}
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
const wrapper = current;
|
|
5687
|
-
current = wrapper._subtype ?? wrapper.getSubType?.(false);
|
|
5658
|
+
return model;
|
|
5659
|
+
}
|
|
5660
|
+
function findIntendedModelType(type) {
|
|
5661
|
+
const unwrapped = unwrapType(type);
|
|
5662
|
+
if (unwrapped instanceof ModelType) {
|
|
5663
|
+
return unwrapped;
|
|
5688
5664
|
}
|
|
5689
|
-
return
|
|
5665
|
+
return unwrapped instanceof Resilient
|
|
5666
|
+
? findIntendedModelType(unwrapped.primaryType)
|
|
5667
|
+
: undefined;
|
|
5690
5668
|
}
|
|
5691
5669
|
// The quick-match paths below already know a type carries TypeFlags.Literal,
|
|
5692
5670
|
// but `is()` still routes through BaseType.validate — a context array, an entry
|
|
@@ -5724,13 +5702,17 @@ class Union extends BaseType {
|
|
|
5724
5702
|
if (cached !== undefined) {
|
|
5725
5703
|
return cached;
|
|
5726
5704
|
}
|
|
5705
|
+
const result = this.foldFlags();
|
|
5706
|
+
if (!(result & TypeFlags.Late)) {
|
|
5707
|
+
this._flags = result;
|
|
5708
|
+
}
|
|
5709
|
+
return result;
|
|
5710
|
+
}
|
|
5711
|
+
foldFlags() {
|
|
5727
5712
|
let result = TypeFlags.Union;
|
|
5728
5713
|
for (const type of this.members()) {
|
|
5729
5714
|
result |= type.flags;
|
|
5730
5715
|
}
|
|
5731
|
-
if (!(result & TypeFlags.Late)) {
|
|
5732
|
-
this._flags = result;
|
|
5733
|
-
}
|
|
5734
5716
|
return result;
|
|
5735
5717
|
}
|
|
5736
5718
|
computeName() {
|
|
@@ -6065,11 +6047,7 @@ class DynamicUnion extends Union {
|
|
|
6065
6047
|
return this._members();
|
|
6066
6048
|
}
|
|
6067
6049
|
get flags() {
|
|
6068
|
-
|
|
6069
|
-
for (const type of this.members()) {
|
|
6070
|
-
result |= type.flags;
|
|
6071
|
-
}
|
|
6072
|
-
return result;
|
|
6050
|
+
return this.foldFlags();
|
|
6073
6051
|
}
|
|
6074
6052
|
get name() {
|
|
6075
6053
|
return this._explicitName !== undefined
|
|
@@ -6148,11 +6126,9 @@ function union(...args) {
|
|
|
6148
6126
|
/**
|
|
6149
6127
|
* Returns if a given value represents a union type.
|
|
6150
6128
|
*
|
|
6151
|
-
*
|
|
6152
|
-
*
|
|
6153
|
-
*
|
|
6154
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
6155
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
6129
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
6130
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
6131
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
6156
6132
|
*
|
|
6157
6133
|
* @param type
|
|
6158
6134
|
* @returns
|
|
@@ -6161,13 +6137,9 @@ function isUnionType(type) {
|
|
|
6161
6137
|
return isType(type) && (type.flags & TypeFlags.Union) > 0;
|
|
6162
6138
|
}
|
|
6163
6139
|
/**
|
|
6164
|
-
* Returns the member types of a union
|
|
6165
|
-
*
|
|
6166
|
-
*
|
|
6167
|
-
* the type they wrap, so `isUnionType` is true for e.g. an optional-of-union,
|
|
6168
|
-
* but their `getSubTypes()` reports the single wrapped type rather than the
|
|
6169
|
-
* union's members. This drills through those wrappers until the union's member
|
|
6170
|
-
* array surfaces.
|
|
6140
|
+
* Returns the member types of a union, seeing through the wrappers
|
|
6141
|
+
* {@link unwrapType} does: `isUnionType` is also true for e.g. an
|
|
6142
|
+
* optional-of-union.
|
|
6171
6143
|
*
|
|
6172
6144
|
* @param type a type for which `isUnionType` is true
|
|
6173
6145
|
* @returns the array of member types of the underlying union
|
|
@@ -6176,16 +6148,11 @@ function getUnionSubtypes(type) {
|
|
|
6176
6148
|
if (!isUnionType(type)) {
|
|
6177
6149
|
throw fail("expected a union type");
|
|
6178
6150
|
}
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
subtypes !== null &&
|
|
6182
|
-
!Array.isArray(subtypes)) {
|
|
6183
|
-
subtypes = subtypes.getSubTypes();
|
|
6184
|
-
}
|
|
6185
|
-
if (!Array.isArray(subtypes)) {
|
|
6151
|
+
const union = unwrapType(type);
|
|
6152
|
+
if (!(union instanceof Union)) {
|
|
6186
6153
|
throw fail("could not extract subtypes from union type");
|
|
6187
6154
|
}
|
|
6188
|
-
return
|
|
6155
|
+
return union.getSubTypes();
|
|
6189
6156
|
}
|
|
6190
6157
|
|
|
6191
6158
|
/**
|
|
@@ -6332,11 +6299,9 @@ const undefinedAsOptionalValues = [undefined];
|
|
|
6332
6299
|
/**
|
|
6333
6300
|
* Returns if a value represents an optional type.
|
|
6334
6301
|
*
|
|
6335
|
-
*
|
|
6336
|
-
*
|
|
6337
|
-
*
|
|
6338
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
6339
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
6302
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
6303
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
6304
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
6340
6305
|
*
|
|
6341
6306
|
* @param type
|
|
6342
6307
|
* @returns
|
|
@@ -6347,26 +6312,6 @@ function isOptionalType(type) {
|
|
|
6347
6312
|
function isRecord(value) {
|
|
6348
6313
|
return typeof value === "object" && value !== null;
|
|
6349
6314
|
}
|
|
6350
|
-
/**
|
|
6351
|
-
* The identifier attribute of the model a stripDefault ultimately wraps, or
|
|
6352
|
-
* `null` when there is none. Drills through the single-subtype wrappers the way
|
|
6353
|
-
* `resolveModelType` in union.ts does — that one is module-private there, and
|
|
6354
|
-
* this file may not reach into it.
|
|
6355
|
-
*
|
|
6356
|
-
* `null` is also the answer for an unresolved `types.late`, which only costs the
|
|
6357
|
-
* short-circuit, never correctness: the full structural walk still runs.
|
|
6358
|
-
*/
|
|
6359
|
-
function resolveIdentifierAttribute(type) {
|
|
6360
|
-
let current = type;
|
|
6361
|
-
for (let depth = 0; current && depth < 20; depth++) {
|
|
6362
|
-
if (current instanceof ModelType) {
|
|
6363
|
-
return current.identifierAttribute ? current.identifierAttribute : null;
|
|
6364
|
-
}
|
|
6365
|
-
const wrapper = current;
|
|
6366
|
-
current = wrapper._subtype ?? wrapper.getSubType?.(false);
|
|
6367
|
-
}
|
|
6368
|
-
return null;
|
|
6369
|
-
}
|
|
6370
6315
|
/**
|
|
6371
6316
|
* Compare a child snapshot to a stripped-default's reference snapshot: identity
|
|
6372
6317
|
* for primitives, structural for objects/arrays.
|
|
@@ -6448,7 +6393,10 @@ class StripDefaultValue extends OptionalValue {
|
|
|
6448
6393
|
equalsDefault(snapshot, defaultSnapshot) {
|
|
6449
6394
|
let identifierAttribute = this._identifierAttribute;
|
|
6450
6395
|
if (identifierAttribute === undefined) {
|
|
6451
|
-
|
|
6396
|
+
// null when not wrapping an identified model; an unresolved late member
|
|
6397
|
+
// also lands here, which only costs the short-circuit below
|
|
6398
|
+
identifierAttribute =
|
|
6399
|
+
asModelType(this.getSubTypes())?.identifierAttribute ?? null;
|
|
6452
6400
|
this._identifierAttribute = identifierAttribute;
|
|
6453
6401
|
}
|
|
6454
6402
|
// an identified model's snapshot normally has the same shape as the default
|
|
@@ -6558,16 +6506,14 @@ class Late extends BaseType {
|
|
|
6558
6506
|
}
|
|
6559
6507
|
getSubType(mustSucceed) {
|
|
6560
6508
|
if (!this._subType) {
|
|
6561
|
-
let t
|
|
6509
|
+
let t;
|
|
6562
6510
|
try {
|
|
6563
6511
|
t = this._definition();
|
|
6564
6512
|
}
|
|
6565
6513
|
catch (e) {
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
}
|
|
6570
|
-
else {
|
|
6514
|
+
// a self-referencing definition can read its binding before it is
|
|
6515
|
+
// initialized; that is "not defined yet", like returning undefined
|
|
6516
|
+
if (!(e instanceof ReferenceError)) {
|
|
6571
6517
|
throw e;
|
|
6572
6518
|
}
|
|
6573
6519
|
}
|
|
@@ -6583,10 +6529,15 @@ class Late extends BaseType {
|
|
|
6583
6529
|
}
|
|
6584
6530
|
return this._subType;
|
|
6585
6531
|
}
|
|
6586
|
-
constructor(
|
|
6532
|
+
constructor(_definition, name) {
|
|
6587
6533
|
super(name);
|
|
6588
6534
|
this._definition = _definition;
|
|
6589
6535
|
}
|
|
6536
|
+
// the unnamed form is named after the definition's source text, which is
|
|
6537
|
+
// only worth building if something reads it
|
|
6538
|
+
computeName() {
|
|
6539
|
+
return `late(${this._definition.toString()})`;
|
|
6540
|
+
}
|
|
6590
6541
|
instantiate(parent, subpath, environment, initialValue) {
|
|
6591
6542
|
return this.getSubType(true).instantiate(parent, subpath, environment, initialValue);
|
|
6592
6543
|
}
|
|
@@ -6595,7 +6546,7 @@ class Late extends BaseType {
|
|
|
6595
6546
|
}
|
|
6596
6547
|
describe() {
|
|
6597
6548
|
const t = this.getSubType(false);
|
|
6598
|
-
return t ? t.name : "<
|
|
6549
|
+
return t ? t.name : "<unknown late type>";
|
|
6599
6550
|
}
|
|
6600
6551
|
isValidSnapshot(value, context) {
|
|
6601
6552
|
const t = this.getSubType(false);
|
|
@@ -6610,8 +6561,7 @@ class Late extends BaseType {
|
|
|
6610
6561
|
return t ? t.isAssignableFrom(type) : false;
|
|
6611
6562
|
}
|
|
6612
6563
|
getSubTypes() {
|
|
6613
|
-
|
|
6614
|
-
return subtype ? subtype : cannotDetermineSubtype;
|
|
6564
|
+
return this.getSubType(false) ?? cannotDetermineSubtype;
|
|
6615
6565
|
}
|
|
6616
6566
|
}
|
|
6617
6567
|
/**
|
|
@@ -6631,26 +6581,21 @@ class Late extends BaseType {
|
|
|
6631
6581
|
* @returns
|
|
6632
6582
|
*/
|
|
6633
6583
|
function late(nameOrType, maybeType) {
|
|
6634
|
-
const name = typeof nameOrType === "string"
|
|
6635
|
-
? nameOrType
|
|
6636
|
-
: `late(${nameOrType.toString()})`;
|
|
6584
|
+
const name = typeof nameOrType === "string" ? nameOrType : undefined;
|
|
6637
6585
|
const type = typeof nameOrType === "string" ? maybeType : nameOrType;
|
|
6638
|
-
// checks that the type is actually a late type
|
|
6639
6586
|
if (devMode()) {
|
|
6640
6587
|
if (!(typeof type === "function" && type.length === 0)) {
|
|
6641
6588
|
throw fail(`Invalid late type, expected a function with zero arguments that returns a type, got: ${type}`);
|
|
6642
6589
|
}
|
|
6643
6590
|
}
|
|
6644
|
-
return new Late(
|
|
6591
|
+
return new Late(type, name);
|
|
6645
6592
|
}
|
|
6646
6593
|
/**
|
|
6647
6594
|
* Returns if a given value represents a late type.
|
|
6648
6595
|
*
|
|
6649
|
-
*
|
|
6650
|
-
*
|
|
6651
|
-
*
|
|
6652
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
6653
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
6596
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
6597
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
6598
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
6654
6599
|
*
|
|
6655
6600
|
* @param type
|
|
6656
6601
|
* @returns
|
|
@@ -6660,7 +6605,8 @@ function isLateType(type) {
|
|
|
6660
6605
|
}
|
|
6661
6606
|
|
|
6662
6607
|
function lazy(name, options) {
|
|
6663
|
-
//
|
|
6608
|
+
// a lazy type stands in for the type it loads, down to that type's own
|
|
6609
|
+
// methods (a model's `.props`, say), which the placeholder does not have
|
|
6664
6610
|
return new Lazy(name, options);
|
|
6665
6611
|
}
|
|
6666
6612
|
/**
|
|
@@ -6827,11 +6773,9 @@ function frozen(arg) {
|
|
|
6827
6773
|
/**
|
|
6828
6774
|
* Returns if a given value represents a frozen type.
|
|
6829
6775
|
*
|
|
6830
|
-
*
|
|
6831
|
-
*
|
|
6832
|
-
*
|
|
6833
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
6834
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
6776
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
6777
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
6778
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
6835
6779
|
*
|
|
6836
6780
|
* @param type
|
|
6837
6781
|
* @returns
|
|
@@ -6975,9 +6919,10 @@ class BaseReferenceType extends SimpleType {
|
|
|
6975
6919
|
return undefined;
|
|
6976
6920
|
}
|
|
6977
6921
|
const refTargetNode = getStateTreeNode(refTargetValue);
|
|
6978
|
-
const hookHandler = (
|
|
6922
|
+
const hookHandler = (subject, refTargetNodeHook) => {
|
|
6979
6923
|
const cause = getInvalidationCause(refTargetNodeHook);
|
|
6980
|
-
|
|
6924
|
+
// a reference detached along with its target still resolves it
|
|
6925
|
+
if (!cause || (cause === "detach" && storedRefNode.isWithin(subject))) {
|
|
6981
6926
|
return;
|
|
6982
6927
|
}
|
|
6983
6928
|
this.fireInvalidated(cause, storedRefNode, referenceId, refTargetNode);
|
|
@@ -7175,11 +7120,9 @@ function reference(subType, options) {
|
|
|
7175
7120
|
/**
|
|
7176
7121
|
* Returns if a given value represents a reference type.
|
|
7177
7122
|
*
|
|
7178
|
-
*
|
|
7179
|
-
*
|
|
7180
|
-
*
|
|
7181
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
7182
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
7123
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
7124
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
7125
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
7183
7126
|
*
|
|
7184
7127
|
* @param type
|
|
7185
7128
|
* @returns
|
|
@@ -7304,11 +7247,9 @@ const identifierNumber = new IdentifierNumberType();
|
|
|
7304
7247
|
/**
|
|
7305
7248
|
* Returns if a given value represents an identifier type.
|
|
7306
7249
|
*
|
|
7307
|
-
*
|
|
7308
|
-
*
|
|
7309
|
-
*
|
|
7310
|
-
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
7311
|
-
* `isMapType`, `isModelType`) keep their predicate.
|
|
7250
|
+
* Like every `isXType` guard it reads the type's flags, which wrappers and
|
|
7251
|
+
* unions inherit from what they hold, so it is also true for a type that wraps
|
|
7252
|
+
* or unions one. Use {@link unwrapType} to get at the type itself.
|
|
7312
7253
|
*
|
|
7313
7254
|
* @param type
|
|
7314
7255
|
* @returns
|
|
@@ -7439,6 +7380,10 @@ class CustomType extends SimpleType {
|
|
|
7439
7380
|
}
|
|
7440
7381
|
}
|
|
7441
7382
|
|
|
7383
|
+
/**
|
|
7384
|
+
* @internal
|
|
7385
|
+
* @hidden
|
|
7386
|
+
*/
|
|
7442
7387
|
class Resilient extends BaseType {
|
|
7443
7388
|
_subtype;
|
|
7444
7389
|
_fallbackType;
|
|
@@ -7446,6 +7391,10 @@ class Resilient extends BaseType {
|
|
|
7446
7391
|
get flags() {
|
|
7447
7392
|
return this._subtype.flags;
|
|
7448
7393
|
}
|
|
7394
|
+
/** the type tried first; the fallback takes over only when it fails */
|
|
7395
|
+
get primaryType() {
|
|
7396
|
+
return this._subtype;
|
|
7397
|
+
}
|
|
7449
7398
|
constructor(_subtype, _fallbackType, _createFallbackSnapshot) {
|
|
7450
7399
|
super();
|
|
7451
7400
|
this._subtype = _subtype;
|
|
@@ -7606,6 +7555,9 @@ exports.addMiddleware = addMiddleware;
|
|
|
7606
7555
|
exports.applyAction = applyAction;
|
|
7607
7556
|
exports.applyPatch = applyPatch;
|
|
7608
7557
|
exports.applySnapshot = applySnapshot;
|
|
7558
|
+
exports.asArrayType = asArrayType;
|
|
7559
|
+
exports.asMapType = asMapType;
|
|
7560
|
+
exports.asModelType = asModelType;
|
|
7609
7561
|
exports.cannotDetermineSubtype = cannotDetermineSubtype;
|
|
7610
7562
|
exports.cast = cast;
|
|
7611
7563
|
exports.castFlowReturn = castFlowReturn;
|
|
@@ -7637,6 +7589,7 @@ exports.getRunningActionContext = getRunningActionContext;
|
|
|
7637
7589
|
exports.getSnapshot = getSnapshot;
|
|
7638
7590
|
exports.getType = getType;
|
|
7639
7591
|
exports.getUnionSubtypes = getUnionSubtypes;
|
|
7592
|
+
exports.getWrappedType = getWrappedType;
|
|
7640
7593
|
exports.hasParent = hasParent;
|
|
7641
7594
|
exports.hasParentOfType = hasParentOfType;
|
|
7642
7595
|
exports.isActionContextChildOf = isActionContextChildOf;
|
|
@@ -7682,5 +7635,6 @@ exports.typecheck = typecheck;
|
|
|
7682
7635
|
exports.types = types;
|
|
7683
7636
|
exports.unescapeJsonPath = unescapeJsonPath;
|
|
7684
7637
|
exports.unprotect = unprotect;
|
|
7638
|
+
exports.unwrapType = unwrapType;
|
|
7685
7639
|
exports.walk = walk;
|
|
7686
7640
|
//# sourceMappingURL=mobx-state-tree.cjs.map
|