diff --git a/src/jsutils/keyMap.js b/src/jsutils/keyMap.js index 5afd5b18b8..c8c021f439 100644 --- a/src/jsutils/keyMap.js +++ b/src/jsutils/keyMap.js @@ -35,5 +35,8 @@ export default function keyMap( list: Array, keyFn: (item: T) => string ): {[key: string]: T} { - return list.reduce((map, item) => ((map[keyFn(item)] = item), map), {}); + return list.reduce( + (map, item) => ((map[keyFn(item)] = item), map), + Object.create(null) + ); } diff --git a/src/jsutils/keyValMap.js b/src/jsutils/keyValMap.js index 60ca478a80..ad2ecde7f8 100644 --- a/src/jsutils/keyValMap.js +++ b/src/jsutils/keyValMap.js @@ -32,6 +32,6 @@ export default function keyValMap( ): {[key: string]: V} { return list.reduce( (map, item) => ((map[keyFn(item)] = valFn(item)), map), - {} + Object.create(null) ); } diff --git a/src/type/definition.js b/src/type/definition.js index cbc7f35e2d..434b0c99be 100644 --- a/src/type/definition.js +++ b/src/type/definition.js @@ -470,7 +470,7 @@ function defineInterfaces( 'an Array.' ); - const implementedTypeNames = {}; + const implementedTypeNames = Object.create(null); interfaces.forEach(iface => { invariant( iface instanceof GraphQLInterfaceType, @@ -513,7 +513,7 @@ function defineFieldMap( 'function which returns such an object.' ); - const resultFieldMap = {}; + const resultFieldMap = Object.create(null); fieldNames.forEach(fieldName => { assertValidName(fieldName); const fieldConfig = fieldMap[fieldName]; @@ -818,7 +818,7 @@ function defineTypes( 'Must provide Array of types or a function which returns ' + `such an array for Union ${unionType.name}.` ); - const includedTypeNames = {}; + const includedTypeNames = Object.create(null); types.forEach(objType => { invariant( objType instanceof GraphQLObjectType, @@ -1091,7 +1091,7 @@ export class GraphQLInputObjectType { `${this.name} fields must be an object with field names as keys or a ` + 'function which returns such an object.' ); - const resultFieldMap = {}; + const resultFieldMap = Object.create(null); fieldNames.forEach(fieldName => { assertValidName(fieldName); const field = { diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index 02c42453b8..2b24a3e157 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -123,8 +123,8 @@ export function extendSchema( ); // Collect the type definitions and extensions found in the document. - const typeDefinitionMap = {}; - const typeExtensionsMap = {}; + const typeDefinitionMap = Object.create(null); + const typeExtensionsMap = Object.create(null); // New directives and types are separate because a directives and types can // have the same name. For example, a type named "skip". @@ -400,7 +400,7 @@ export function extendSchema( } function extendFieldMap(type: GraphQLObjectType | GraphQLInterfaceType) { - const newFieldMap = {}; + const newFieldMap = Object.create(null); const oldFieldMap = type.getFields(); Object.keys(oldFieldMap).forEach(fieldName => { const field = oldFieldMap[fieldName]; diff --git a/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js b/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js index ecbb3f9a1d..a7224fff5a 100644 --- a/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js +++ b/src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js @@ -936,6 +936,35 @@ describe('Validate: Overlapping fields can be merged', () => { ); }); + it('works for field names that are JS keywords', () => { + const FooType = new GraphQLObjectType({ + name: 'Foo', + fields: { + constructor: { + type: GraphQLString + }, + } + }); + + const schemaWithKeywords = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + foo: { type: FooType }, + }) + }), + }); + + expectPassesRuleWithSchema( + schemaWithKeywords, + OverlappingFieldsCanBeMerged, + `{ + foo { + constructor + } + }` + ); + }); }); }); diff --git a/src/validation/rules/OverlappingFieldsCanBeMerged.js b/src/validation/rules/OverlappingFieldsCanBeMerged.js index fd7fc92c27..ae70ddc391 100644 --- a/src/validation/rules/OverlappingFieldsCanBeMerged.js +++ b/src/validation/rules/OverlappingFieldsCanBeMerged.js @@ -665,8 +665,8 @@ function getFieldsAndFragmentNames( ): [ NodeAndDefCollection, Array ] { let cached = cachedFieldsAndFragmentNames.get(selectionSet); if (!cached) { - const nodeAndDefs = {}; - const fragmentNames = {}; + const nodeAndDefs = Object.create(null); + const fragmentNames = Object.create(null); _collectFieldsAndFragmentNames( context, parentType, diff --git a/src/validation/validate.js b/src/validation/validate.js index a13a53a2f1..0aab782d58 100644 --- a/src/validation/validate.js +++ b/src/validation/validate.js @@ -151,7 +151,7 @@ export class ValidationContext { frags[statement.name.value] = statement; } return frags; - }, {}); + }, Object.create(null)); } return fragments[name]; }