|
5 | 5 | "errors"
|
6 | 6 | "fmt"
|
7 | 7 | "reflect"
|
| 8 | + "sort" |
8 | 9 | "strings"
|
9 | 10 |
|
10 | 11 | "github.com/graphql-go/graphql/gqlerrors"
|
@@ -254,7 +255,9 @@ func executeFieldsSerially(p executeFieldsParams) *Result {
|
254 | 255 | }
|
255 | 256 |
|
256 | 257 | finalResults := make(map[string]interface{}, len(p.Fields))
|
257 |
| - for responseName, fieldASTs := range p.Fields { |
| 258 | + for _, orderedField := range orderedFields(p.Fields) { |
| 259 | + responseName := orderedField.responseName |
| 260 | + fieldASTs := orderedField.fieldASTs |
258 | 261 | fieldPath := p.Path.WithKey(responseName)
|
259 | 262 | resolved, state := resolveField(p.ExecutionContext, p.ParentType, p.Source, fieldASTs, fieldPath)
|
260 | 263 | if state.hasNoFieldDefs {
|
@@ -650,15 +653,15 @@ func resolveField(eCtx *executionContext, parentType *Object, source interface{}
|
650 | 653 | Context: eCtx.Context,
|
651 | 654 | })
|
652 | 655 |
|
653 |
| - if resolveFnError != nil { |
654 |
| - panic(resolveFnError) |
655 |
| - } |
656 |
| - |
657 | 656 | extErrs = resolveFieldFinishFn(result, resolveFnError)
|
658 | 657 | if len(extErrs) != 0 {
|
659 | 658 | eCtx.Errors = append(eCtx.Errors, extErrs...)
|
660 | 659 | }
|
661 | 660 |
|
| 661 | + if resolveFnError != nil { |
| 662 | + panic(resolveFnError) |
| 663 | + } |
| 664 | + |
662 | 665 | completed := completeValueCatchingError(eCtx, returnType, fieldASTs, info, path, result)
|
663 | 666 | return completed, resultState
|
664 | 667 | }
|
@@ -1038,3 +1041,39 @@ func getFieldDef(schema Schema, parentType *Object, fieldName string) *FieldDefi
|
1038 | 1041 | }
|
1039 | 1042 | return parentType.Fields()[fieldName]
|
1040 | 1043 | }
|
| 1044 | + |
| 1045 | +// contains field information that will be placed in an ordered slice |
| 1046 | +type orderedField struct { |
| 1047 | + responseName string |
| 1048 | + fieldASTs []*ast.Field |
| 1049 | +} |
| 1050 | + |
| 1051 | +// orders fields from a fields map by location in the source |
| 1052 | +func orderedFields(fields map[string][]*ast.Field) []*orderedField { |
| 1053 | + orderedFields := []*orderedField{} |
| 1054 | + fieldMap := map[int]*orderedField{} |
| 1055 | + startLocs := []int{} |
| 1056 | + |
| 1057 | + for responseName, fieldASTs := range fields { |
| 1058 | + // find the lowest location in the current fieldASTs |
| 1059 | + lowest := -1 |
| 1060 | + for _, fieldAST := range fieldASTs { |
| 1061 | + loc := fieldAST.GetLoc().Start |
| 1062 | + if lowest == -1 || loc < lowest { |
| 1063 | + lowest = loc |
| 1064 | + } |
| 1065 | + } |
| 1066 | + startLocs = append(startLocs, lowest) |
| 1067 | + fieldMap[lowest] = &orderedField{ |
| 1068 | + responseName: responseName, |
| 1069 | + fieldASTs: fieldASTs, |
| 1070 | + } |
| 1071 | + } |
| 1072 | + |
| 1073 | + sort.Ints(startLocs) |
| 1074 | + for _, startLoc := range startLocs { |
| 1075 | + orderedFields = append(orderedFields, fieldMap[startLoc]) |
| 1076 | + } |
| 1077 | + |
| 1078 | + return orderedFields |
| 1079 | +} |
0 commit comments