diff options
Diffstat (limited to 'school/node_modules/graphql/jsutils/inspect.js.flow')
-rw-r--r-- | school/node_modules/graphql/jsutils/inspect.js.flow | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/school/node_modules/graphql/jsutils/inspect.js.flow b/school/node_modules/graphql/jsutils/inspect.js.flow new file mode 100644 index 0000000..77a2b2c --- /dev/null +++ b/school/node_modules/graphql/jsutils/inspect.js.flow @@ -0,0 +1,128 @@ +// @flow strict +/* eslint-disable flowtype/no-weak-types */ +import nodejsCustomInspectSymbol from './nodejsCustomInspectSymbol'; + +const MAX_ARRAY_LENGTH = 10; +const MAX_RECURSIVE_DEPTH = 2; + +/** + * Used to print values in error messages. + */ +export default 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': + if (value === null) { + return 'null'; + } + return formatObjectValue(value, seenValues); + default: + return String(value); + } +} + +function formatObjectValue( + value: Object, + previouslySeenValues: Array<mixed>, +): string { + if (previouslySeenValues.indexOf(value) !== -1) { + return '[Circular]'; + } + + const seenValues = [...previouslySeenValues, value]; + const customInspectFn = getCustomFn(value); + + if (customInspectFn !== undefined) { + const customValue = customInspectFn.call(value); + + // check for infinite recursion + if (customValue !== value) { + return typeof customValue === 'string' + ? customValue + : formatValue(customValue, seenValues); + } + } else if (Array.isArray(value)) { + return formatArray(value, seenValues); + } + + return formatObject(value, seenValues); +} + +function formatObject(object: Object, seenValues: Array<mixed>): string { + const keys = Object.keys(object); + if (keys.length === 0) { + return '{}'; + } + + if (seenValues.length > MAX_RECURSIVE_DEPTH) { + return '[' + getObjectTag(object) + ']'; + } + + const properties = keys.map((key) => { + const value = formatValue(object[key], seenValues); + return key + ': ' + value; + }); + + 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 getCustomFn(object: Object) { + const customInspectFn = object[String(nodejsCustomInspectSymbol)]; + + if (typeof customInspectFn === 'function') { + return customInspectFn; + } + + if (typeof object.inspect === 'function') { + return object.inspect; + } +} + +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; +} |