Skip to content

Commit

Permalink
Make 'toJSON' definition explicit
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed May 9, 2020
1 parent 02d59dc commit a4b738f
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ rules:
no-implicit-coercion: error
no-implicit-globals: off
no-implied-eval: error
no-invalid-this: off
no-invalid-this: error
no-iterator: error
no-labels: error
no-lone-blocks: error
Expand Down
1 change: 1 addition & 0 deletions src/jsutils/__tests__/inspect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ describe('inspect', () => {
expect(inspect([[new Foo()]])).to.equal('[[[Bar]]]');

const objectWithoutClassName = new (function () {
// eslint-disable-next-line no-invalid-this
this.foo = 1;
})();
expect(inspect([[objectWithoutClassName]])).to.equal('[[[Object]]]');
Expand Down
11 changes: 6 additions & 5 deletions src/jsutils/defineToJSON.js → src/jsutils/defineInspect.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// @flow strict

import devAssert from './devAssert';
import nodejsCustomInspectSymbol from './nodejsCustomInspectSymbol';

/**
* The `defineToJSON()` function defines toJSON() and inspect() prototype
* methods, if no function provided they become aliases for toString().
* The `defineInspect()` function defines `inspect()` prototype method as alias of `toJSON`
*/
export default function defineToJSON(
export default function defineInspect(
classObject: Class<any> | ((...args: Array<any>) => mixed),
fn?: () => mixed = classObject.prototype.toString,
): void {
classObject.prototype.toJSON = fn;
const fn = classObject.prototype.toJSON;
devAssert(typeof fn === 'function', 'Missing toJSON on class prototype.');

classObject.prototype.inspect = fn;

/* istanbul ignore else (See: https://github.com/graphql/graphql-js/issues/2317) */
Expand Down
9 changes: 9 additions & 0 deletions src/language/ast.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export class Location {
readonly source: Source;

constructor(startToken: Token, endToken: Token, source: Source);

toJSON(): { start: number; end: number };
}

/**
Expand Down Expand Up @@ -86,6 +88,13 @@ export class Token {
prev: Token | null,
value?: string,
);

toJSON(): {
kind: TokenKindEnum;
value: string | undefined;
line: number;
column: number;
};
}

/**
Expand Down
37 changes: 23 additions & 14 deletions src/language/ast.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow strict

import defineToJSON from '../jsutils/defineToJSON';
import defineInspect from '../jsutils/defineInspect';

import { type Source } from './source';
import { type TokenKindEnum } from './tokenKind';
Expand Down Expand Up @@ -42,12 +42,14 @@ export class Location {
this.endToken = endToken;
this.source = source;
}

toJSON(): {| start: number, end: number |} {
return { start: this.start, end: this.end };
}
}

// Print a simplified form when appearing in JSON/util.inspect.
defineToJSON(Location, function () {
return { start: this.start, end: this.end };
});
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(Location);

/**
* Represents a range of characters represented by a lexical token
Expand Down Expand Up @@ -110,17 +112,24 @@ export class Token {
this.prev = prev;
this.next = null;
}

toJSON(): {|
kind: TokenKindEnum,
value: string | void,
line: number,
column: number,
|} {
return {
kind: this.kind,
value: this.value,
line: this.line,
column: this.column,
};
}
}

// Print a simplified form when appearing in JSON/util.inspect.
defineToJSON(Token, function () {
return {
kind: this.kind,
value: this.value,
line: this.line,
column: this.column,
};
});
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(Token);

/**
* @internal
Expand Down
58 changes: 49 additions & 9 deletions src/type/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import instanceOf from '../jsutils/instanceOf';
import didYouMean from '../jsutils/didYouMean';
import isObjectLike from '../jsutils/isObjectLike';
import identityFunc from '../jsutils/identityFunc';
import defineToJSON from '../jsutils/defineToJSON';
import defineInspect from '../jsutils/defineInspect';
import suggestionList from '../jsutils/suggestionList';
import { type PromiseOrValue } from '../jsutils/PromiseOrValue';
import {
Expand Down Expand Up @@ -373,13 +373,18 @@ export function GraphQLList(ofType) {
return '[' + String(this.ofType) + ']';
};

(GraphQLList.prototype: any).toJSON = function toJSON() {
return this.toString();
};

Object.defineProperty(GraphQLList.prototype, SYMBOL_TO_STRING_TAG, {
get() {
return 'GraphQLList';
},
});

defineToJSON(GraphQLList);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLList);

/**
* Non-Null Type Wrapper
Expand Down Expand Up @@ -424,13 +429,18 @@ export function GraphQLNonNull(ofType) {
return String(this.ofType) + '!';
};

(GraphQLNonNull.prototype: any).toJSON = function toJSON() {
return this.toString();
};

Object.defineProperty(GraphQLNonNull.prototype, SYMBOL_TO_STRING_TAG, {
get() {
return 'GraphQLNonNull';
},
});

defineToJSON(GraphQLNonNull);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLNonNull);

/**
* These types wrap and modify other types
Expand Down Expand Up @@ -637,13 +647,18 @@ export class GraphQLScalarType {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLScalarType';
}
}

defineToJSON(GraphQLScalarType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLScalarType);

export type GraphQLScalarSerializer<TExternal> = (
outputValue: mixed,
Expand Down Expand Up @@ -776,13 +791,18 @@ export class GraphQLObjectType {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLObjectType';
}
}

defineToJSON(GraphQLObjectType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLObjectType);

function defineInterfaces(
config: $ReadOnly<
Expand Down Expand Up @@ -1086,13 +1106,18 @@ export class GraphQLInterfaceType {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLInterfaceType';
}
}

defineToJSON(GraphQLInterfaceType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLInterfaceType);

export type GraphQLInterfaceTypeConfig<TSource, TContext> = {|
name: string,
Expand Down Expand Up @@ -1188,13 +1213,18 @@ export class GraphQLUnionType {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLUnionType';
}
}

defineToJSON(GraphQLUnionType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLUnionType);

function defineTypes(
config: $ReadOnly<GraphQLUnionTypeConfig<mixed, mixed>>,
Expand Down Expand Up @@ -1361,13 +1391,18 @@ export class GraphQLEnumType /* <T> */ {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLEnumType';
}
}

defineToJSON(GraphQLEnumType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLEnumType);

function didYouMeanEnumValue(
enumType: GraphQLEnumType,
Expand Down Expand Up @@ -1513,13 +1548,18 @@ export class GraphQLInputObjectType {
return this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLInputObjectType';
}
}

defineToJSON(GraphQLInputObjectType);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLInputObjectType);

function defineInputFieldMap(
config: $ReadOnly<GraphQLInputObjectTypeConfig>,
Expand Down
9 changes: 7 additions & 2 deletions src/type/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import inspect from '../jsutils/inspect';
import toObjMap from '../jsutils/toObjMap';
import devAssert from '../jsutils/devAssert';
import instanceOf from '../jsutils/instanceOf';
import defineToJSON from '../jsutils/defineToJSON';
import isObjectLike from '../jsutils/isObjectLike';
import defineInspect from '../jsutils/defineInspect';
import {
type ReadOnlyObjMap,
type ReadOnlyObjMapLike,
Expand Down Expand Up @@ -112,13 +112,18 @@ export class GraphQLDirective {
return '@' + this.name;
}

toJSON(): string {
return this.toString();
}

// $FlowFixMe Flow doesn't support computed properties yet
get [SYMBOL_TO_STRING_TAG]() {
return 'GraphQLDirective';
}
}

defineToJSON(GraphQLDirective);
// Print a simplified form when appearing in `inspect` and `util.inspect`.
defineInspect(GraphQLDirective);

export type GraphQLDirectiveConfig = {|
name: string,
Expand Down

0 comments on commit a4b738f

Please sign in to comment.