diff --git a/src/jsutils/__tests__/inspect-test.js b/src/jsutils/__tests__/inspect-test.js index 41045c25ae..2d754ba2ed 100644 --- a/src/jsutils/__tests__/inspect-test.js +++ b/src/jsutils/__tests__/inspect-test.js @@ -78,7 +78,7 @@ describe('inspect', () => { expect(inspect(object)).to.equal(''); }); - it('custom inspect', () => { + it('custom symbol inspect is take precedence', () => { invariant(nodejsCustomInspectSymbol); const object = { @@ -92,4 +92,25 @@ describe('inspect', () => { expect(inspect(object)).to.equal(''); }); + + it('custom inspect returning object values', () => { + const object = { + inspect() { + return { custom: 'inspect' }; + }, + }; + + expect(inspect(object)).to.equal('{ custom: "inspect" }'); + }); + + it('custom inspect function that uses this', () => { + const object = { + str: 'Hello World!', + inspect() { + return this.str; + }, + }; + + expect(inspect(object)).to.equal('Hello World!'); + }); }); diff --git a/src/jsutils/inspect.js b/src/jsutils/inspect.js index 2f2564c45b..f925592609 100644 --- a/src/jsutils/inspect.js +++ b/src/jsutils/inspect.js @@ -20,11 +20,13 @@ export default function inspect(value: mixed): string { return value.name ? `[function ${value.name}]` : '[function]'; case 'object': if (value) { - const customInspectFn = value[String(nodejsCustomInspectSymbol)]; - if (typeof customInspectFn === 'function') { - return customInspectFn(); - } else if (typeof value.inspect === 'function') { - return value.inspect(); + const customInspectFn = getCustomFn(value); + + if (customInspectFn) { + const customValue = customInspectFn.call(value); + return typeof customValue === 'string' + ? customValue + : inspect(customValue); } else if (Array.isArray(value)) { return '[' + value.map(inspect).join(', ') + ']'; } @@ -39,3 +41,15 @@ export default function inspect(value: mixed): string { return String(value); } } + +function getCustomFn(object) { + const customInspectFn = object[String(nodejsCustomInspectSymbol)]; + + if (typeof customInspectFn === 'function') { + return customInspectFn; + } + + if (typeof object.inspect === 'function') { + return object.inspect; + } +} diff --git a/src/language/__tests__/lexer-test.js b/src/language/__tests__/lexer-test.js index b92483a88c..922753d558 100644 --- a/src/language/__tests__/lexer-test.js +++ b/src/language/__tests__/lexer-test.js @@ -7,11 +7,12 @@ * @flow strict */ -import { inspect as utilInspect } from 'util'; +import { inspect as nodeInspect } from 'util'; import { expect } from 'chai'; import { describe, it } from 'mocha'; import dedent from '../../jsutils/dedent'; +import inspect from '../../jsutils/inspect'; import { GraphQLError } from '../../error'; import { Source } from '../source'; import { createLexer, TokenKind } from '../lexer'; @@ -62,14 +63,17 @@ describe('Lexer', () => { }); }); - it('can be JSON.stringified or util.inspected', () => { + it('can be JSON.stringified, util.inspected or jsutils.inspect', () => { const token = lexOne('foo'); expect(JSON.stringify(token)).to.equal( '{"kind":"Name","value":"foo","line":1,"column":1}', ); - expect(utilInspect(token)).to.equal( + expect(nodeInspect(token)).to.equal( "{ kind: 'Name', value: 'foo', line: 1, column: 1 }", ); + expect(inspect(token)).to.equal( + '{ kind: "Name", value: "foo", line: 1, column: 1 }', + ); }); it('skips whitespace and comments', () => { diff --git a/src/language/__tests__/parser-test.js b/src/language/__tests__/parser-test.js index 43f802196f..2a0ca0996d 100644 --- a/src/language/__tests__/parser-test.js +++ b/src/language/__tests__/parser-test.js @@ -7,7 +7,7 @@ * @flow strict */ -import { inspect } from 'util'; +import { inspect as nodeInspect } from 'util'; import { readFileSync } from 'fs'; import { join } from 'path'; @@ -18,6 +18,7 @@ import { TokenKind } from '../lexer'; import { parse, parseValue, parseType } from '../parser'; import { Source } from '../source'; import dedent from '../../jsutils/dedent'; +import inspect from '../../jsutils/inspect'; import toJSONDeep from './toJSONDeep'; function expectSyntaxError(text, message, location) { @@ -391,6 +392,7 @@ describe('Parser', () => { const result = parse('{ id }'); expect(JSON.stringify(result.loc)).to.equal('{"start":0,"end":6}'); + expect(nodeInspect(result.loc)).to.equal('{ start: 0, end: 6 }'); expect(inspect(result.loc)).to.equal('{ start: 0, end: 6 }'); });