@@ -245,7 +245,7 @@ func executeFieldsSerially(p executeFieldsParams) *Result {
245
245
}
246
246
finalResults [responseName ] = resolved
247
247
}
248
- dethunkWithBreadthFirstTraversal (finalResults )
248
+ dethunkMapDepthFirst (finalResults )
249
249
250
250
return & Result {
251
251
Data : finalResults ,
@@ -257,7 +257,7 @@ func executeFieldsSerially(p executeFieldsParams) *Result {
257
257
func executeFields (p executeFieldsParams ) * Result {
258
258
finalResults := executeSubFields (p )
259
259
260
- dethunkWithBreadthFirstTraversal (finalResults )
260
+ dethunkMapWithBreadthFirstTraversal (finalResults )
261
261
262
262
return & Result {
263
263
Data : finalResults ,
@@ -302,17 +302,19 @@ func (d *dethunkQueue) shift() func() {
302
302
}
303
303
304
304
// dethunkWithBreadthFirstTraversal performs a breadth-first descent of the map, calling any thunks
305
- // in the map values and replacing each thunk with that thunk's return value.
306
- func dethunkWithBreadthFirstTraversal (finalResults map [string ]interface {}) {
305
+ // in the map values and replacing each thunk with that thunk's return value. This parallels
306
+ // the reference graphql-js implementation, which calls Promise.all on thunks at each depth (which
307
+ // is an implicit parallel descent).
308
+ func dethunkMapWithBreadthFirstTraversal (finalResults map [string ]interface {}) {
307
309
dethunkQueue := & dethunkQueue {DethunkFuncs : []func (){}}
308
- dethunkMap (finalResults , dethunkQueue )
310
+ dethunkMapBreadthFirst (finalResults , dethunkQueue )
309
311
for len (dethunkQueue .DethunkFuncs ) > 0 {
310
312
f := dethunkQueue .shift ()
311
313
f ()
312
314
}
313
315
}
314
316
315
- func dethunkMap (m map [string ]interface {}, dethunkQueue * dethunkQueue ) {
317
+ func dethunkMapBreadthFirst (m map [string ]interface {}, dethunkQueue * dethunkQueue ) {
316
318
for k , v := range m {
317
319
if f , ok := v .(func () interface {}); ok {
318
320
m [k ] = f ()
@@ -321,14 +323,14 @@ func dethunkMap(m map[string]interface{}, dethunkQueue *dethunkQueue) {
321
323
for _ , v := range m {
322
324
switch val := v .(type ) {
323
325
case map [string ]interface {}:
324
- dethunkQueue .push (func () { dethunkMap (val , dethunkQueue ) })
326
+ dethunkQueue .push (func () { dethunkMapBreadthFirst (val , dethunkQueue ) })
325
327
case []interface {}:
326
- dethunkQueue .push (func () { dethunkList (val , dethunkQueue ) })
328
+ dethunkQueue .push (func () { dethunkListBreadthFirst (val , dethunkQueue ) })
327
329
}
328
330
}
329
331
}
330
332
331
- func dethunkList (list []interface {}, dethunkQueue * dethunkQueue ) {
333
+ func dethunkListBreadthFirst (list []interface {}, dethunkQueue * dethunkQueue ) {
332
334
for i , v := range list {
333
335
if f , ok := v .(func () interface {}); ok {
334
336
list [i ] = f ()
@@ -337,9 +339,41 @@ func dethunkList(list []interface{}, dethunkQueue *dethunkQueue) {
337
339
for _ , v := range list {
338
340
switch val := v .(type ) {
339
341
case map [string ]interface {}:
340
- dethunkQueue .push (func () { dethunkMap (val , dethunkQueue ) })
342
+ dethunkQueue .push (func () { dethunkMapBreadthFirst (val , dethunkQueue ) })
341
343
case []interface {}:
342
- dethunkQueue .push (func () { dethunkList (val , dethunkQueue ) })
344
+ dethunkQueue .push (func () { dethunkListBreadthFirst (val , dethunkQueue ) })
345
+ }
346
+ }
347
+ }
348
+
349
+ // dethunkMapDepthFirst performs a serial descent of the map, calling any thunks
350
+ // in the map values and replacing each thunk with that thunk's return value. This is needed
351
+ // to conform to the graphql-js reference implementation, which requires serial (depth-first)
352
+ // implementations for mutation selects.
353
+ func dethunkMapDepthFirst (m map [string ]interface {}) {
354
+ for k , v := range m {
355
+ if f , ok := v .(func () interface {}); ok {
356
+ m [k ] = f ()
357
+ }
358
+ switch val := m [k ].(type ) {
359
+ case map [string ]interface {}:
360
+ dethunkMapDepthFirst (val )
361
+ case []interface {}:
362
+ dethunkListDepthFirst (val )
363
+ }
364
+ }
365
+ }
366
+
367
+ func dethunkListDepthFirst (list []interface {}) {
368
+ for i , v := range list {
369
+ if f , ok := v .(func () interface {}); ok {
370
+ list [i ] = f ()
371
+ }
372
+ switch val := list [i ].(type ) {
373
+ case map [string ]interface {}:
374
+ dethunkMapDepthFirst (val )
375
+ case []interface {}:
376
+ dethunkListDepthFirst (val )
343
377
}
344
378
}
345
379
}
0 commit comments