diff --git a/src/type/definition.js b/src/type/definition.js index 17c3c16e87..396ece2543 100644 --- a/src/type/definition.js +++ b/src/type/definition.js @@ -11,7 +11,9 @@ import invariant from '../jsutils/invariant'; import isNullish from '../jsutils/isNullish'; import * as Kind from '../language/kinds'; + import { assertValidName } from '../utilities/assertValidName'; +import attachHasInstanceSymbol from '../utilities/attachHasInstanceSymbol'; import type { ScalarTypeDefinitionNode, ObjectTypeDefinitionNode, @@ -368,6 +370,8 @@ export class GraphQLScalarType { inspect: () => string; } +attachHasInstanceSymbol(GraphQLScalarType); + // Also provide toJSON and inspect aliases for toString. GraphQLScalarType.prototype.toJSON = GraphQLScalarType.prototype.inspect = @@ -468,6 +472,8 @@ export class GraphQLObjectType { inspect: () => string; } +attachHasInstanceSymbol(GraphQLObjectType); + // Also provide toJSON and inspect aliases for toString. GraphQLObjectType.prototype.toJSON = GraphQLObjectType.prototype.inspect = @@ -749,6 +755,8 @@ export class GraphQLInterfaceType { inspect: () => string; } +attachHasInstanceSymbol(GraphQLInterfaceType); + // Also provide toJSON and inspect aliases for toString. GraphQLInterfaceType.prototype.toJSON = GraphQLInterfaceType.prototype.inspect = @@ -831,6 +839,8 @@ export class GraphQLUnionType { inspect: () => string; } +attachHasInstanceSymbol(GraphQLUnionType); + // Also provide toJSON and inspect aliases for toString. GraphQLUnionType.prototype.toJSON = GraphQLUnionType.prototype.inspect = @@ -999,6 +1009,8 @@ export class GraphQLEnumType/* */ { inspect: () => string; } +attachHasInstanceSymbol(GraphQLEnumType); + // Also provide toJSON and inspect aliases for toString. GraphQLEnumType.prototype.toJSON = GraphQLEnumType.prototype.inspect = @@ -1159,6 +1171,8 @@ export class GraphQLInputObjectType { inspect: () => string; } +attachHasInstanceSymbol(GraphQLInputObjectType); + // Also provide toJSON and inspect aliases for toString. GraphQLInputObjectType.prototype.toJSON = GraphQLInputObjectType.prototype.inspect = @@ -1233,6 +1247,8 @@ export class GraphQLList { inspect: () => string; } +attachHasInstanceSymbol(GraphQLList); + // Also provide toJSON and inspect aliases for toString. GraphQLList.prototype.toJSON = GraphQLList.prototype.inspect = @@ -1279,6 +1295,8 @@ export class GraphQLNonNull { inspect: () => string; } +attachHasInstanceSymbol(GraphQLNonNull); + // Also provide toJSON and inspect aliases for toString. GraphQLNonNull.prototype.toJSON = GraphQLNonNull.prototype.inspect = diff --git a/src/type/schema.js b/src/type/schema.js index 92fb236538..876e939aa4 100644 --- a/src/type/schema.js +++ b/src/type/schema.js @@ -26,6 +26,7 @@ import { GraphQLDirective, specifiedDirectives } from './directives'; import { __Schema } from './introspection'; import find from '../jsutils/find'; import invariant from '../jsutils/invariant'; +import attachHasInstanceSymbol from '../utilities/attachHasInstanceSymbol'; import { isEqualType, isTypeSubTypeOf } from '../utilities/typeComparators'; @@ -222,6 +223,8 @@ export class GraphQLSchema { } } +attachHasInstanceSymbol(GraphQLSchema); + type TypeMap = { [typeName: string]: GraphQLNamedType }; type GraphQLSchemaConfig = { diff --git a/src/utilities/__tests__/attachHasInstanceSymbol.js b/src/utilities/__tests__/attachHasInstanceSymbol.js new file mode 100644 index 0000000000..af395e384f --- /dev/null +++ b/src/utilities/__tests__/attachHasInstanceSymbol.js @@ -0,0 +1,18 @@ +import { describe, it} from 'mocha'; +import chai from 'chai'; +import attachHasInstanceSymbol from '../attachHasInstanceSymbol'; +import { GraphQLInputObjectType as RealInputType } from '../../type'; + + +describe('attachHasInstanceSymbol()', () => { + it('passes instanceof checks for types for other package instances', () => { + class GraphQLInputObjectType { + constructor() {} + } + + attachHasInstanceSymbol(GraphQLInputObjectType); + + chai.expect(new GraphQLInputObjectType() instanceof RealInputType) + .to.equal(true); + }); +}); diff --git a/src/utilities/attachHasInstanceSymbol.js b/src/utilities/attachHasInstanceSymbol.js new file mode 100644 index 0000000000..9a680e1448 --- /dev/null +++ b/src/utilities/attachHasInstanceSymbol.js @@ -0,0 +1,25 @@ +/* @flow */ +/** + * Copyright (c) 2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +// eslint-disable-next-line flowtype/no-weak-types +export default function attachHasInstanceSymbol(ctor: Function): void { + if (typeof Symbol === 'undefined' || !Symbol.for || !Symbol.hasInstance) { + return; + } + const tag = `@@typeof/${ctor.name}`; + + Object.defineProperty(ctor, Symbol.hasInstance, { + value: function $hasInstance(instance) { + return instance && instance[Symbol.for(tag)] === true; + }, + }); + + ctor.prototype[Symbol.for(tag)] = true; +}