Skip to content

Commit 93ac2b2

Browse files
Merge branch '16.x.x' into type-generation
2 parents c11f237 + 1f1d89d commit 93ac2b2

30 files changed

+832
-152
lines changed

.c8rc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"src/jsutils/ObjMap.ts",
99
"src/jsutils/PromiseOrValue.ts",
1010
"src/utilities/assertValidName.ts",
11-
"src/utilities/typedQueryDocumentNode.ts"
11+
"src/utilities/typedQueryDocumentNode.ts",
12+
"src/**/__tests__/**/*.ts"
1213
],
1314
"clean": true,
1415
"temp-directory": "coverage",

cspell.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ overrides:
2828
- codegen
2929
- composability
3030
- deduplication
31+
- debuggable
3132

3233
ignoreRegExpList:
3334
- u\{[0-9a-f]{1,8}\}
@@ -119,4 +120,3 @@ words:
119120
- XXXF
120121
- bfnrt
121122
- wrds
122-
- pgsql

src/execution/__tests__/union-interface-test.ts

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { GraphQLBoolean, GraphQLString } from '../../type/scalars';
1313
import { GraphQLSchema } from '../../type/schema';
1414

15-
import { executeSync } from '../execute';
15+
import { execute, executeSync } from '../execute';
1616

