Skip to content

Commit bf267ac

Browse files
committed
incremental delivery without branching
1 parent de008c3 commit bf267ac

File tree

10 files changed

+1279
-545
lines changed

10 files changed

+1279
-545
lines changed

src/execution/__tests__/defer-test.ts

+50-79
Original file line numberDiff line numberDiff line change
@@ -362,17 +362,17 @@ describe('Execute: defer directive', () => {
362362
incremental: [
363363
{
364364
data: {
365-
friends: [{ name: 'Han' }, { name: 'Leia' }, { name: 'C-3PO' }],
365+
id: '1',
366366
},
367367
path: ['hero'],
368-
label: 'DeferNested',
368+
label: 'DeferTop',
369369
},
370370
{
371371
data: {
372-
id: '1',
372+
friends: [{ name: 'Han' }, { name: 'Leia' }, { name: 'C-3PO' }],
373373
},
374374
path: ['hero'],
375-
label: 'DeferTop',
375+
label: 'DeferNested',
376376
},
377377
],
378378
hasNext: false,
@@ -627,13 +627,6 @@ describe('Execute: defer directive', () => {
627627
},
628628
{
629629
incremental: [
630-
{
631-
data: {
632-
id: '1',
633-
},
634-
path: ['hero'],
635-
label: 'DeferID',
636-
},
637630
{
638631
data: {
639632
hero: {
@@ -643,6 +636,13 @@ describe('Execute: defer directive', () => {
643636
path: [],
644637
label: 'DeferName',
645638
},
639+
{
640+
data: {
641+
id: '1',
642+
},
643+
path: ['hero'],
644+
label: 'DeferID',
645+
},
646646
],
647647
hasNext: false,
648648
},
@@ -697,7 +697,7 @@ describe('Execute: defer directive', () => {
697697
]);
698698
});
699699

700-
it('Does not deduplicate multiple defers on the same object', async () => {
700+
it('Can deduplicate multiple defers on the same object', async () => {
701701
const document = parse(`
702702
query {
703703
hero {
@@ -732,17 +732,8 @@ describe('Execute: defer directive', () => {
732732
},
733733
{
734734
incremental: [
735-
{ data: {}, path: ['hero', 'friends', 0] },
736-
{ data: {}, path: ['hero', 'friends', 0] },
737-
{ data: {}, path: ['hero', 'friends', 0] },
738735
{ data: { id: '2', name: 'Han' }, path: ['hero', 'friends', 0] },
739-
{ data: {}, path: ['hero', 'friends', 1] },
740-
{ data: {}, path: ['hero', 'friends', 1] },
741-
{ data: {}, path: ['hero', 'friends', 1] },
742736
{ data: { id: '3', name: 'Leia' }, path: ['hero', 'friends', 1] },
743-
{ data: {}, path: ['hero', 'friends', 2] },
744-
{ data: {}, path: ['hero', 'friends', 2] },
745-
{ data: {}, path: ['hero', 'friends', 2] },
746737
{ data: { id: '4', name: 'C-3PO' }, path: ['hero', 'friends', 2] },
747738
],
748739
hasNext: false,
@@ -937,11 +928,6 @@ describe('Execute: defer directive', () => {
937928
},
938929
path: ['hero'],
939930
},
940-
],
941-
hasNext: true,
942-
},
943-
{
944-
incremental: [
945931
{
946932
data: {
947933
deeperObject: {
@@ -952,11 +938,6 @@ describe('Execute: defer directive', () => {
952938
},
953939
path: ['hero', 'nestedObject'],
954940
},
955-
],
956-
hasNext: true,
957-
},
958-
{
959-
incremental: [
960941
{
961942
data: {
962943
foo: 'foo',
@@ -972,7 +953,7 @@ describe('Execute: defer directive', () => {
972953
]);
973954
});
974955

975-
it('Does not combine multiple fields from deferred fragments from different branches occurring at the same level', async () => {
956+
it('Can combine multiple fields from deferred fragments from different branches occurring at the same level', async () => {
976957
const document = parse(`
977958
query {
978959
hero {
@@ -1010,12 +991,6 @@ describe('Execute: defer directive', () => {
1010991
},
1011992
{
1012993
incremental: [
1013-
{
1014-
data: {
1015-
foo: 'foo',
1016-
},
1017-
path: ['hero', 'nestedObject', 'deeperObject'],
1018-
},
1019994
{
1020995
data: {
1021996
nestedObject: {
@@ -1024,11 +999,6 @@ describe('Execute: defer directive', () => {
1024999
},
10251000
path: ['hero'],
10261001
},
1027-
],
1028-
hasNext: true,
1029-
},
1030-
{
1031-
incremental: [
10321002
{
10331003
data: {
10341004
foo: 'foo',
@@ -1087,14 +1057,6 @@ describe('Execute: defer directive', () => {
10871057
},
10881058
{
10891059
incremental: [
1090-
{
1091-
data: {
1092-
e: {
1093-
f: 'f',
1094-
},
1095-
},
1096-
path: ['a', 'b'],
1097-
},
10981060
{
10991061
data: {
11001062
a: {
@@ -1110,6 +1072,14 @@ describe('Execute: defer directive', () => {
11101072
},
11111073
path: [],
11121074
},
1075+
{
1076+
data: {
1077+
e: {
1078+
f: 'f',
1079+
},
1080+
},
1081+
path: ['a', 'b'],
1082+
},
11131083
],
11141084
hasNext: false,
11151085
},
@@ -1150,16 +1120,6 @@ describe('Execute: defer directive', () => {
11501120
},
11511121
{
11521122
incremental: [
1153-
{
1154-
data: {
1155-
b: {
1156-
c: {
1157-
d: 'd',
1158-
},
1159-
},
1160-
},
1161-
path: ['a'],
1162-
},
11631123
{
11641124
data: {
11651125
a: {
@@ -1179,6 +1139,16 @@ describe('Execute: defer directive', () => {
11791139
],
11801140
path: [],
11811141
},
1142+
{
1143+
data: {
1144+
b: {
1145+
c: {
1146+
d: 'd',
1147+
},
1148+
},
1149+
},
1150+
path: ['a'],
1151+
},
11821152
],
11831153
hasNext: false,
11841154
},
@@ -1217,21 +1187,6 @@ describe('Execute: defer directive', () => {
12171187
},
12181188
hasNext: true,
12191189
},
1220-
{
1221-
incremental: [
1222-
{
1223-
data: {
1224-
b: {
1225-
c: {
1226-
d: 'd',
1227-
},
1228-
},
1229-
},
1230-
path: ['a'],
1231-
},
1232-
],
1233-
hasNext: true,
1234-
},
12351190
{
12361191
incremental: [
12371192
{
@@ -1253,6 +1208,16 @@ describe('Execute: defer directive', () => {
12531208
],
12541209
path: [],
12551210
},
1211+
{
1212+
data: {
1213+
b: {
1214+
c: {
1215+
d: 'd',
1216+
},
1217+
},
1218+
},
1219+
path: ['a'],
1220+
},
12561221
],
12571222
hasNext: false,
12581223
},
@@ -1297,10 +1262,16 @@ describe('Execute: defer directive', () => {
12971262
incremental: [
12981263
{
12991264
data: {
1300-
hero: {
1301-
name: 'Luke',
1302-
},
1265+
hero: null,
13031266
},
1267+
errors: [
1268+
{
1269+
message:
1270+
'Cannot return null for non-nullable field Hero.nonNullName.',
1271+
locations: [{ line: 4, column: 11 }],
1272+
path: ['hero', 'nonNullName'],
1273+
},
1274+
],
13041275
path: [],
13051276
},
13061277
],

src/execution/__tests__/executor-test.ts

+38-14
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import { expectJSON } from '../../__testUtils__/expectJSON.js';
55
import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js';
66

77
import { inspect } from '../../jsutils/inspect.js';
8+
import type { Path } from '../../jsutils/Path.js';
89

910
import { Kind } from '../../language/kinds.js';
1011
import { parse } from '../../language/parser.js';
1112

13+
import type { GraphQLResolveInfo } from '../../type/definition.js';
1214
import {
1315
GraphQLInterfaceType,
1416
GraphQLList,
@@ -191,7 +193,7 @@ describe('Execute: Handles basic execution tasks', () => {
191193
});
192194

193195
it('provides info about current execution state', () => {
194-
let resolvedInfo;
196+
let resolvedInfo: GraphQLResolveInfo | undefined;
195197
const testType = new GraphQLObjectType({
196198
name: 'Test',
197199
fields: {
@@ -239,13 +241,22 @@ describe('Execute: Handles basic execution tasks', () => {
239241
const field = operation.selectionSet.selections[0];
240242
expect(resolvedInfo).to.deep.include({
241243
fieldNodes: [field],
242-
path: { prev: undefined, key: 'result', typename: 'Test' },
243244
variableValues: { var: 'abc' },
244245
});
246+
247+
expect(resolvedInfo?.path).to.deep.include({
248+
prev: undefined,
249+
key: 'result',
250+
});
251+
252+
expect(resolvedInfo?.path.info).to.deep.include({
253+
parentType: testType,
254+
fieldName: 'test',
255+
});
245256
});
246257

247258
it('populates path correctly with complex types', () => {
248-
let path;
259+
let path: Path<unknown> | undefined;
249260
const someObject = new GraphQLObjectType({
250261
name: 'SomeObject',
251262
fields: {
@@ -288,18 +299,31 @@ describe('Execute: Handles basic execution tasks', () => {
288299

289300
executeSync({ schema, document, rootValue });
290301

291-
expect(path).to.deep.equal({
302+
expect(path).to.deep.include({
292303
key: 'l2',
293-
typename: 'SomeObject',
294-
prev: {
295-
key: 0,
296-
typename: undefined,
297-
prev: {
298-
key: 'l1',
299-
typename: 'SomeQuery',
300-
prev: undefined,
301-
},
302-
},
304+
});
305+
306+
expect(path?.info).to.deep.include({
307+
parentType: someObject,
308+
fieldName: 'test',
309+
});
310+
311+
expect(path?.prev).to.deep.include({
312+
key: 0,
313+
});
314+
315+
expect(path?.prev?.info).to.deep.include({
316+
parentType: testType,
317+
fieldName: 'test',
318+
});
319+
320+
expect(path?.prev?.prev).to.deep.include({
321+
key: 'l1',
322+
});
323+
324+
expect(path?.prev?.prev?.info).to.deep.include({
325+
parentType: testType,
326+
fieldName: 'test',
303327
});
304328
});
305329

0 commit comments

Comments
 (0)