|
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