Skip to content

Commit 7d6e654

Browse files
committed
Changed executor.go so that executeSerially executes a depth-first
traversal.
1 parent cc18794 commit 7d6e654

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

executor.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ func executeFieldsSerially(p executeFieldsParams) *Result {
245245
}
246246
finalResults[responseName] = resolved
247247
}
248-
dethunkWithBreadthFirstTraversal(finalResults)
248+
dethunkMapDepthFirst(finalResults)
249249

250250
return &Result{
251251
Data: finalResults,
@@ -257,7 +257,7 @@ func executeFieldsSerially(p executeFieldsParams) *Result {
257257
func executeFields(p executeFieldsParams) *Result {
258258
finalResults := executeSubFields(p)
259259

260-
dethunkWithBreadthFirstTraversal(finalResults)
260+
dethunkMapWithBreadthFirstTraversal(finalResults)
261261

262262
return &Result{
263263
Data: finalResults,
@@ -302,17 +302,19 @@ func (d *dethunkQueue) shift() func() {
302302
}
303303

304304
// 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{}) {
307309
dethunkQueue := &dethunkQueue{DethunkFuncs: []func(){}}
308-
dethunkMap(finalResults, dethunkQueue)
310+
dethunkMapBreadthFirst(finalResults, dethunkQueue)
309311
for len(dethunkQueue.DethunkFuncs) > 0 {
310312
f := dethunkQueue.shift()
311313
f()
312314
}
313315
}
314316

315-
func dethunkMap(m map[string]interface{}, dethunkQueue *dethunkQueue) {
317+
func dethunkMapBreadthFirst(m map[string]interface{}, dethunkQueue *dethunkQueue) {
316318
for k, v := range m {
317319
if f, ok := v.(func() interface{}); ok {
318320
m[k] = f()
@@ -321,14 +323,14 @@ func dethunkMap(m map[string]interface{}, dethunkQueue *dethunkQueue) {
321323
for _, v := range m {
322324
switch val := v.(type) {
323325
case map[string]interface{}:
324-
dethunkQueue.push(func() { dethunkMap(val, dethunkQueue) })
326+
dethunkQueue.push(func() { dethunkMapBreadthFirst(val, dethunkQueue) })
325327
case []interface{}:
326-
dethunkQueue.push(func() { dethunkList(val, dethunkQueue) })
328+
dethunkQueue.push(func() { dethunkListBreadthFirst(val, dethunkQueue) })
327329
}
328330
}
329331
}
330332

331-
func dethunkList(list []interface{}, dethunkQueue *dethunkQueue) {
333+
func dethunkListBreadthFirst(list []interface{}, dethunkQueue *dethunkQueue) {
332334
for i, v := range list {
333335
if f, ok := v.(func() interface{}); ok {
334336
list[i] = f()
@@ -337,9 +339,41 @@ func dethunkList(list []interface{}, dethunkQueue *dethunkQueue) {
337339
for _, v := range list {
338340
switch val := v.(type) {
339341
case map[string]interface{}:
340-
dethunkQueue.push(func() { dethunkMap(val, dethunkQueue) })
342+
dethunkQueue.push(func() { dethunkMapBreadthFirst(val, dethunkQueue) })
341343
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)
343377
}
344378
}
345379
}

0 commit comments

Comments
 (0)