Skip to content

Commit

Permalink
Add 'extensions' to all Type System objects (#2097)
Browse files Browse the repository at this point in the history
Fixes #1527
  • Loading branch information
IvanGoncharov committed Aug 20, 2019
1 parent 57e7e1b commit 493a9b6
Show file tree
Hide file tree
Showing 13 changed files with 564 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/jsutils/ObjMap.js
@@ -1,3 +1,9 @@
// @flow strict

export type ObjMap<T> = { [key: string]: T, __proto__: null, ... };
export type ObjMapLike<T> = ObjMap<T> | { [key: string]: T, ... };

export type ReadOnlyObjMap<T> = { +[key: string]: T, __proto__: null, ... };
export type ReadOnlyObjMapLike<T> =
| ReadOnlyObjMap<T>
| { +[key: string]: T, ... };
51 changes: 51 additions & 0 deletions src/jsutils/__tests__/toObjMap-test.js
@@ -0,0 +1,51 @@
// @flow strict

import { expect } from 'chai';
import { describe, it } from 'mocha';

import toObjMap from '../toObjMap';
import { type ObjMapLike } from '../ObjMap';

// Workaround to make both ESLint and Flow happy
const __proto__: string = '__proto__';

describe('toObjMap', () => {
it('convert empty object to ObjMap', () => {
const result = toObjMap({});
expect(result).to.deep.equal({});
expect(Object.getPrototypeOf(result)).to.equal(null);
});

it('convert object with own properties to ObjMap', () => {
const obj: ObjMapLike<string> = Object.freeze({ foo: 'bar' });

const result = toObjMap(obj);
expect(result).to.deep.equal(obj);
expect(Object.getPrototypeOf(result)).to.equal(null);
});

it('convert object with __proto__ property to ObjMap', () => {
const protoObj = Object.freeze({ toString: false });
const obj = Object.create(null);
obj[__proto__] = protoObj;
Object.freeze(obj);

const result = toObjMap(obj);
expect(Object.keys(result)).to.deep.equal(['__proto__']);
expect(Object.getPrototypeOf(result)).to.equal(null);
expect(result[__proto__]).to.equal(protoObj);
});

it('passthrough empty ObjMap', () => {
const objMap = Object.create(null);
expect(toObjMap(objMap)).to.deep.equal(objMap);
});

it('passthrough ObjMap with properties', () => {
const objMap = Object.freeze({
__proto__: null,
foo: 'bar',
});
expect(toObjMap(objMap)).to.deep.equal(objMap);
});
});
26 changes: 26 additions & 0 deletions src/jsutils/toObjMap.js
@@ -0,0 +1,26 @@
// @flow strict

import objectEntries from '../polyfills/objectEntries';
import {
type ObjMap,
type ObjMapLike,
type ReadOnlyObjMap,
type ReadOnlyObjMapLike,
} from './ObjMap';

/* eslint-disable no-redeclare */
declare function toObjMap<T>(obj: ObjMapLike<T>): ObjMap<T>;
declare function toObjMap<T>(obj: ReadOnlyObjMapLike<T>): ReadOnlyObjMap<T>;

export default function toObjMap(obj) {
/* eslint-enable no-redeclare */
if (Object.getPrototypeOf(obj) === null) {
return obj;
}

const map = Object.create(null);
for (const [key, value] of objectEntries(obj)) {
map[key] = value;
}
return map;
}
9 changes: 9 additions & 0 deletions src/type/__tests__/definition-test.js
Expand Up @@ -195,6 +195,7 @@ describe('Type System: Objects', () => {
subscribe: undefined,
isDeprecated: true,
deprecationReason: 'A terrible reason',
extensions: undefined,
astNode: undefined,
});
});
Expand All @@ -216,6 +217,7 @@ describe('Type System: Objects', () => {
subscribe: undefined,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
});
Expand Down Expand Up @@ -244,13 +246,15 @@ describe('Type System: Objects', () => {
description: null,
type: ScalarType,
defaultValue: undefined,
extensions: undefined,
astNode: undefined,
},
],
resolve: undefined,
subscribe: undefined,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
});
Expand Down Expand Up @@ -524,6 +528,7 @@ describe('Type System: Enums', () => {
isDeprecated: true,
deprecationReason: 'Just because',
value: 'foo',
extensions: undefined,
astNode: undefined,
});
});
Expand All @@ -544,6 +549,7 @@ describe('Type System: Enums', () => {
value: null,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
{
Expand All @@ -552,6 +558,7 @@ describe('Type System: Enums', () => {
value: undefined,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
]);
Expand Down Expand Up @@ -649,6 +656,7 @@ describe('Type System: Input Objects', () => {
description: undefined,
type: ScalarType,
defaultValue: undefined,
extensions: undefined,
astNode: undefined,
},
});
Expand All @@ -667,6 +675,7 @@ describe('Type System: Input Objects', () => {
description: undefined,
type: ScalarType,
defaultValue: undefined,
extensions: undefined,
astNode: undefined,
},
});
Expand Down
2 changes: 2 additions & 0 deletions src/type/__tests__/directive-test.js
Expand Up @@ -39,13 +39,15 @@ describe('Type System: Directive', () => {
description: null,
type: GraphQLString,
defaultValue: undefined,
extensions: undefined,
astNode: undefined,
},
{
name: 'bar',
description: null,
type: GraphQLInt,
defaultValue: undefined,
extensions: undefined,
astNode: undefined,
},
],
Expand Down
2 changes: 2 additions & 0 deletions src/type/__tests__/enumType-test.js
Expand Up @@ -345,6 +345,7 @@ describe('Type System: Enum Values', () => {
value: Complex1,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
{
Expand All @@ -353,6 +354,7 @@ describe('Type System: Enum Values', () => {
value: Complex2,
isDeprecated: false,
deprecationReason: undefined,
extensions: undefined,
astNode: undefined,
},
]);
Expand Down

0 comments on commit 493a9b6

Please sign in to comment.