objectmodel 4.3.0 → 4.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/.eslintignore +8 -8
- package/.eslintrc.json +25 -25
- package/.travis.yml +2 -2
- package/LICENSE +22 -22
- package/README.md +67 -67
- package/build/{add-banner.cjs → add-banner.js} +13 -13
- package/build/bundle-entry.dev.js +2 -2
- package/build/bundle-entry.js +11 -11
- package/build/{update-docs.cjs → update-docs.js} +7 -5
- package/dist/object-model.cjs +466 -472
- package/dist/object-model.js +466 -472
- package/dist/object-model.js.map +1 -1
- package/dist/object-model.min.js +2 -2
- package/dist/object-model.min.js.map +1 -1
- package/index.html +1603 -1603
- package/package.json +20 -10
- package/rollup.config.js +13 -13
- package/src/array-model.d.ts +16 -0
- package/src/array-model.js +68 -68
- package/src/devtool-formatter.js +198 -198
- package/src/function-model.d.ts +24 -0
- package/src/function-model.js +58 -65
- package/src/helpers.js +43 -43
- package/src/index.js +4 -4
- package/src/list-model.js +43 -43
- package/src/map-model.d.ts +18 -0
- package/src/map-model.js +48 -48
- package/src/object-model.d.ts +74 -0
- package/src/object-model.js +4 -3
- package/src/set-model.d.ts +16 -0
- package/src/set-model.js +41 -41
- package/test/array-model.spec.cjs +291 -291
- package/test/array-model.test-d.ts +24 -0
- package/test/basic-model.spec.cjs +263 -263
- package/test/basic-model.test-d.ts +30 -0
- package/test/bench/array.html +51 -51
- package/test/bench/bench-lib.js +49 -49
- package/test/bench/map-no-cast.html +53 -53
- package/test/bench/map-set.html +52 -52
- package/test/bench/map.html +51 -51
- package/test/bench/object-models.html +87 -87
- package/test/function-model.spec.cjs +161 -162
- package/test/function-model.test-d.ts +18 -0
- package/test/index.cjs +13 -13
- package/test/index.html +27 -27
- package/test/map-model.spec.cjs +224 -224
- package/test/map-model.test-d.ts +21 -0
- package/test/model.spec.cjs +30 -30
- package/test/object-model.spec.cjs +1345 -1327
- package/test/object-model.test-d.ts +53 -0
- package/test/set-model.spec.cjs +213 -213
- package/test/set-model.test-d.ts +17 -0
- package/test/umd.html +25 -25
- package/types/definitions.d.ts +43 -0
- package/types/helpers.d.ts +4 -0
- package/types/index.d.ts +6 -128
- package/test/lib/qunit.css +0 -436
- package/test/lib/qunit.js +0 -6582
- package/tsconfig.json +0 -10
package/dist/object-model.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
// ObjectModel v4.
|
|
1
|
+
// ObjectModel v4.4.0 - http://objectmodel.js.org
|
|
2
2
|
// MIT License - Sylvain Pollet-Villard
|
|
3
|
-
const
|
|
4
|
-
ObjectProto = Object.prototype,
|
|
5
|
-
bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
|
|
6
|
-
getProto = Object.getPrototypeOf,
|
|
7
|
-
setProto = Object.setPrototypeOf,
|
|
8
|
-
|
|
9
|
-
has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
|
|
10
|
-
is = (Constructor, obj) => obj instanceof Constructor,
|
|
11
|
-
isFunction = f => typeof f === "function",
|
|
12
|
-
isObject = o => o && typeof o === "object",
|
|
13
|
-
isString = s => typeof s === "string",
|
|
14
|
-
isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
|
|
15
|
-
isIterable = x => x && isFunction(x[Symbol.iterator]),
|
|
16
|
-
|
|
17
|
-
proxify = (val, traps) => new Proxy(val, traps),
|
|
18
|
-
|
|
19
|
-
merge = (target, src = {}) => {
|
|
20
|
-
for (let key in src) {
|
|
21
|
-
if (isPlainObject(src[key])) {
|
|
22
|
-
const o = {};
|
|
23
|
-
merge(o, target[key]);
|
|
24
|
-
merge(o, src[key]);
|
|
25
|
-
target[key] = o;
|
|
26
|
-
} else {
|
|
27
|
-
target[key] = src[key];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return target
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
define = (obj, key, value, enumerable = false) => {
|
|
34
|
-
Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true });
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
extend = (child, parent, props) => {
|
|
38
|
-
child.prototype = Object.assign(Object.create(parent.prototype, {
|
|
39
|
-
constructor: {
|
|
40
|
-
value: child,
|
|
41
|
-
writable: true,
|
|
42
|
-
configurable: true
|
|
43
|
-
}
|
|
44
|
-
}), props);
|
|
45
|
-
setProto(child, parent);
|
|
3
|
+
const
|
|
4
|
+
ObjectProto = Object.prototype,
|
|
5
|
+
bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
|
|
6
|
+
getProto = Object.getPrototypeOf,
|
|
7
|
+
setProto = Object.setPrototypeOf,
|
|
8
|
+
|
|
9
|
+
has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
|
|
10
|
+
is = (Constructor, obj) => obj instanceof Constructor,
|
|
11
|
+
isFunction = f => typeof f === "function",
|
|
12
|
+
isObject = o => o && typeof o === "object",
|
|
13
|
+
isString = s => typeof s === "string",
|
|
14
|
+
isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
|
|
15
|
+
isIterable = x => x && isFunction(x[Symbol.iterator]),
|
|
16
|
+
|
|
17
|
+
proxify = (val, traps) => new Proxy(val, traps),
|
|
18
|
+
|
|
19
|
+
merge = (target, src = {}) => {
|
|
20
|
+
for (let key in src) {
|
|
21
|
+
if (isPlainObject(src[key])) {
|
|
22
|
+
const o = {};
|
|
23
|
+
merge(o, target[key]);
|
|
24
|
+
merge(o, src[key]);
|
|
25
|
+
target[key] = o;
|
|
26
|
+
} else {
|
|
27
|
+
target[key] = src[key];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return target
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
define = (obj, key, value, enumerable = false) => {
|
|
34
|
+
Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true });
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
extend = (child, parent, props) => {
|
|
38
|
+
child.prototype = Object.assign(Object.create(parent.prototype, {
|
|
39
|
+
constructor: {
|
|
40
|
+
value: child,
|
|
41
|
+
writable: true,
|
|
42
|
+
configurable: true
|
|
43
|
+
}
|
|
44
|
+
}), props);
|
|
45
|
+
setProto(child, parent);
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const
|
|
@@ -74,7 +74,8 @@ const
|
|
|
74
74
|
if (is(model, obj)) return obj
|
|
75
75
|
|
|
76
76
|
if (!isObject(obj) && !isFunction(obj) && obj !== undefined) {
|
|
77
|
-
|
|
77
|
+
// short circuit validation if not receiving an object as expected
|
|
78
|
+
return obj
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
merge(_this, model.default);
|
|
@@ -366,8 +367,8 @@ const
|
|
|
366
367
|
};
|
|
367
368
|
|
|
368
369
|
|
|
369
|
-
function Model(def
|
|
370
|
-
return isPlainObject(def) ? new ObjectModel(def
|
|
370
|
+
function Model(def) {
|
|
371
|
+
return isPlainObject(def) ? new ObjectModel(def) : new BasicModel(def)
|
|
371
372
|
}
|
|
372
373
|
|
|
373
374
|
Object.assign(Model.prototype, {
|
|
@@ -519,441 +520,434 @@ extend(Any.remaining, Any, {
|
|
|
519
520
|
});
|
|
520
521
|
Any[Symbol.iterator] = function* () { yield new Any.remaining(this.definition); };
|
|
521
522
|
|
|
522
|
-
const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
|
|
523
|
-
|
|
524
|
-
return initModel(def, constructor, base, init, model => Object.assign({
|
|
525
|
-
getPrototypeOf: () => model.prototype,
|
|
526
|
-
get(l, key) {
|
|
527
|
-
if (key === _original) return l
|
|
528
|
-
|
|
529
|
-
const val = l[key];
|
|
530
|
-
return isFunction(val) ? proxify(val, {
|
|
531
|
-
apply(fn, ctx, args) {
|
|
532
|
-
if (has(mutators, key)) {
|
|
533
|
-
// indexes of arguments to check def + cast
|
|
534
|
-
const [begin, end = args.length - 1, getArgDef] = mutators[key];
|
|
535
|
-
for (let i = begin; i <= end; i++) {
|
|
536
|
-
const argDef = getArgDef ? getArgDef(i) : model.definition;
|
|
537
|
-
args[i] = checkDefinition(
|
|
538
|
-
args[i],
|
|
539
|
-
argDef,
|
|
540
|
-
`${base.name}.${key} arguments[${i}]`,
|
|
541
|
-
model.errors,
|
|
542
|
-
[],
|
|
543
|
-
true
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
if (model.assertions.length > 0) {
|
|
548
|
-
const testingClone = clone(l);
|
|
549
|
-
fn.apply(testingClone, args);
|
|
550
|
-
checkAssertions(testingClone, model, `after ${key} mutation`);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
unstackErrors(model);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
return fn.apply(l, args)
|
|
557
|
-
}
|
|
558
|
-
}) : val
|
|
559
|
-
}
|
|
560
|
-
}, otherTraps))
|
|
523
|
+
const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
|
|
524
|
+
|
|
525
|
+
return initModel(def, constructor, base, init, model => Object.assign({
|
|
526
|
+
getPrototypeOf: () => model.prototype,
|
|
527
|
+
get(l, key) {
|
|
528
|
+
if (key === _original) return l
|
|
529
|
+
|
|
530
|
+
const val = l[key];
|
|
531
|
+
return isFunction(val) ? proxify(val, {
|
|
532
|
+
apply(fn, ctx, args) {
|
|
533
|
+
if (has(mutators, key)) {
|
|
534
|
+
// indexes of arguments to check def + cast
|
|
535
|
+
const [begin, end = args.length - 1, getArgDef] = mutators[key];
|
|
536
|
+
for (let i = begin; i <= end; i++) {
|
|
537
|
+
const argDef = getArgDef ? getArgDef(i) : model.definition;
|
|
538
|
+
args[i] = checkDefinition(
|
|
539
|
+
args[i],
|
|
540
|
+
argDef,
|
|
541
|
+
`${base.name}.${key} arguments[${i}]`,
|
|
542
|
+
model.errors,
|
|
543
|
+
[],
|
|
544
|
+
true
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (model.assertions.length > 0) {
|
|
549
|
+
const testingClone = clone(l);
|
|
550
|
+
fn.apply(testingClone, args);
|
|
551
|
+
checkAssertions(testingClone, model, `after ${key} mutation`);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
unstackErrors(model);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return fn.apply(l, args)
|
|
558
|
+
}
|
|
559
|
+
}) : val
|
|
560
|
+
}
|
|
561
|
+
}, otherTraps))
|
|
561
562
|
};
|
|
562
563
|
|
|
563
|
-
function ArrayModel(initialDefinition) {
|
|
564
|
-
const model = initListModel(
|
|
565
|
-
Array,
|
|
566
|
-
ArrayModel,
|
|
567
|
-
initialDefinition,
|
|
568
|
-
a => Array.isArray(a) ? a.map(arg => cast(arg, model.definition)) : a,
|
|
569
|
-
a => [...a],
|
|
570
|
-
{
|
|
571
|
-
"copyWithin": [],
|
|
572
|
-
"fill": [0, 0],
|
|
573
|
-
"pop": [],
|
|
574
|
-
"push": [0],
|
|
575
|
-
"reverse": [],
|
|
576
|
-
"shift": [],
|
|
577
|
-
"sort": [],
|
|
578
|
-
"splice": [2],
|
|
579
|
-
"unshift": [0]
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
set(arr, key, val) {
|
|
583
|
-
return controlMutation(model, arr, key, val, (a, v) => a[key] = v, true)
|
|
584
|
-
},
|
|
585
|
-
|
|
586
|
-
deleteProperty(arr, key) {
|
|
587
|
-
return controlMutation(model, arr, key, undefined, a => delete a[key])
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
);
|
|
591
|
-
|
|
592
|
-
return model
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
extend(ArrayModel, Model, {
|
|
596
|
-
toString(stack) {
|
|
597
|
-
return "Array of " + formatDefinition(this.definition, stack)
|
|
598
|
-
},
|
|
599
|
-
|
|
600
|
-
[_check](arr, path, errors, stack) {
|
|
601
|
-
if (Array.isArray(arr))
|
|
602
|
-
(arr[_original] || arr).forEach((a, i) => checkDefinition(a, this.definition, `${path || "Array"}[${i}]`, errors, stack));
|
|
603
|
-
else stackError(errors, this, arr, path);
|
|
604
|
-
|
|
605
|
-
checkAssertions(arr, this, path, errors);
|
|
606
|
-
},
|
|
607
|
-
|
|
608
|
-
extend(...newParts) {
|
|
609
|
-
return extendModel(new ArrayModel(extendDefinition(this.definition, newParts)), this)
|
|
610
|
-
}
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
const controlMutation = (model, array, key, value, applyMutation, canBeExtended) => {
|
|
614
|
-
const path = `Array[${key}]`;
|
|
615
|
-
const isInDef = (+key >= 0 && (canBeExtended || key in array));
|
|
616
|
-
if (isInDef) value = checkDefinition(value, model.definition, path, model.errors, [], true);
|
|
617
|
-
|
|
618
|
-
const testArray = [...array];
|
|
619
|
-
applyMutation(testArray);
|
|
620
|
-
checkAssertions(testArray, model, path);
|
|
621
|
-
const isSuccess = !unstackErrors(model);
|
|
622
|
-
if (isSuccess) applyMutation(array, value);
|
|
623
|
-
return isSuccess
|
|
564
|
+
function ArrayModel(initialDefinition) {
|
|
565
|
+
const model = initListModel(
|
|
566
|
+
Array,
|
|
567
|
+
ArrayModel,
|
|
568
|
+
initialDefinition,
|
|
569
|
+
a => Array.isArray(a) ? a.map(arg => cast(arg, model.definition)) : a,
|
|
570
|
+
a => [...a],
|
|
571
|
+
{
|
|
572
|
+
"copyWithin": [],
|
|
573
|
+
"fill": [0, 0],
|
|
574
|
+
"pop": [],
|
|
575
|
+
"push": [0],
|
|
576
|
+
"reverse": [],
|
|
577
|
+
"shift": [],
|
|
578
|
+
"sort": [],
|
|
579
|
+
"splice": [2],
|
|
580
|
+
"unshift": [0]
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
set(arr, key, val) {
|
|
584
|
+
return controlMutation(model, arr, key, val, (a, v) => a[key] = v, true)
|
|
585
|
+
},
|
|
586
|
+
|
|
587
|
+
deleteProperty(arr, key) {
|
|
588
|
+
return controlMutation(model, arr, key, undefined, a => delete a[key])
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
|
|
593
|
+
return model
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
extend(ArrayModel, Model, {
|
|
597
|
+
toString(stack) {
|
|
598
|
+
return "Array of " + formatDefinition(this.definition, stack)
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
[_check](arr, path, errors, stack) {
|
|
602
|
+
if (Array.isArray(arr))
|
|
603
|
+
(arr[_original] || arr).forEach((a, i) => checkDefinition(a, this.definition, `${path || "Array"}[${i}]`, errors, stack));
|
|
604
|
+
else stackError(errors, this, arr, path);
|
|
605
|
+
|
|
606
|
+
checkAssertions(arr, this, path, errors);
|
|
607
|
+
},
|
|
608
|
+
|
|
609
|
+
extend(...newParts) {
|
|
610
|
+
return extendModel(new ArrayModel(extendDefinition(this.definition, newParts)), this)
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
const controlMutation = (model, array, key, value, applyMutation, canBeExtended) => {
|
|
615
|
+
const path = `Array[${key}]`;
|
|
616
|
+
const isInDef = (+key >= 0 && (canBeExtended || key in array));
|
|
617
|
+
if (isInDef) value = checkDefinition(value, model.definition, path, model.errors, [], true);
|
|
618
|
+
|
|
619
|
+
const testArray = [...array];
|
|
620
|
+
applyMutation(testArray);
|
|
621
|
+
checkAssertions(testArray, model, path);
|
|
622
|
+
const isSuccess = !unstackErrors(model);
|
|
623
|
+
if (isSuccess) applyMutation(array, value);
|
|
624
|
+
return isSuccess
|
|
624
625
|
};
|
|
625
626
|
|
|
626
|
-
function SetModel(initialDefinition) {
|
|
627
|
-
const model = initListModel(
|
|
628
|
-
Set,
|
|
629
|
-
SetModel,
|
|
630
|
-
initialDefinition,
|
|
631
|
-
it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
|
|
632
|
-
set => new Set(set),
|
|
633
|
-
{
|
|
634
|
-
"add": [0, 0],
|
|
635
|
-
"delete": [],
|
|
636
|
-
"clear": []
|
|
637
|
-
}
|
|
638
|
-
);
|
|
639
|
-
|
|
640
|
-
return model
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
extend(SetModel, Model, {
|
|
644
|
-
toString(stack) {
|
|
645
|
-
return "Set of " + formatDefinition(this.definition, stack)
|
|
646
|
-
},
|
|
647
|
-
|
|
648
|
-
[_check](set, path, errors, stack) {
|
|
649
|
-
if (is(Set, set)) {
|
|
650
|
-
for (let item of set.values()) {
|
|
651
|
-
checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack);
|
|
652
|
-
}
|
|
653
|
-
} else stackError(errors, this, set, path);
|
|
654
|
-
checkAssertions(set, this, path, errors);
|
|
655
|
-
},
|
|
656
|
-
|
|
657
|
-
extend(...newParts) {
|
|
658
|
-
return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
|
|
659
|
-
}
|
|
627
|
+
function SetModel(initialDefinition) {
|
|
628
|
+
const model = initListModel(
|
|
629
|
+
Set,
|
|
630
|
+
SetModel,
|
|
631
|
+
initialDefinition,
|
|
632
|
+
it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
|
|
633
|
+
set => new Set(set),
|
|
634
|
+
{
|
|
635
|
+
"add": [0, 0],
|
|
636
|
+
"delete": [],
|
|
637
|
+
"clear": []
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
return model
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
extend(SetModel, Model, {
|
|
645
|
+
toString(stack) {
|
|
646
|
+
return "Set of " + formatDefinition(this.definition, stack)
|
|
647
|
+
},
|
|
648
|
+
|
|
649
|
+
[_check](set, path, errors, stack) {
|
|
650
|
+
if (is(Set, set)) {
|
|
651
|
+
for (let item of set.values()) {
|
|
652
|
+
checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack);
|
|
653
|
+
}
|
|
654
|
+
} else stackError(errors, this, set, path);
|
|
655
|
+
checkAssertions(set, this, path, errors);
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
extend(...newParts) {
|
|
659
|
+
return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
|
|
660
|
+
}
|
|
660
661
|
});
|
|
661
662
|
|
|
662
|
-
function MapModel(initialKeyDefinition, initialValueDefinition) {
|
|
663
|
-
const getDef = i => i === 0 ? model.definition.key : model.definition.value;
|
|
664
|
-
const model = initListModel(
|
|
665
|
-
Map,
|
|
666
|
-
MapModel,
|
|
667
|
-
{ key: initialKeyDefinition, value: initialValueDefinition },
|
|
668
|
-
it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
|
|
669
|
-
map => new Map(map),
|
|
670
|
-
{
|
|
671
|
-
"set": [0, 1, getDef],
|
|
672
|
-
"delete": [],
|
|
673
|
-
"clear": []
|
|
674
|
-
}
|
|
675
|
-
);
|
|
676
|
-
|
|
677
|
-
return model
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
extend(MapModel, Model, {
|
|
681
|
-
toString(stack) {
|
|
682
|
-
return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
|
|
683
|
-
},
|
|
684
|
-
|
|
685
|
-
[_check](map, path, errors, stack) {
|
|
686
|
-
if (is(Map, map)) {
|
|
687
|
-
path = path || "Map";
|
|
688
|
-
for (let [key, value] of map) {
|
|
689
|
-
checkDefinition(key, this.definition.key, `${path} key`, errors, stack);
|
|
690
|
-
checkDefinition(value, this.definition.value, `${path}[${format$1(key)}]`, errors, stack);
|
|
691
|
-
}
|
|
692
|
-
} else stackError(errors, this, map, path);
|
|
693
|
-
|
|
694
|
-
checkAssertions(map, this, path, errors);
|
|
695
|
-
},
|
|
696
|
-
|
|
697
|
-
extend(keyParts, valueParts) {
|
|
698
|
-
return extendModel(new MapModel(
|
|
699
|
-
extendDefinition(this.definition.key, keyParts),
|
|
700
|
-
extendDefinition(this.definition.value, valueParts)
|
|
701
|
-
), this)
|
|
702
|
-
}
|
|
663
|
+
function MapModel(initialKeyDefinition, initialValueDefinition) {
|
|
664
|
+
const getDef = i => i === 0 ? model.definition.key : model.definition.value;
|
|
665
|
+
const model = initListModel(
|
|
666
|
+
Map,
|
|
667
|
+
MapModel,
|
|
668
|
+
{ key: initialKeyDefinition, value: initialValueDefinition },
|
|
669
|
+
it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
|
|
670
|
+
map => new Map(map),
|
|
671
|
+
{
|
|
672
|
+
"set": [0, 1, getDef],
|
|
673
|
+
"delete": [],
|
|
674
|
+
"clear": []
|
|
675
|
+
}
|
|
676
|
+
);
|
|
677
|
+
|
|
678
|
+
return model
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
extend(MapModel, Model, {
|
|
682
|
+
toString(stack) {
|
|
683
|
+
return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
|
|
684
|
+
},
|
|
685
|
+
|
|
686
|
+
[_check](map, path, errors, stack) {
|
|
687
|
+
if (is(Map, map)) {
|
|
688
|
+
path = path || "Map";
|
|
689
|
+
for (let [key, value] of map) {
|
|
690
|
+
checkDefinition(key, this.definition.key, `${path} key`, errors, stack);
|
|
691
|
+
checkDefinition(value, this.definition.value, `${path}[${format$1(key)}]`, errors, stack);
|
|
692
|
+
}
|
|
693
|
+
} else stackError(errors, this, map, path);
|
|
694
|
+
|
|
695
|
+
checkAssertions(map, this, path, errors);
|
|
696
|
+
},
|
|
697
|
+
|
|
698
|
+
extend(keyParts, valueParts) {
|
|
699
|
+
return extendModel(new MapModel(
|
|
700
|
+
extendDefinition(this.definition.key, keyParts),
|
|
701
|
+
extendDefinition(this.definition.value, valueParts)
|
|
702
|
+
), this)
|
|
703
|
+
}
|
|
703
704
|
});
|
|
704
705
|
|
|
705
|
-
function FunctionModel(...argsDef) {
|
|
706
|
-
return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
|
|
707
|
-
getPrototypeOf: () => model.prototype,
|
|
708
|
-
|
|
709
|
-
get(fn, key) {
|
|
710
|
-
return key === _original ? fn : fn[key]
|
|
711
|
-
},
|
|
712
|
-
|
|
713
|
-
apply(fn, ctx, args) {
|
|
714
|
-
const def = model.definition;
|
|
715
|
-
const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef));
|
|
716
|
-
const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length;
|
|
717
|
-
|
|
718
|
-
for (let i = 0; i < nbArgsToCheck; i++) {
|
|
719
|
-
const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i];
|
|
720
|
-
args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
checkAssertions(args, model, "arguments");
|
|
724
|
-
|
|
725
|
-
let result;
|
|
726
|
-
if (!model.errors.length) {
|
|
727
|
-
result = Reflect.apply(fn, ctx, args);
|
|
728
|
-
if ("return" in def)
|
|
729
|
-
result = checkDefinition(result, def.return, "return value", model.errors, [], true);
|
|
730
|
-
}
|
|
731
|
-
unstackErrors(model);
|
|
732
|
-
return result
|
|
733
|
-
}
|
|
734
|
-
}))
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
extend(FunctionModel, Model, {
|
|
738
|
-
toString(stack = []) {
|
|
739
|
-
let out = `Function(${this.definition.arguments.map(
|
|
740
|
-
argDef => formatDefinition(argDef, [...stack])
|
|
741
|
-
).join(", ")})`;
|
|
742
|
-
|
|
743
|
-
if ("return" in this.definition) {
|
|
744
|
-
out += " => " + formatDefinition(this.definition.return, stack);
|
|
745
|
-
}
|
|
746
|
-
return out
|
|
747
|
-
},
|
|
748
|
-
|
|
749
|
-
return(def) {
|
|
750
|
-
this.definition.return = def;
|
|
751
|
-
return this
|
|
752
|
-
},
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
mixedReturns = extendDefinition(this.definition.return, newReturns);
|
|
758
|
-
return extendModel(new FunctionModel(...mixedArgs).return(mixedReturns), this)
|
|
759
|
-
},
|
|
760
|
-
|
|
761
|
-
[_check](f, path, errors) {
|
|
762
|
-
if (!isFunction(f)) stackError(errors, "Function", f, path);
|
|
763
|
-
}
|
|
706
|
+
function FunctionModel(...argsDef) {
|
|
707
|
+
return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
|
|
708
|
+
getPrototypeOf: () => model.prototype,
|
|
709
|
+
|
|
710
|
+
get(fn, key) {
|
|
711
|
+
return key === _original ? fn : fn[key]
|
|
712
|
+
},
|
|
713
|
+
|
|
714
|
+
apply(fn, ctx, args) {
|
|
715
|
+
const def = model.definition;
|
|
716
|
+
const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef));
|
|
717
|
+
const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length;
|
|
718
|
+
|
|
719
|
+
for (let i = 0; i < nbArgsToCheck; i++) {
|
|
720
|
+
const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i];
|
|
721
|
+
args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
checkAssertions(args, model, "arguments");
|
|
725
|
+
|
|
726
|
+
let result;
|
|
727
|
+
if (!model.errors.length) {
|
|
728
|
+
result = Reflect.apply(fn, ctx, args);
|
|
729
|
+
if ("return" in def)
|
|
730
|
+
result = checkDefinition(result, def.return, "return value", model.errors, [], true);
|
|
731
|
+
}
|
|
732
|
+
unstackErrors(model);
|
|
733
|
+
return result
|
|
734
|
+
}
|
|
735
|
+
}))
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
extend(FunctionModel, Model, {
|
|
739
|
+
toString(stack = []) {
|
|
740
|
+
let out = `Function(${this.definition.arguments.map(
|
|
741
|
+
argDef => formatDefinition(argDef, [...stack])
|
|
742
|
+
).join(", ")})`;
|
|
743
|
+
|
|
744
|
+
if ("return" in this.definition) {
|
|
745
|
+
out += " => " + formatDefinition(this.definition.return, stack);
|
|
746
|
+
}
|
|
747
|
+
return out
|
|
748
|
+
},
|
|
749
|
+
|
|
750
|
+
return(def) {
|
|
751
|
+
this.definition.return = def;
|
|
752
|
+
return this
|
|
753
|
+
},
|
|
754
|
+
|
|
755
|
+
[_check](f, path, errors) {
|
|
756
|
+
if (!isFunction(f)) stackError(errors, "Function", f, path);
|
|
757
|
+
}
|
|
764
758
|
});
|
|
765
759
|
|
|
766
|
-
const styles = {
|
|
767
|
-
list: "list-style-type: none; padding: 0; margin: 0;",
|
|
768
|
-
listItem: "padding: 0 0 0 1em;",
|
|
769
|
-
model: "color: #3e999f;",
|
|
770
|
-
instance: "color: #718c00; font-style: italic",
|
|
771
|
-
function: "color: #4271AE",
|
|
772
|
-
string: "color: #C41A16",
|
|
773
|
-
number: "color: #1C00CF",
|
|
774
|
-
boolean: "color: #AA0D91",
|
|
775
|
-
property: "color: #8959a8",
|
|
776
|
-
private: "color: #C19ED8",
|
|
777
|
-
constant: "color: #8959a8; font-weight: bold",
|
|
778
|
-
privateConstant: "color: #C19ED8; font-weight: bold",
|
|
779
|
-
null: "color: #8e908c",
|
|
780
|
-
undeclared: "color: #C0C0C0;",
|
|
781
|
-
proto: "color: #B871BD; font-style: italic"
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
const getModel = (instance) => {
|
|
785
|
-
if (instance === undefined || instance === null)
|
|
786
|
-
return null
|
|
787
|
-
|
|
788
|
-
const proto = getProto(instance);
|
|
789
|
-
if (!proto || !proto.constructor || !is(Model, proto.constructor))
|
|
790
|
-
return null
|
|
791
|
-
|
|
792
|
-
return proto.constructor
|
|
793
|
-
};
|
|
794
|
-
|
|
795
|
-
const span = (style, ...children) => ["span", { style }, ...children];
|
|
796
|
-
|
|
797
|
-
const format = (x, config = {}) => {
|
|
798
|
-
if (x === null || x === undefined)
|
|
799
|
-
return span(styles.null, "" + x);
|
|
800
|
-
|
|
801
|
-
if (typeof x === "boolean")
|
|
802
|
-
return span(styles.boolean, x);
|
|
803
|
-
|
|
804
|
-
if (typeof x === "number")
|
|
805
|
-
return span(styles.number, x);
|
|
806
|
-
|
|
807
|
-
if (typeof x === "string")
|
|
808
|
-
return span(styles.string, `"${x}"`);
|
|
809
|
-
|
|
810
|
-
if (Array.isArray(x) && config.isModelDefinition) {
|
|
811
|
-
return span("", ...x.flatMap(part => [format(part, config), " or "]).slice(0, -1))
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
if (isPlainObject(x))
|
|
815
|
-
return formatObject(x, getModel(x), config)
|
|
816
|
-
|
|
817
|
-
if (isFunction(x) && !is(Model, x) && config.isModelDefinition)
|
|
818
|
-
return span(styles.function, x.name || x.toString());
|
|
819
|
-
|
|
820
|
-
return ["object", { object: x, config }]
|
|
821
|
-
};
|
|
822
|
-
|
|
823
|
-
const formatObject = (o, model, config) => span("",
|
|
824
|
-
"{",
|
|
825
|
-
["ol", { style: styles.list }, ...Object.keys(o).map(prop =>
|
|
826
|
-
["li", { style: styles.listItem }, span(styles.property, prop), ": ", format(o[prop], config)])
|
|
827
|
-
],
|
|
828
|
-
"}"
|
|
829
|
-
);
|
|
830
|
-
|
|
831
|
-
const formatModel = model => {
|
|
832
|
-
const
|
|
833
|
-
cfg = { isModelDefinition: true },
|
|
834
|
-
def = model.definition,
|
|
835
|
-
formatList = (list, map) => list.flatMap(e => [map(e), ", "]).slice(0, -1);
|
|
836
|
-
let parts = [];
|
|
837
|
-
|
|
838
|
-
if (is(BasicModel, model)) parts = [format(def, cfg)];
|
|
839
|
-
if (is(ArrayModel, model)) parts = ["Array of ", format(def, cfg)];
|
|
840
|
-
if (is(SetModel, model)) parts = ["Set of ", format(def, cfg)];
|
|
841
|
-
if (is(MapModel, model)) parts = ["Map of ", format(def.key, cfg), " : ", format(def.value, cfg)];
|
|
842
|
-
if (is(FunctionModel, model)) {
|
|
843
|
-
parts = ["Function(", ...formatList(def.arguments, arg => format(arg, cfg)), ")"];
|
|
844
|
-
if ("return" in def) parts.push(" => ", format(def.return, cfg));
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
if (model.assertions.length > 0) {
|
|
848
|
-
parts.push("\n(assertions: ", ...formatList(model.assertions, f => ["object", { object: f }]), ")");
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
return span(styles.model, ...parts)
|
|
852
|
-
};
|
|
853
|
-
|
|
854
|
-
const ModelFormatter = {
|
|
855
|
-
header(x, config = {}) {
|
|
856
|
-
if (x === Any)
|
|
857
|
-
return span(styles.model, "Any")
|
|
858
|
-
|
|
859
|
-
if (is(Any.remaining, x))
|
|
860
|
-
return span(styles.model, "...", format(x.definition, { isModelDefinition: true }))
|
|
861
|
-
|
|
862
|
-
if (is(ObjectModel, x))
|
|
863
|
-
return span(styles.model, x.name)
|
|
864
|
-
|
|
865
|
-
if (is(Model, x)) {
|
|
866
|
-
return formatModel(x)
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
if (config.isModelDefinition && isPlainObject(x))
|
|
870
|
-
return format(x, config)
|
|
871
|
-
|
|
872
|
-
return null;
|
|
873
|
-
},
|
|
874
|
-
hasBody(x) {
|
|
875
|
-
return is(ObjectModel, x)
|
|
876
|
-
},
|
|
877
|
-
body(model) {
|
|
878
|
-
return span("",
|
|
879
|
-
"{",
|
|
880
|
-
["ol", { style: styles.list }, ...Object.keys(model.definition).map(prop => {
|
|
881
|
-
const isPrivate = model.conventionForPrivate(prop);
|
|
882
|
-
const isConstant = model.conventionForConstant(prop);
|
|
883
|
-
const hasDefault = model.default && has(model.default, prop);
|
|
884
|
-
let style = styles.property;
|
|
885
|
-
|
|
886
|
-
if (isPrivate) {
|
|
887
|
-
style = isConstant ? styles.privateConstant : styles.private;
|
|
888
|
-
} else if (isConstant) {
|
|
889
|
-
style = styles.constant;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
return ["li", { style: styles.listItem },
|
|
893
|
-
span(style, prop), ": ", format(model.definition[prop], { isModelDefinition: true }),
|
|
894
|
-
hasDefault ? span(styles.proto, " = ", format(model.default[prop])) : ""
|
|
895
|
-
]
|
|
896
|
-
})],
|
|
897
|
-
"}"
|
|
898
|
-
)
|
|
899
|
-
}
|
|
900
|
-
};
|
|
901
|
-
|
|
902
|
-
const ModelInstanceFormatter = {
|
|
903
|
-
header(x, config = {}) {
|
|
904
|
-
if (config.isInstanceProperty && isPlainObject(x)) {
|
|
905
|
-
return format(x, config)
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
const model = getModel(x);
|
|
909
|
-
if (is(Model, model)) {
|
|
910
|
-
const parts = is(ObjectModel, model) ? [model.name] : [["object", { object: x[_original] }], ` (${model.name})`];
|
|
911
|
-
return span(styles.instance, ...parts)
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
return null;
|
|
915
|
-
},
|
|
916
|
-
hasBody(x) {
|
|
917
|
-
return x && is(ObjectModel, getModel(x))
|
|
918
|
-
},
|
|
919
|
-
body(x) {
|
|
920
|
-
const model = getModel(x);
|
|
921
|
-
const o = x[_original] || x;
|
|
922
|
-
return span("",
|
|
923
|
-
"{",
|
|
924
|
-
[
|
|
925
|
-
"ol",
|
|
926
|
-
{ style: styles.list },
|
|
927
|
-
...Object.keys(o).map(prop => {
|
|
928
|
-
const isPrivate = model.conventionForPrivate(prop);
|
|
929
|
-
const isConstant = model.conventionForConstant(prop);
|
|
930
|
-
const isDeclared = prop in model.definition;
|
|
931
|
-
let style = styles.property;
|
|
932
|
-
|
|
933
|
-
if (!isDeclared) {
|
|
934
|
-
style = styles.undeclared;
|
|
935
|
-
} else if (isPrivate) {
|
|
936
|
-
style = isConstant ? styles.privateConstant : styles.private;
|
|
937
|
-
} else if (isConstant) {
|
|
938
|
-
style = styles.constant;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
return ["li", { style: styles.listItem },
|
|
942
|
-
span(style, prop), ": ", format(o[prop], { isInstanceProperty: true })
|
|
943
|
-
]
|
|
944
|
-
}),
|
|
945
|
-
["li", { style: styles.listItem },
|
|
946
|
-
span(styles.proto, "__proto__", ": ", ["object", { object: getProto(x) }])
|
|
947
|
-
]
|
|
948
|
-
],
|
|
949
|
-
"}"
|
|
950
|
-
)
|
|
951
|
-
}
|
|
952
|
-
};
|
|
953
|
-
|
|
954
|
-
if (typeof window !== "undefined") {
|
|
955
|
-
window.devtoolsFormatters = (window.devtoolsFormatters || [])
|
|
956
|
-
.concat(ModelFormatter, ModelInstanceFormatter);
|
|
760
|
+
const styles = {
|
|
761
|
+
list: "list-style-type: none; padding: 0; margin: 0;",
|
|
762
|
+
listItem: "padding: 0 0 0 1em;",
|
|
763
|
+
model: "color: #3e999f;",
|
|
764
|
+
instance: "color: #718c00; font-style: italic",
|
|
765
|
+
function: "color: #4271AE",
|
|
766
|
+
string: "color: #C41A16",
|
|
767
|
+
number: "color: #1C00CF",
|
|
768
|
+
boolean: "color: #AA0D91",
|
|
769
|
+
property: "color: #8959a8",
|
|
770
|
+
private: "color: #C19ED8",
|
|
771
|
+
constant: "color: #8959a8; font-weight: bold",
|
|
772
|
+
privateConstant: "color: #C19ED8; font-weight: bold",
|
|
773
|
+
null: "color: #8e908c",
|
|
774
|
+
undeclared: "color: #C0C0C0;",
|
|
775
|
+
proto: "color: #B871BD; font-style: italic"
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
const getModel = (instance) => {
|
|
779
|
+
if (instance === undefined || instance === null)
|
|
780
|
+
return null
|
|
781
|
+
|
|
782
|
+
const proto = getProto(instance);
|
|
783
|
+
if (!proto || !proto.constructor || !is(Model, proto.constructor))
|
|
784
|
+
return null
|
|
785
|
+
|
|
786
|
+
return proto.constructor
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
const span = (style, ...children) => ["span", { style }, ...children];
|
|
790
|
+
|
|
791
|
+
const format = (x, config = {}) => {
|
|
792
|
+
if (x === null || x === undefined)
|
|
793
|
+
return span(styles.null, "" + x);
|
|
794
|
+
|
|
795
|
+
if (typeof x === "boolean")
|
|
796
|
+
return span(styles.boolean, x);
|
|
797
|
+
|
|
798
|
+
if (typeof x === "number")
|
|
799
|
+
return span(styles.number, x);
|
|
800
|
+
|
|
801
|
+
if (typeof x === "string")
|
|
802
|
+
return span(styles.string, `"${x}"`);
|
|
803
|
+
|
|
804
|
+
if (Array.isArray(x) && config.isModelDefinition) {
|
|
805
|
+
return span("", ...x.flatMap(part => [format(part, config), " or "]).slice(0, -1))
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (isPlainObject(x))
|
|
809
|
+
return formatObject(x, getModel(x), config)
|
|
810
|
+
|
|
811
|
+
if (isFunction(x) && !is(Model, x) && config.isModelDefinition)
|
|
812
|
+
return span(styles.function, x.name || x.toString());
|
|
813
|
+
|
|
814
|
+
return ["object", { object: x, config }]
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
const formatObject = (o, model, config) => span("",
|
|
818
|
+
"{",
|
|
819
|
+
["ol", { style: styles.list }, ...Object.keys(o).map(prop =>
|
|
820
|
+
["li", { style: styles.listItem }, span(styles.property, prop), ": ", format(o[prop], config)])
|
|
821
|
+
],
|
|
822
|
+
"}"
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
const formatModel = model => {
|
|
826
|
+
const
|
|
827
|
+
cfg = { isModelDefinition: true },
|
|
828
|
+
def = model.definition,
|
|
829
|
+
formatList = (list, map) => list.flatMap(e => [map(e), ", "]).slice(0, -1);
|
|
830
|
+
let parts = [];
|
|
831
|
+
|
|
832
|
+
if (is(BasicModel, model)) parts = [format(def, cfg)];
|
|
833
|
+
if (is(ArrayModel, model)) parts = ["Array of ", format(def, cfg)];
|
|
834
|
+
if (is(SetModel, model)) parts = ["Set of ", format(def, cfg)];
|
|
835
|
+
if (is(MapModel, model)) parts = ["Map of ", format(def.key, cfg), " : ", format(def.value, cfg)];
|
|
836
|
+
if (is(FunctionModel, model)) {
|
|
837
|
+
parts = ["Function(", ...formatList(def.arguments, arg => format(arg, cfg)), ")"];
|
|
838
|
+
if ("return" in def) parts.push(" => ", format(def.return, cfg));
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (model.assertions.length > 0) {
|
|
842
|
+
parts.push("\n(assertions: ", ...formatList(model.assertions, f => ["object", { object: f }]), ")");
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return span(styles.model, ...parts)
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
const ModelFormatter = {
|
|
849
|
+
header(x, config = {}) {
|
|
850
|
+
if (x === Any)
|
|
851
|
+
return span(styles.model, "Any")
|
|
852
|
+
|
|
853
|
+
if (is(Any.remaining, x))
|
|
854
|
+
return span(styles.model, "...", format(x.definition, { isModelDefinition: true }))
|
|
855
|
+
|
|
856
|
+
if (is(ObjectModel, x))
|
|
857
|
+
return span(styles.model, x.name)
|
|
858
|
+
|
|
859
|
+
if (is(Model, x)) {
|
|
860
|
+
return formatModel(x)
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
if (config.isModelDefinition && isPlainObject(x))
|
|
864
|
+
return format(x, config)
|
|
865
|
+
|
|
866
|
+
return null;
|
|
867
|
+
},
|
|
868
|
+
hasBody(x) {
|
|
869
|
+
return is(ObjectModel, x)
|
|
870
|
+
},
|
|
871
|
+
body(model) {
|
|
872
|
+
return span("",
|
|
873
|
+
"{",
|
|
874
|
+
["ol", { style: styles.list }, ...Object.keys(model.definition).map(prop => {
|
|
875
|
+
const isPrivate = model.conventionForPrivate(prop);
|
|
876
|
+
const isConstant = model.conventionForConstant(prop);
|
|
877
|
+
const hasDefault = model.default && has(model.default, prop);
|
|
878
|
+
let style = styles.property;
|
|
879
|
+
|
|
880
|
+
if (isPrivate) {
|
|
881
|
+
style = isConstant ? styles.privateConstant : styles.private;
|
|
882
|
+
} else if (isConstant) {
|
|
883
|
+
style = styles.constant;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
return ["li", { style: styles.listItem },
|
|
887
|
+
span(style, prop), ": ", format(model.definition[prop], { isModelDefinition: true }),
|
|
888
|
+
hasDefault ? span(styles.proto, " = ", format(model.default[prop])) : ""
|
|
889
|
+
]
|
|
890
|
+
})],
|
|
891
|
+
"}"
|
|
892
|
+
)
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
const ModelInstanceFormatter = {
|
|
897
|
+
header(x, config = {}) {
|
|
898
|
+
if (config.isInstanceProperty && isPlainObject(x)) {
|
|
899
|
+
return format(x, config)
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
const model = getModel(x);
|
|
903
|
+
if (is(Model, model)) {
|
|
904
|
+
const parts = is(ObjectModel, model) ? [model.name] : [["object", { object: x[_original] }], ` (${model.name})`];
|
|
905
|
+
return span(styles.instance, ...parts)
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
return null;
|
|
909
|
+
},
|
|
910
|
+
hasBody(x) {
|
|
911
|
+
return x && is(ObjectModel, getModel(x))
|
|
912
|
+
},
|
|
913
|
+
body(x) {
|
|
914
|
+
const model = getModel(x);
|
|
915
|
+
const o = x[_original] || x;
|
|
916
|
+
return span("",
|
|
917
|
+
"{",
|
|
918
|
+
[
|
|
919
|
+
"ol",
|
|
920
|
+
{ style: styles.list },
|
|
921
|
+
...Object.keys(o).map(prop => {
|
|
922
|
+
const isPrivate = model.conventionForPrivate(prop);
|
|
923
|
+
const isConstant = model.conventionForConstant(prop);
|
|
924
|
+
const isDeclared = prop in model.definition;
|
|
925
|
+
let style = styles.property;
|
|
926
|
+
|
|
927
|
+
if (!isDeclared) {
|
|
928
|
+
style = styles.undeclared;
|
|
929
|
+
} else if (isPrivate) {
|
|
930
|
+
style = isConstant ? styles.privateConstant : styles.private;
|
|
931
|
+
} else if (isConstant) {
|
|
932
|
+
style = styles.constant;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
return ["li", { style: styles.listItem },
|
|
936
|
+
span(style, prop), ": ", format(o[prop], { isInstanceProperty: true })
|
|
937
|
+
]
|
|
938
|
+
}),
|
|
939
|
+
["li", { style: styles.listItem },
|
|
940
|
+
span(styles.proto, "__proto__", ": ", ["object", { object: getProto(x) }])
|
|
941
|
+
]
|
|
942
|
+
],
|
|
943
|
+
"}"
|
|
944
|
+
)
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
if (typeof window !== "undefined") {
|
|
949
|
+
window.devtoolsFormatters = (window.devtoolsFormatters || [])
|
|
950
|
+
.concat(ModelFormatter, ModelInstanceFormatter);
|
|
957
951
|
}
|
|
958
952
|
|
|
959
953
|
export { Any, ArrayModel, BasicModel, FunctionModel, MapModel, Model, ObjectModel, SetModel };
|