@jbrowse/mobx-state-tree 6.3.0 → 6.4.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/index.d.ts +64 -114
- package/dist/mobx-state-tree.cjs +205 -192
- package/dist/mobx-state-tree.cjs.map +1 -1
- package/dist/mobx-state-tree.mjs +205 -193
- package/dist/mobx-state-tree.mjs.map +1 -1
- package/package.json +1 -1
package/dist/mobx-state-tree.cjs
CHANGED
|
@@ -272,6 +272,8 @@ function unprotect(target) {
|
|
|
272
272
|
* Returns true if the object is in protected mode, @see protect
|
|
273
273
|
*/
|
|
274
274
|
function isProtected(target) {
|
|
275
|
+
// check all arguments
|
|
276
|
+
assertIsStateTreeNode(target, 1);
|
|
275
277
|
return getStateTreeNode(target).isProtected;
|
|
276
278
|
}
|
|
277
279
|
/**
|
|
@@ -303,6 +305,27 @@ function getSnapshot(target, applyPostProcess = true) {
|
|
|
303
305
|
}
|
|
304
306
|
return freeze(node.type.getSnapshot(node, false));
|
|
305
307
|
}
|
|
308
|
+
function findParentAtDepth(node, depth) {
|
|
309
|
+
let remaining = depth;
|
|
310
|
+
let parent = node.parent;
|
|
311
|
+
while (parent) {
|
|
312
|
+
if (--remaining === 0) {
|
|
313
|
+
return parent;
|
|
314
|
+
}
|
|
315
|
+
parent = parent.parent;
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
function findParentOfType(node, type) {
|
|
320
|
+
let parent = node.parent;
|
|
321
|
+
while (parent) {
|
|
322
|
+
if (type.is(parent.storedValue)) {
|
|
323
|
+
return parent;
|
|
324
|
+
}
|
|
325
|
+
parent = parent.parent;
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
306
329
|
/**
|
|
307
330
|
* Given a model instance, returns `true` if the object has a parent, that is, is part of another object, map or array.
|
|
308
331
|
*
|
|
@@ -314,14 +337,7 @@ function hasParent(target, depth = 1) {
|
|
|
314
337
|
// check all arguments
|
|
315
338
|
assertIsStateTreeNode(target, 1);
|
|
316
339
|
assertIsNumber(depth, 2, 0);
|
|
317
|
-
|
|
318
|
-
while (parent) {
|
|
319
|
-
if (--depth === 0) {
|
|
320
|
-
return true;
|
|
321
|
-
}
|
|
322
|
-
parent = parent.parent;
|
|
323
|
-
}
|
|
324
|
-
return false;
|
|
340
|
+
return findParentAtDepth(getStateTreeNode(target), depth) !== null;
|
|
325
341
|
}
|
|
326
342
|
/**
|
|
327
343
|
* Returns the immediate parent of this object, or throws.
|
|
@@ -340,15 +356,11 @@ function getParent(target, depth = 1) {
|
|
|
340
356
|
// check all arguments
|
|
341
357
|
assertIsStateTreeNode(target, 1);
|
|
342
358
|
assertIsNumber(depth, 2, 0);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (--d === 0) {
|
|
347
|
-
return parent.storedValue;
|
|
348
|
-
}
|
|
349
|
-
parent = parent.parent;
|
|
359
|
+
const parent = findParentAtDepth(getStateTreeNode(target), depth);
|
|
360
|
+
if (!parent) {
|
|
361
|
+
throw fail(`Failed to find the parent of ${getStateTreeNode(target)} at depth ${depth}`);
|
|
350
362
|
}
|
|
351
|
-
|
|
363
|
+
return parent.storedValue;
|
|
352
364
|
}
|
|
353
365
|
/**
|
|
354
366
|
* Given a model instance, returns `true` if the object has a parent of given type, that is, is part of another object, map or array
|
|
@@ -361,14 +373,7 @@ function hasParentOfType(target, type) {
|
|
|
361
373
|
// check all arguments
|
|
362
374
|
assertIsStateTreeNode(target, 1);
|
|
363
375
|
assertIsType(type, 2);
|
|
364
|
-
|
|
365
|
-
while (parent) {
|
|
366
|
-
if (type.is(parent.storedValue)) {
|
|
367
|
-
return true;
|
|
368
|
-
}
|
|
369
|
-
parent = parent.parent;
|
|
370
|
-
}
|
|
371
|
-
return false;
|
|
376
|
+
return findParentOfType(getStateTreeNode(target), type) !== null;
|
|
372
377
|
}
|
|
373
378
|
/**
|
|
374
379
|
* Returns the target's parent of a given type, or throws.
|
|
@@ -381,14 +386,11 @@ function getParentOfType(target, type) {
|
|
|
381
386
|
// check all arguments
|
|
382
387
|
assertIsStateTreeNode(target, 1);
|
|
383
388
|
assertIsType(type, 2);
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return parent.storedValue;
|
|
388
|
-
}
|
|
389
|
-
parent = parent.parent;
|
|
389
|
+
const parent = findParentOfType(getStateTreeNode(target), type);
|
|
390
|
+
if (!parent) {
|
|
391
|
+
throw fail(`Failed to find the parent of ${getStateTreeNode(target)} of a given type`);
|
|
390
392
|
}
|
|
391
|
-
|
|
393
|
+
return parent.storedValue;
|
|
392
394
|
}
|
|
393
395
|
/**
|
|
394
396
|
* Given an object in a model tree, returns the root object of that tree.
|
|
@@ -1197,11 +1199,11 @@ class ObjectNode extends BaseNode {
|
|
|
1197
1199
|
this.identifier = normalizeIdentifier(id);
|
|
1198
1200
|
this.unnormalizedIdentifier = id;
|
|
1199
1201
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1202
|
+
// addNodeToCache no-ops without an identifier attribute, and reaching the
|
|
1203
|
+
// root to ask it is a walk up the whole parent chain
|
|
1204
|
+
if (this.identifierAttribute) {
|
|
1205
|
+
const cache = parent ? parent.root.identifierCache : this.identifierCache;
|
|
1206
|
+
cache.addNodeToCache(this);
|
|
1205
1207
|
}
|
|
1206
1208
|
}
|
|
1207
1209
|
createObservableInstanceIfNeeded(fireHooks = true) {
|
|
@@ -1349,15 +1351,9 @@ class ObjectNode extends BaseNode {
|
|
|
1349
1351
|
typeof this.storedValue === "object" &&
|
|
1350
1352
|
this.storedValue[name];
|
|
1351
1353
|
if (typeof fn === "function") {
|
|
1352
|
-
|
|
1353
|
-
if (mobx._allowStateChangesInsideComputed) {
|
|
1354
|
-
mobx._allowStateChangesInsideComputed(() => {
|
|
1355
|
-
fn.apply(this.storedValue);
|
|
1356
|
-
});
|
|
1357
|
-
}
|
|
1358
|
-
else {
|
|
1354
|
+
mobx._allowStateChangesInsideComputed(() => {
|
|
1359
1355
|
fn.apply(this.storedValue);
|
|
1360
|
-
}
|
|
1356
|
+
});
|
|
1361
1357
|
}
|
|
1362
1358
|
}
|
|
1363
1359
|
_snapshotUponDeath;
|
|
@@ -1737,8 +1733,8 @@ var TypeFlags;
|
|
|
1737
1733
|
TypeFlags[TypeFlags["Float"] = 4194304] = "Float";
|
|
1738
1734
|
})(TypeFlags || (TypeFlags = {}));
|
|
1739
1735
|
/**
|
|
1740
|
-
*
|
|
1741
|
-
*
|
|
1736
|
+
* The value `getSubTypes()` returns when a type cannot report its subtype,
|
|
1737
|
+
* which is distinct from reporting that it has none (`null`).
|
|
1742
1738
|
*/
|
|
1743
1739
|
const cannotDetermineSubtype = "cannotDetermine";
|
|
1744
1740
|
/**
|
|
@@ -1790,6 +1786,9 @@ class BaseType {
|
|
|
1790
1786
|
// istanbul ignore next
|
|
1791
1787
|
throw fail("unimplemented method");
|
|
1792
1788
|
}
|
|
1789
|
+
describe() {
|
|
1790
|
+
return this.name;
|
|
1791
|
+
}
|
|
1793
1792
|
isAssignableFrom(type) {
|
|
1794
1793
|
return type === this;
|
|
1795
1794
|
}
|
|
@@ -1935,7 +1934,7 @@ class SimpleType extends BaseType {
|
|
|
1935
1934
|
* @returns `true` if the value is a type.
|
|
1936
1935
|
*/
|
|
1937
1936
|
function isType(value) {
|
|
1938
|
-
return typeof value === "object" && value?.isType === true;
|
|
1937
|
+
return (typeof value === "object" && value?.isType === true);
|
|
1939
1938
|
}
|
|
1940
1939
|
/**
|
|
1941
1940
|
* @internal
|
|
@@ -2670,10 +2669,6 @@ function safeStringify(value) {
|
|
|
2670
2669
|
return `<Unserializable: ${e}>`;
|
|
2671
2670
|
}
|
|
2672
2671
|
}
|
|
2673
|
-
/**
|
|
2674
|
-
* @internal
|
|
2675
|
-
* @hidden
|
|
2676
|
-
*/
|
|
2677
2672
|
function prettyPrintValue(value) {
|
|
2678
2673
|
return typeof value === "function"
|
|
2679
2674
|
? `<function${value.name ? ` ${value.name}` : ""}>`
|
|
@@ -2706,12 +2701,8 @@ function toErrorString(error) {
|
|
|
2706
2701
|
expectation = ".";
|
|
2707
2702
|
}
|
|
2708
2703
|
else {
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
// annotation restores the type it actually has here.
|
|
2712
|
-
const complexType = type;
|
|
2713
|
-
const isSnapshotCompatible = isStateTreeNode(value) && complexType.is(getStateTreeNode(value).snapshot);
|
|
2714
|
-
expectation = `, expected an instance of \`${complexType.name}\` or a snapshot like \`${shortenPrintValue(complexType.describe())}\` instead.${isSnapshotCompatible
|
|
2704
|
+
const isSnapshotCompatible = isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
|
|
2705
|
+
expectation = `, expected an instance of \`${type.name}\` or a snapshot like \`${shortenPrintValue(type.describe())}\` instead.${isSnapshotCompatible
|
|
2715
2706
|
? " (Note that a snapshot of the provided value is compatible with the targeted type)"
|
|
2716
2707
|
: ""}`;
|
|
2717
2708
|
}
|
|
@@ -2992,7 +2983,7 @@ function getStateTreeNode(value) {
|
|
|
2992
2983
|
* @hidden
|
|
2993
2984
|
*/
|
|
2994
2985
|
function getStateTreeNodeSafe(value) {
|
|
2995
|
-
return value
|
|
2986
|
+
return value?.["$treenode"] || null;
|
|
2996
2987
|
}
|
|
2997
2988
|
/**
|
|
2998
2989
|
* @internal
|
|
@@ -3304,9 +3295,6 @@ class EventHandler {
|
|
|
3304
3295
|
this.handlers.splice(index, 1);
|
|
3305
3296
|
}
|
|
3306
3297
|
}
|
|
3307
|
-
clear() {
|
|
3308
|
-
this.handlers.length = 0;
|
|
3309
|
-
}
|
|
3310
3298
|
emit(...args) {
|
|
3311
3299
|
const handlers = this.handlers;
|
|
3312
3300
|
// 0 and 1 handlers are by far the common cases (a patch/snapshot listener, a
|
|
@@ -3451,21 +3439,6 @@ function assertIsString(value, argNumber, canBeEmpty = true) {
|
|
|
3451
3439
|
assertArg(value, s => s !== "", "not empty string", argNumber);
|
|
3452
3440
|
}
|
|
3453
3441
|
}
|
|
3454
|
-
/**
|
|
3455
|
-
* @internal
|
|
3456
|
-
* @hidden
|
|
3457
|
-
*/
|
|
3458
|
-
function setImmediateWithFallback(fn) {
|
|
3459
|
-
if (typeof queueMicrotask === "function") {
|
|
3460
|
-
queueMicrotask(fn);
|
|
3461
|
-
}
|
|
3462
|
-
else if (typeof setImmediate === "function") {
|
|
3463
|
-
setImmediate(fn);
|
|
3464
|
-
}
|
|
3465
|
-
else {
|
|
3466
|
-
setTimeout(fn, 1);
|
|
3467
|
-
}
|
|
3468
|
-
}
|
|
3469
3442
|
|
|
3470
3443
|
/**
|
|
3471
3444
|
* See [asynchronous actions](concepts/async-actions.md).
|
|
@@ -3536,10 +3509,6 @@ function toGeneratorFunction(p) {
|
|
|
3536
3509
|
function* toGenerator(p) {
|
|
3537
3510
|
return (yield p);
|
|
3538
3511
|
}
|
|
3539
|
-
/**
|
|
3540
|
-
* @internal
|
|
3541
|
-
* @hidden
|
|
3542
|
-
*/
|
|
3543
3512
|
function createFlowSpawner(name, generator) {
|
|
3544
3513
|
const spawner = function flowSpawner(...flowArgs) {
|
|
3545
3514
|
// Implementation based on https://github.com/tj/co/blob/master/index.js
|
|
@@ -3597,7 +3566,7 @@ function createFlowSpawner(name, generator) {
|
|
|
3597
3566
|
}
|
|
3598
3567
|
catch (e) {
|
|
3599
3568
|
// prettier-ignore
|
|
3600
|
-
|
|
3569
|
+
queueMicrotask(() => {
|
|
3601
3570
|
wrap((_r) => { reject(e); }, "flow_throw", e);
|
|
3602
3571
|
});
|
|
3603
3572
|
return;
|
|
@@ -3613,7 +3582,7 @@ function createFlowSpawner(name, generator) {
|
|
|
3613
3582
|
}
|
|
3614
3583
|
catch (e) {
|
|
3615
3584
|
// prettier-ignore
|
|
3616
|
-
|
|
3585
|
+
queueMicrotask(() => {
|
|
3617
3586
|
wrap((_r) => { reject(e); }, "flow_throw", e);
|
|
3618
3587
|
});
|
|
3619
3588
|
return;
|
|
@@ -3623,7 +3592,7 @@ function createFlowSpawner(name, generator) {
|
|
|
3623
3592
|
function next(ret) {
|
|
3624
3593
|
if (ret.done) {
|
|
3625
3594
|
// prettier-ignore
|
|
3626
|
-
|
|
3595
|
+
queueMicrotask(() => {
|
|
3627
3596
|
wrap((r) => { resolve(r); }, "flow_return", ret.value);
|
|
3628
3597
|
});
|
|
3629
3598
|
return;
|
|
@@ -3651,10 +3620,6 @@ function splitPatch(patch) {
|
|
|
3651
3620
|
}
|
|
3652
3621
|
return [stripPatch(patch), invertPatch(patch)];
|
|
3653
3622
|
}
|
|
3654
|
-
/**
|
|
3655
|
-
* @internal
|
|
3656
|
-
* @hidden
|
|
3657
|
-
*/
|
|
3658
3623
|
function stripPatch(patch) {
|
|
3659
3624
|
// strips `oldvalue` information from the patch, so that it becomes a patch conform the json-patch spec
|
|
3660
3625
|
// this removes the ability to undo the patch
|
|
@@ -4001,13 +3966,6 @@ var MapIdentifierMode;
|
|
|
4001
3966
|
MapIdentifierMode[MapIdentifierMode["NO"] = 2] = "NO";
|
|
4002
3967
|
})(MapIdentifierMode || (MapIdentifierMode = {}));
|
|
4003
3968
|
class MSTMap extends mobx.ObservableMap {
|
|
4004
|
-
constructor(initialData, name) {
|
|
4005
|
-
// mobx's default (deep) enhancer. The old `observable.ref.enhancer` arg
|
|
4006
|
-
// read undefined ever since mobx 6 renamed the field to `options_.enhancer`,
|
|
4007
|
-
// so deep has been the effective behavior all along; mobx 7 dropped
|
|
4008
|
-
// `observable.ref` entirely.
|
|
4009
|
-
super(initialData, undefined, name);
|
|
4010
|
-
}
|
|
4011
3969
|
get(key) {
|
|
4012
3970
|
// maybe this is over-enthousiastic? normalize numeric keys to strings
|
|
4013
3971
|
return super.get(`${key}`);
|
|
@@ -4120,7 +4078,8 @@ class MapType extends ComplexType {
|
|
|
4120
4078
|
return result;
|
|
4121
4079
|
}
|
|
4122
4080
|
createNewInstance(childNodes) {
|
|
4123
|
-
|
|
4081
|
+
// undefined is mobx's enhancer argument, left at its deep default
|
|
4082
|
+
return new MSTMap(childNodes, undefined, this.name);
|
|
4124
4083
|
}
|
|
4125
4084
|
finalizeNewInstance(node, instance) {
|
|
4126
4085
|
mobx._interceptReads(instance, node.unbox);
|
|
@@ -4128,9 +4087,6 @@ class MapType extends ComplexType {
|
|
|
4128
4087
|
mobx.intercept(instance, this.willChange);
|
|
4129
4088
|
mobx.observe(instance, this.didChange);
|
|
4130
4089
|
}
|
|
4131
|
-
describe() {
|
|
4132
|
-
return this.name;
|
|
4133
|
-
}
|
|
4134
4090
|
getChildren(node) {
|
|
4135
4091
|
// return (node.storedValue as ObservableMap<any>).values()
|
|
4136
4092
|
return mobx.values(node.storedValue);
|
|
@@ -4307,6 +4263,7 @@ MapType.prototype.applySnapshot = mobx.action(MapType.prototype.applySnapshot);
|
|
|
4307
4263
|
* @returns
|
|
4308
4264
|
*/
|
|
4309
4265
|
function map(subtype) {
|
|
4266
|
+
assertIsType(subtype, 1);
|
|
4310
4267
|
return new MapType(subtype);
|
|
4311
4268
|
}
|
|
4312
4269
|
/**
|
|
@@ -4360,9 +4317,6 @@ class ArrayType extends ComplexType {
|
|
|
4360
4317
|
mobx.intercept(instance, this.willChange);
|
|
4361
4318
|
mobx.observe(instance, this.didChange);
|
|
4362
4319
|
}
|
|
4363
|
-
describe() {
|
|
4364
|
-
return this.name;
|
|
4365
|
-
}
|
|
4366
4320
|
getChildren(node) {
|
|
4367
4321
|
return node.storedValue.slice();
|
|
4368
4322
|
}
|
|
@@ -4734,8 +4688,8 @@ function objectTypeToString() {
|
|
|
4734
4688
|
}
|
|
4735
4689
|
const ANONYMOUS_MODEL_NAME = "AnonymousModel";
|
|
4736
4690
|
/**
|
|
4737
|
-
* A plain loop rather than
|
|
4738
|
-
* indirect call
|
|
4691
|
+
* A plain loop rather than a callback per property, which allocated a closure
|
|
4692
|
+
* and made an indirect call. This runs once per `types.model()` over every
|
|
4739
4693
|
* declared property, and jbrowse builds a ~40-slot schema per track.
|
|
4740
4694
|
*/
|
|
4741
4695
|
function findIdentifierAttribute(properties, propertyNames) {
|
|
@@ -4933,12 +4887,6 @@ class ModelType extends ComplexType {
|
|
|
4933
4887
|
(!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, name, actionInvoker);
|
|
4934
4888
|
});
|
|
4935
4889
|
}
|
|
4936
|
-
named = name => {
|
|
4937
|
-
return this.cloneAndEnhance({ name });
|
|
4938
|
-
};
|
|
4939
|
-
props = properties => {
|
|
4940
|
-
return this.cloneAndEnhance({ properties });
|
|
4941
|
-
};
|
|
4942
4890
|
volatile(fn) {
|
|
4943
4891
|
if (typeof fn !== "function") {
|
|
4944
4892
|
throw fail(`You passed an ${typeof fn} to volatile state as an argument, when function is expected`);
|
|
@@ -5021,28 +4969,6 @@ class ModelType extends ComplexType {
|
|
|
5021
4969
|
}
|
|
5022
4970
|
});
|
|
5023
4971
|
}
|
|
5024
|
-
preProcessSnapshot = preProcessor => {
|
|
5025
|
-
const currentPreprocessor = this.preProcessor;
|
|
5026
|
-
if (!currentPreprocessor) {
|
|
5027
|
-
return this.cloneAndEnhance({ preProcessor });
|
|
5028
|
-
}
|
|
5029
|
-
else {
|
|
5030
|
-
return this.cloneAndEnhance({
|
|
5031
|
-
preProcessor: snapshot => currentPreprocessor(preProcessor(snapshot))
|
|
5032
|
-
});
|
|
5033
|
-
}
|
|
5034
|
-
};
|
|
5035
|
-
postProcessSnapshot = postProcessor => {
|
|
5036
|
-
const currentPostprocessor = this.postProcessor;
|
|
5037
|
-
if (!currentPostprocessor) {
|
|
5038
|
-
return this.cloneAndEnhance({ postProcessor });
|
|
5039
|
-
}
|
|
5040
|
-
else {
|
|
5041
|
-
return this.cloneAndEnhance({
|
|
5042
|
-
postProcessor: snapshot => postProcessor(currentPostprocessor(snapshot))
|
|
5043
|
-
});
|
|
5044
|
-
}
|
|
5045
|
-
};
|
|
5046
4972
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5047
4973
|
const value = isStateTreeNode(initialValue)
|
|
5048
4974
|
? initialValue
|
|
@@ -5053,10 +4979,11 @@ class ModelType extends ComplexType {
|
|
|
5053
4979
|
}
|
|
5054
4980
|
initializeChildNodes(objNode, initialSnapshot = {}) {
|
|
5055
4981
|
const type = objNode.type;
|
|
4982
|
+
const properties = type.properties;
|
|
5056
4983
|
const result = {};
|
|
5057
|
-
|
|
5058
|
-
result[name] =
|
|
5059
|
-
}
|
|
4984
|
+
for (const name of type.propertyNames) {
|
|
4985
|
+
result[name] = properties[name].instantiate(objNode, name, undefined, initialSnapshot[name]);
|
|
4986
|
+
}
|
|
5060
4987
|
return result;
|
|
5061
4988
|
}
|
|
5062
4989
|
createNewInstance(childNodes) {
|
|
@@ -5075,9 +5002,9 @@ class ModelType extends ComplexType {
|
|
|
5075
5002
|
}
|
|
5076
5003
|
}
|
|
5077
5004
|
else {
|
|
5078
|
-
|
|
5005
|
+
for (const name of this.propertyNames) {
|
|
5079
5006
|
mobx._interceptReads(instance, name, node.unbox);
|
|
5080
|
-
}
|
|
5007
|
+
}
|
|
5081
5008
|
}
|
|
5082
5009
|
this.initializers.reduce((self, fn) => fn(self), instance);
|
|
5083
5010
|
// views, actions and volatile share the instance namespace with properties,
|
|
@@ -5088,12 +5015,12 @@ class ModelType extends ComplexType {
|
|
|
5088
5015
|
// function/value stops being observable at all. The flag is only set on
|
|
5089
5016
|
// success so a broken type keeps throwing on every create.
|
|
5090
5017
|
if (!this.duplicateKeysChecked) {
|
|
5091
|
-
|
|
5018
|
+
for (const name of this.propertyNames) {
|
|
5092
5019
|
if (mobx.isComputedProp(instance, name) ||
|
|
5093
5020
|
!mobx.isObservableProp(instance, name)) {
|
|
5094
5021
|
throw fail(`${name} property is declared twice`);
|
|
5095
5022
|
}
|
|
5096
|
-
}
|
|
5023
|
+
}
|
|
5097
5024
|
this.duplicateKeysChecked = true;
|
|
5098
5025
|
}
|
|
5099
5026
|
mobx.intercept(instance, this.willChange);
|
|
@@ -5146,24 +5073,16 @@ class ModelType extends ComplexType {
|
|
|
5146
5073
|
}
|
|
5147
5074
|
return res;
|
|
5148
5075
|
}
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
*/
|
|
5154
|
-
getPropertyNode(node, key) {
|
|
5076
|
+
getChildNode(node, key) {
|
|
5077
|
+
if (!(key in this.properties)) {
|
|
5078
|
+
throw fail(`Not a value property: ${key}`);
|
|
5079
|
+
}
|
|
5155
5080
|
const childNode = getPropObservable(node.storedValue, key).raw();
|
|
5156
5081
|
if (!childNode) {
|
|
5157
5082
|
throw fail(`Node not available for property ${key}`);
|
|
5158
5083
|
}
|
|
5159
5084
|
return childNode;
|
|
5160
5085
|
}
|
|
5161
|
-
getChildNode(node, key) {
|
|
5162
|
-
if (!(key in this.properties)) {
|
|
5163
|
-
throw fail(`Not a value property: ${key}`);
|
|
5164
|
-
}
|
|
5165
|
-
return this.getPropertyNode(node, key);
|
|
5166
|
-
}
|
|
5167
5086
|
getSnapshot(node, applyPostProcess = true) {
|
|
5168
5087
|
const res = {};
|
|
5169
5088
|
const storedValue = node.storedValue;
|
|
@@ -5215,9 +5134,9 @@ class ModelType extends ComplexType {
|
|
|
5215
5134
|
applySnapshot(node, snapshot) {
|
|
5216
5135
|
typecheckInternal(this, snapshot);
|
|
5217
5136
|
const preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
|
|
5218
|
-
|
|
5137
|
+
for (const name of this.propertyNames) {
|
|
5219
5138
|
node.storedValue[name] = preProcessedSnapshot[name];
|
|
5220
|
-
}
|
|
5139
|
+
}
|
|
5221
5140
|
}
|
|
5222
5141
|
applySnapshotPreProcessor(snapshot) {
|
|
5223
5142
|
const processor = this.preProcessor;
|
|
@@ -5250,12 +5169,6 @@ class ModelType extends ComplexType {
|
|
|
5250
5169
|
}
|
|
5251
5170
|
return typeCheckSuccess();
|
|
5252
5171
|
}
|
|
5253
|
-
forAllProps(fn) {
|
|
5254
|
-
const properties = this.properties;
|
|
5255
|
-
for (const key of this.propertyNames) {
|
|
5256
|
-
fn(key, properties[key]);
|
|
5257
|
-
}
|
|
5258
|
-
}
|
|
5259
5172
|
describe() {
|
|
5260
5173
|
// optimization: cache
|
|
5261
5174
|
return `{ ${this.propertyNames
|
|
@@ -5270,6 +5183,38 @@ class ModelType extends ComplexType {
|
|
|
5270
5183
|
}
|
|
5271
5184
|
}
|
|
5272
5185
|
ModelType.prototype.applySnapshot = mobx.action(ModelType.prototype.applySnapshot);
|
|
5186
|
+
// Chain steps shared by every model type; see the field declarations in the
|
|
5187
|
+
// class for why they are not own slots.
|
|
5188
|
+
Object.assign(ModelType.prototype, {
|
|
5189
|
+
named(name) {
|
|
5190
|
+
return this.cloneAndEnhance({ name });
|
|
5191
|
+
},
|
|
5192
|
+
props(properties) {
|
|
5193
|
+
return this.cloneAndEnhance({ properties });
|
|
5194
|
+
},
|
|
5195
|
+
preProcessSnapshot(preProcessor) {
|
|
5196
|
+
const currentPreprocessor = this.preProcessor;
|
|
5197
|
+
if (!currentPreprocessor) {
|
|
5198
|
+
return this.cloneAndEnhance({ preProcessor });
|
|
5199
|
+
}
|
|
5200
|
+
else {
|
|
5201
|
+
return this.cloneAndEnhance({
|
|
5202
|
+
preProcessor: snapshot => currentPreprocessor(preProcessor(snapshot))
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
},
|
|
5206
|
+
postProcessSnapshot(postProcessor) {
|
|
5207
|
+
const currentPostprocessor = this.postProcessor;
|
|
5208
|
+
if (!currentPostprocessor) {
|
|
5209
|
+
return this.cloneAndEnhance({ postProcessor });
|
|
5210
|
+
}
|
|
5211
|
+
else {
|
|
5212
|
+
return this.cloneAndEnhance({
|
|
5213
|
+
postProcessor: snapshot => postProcessor(currentPostprocessor(snapshot))
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
});
|
|
5273
5218
|
/**
|
|
5274
5219
|
* `types.model` - Creates a new model type by providing a name, properties, volatile state and actions.
|
|
5275
5220
|
*
|
|
@@ -5380,9 +5325,6 @@ class CoreType extends SimpleType {
|
|
|
5380
5325
|
this.checker = checker;
|
|
5381
5326
|
this.initializer = initializer;
|
|
5382
5327
|
}
|
|
5383
|
-
describe() {
|
|
5384
|
-
return this.name;
|
|
5385
|
-
}
|
|
5386
5328
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5387
5329
|
return createScalarNode(this, parent, subpath, environment, initialValue);
|
|
5388
5330
|
}
|
|
@@ -5549,15 +5491,15 @@ class Literal extends SimpleType {
|
|
|
5549
5491
|
value;
|
|
5550
5492
|
flags = TypeFlags.Literal;
|
|
5551
5493
|
constructor(value) {
|
|
5552
|
-
super(
|
|
5494
|
+
super();
|
|
5553
5495
|
this.value = value;
|
|
5554
5496
|
}
|
|
5497
|
+
computeName() {
|
|
5498
|
+
return JSON.stringify(this.value);
|
|
5499
|
+
}
|
|
5555
5500
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5556
5501
|
return createScalarNode(this, parent, subpath, environment, initialValue);
|
|
5557
5502
|
}
|
|
5558
|
-
describe() {
|
|
5559
|
-
return JSON.stringify(this.value);
|
|
5560
|
-
}
|
|
5561
5503
|
isValidSnapshot(value, context) {
|
|
5562
5504
|
if (isPrimitive(value) && value === this.value) {
|
|
5563
5505
|
return typeCheckSuccess();
|
|
@@ -5615,9 +5557,6 @@ class Refinement extends BaseType {
|
|
|
5615
5557
|
this._predicate = _predicate;
|
|
5616
5558
|
this._message = _message;
|
|
5617
5559
|
}
|
|
5618
|
-
describe() {
|
|
5619
|
-
return this.name;
|
|
5620
|
-
}
|
|
5621
5560
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5622
5561
|
// create the child type
|
|
5623
5562
|
return this._subtype.instantiate(parent, subpath, environment, initialValue);
|
|
@@ -5749,6 +5688,16 @@ function resolveModelType(type) {
|
|
|
5749
5688
|
}
|
|
5750
5689
|
return undefined;
|
|
5751
5690
|
}
|
|
5691
|
+
// The quick-match paths below already know a type carries TypeFlags.Literal,
|
|
5692
|
+
// but `is()` still routes through BaseType.validate — a context array, an entry
|
|
5693
|
+
// object and a `$treenode` probe per property, per candidate member. A real
|
|
5694
|
+
// `Literal` stores its primitive, and its isValidSnapshot is exactly value
|
|
5695
|
+
// equality against it, so compare directly. The `instanceof` gate is load
|
|
5696
|
+
// bearing: wrappers (optional, refinement, snapshotProcessor, late, union)
|
|
5697
|
+
// inherit the Literal flag from what they wrap and must keep the full check.
|
|
5698
|
+
function matchesLiteral(type, value) {
|
|
5699
|
+
return type instanceof Literal ? type.value === value : type.is(value);
|
|
5700
|
+
}
|
|
5752
5701
|
/**
|
|
5753
5702
|
* @internal
|
|
5754
5703
|
* @hidden
|
|
@@ -5866,10 +5815,10 @@ class Union extends BaseType {
|
|
|
5866
5815
|
if (!model) {
|
|
5867
5816
|
continue;
|
|
5868
5817
|
}
|
|
5869
|
-
const typeProp = model.properties
|
|
5818
|
+
const typeProp = model.properties["type"];
|
|
5870
5819
|
if (!typeProp ||
|
|
5871
5820
|
!(typeProp.flags & TypeFlags.Literal) ||
|
|
5872
|
-
!typeProp
|
|
5821
|
+
!matchesLiteral(typeProp, discriminator)) {
|
|
5873
5822
|
continue;
|
|
5874
5823
|
}
|
|
5875
5824
|
if (found) {
|
|
@@ -5889,7 +5838,7 @@ class Union extends BaseType {
|
|
|
5889
5838
|
this._allMembersDiscriminated = this._types.every(t => {
|
|
5890
5839
|
const model = resolveModelType(t);
|
|
5891
5840
|
const typeProp = model &&
|
|
5892
|
-
model.properties
|
|
5841
|
+
model.properties["type"];
|
|
5893
5842
|
return !!typeProp && (typeProp.flags & TypeFlags.Literal) !== 0;
|
|
5894
5843
|
});
|
|
5895
5844
|
}
|
|
@@ -5963,7 +5912,7 @@ class Union extends BaseType {
|
|
|
5963
5912
|
}
|
|
5964
5913
|
// for literals, check exact value match
|
|
5965
5914
|
if (flags & TypeFlags.Literal) {
|
|
5966
|
-
if (type
|
|
5915
|
+
if (matchesLiteral(type, value)) {
|
|
5967
5916
|
return type;
|
|
5968
5917
|
}
|
|
5969
5918
|
}
|
|
@@ -5995,7 +5944,7 @@ class Union extends BaseType {
|
|
|
5995
5944
|
// for literal types, verify the value matches exactly
|
|
5996
5945
|
// this is critical for discriminated unions
|
|
5997
5946
|
if (flags & TypeFlags.Literal) {
|
|
5998
|
-
if (!propType
|
|
5947
|
+
if (!matchesLiteral(propType, propValue)) {
|
|
5999
5948
|
return false;
|
|
6000
5949
|
}
|
|
6001
5950
|
}
|
|
@@ -6071,6 +6020,22 @@ Object.assign(Union.prototype, {
|
|
|
6071
6020
|
_discriminatorCache: undefined,
|
|
6072
6021
|
_allMembersDiscriminated: undefined
|
|
6073
6022
|
});
|
|
6023
|
+
const unionInternRoot = {};
|
|
6024
|
+
function internUnion(types) {
|
|
6025
|
+
let node = unionInternRoot;
|
|
6026
|
+
for (const type of types) {
|
|
6027
|
+
const level = (node.next ??= new WeakMap());
|
|
6028
|
+
const existing = level.get(type);
|
|
6029
|
+
if (existing) {
|
|
6030
|
+
node = existing;
|
|
6031
|
+
}
|
|
6032
|
+
else {
|
|
6033
|
+
node = {};
|
|
6034
|
+
level.set(type, node);
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
return (node.union ??= new Union(types));
|
|
6038
|
+
}
|
|
6074
6039
|
/**
|
|
6075
6040
|
* `types.union` - Create a union of multiple types. If the correct type cannot be inferred unambiguously from a snapshot, provide a dispatcher function of the form `(snapshot) => Type`.
|
|
6076
6041
|
*
|
|
@@ -6099,7 +6064,7 @@ function union(...args) {
|
|
|
6099
6064
|
assertIsType(type, options ? i + 2 : i + 1);
|
|
6100
6065
|
});
|
|
6101
6066
|
}
|
|
6102
|
-
return new Union(types, options);
|
|
6067
|
+
return options === undefined ? internUnion(types) : new Union(types, options);
|
|
6103
6068
|
}
|
|
6104
6069
|
/**
|
|
6105
6070
|
* Returns if a given value represents a union type.
|
|
@@ -6294,13 +6259,35 @@ const undefinedAsOptionalValues = [undefined];
|
|
|
6294
6259
|
* to compile. Guards with a distinct narrowing target (`isArrayType`,
|
|
6295
6260
|
* `isMapType`, `isModelType`) keep their predicate.
|
|
6296
6261
|
*
|
|
6297
|
-
* @template IT
|
|
6298
6262
|
* @param type
|
|
6299
6263
|
* @returns
|
|
6300
6264
|
*/
|
|
6301
6265
|
function isOptionalType(type) {
|
|
6302
6266
|
return isType(type) && (type.flags & TypeFlags.Optional) > 0;
|
|
6303
6267
|
}
|
|
6268
|
+
function isRecord(value) {
|
|
6269
|
+
return typeof value === "object" && value !== null;
|
|
6270
|
+
}
|
|
6271
|
+
/**
|
|
6272
|
+
* The identifier attribute of the model a stripDefault ultimately wraps, or
|
|
6273
|
+
* `null` when there is none. Drills through the single-subtype wrappers the way
|
|
6274
|
+
* `resolveModelType` in union.ts does — that one is module-private there, and
|
|
6275
|
+
* this file may not reach into it.
|
|
6276
|
+
*
|
|
6277
|
+
* `null` is also the answer for an unresolved `types.late`, which only costs the
|
|
6278
|
+
* short-circuit, never correctness: the full structural walk still runs.
|
|
6279
|
+
*/
|
|
6280
|
+
function resolveIdentifierAttribute(type) {
|
|
6281
|
+
let current = type;
|
|
6282
|
+
for (let depth = 0; current && depth < 20; depth++) {
|
|
6283
|
+
if (current instanceof ModelType) {
|
|
6284
|
+
return current.identifierAttribute ? current.identifierAttribute : null;
|
|
6285
|
+
}
|
|
6286
|
+
const wrapper = current;
|
|
6287
|
+
current = wrapper._subtype ?? wrapper.getSubType?.(false);
|
|
6288
|
+
}
|
|
6289
|
+
return null;
|
|
6290
|
+
}
|
|
6304
6291
|
/**
|
|
6305
6292
|
* Compare a child snapshot to a stripped-default's reference snapshot: identity
|
|
6306
6293
|
* for primitives, structural for objects/arrays.
|
|
@@ -6379,6 +6366,22 @@ function defaultSnapshotEquals(a, b) {
|
|
|
6379
6366
|
* @internal
|
|
6380
6367
|
*/
|
|
6381
6368
|
class StripDefaultValue extends OptionalValue {
|
|
6369
|
+
equalsDefault(snapshot, defaultSnapshot) {
|
|
6370
|
+
let identifierAttribute = this._identifierAttribute;
|
|
6371
|
+
if (identifierAttribute === undefined) {
|
|
6372
|
+
identifierAttribute = resolveIdentifierAttribute(this.getSubTypes());
|
|
6373
|
+
this._identifierAttribute = identifierAttribute;
|
|
6374
|
+
}
|
|
6375
|
+
// an identified model's snapshot normally has the same shape as the default
|
|
6376
|
+
// and differs only here, so answering from one key beats walking every key
|
|
6377
|
+
// (including nested objects) until the walk reaches it
|
|
6378
|
+
return identifierAttribute !== null &&
|
|
6379
|
+
isRecord(snapshot) &&
|
|
6380
|
+
isRecord(defaultSnapshot) &&
|
|
6381
|
+
snapshot[identifierAttribute] !== defaultSnapshot[identifierAttribute]
|
|
6382
|
+
? false
|
|
6383
|
+
: defaultSnapshotEquals(snapshot, defaultSnapshot);
|
|
6384
|
+
}
|
|
6382
6385
|
shouldStripFromSnapshot(snapshot) {
|
|
6383
6386
|
if (!this._defaultSnapshot) {
|
|
6384
6387
|
// instantiate the subtype detached with the default and read the node's
|
|
@@ -6387,11 +6390,35 @@ class StripDefaultValue extends OptionalValue {
|
|
|
6387
6390
|
const node = this.getSubTypes().instantiate(null, "", undefined, this.getDefaultInstanceOrSnapshot());
|
|
6388
6391
|
this._defaultSnapshot = { value: node.snapshot };
|
|
6389
6392
|
}
|
|
6390
|
-
|
|
6393
|
+
const defaultSnapshot = this._defaultSnapshot.value;
|
|
6394
|
+
let result;
|
|
6395
|
+
if (isRecord(snapshot)) {
|
|
6396
|
+
// a child node's snapshot is a keepAlive computed, so a stable reference
|
|
6397
|
+
// means unchanged content: the same object always gets the same answer
|
|
6398
|
+
let cache = this._equalsDefaultCache;
|
|
6399
|
+
if (!cache) {
|
|
6400
|
+
cache = new WeakMap();
|
|
6401
|
+
this._equalsDefaultCache = cache;
|
|
6402
|
+
}
|
|
6403
|
+
const cached = cache.get(snapshot);
|
|
6404
|
+
if (cached === undefined) {
|
|
6405
|
+
result = this.equalsDefault(snapshot, defaultSnapshot);
|
|
6406
|
+
cache.set(snapshot, result);
|
|
6407
|
+
}
|
|
6408
|
+
else {
|
|
6409
|
+
result = cached;
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
else {
|
|
6413
|
+
result = defaultSnapshotEquals(snapshot, defaultSnapshot);
|
|
6414
|
+
}
|
|
6415
|
+
return result;
|
|
6391
6416
|
}
|
|
6392
6417
|
}
|
|
6393
6418
|
Object.assign(StripDefaultValue.prototype, {
|
|
6394
|
-
_defaultSnapshot: undefined
|
|
6419
|
+
_defaultSnapshot: undefined,
|
|
6420
|
+
_identifierAttribute: undefined,
|
|
6421
|
+
_equalsDefaultCache: undefined
|
|
6395
6422
|
});
|
|
6396
6423
|
/**
|
|
6397
6424
|
* Whether `type` is a strip-default optional whose current child `snapshot`
|
|
@@ -6810,9 +6837,6 @@ class BaseReferenceType extends SimpleType {
|
|
|
6810
6837
|
computeName() {
|
|
6811
6838
|
return `reference(${this.targetType.name})`;
|
|
6812
6839
|
}
|
|
6813
|
-
describe() {
|
|
6814
|
-
return this.name;
|
|
6815
|
-
}
|
|
6816
6840
|
isAssignableFrom(type) {
|
|
6817
6841
|
return this.targetType.isAssignableFrom(type);
|
|
6818
6842
|
}
|
|
@@ -7149,9 +7173,6 @@ class IdentifierType extends BaseIdentifierType {
|
|
|
7149
7173
|
constructor() {
|
|
7150
7174
|
super(`identifier`, "string");
|
|
7151
7175
|
}
|
|
7152
|
-
describe() {
|
|
7153
|
-
return `identifier`;
|
|
7154
|
-
}
|
|
7155
7176
|
}
|
|
7156
7177
|
/**
|
|
7157
7178
|
* @internal
|
|
@@ -7161,12 +7182,6 @@ class IdentifierNumberType extends BaseIdentifierType {
|
|
|
7161
7182
|
constructor() {
|
|
7162
7183
|
super("identifierNumber", "number");
|
|
7163
7184
|
}
|
|
7164
|
-
getSnapshot(node) {
|
|
7165
|
-
return node.storedValue;
|
|
7166
|
-
}
|
|
7167
|
-
describe() {
|
|
7168
|
-
return `identifierNumber`;
|
|
7169
|
-
}
|
|
7170
7185
|
}
|
|
7171
7186
|
/**
|
|
7172
7187
|
* `types.identifier` - Identifiers are used to make references, lifecycle events and reconciling works.
|
|
@@ -7297,9 +7312,6 @@ class CustomType extends SimpleType {
|
|
|
7297
7312
|
super(options.name);
|
|
7298
7313
|
this.options = options;
|
|
7299
7314
|
}
|
|
7300
|
-
describe() {
|
|
7301
|
-
return this.name;
|
|
7302
|
-
}
|
|
7303
7315
|
isValidSnapshot(value, context) {
|
|
7304
7316
|
if (this.options.isTargetType(value)) {
|
|
7305
7317
|
return typeCheckSuccess();
|
|
@@ -7508,6 +7520,7 @@ exports.addMiddleware = addMiddleware;
|
|
|
7508
7520
|
exports.applyAction = applyAction;
|
|
7509
7521
|
exports.applyPatch = applyPatch;
|
|
7510
7522
|
exports.applySnapshot = applySnapshot;
|
|
7523
|
+
exports.cannotDetermineSubtype = cannotDetermineSubtype;
|
|
7511
7524
|
exports.cast = cast;
|
|
7512
7525
|
exports.castFlowReturn = castFlowReturn;
|
|
7513
7526
|
exports.castToReferenceSnapshot = castToReferenceSnapshot;
|