forked from graphql/graphql-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinspect.js
112 lines (91 loc) · 2.61 KB
/
inspect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* eslint-disable flowtype/no-weak-types */
const MAX_ARRAY_LENGTH = 10;
const MAX_RECURSIVE_DEPTH = 2;
/**
* Used to print values in error messages.
*/
export function inspect(value: mixed): string {
return formatValue(value, []);
}
function formatValue(value: mixed, seenValues: Array<mixed>): string {
switch (typeof value) {
case 'string':
return JSON.stringify(value);
case 'function':
return value.name ? `[function ${value.name}]` : '[function]';
case 'object':
return formatObjectValue(value, seenValues);
default:
return String(value);
}
}
function formatObjectValue(
value: Object,
previouslySeenValues: Array<mixed>,
): string {
if (value === null) {
return 'null';
}
if (previouslySeenValues.includes(value)) {
return '[Circular]';
}
const seenValues = [...previouslySeenValues, value];
if (typeof value.toJSON === 'function') {
const jsonValue = (value.toJSON: () => mixed)();
// check for infinite recursion
if (jsonValue !== value) {
return typeof jsonValue === 'string'
? jsonValue
: formatValue(jsonValue, seenValues);
}
} else if (Array.isArray(value)) {
return formatArray(value, seenValues);
}
return formatObject(value, seenValues);
}
function formatObject(object: Object, seenValues: Array<mixed>): string {
const entries = Object.entries(object);
if (entries.length === 0) {
return '{}';
}
if (seenValues.length > MAX_RECURSIVE_DEPTH) {
return '[' + getObjectTag(object) + ']';
}
const properties = entries.map(
([key, value]) => key + ': ' + formatValue(value, seenValues),
);
return '{ ' + properties.join(', ') + ' }';
}
function formatArray(array: Array<mixed>, seenValues: Array<mixed>): string {
if (array.length === 0) {
return '[]';
}
if (seenValues.length > MAX_RECURSIVE_DEPTH) {
return '[Array]';
}
const len = Math.min(MAX_ARRAY_LENGTH, array.length);
const remaining = array.length - len;
const items = [];
for (let i = 0; i < len; ++i) {
items.push(formatValue(array[i], seenValues));
}
if (remaining === 1) {
items.push('... 1 more item');
} else if (remaining > 1) {
items.push(`... ${remaining} more items`);
}
return '[' + items.join(', ') + ']';
}
function getObjectTag(object: Object): string {
const tag = Object.prototype.toString
.call(object)
.replace(/^\[object /, '')
.replace(/]$/, '');
if (tag === 'Object' && typeof object.constructor === 'function') {
const name = object.constructor.name;
if (typeof name === 'string' && name !== '') {
return name;
}
}
return tag;
}