1717
class Dog {
1818
name: string;
@@ -118,7 +118,6 @@ const PetType = new GraphQLUnionType({
118118
if (value instanceof Cat) {
119119
return CatType.name;
120120
}
121-
/* c8 ignore next 3 */
122121
// Not reachable, all possible types have been considered.
123122
expect.fail('Not reachable');
124123
},
@@ -154,6 +153,71 @@ odie.mother.progeny = [odie];
154153
const liz = new Person('Liz');
155154
const john = new Person('John', [garfield, odie], [liz, odie]);
156155

156+
const SearchableInterface = new GraphQLInterfaceType({
157+
name: 'Searchable',
158+
fields: {
159+
id: { type: GraphQLString },
160+
},
161+
});
162+
163+
const TypeA = new GraphQLObjectType({
164+
name: 'TypeA',
165+
interfaces: [SearchableInterface],
166+
fields: () => ({
167+
id: { type: GraphQLString },
168+
nameA: { type: GraphQLString },
169+
}),
170+
isTypeOf: (_value, _context, _info) =>
171+
new Promise((_resolve, reject) =>
172+
// eslint-disable-next-line
173+
setTimeout(() => reject(new Error('TypeA_isTypeOf_rejected')), 10),
174+
),
175+
});
176+
177+
const TypeB = new GraphQLObjectType({
178+
name: 'TypeB',
179+
interfaces: [SearchableInterface],
180+
fields: () => ({
181+
id: { type: GraphQLString },
182+
nameB: { type: GraphQLString },
183+
}),
184+
isTypeOf: (value: any, _context, _info) => value.id === 'b',
185+
});
186+
187+
const queryTypeWithSearchable = new GraphQLObjectType({
188+
name: 'Query',
189+
fields: {
190+
person: {
191+
type: PersonType,
192+
resolve: () => john,
193+
},
194+
search: {
195+
type: SearchableInterface,
196+
args: { id: { type: GraphQLString } },
197+
resolve: (_source, { id }) => {
198+
if (id === 'a') {
199+
return { id: 'a', nameA: 'Object A' };
200+
} else if (id === 'b') {
201+
return { id: 'b', nameB: 'Object B' };
202+
}
203+
},
204+
},
205+
},
206+
});
207+
208+
const schemaWithSearchable = new GraphQLSchema({
209+
query: queryTypeWithSearchable,
210+
types: [
211+
PetType,
212+
TypeA,
213+
TypeB,
214+
SearchableInterface,
215+
PersonType,
216+
DogType,
217+
CatType,
218+
],
219+
});
220+
157221
describe('Execute: Union and intersection types', () => {
158222
it('can introspect on union and intersection types', () => {
159223
const document = parse(`
@@ -545,4 +609,51 @@ describe('Execute: Union and intersection types', () => {
545609
expect(encounteredRootValue).to.equal(rootValue);
546610
expect(encounteredContext).to.equal(contextValue);
547611
});
612+
613+
it('handles promises from isTypeOf correctly when a later type matches synchronously', async () => {
614+
const document = parse(`
615+
query TestSearch {
616+
search(id: "b") {
617+
__typename
618+
id
619+
... on TypeA {
620+
nameA
621+
}
622+
... on TypeB {
623+
nameB
624+
}
625+
}
626+
}
627+
`);
628+
629+
let unhandledRejection: any = null;
630+
const unhandledRejectionListener = (reason: any) => {
631+
unhandledRejection = reason;
632+
};
633+
// eslint-disable-next-line
634+
process.on('unhandledRejection', unhandledRejectionListener);
635+
636+
const result = await execute({
637+
schema: schemaWithSearchable,
638+
document,
639+
});
640+
641+
expect(result.errors).to.equal(undefined);
642+
expect(result.data).to.deep.equal({
643+
search: {
644+
__typename: 'TypeB',
645+
id: 'b',
646+
nameB: 'Object B',
647+
},
648+
});
649+
650+
// Give the TypeA promise a chance to reject and the listener to fire
651+
// eslint-disable-next-line
652+
await new Promise((resolve) => setTimeout(resolve, 20));
653+
654+
// eslint-disable-next-line
655+
process.removeListener('unhandledRejection', unhandledRejectionListener);
656+
657+
expect(unhandledRejection).to.equal(null);
658+
});
548659
});

src/execution/execute.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,14 @@ export const defaultTypeResolver: GraphQLTypeResolver<unknown, unknown> =
10021002
if (isPromise(isTypeOfResult)) {
10031003
promisedIsTypeOfResults[i] = isTypeOfResult;
10041004
} else if (isTypeOfResult) {
1005+
if (promisedIsTypeOfResults.length) {
1006+
// Explicitly ignore any promise rejections
1007+
Promise.allSettled(promisedIsTypeOfResults)
1008+
/* c8 ignore next 3 */
1009+
.catch(() => {
1010+
// Do nothing
1011+
});
1012+
}
10051013
return type.name;
10061014
}
10071015
}

website/pages/api-v16/error.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ The `graphql/error` module is responsible for creating and formatting
1010
GraphQL errors. You can import either from the `graphql/error` module, or from the root `graphql` module. For example:
1111

1212
```js
13-
import { GraphQLError } from 'graphql'; // ES6
14-
const { GraphQLError } = require('graphql'); // CommonJS
13+
import { GraphQLError } from 'graphql';
1514
```
1615

1716
## Overview

website/pages/api-v16/execution.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ The `graphql/execution` module is responsible for the execution phase of
1010
fulfilling a GraphQL request. You can import either from the `graphql/execution` module, or from the root `graphql` module. For example:
1111

1212
```js
13-
import { execute } from 'graphql'; // ES6
14-
const { execute } = require('graphql'); // CommonJS
13+
import { execute } from 'graphql';
1514
```
1615

1716
## Overview

website/pages/api-v16/graphql-http.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ The [official `graphql-http` package](https://github.com/graphql/graphql-http) p
1111
## Express
1212

1313
```js
14-
import { createHandler } from 'graphql-http/lib/use/express'; // ES6
15-
const { createHandler } = require('graphql-http/lib/use/express'); // CommonJS
14+
import { createHandler } from 'graphql-http/lib/use/express';
1615
```
1716

1817
### createHandler

website/pages/api-v16/graphql.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ The `graphql` module exports a core subset of GraphQL functionality for creation
1010
of GraphQL type systems and servers.
1111

1212
```js
13-
import { graphql } from 'graphql'; // ES6
14-
const { graphql } = require('graphql'); // CommonJS
13+
import { graphql } from 'graphql';
1514
```
1615

1716
## Overview

website/pages/api-v16/language.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ title: graphql/language
99
The `graphql/language` module is responsible for parsing and operating on the GraphQL language. You can import either from the `graphql/language` module, or from the root `graphql` module. For example:
1010

1111
```js
12-
import { Source } from 'graphql'; // ES6
13-
const { Source } = require('graphql'); // CommonJS
12+
import { Source } from 'graphql';
1413
```
1514

1615
## Overview

website/pages/api-v16/type.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ title: graphql/type
99
The `graphql/type` module is responsible for defining GraphQL types and schema. You can import either from the `graphql/type` module, or from the root `graphql` module. For example:
1010

1111
```js
12-
import { GraphQLSchema } from 'graphql'; // ES6
13-
const { GraphQLSchema } = require('graphql'); // CommonJS
12+
import { GraphQLSchema } from 'graphql';
1413
```
1514

1615
## Overview

0 commit comments

Comments
 (0)