From 7efae5ecbaada0757ab923d3ea66ca19907f8956 Mon Sep 17 00:00:00 2001 From: Andy Jackson Date: Thu, 24 Aug 2017 13:38:57 -0700 Subject: [PATCH 1/2] Cleaner default resolver, cache FieldDefMap Get, preallocate --- definition.go | 3 +++ executor.go | 49 +++++++++++++++++++------------------------------ 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/definition.go b/definition.go index 83570573..8e56c68f 100644 --- a/definition.go +++ b/definition.go @@ -441,6 +441,9 @@ func (gt *Object) String() string { return gt.PrivateName } func (gt *Object) Fields() FieldDefinitionMap { + if len(gt.fields) != 0 { + return gt.fields + } var configureFields Fields switch gt.typeConfig.Fields.(type) { case Fields: diff --git a/executor.go b/executor.go index 7ca4532e..4118dd6f 100644 --- a/executor.go +++ b/executor.go @@ -278,7 +278,7 @@ func executeFields(p ExecuteFieldsParams) *Result { p.Fields = map[string][]*ast.Field{} } - finalResults := map[string]interface{}{} + finalResults := make(map[string]interface{}, len(p.Fields)) for responseName, fieldASTs := range p.Fields { resolved, state := resolveField(p.ExecutionContext, p.ParentType, p.Source, fieldASTs) if state.hasNoFieldDefs { @@ -741,16 +741,16 @@ func completeObjectValue(eCtx *ExecutionContext, returnType *Object, fieldASTs [ continue } selectionSet := fieldAST.SelectionSet - if selectionSet != nil { - innerParams := CollectFieldsParams{ - ExeContext: eCtx, - RuntimeType: returnType, - SelectionSet: selectionSet, - Fields: subFieldASTs, - VisitedFragmentNames: visitedFragmentNames, - } - subFieldASTs = collectFields(innerParams) + if selectionSet == nil { + continue } + subFieldASTs = collectFields(CollectFieldsParams{ + ExeContext: eCtx, + RuntimeType: returnType, + SelectionSet: selectionSet, + Fields: subFieldASTs, + VisitedFragmentNames: visitedFragmentNames, + }) } executeFieldsParams := ExecuteFieldsParams{ ExecutionContext: eCtx, @@ -790,7 +790,7 @@ func completeListValue(eCtx *ExecutionContext, returnType *List, fieldASTs []*as } itemType := returnType.OfType - completedResults := []interface{}{} + completedResults := make([]interface{}, 0, resultVal.Len()) for i := 0; i < resultVal.Len(); i++ { val := resultVal.Index(i).Interface() completedItem := completeValueCatchingError(eCtx, itemType, fieldASTs, info, val) @@ -834,29 +834,18 @@ func DefaultResolveFn(p ResolveParams) (interface{}, error) { return nil, nil } if sourceVal.Type().Kind() == reflect.Struct { + // try matching the field name first + if v := sourceVal.FieldByName(p.Info.FieldName); v.IsValid() { + return v.Interface(), nil + } + var tag reflect.StructTag for i := 0; i < sourceVal.NumField(); i++ { - valueField := sourceVal.Field(i) - typeField := sourceVal.Type().Field(i) - // try matching the field name first - if typeField.Name == p.Info.FieldName { - return valueField.Interface(), nil - } - tag := typeField.Tag + tag = sourceVal.Type().Field(i).Tag checkTag := func(tagName string) bool { - t := tag.Get(tagName) - tOptions := strings.Split(t, ",") - if len(tOptions) == 0 { - return false - } - if tOptions[0] != p.Info.FieldName { - return false - } - return true + return strings.SplitN(tag.Get(tagName), ",", 1)[0] == p.Info.FieldName } if checkTag("json") || checkTag("graphql") { - return valueField.Interface(), nil - } else { - continue + return sourceVal.Field(i).Interface(), nil } } return nil, nil From 2ae4ce6de316cea36e38764851b0b95d5dde6998 Mon Sep 17 00:00:00 2001 From: Andy Jackson Date: Thu, 24 Aug 2017 14:31:04 -0700 Subject: [PATCH 2/2] save duplicate check for non-pointers --- executor.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/executor.go b/executor.go index 4118dd6f..cc3d5dab 100644 --- a/executor.go +++ b/executor.go @@ -827,12 +827,17 @@ func defaultResolveTypeFn(p ResolveTypeParams, abstractType Abstract) *Object { func DefaultResolveFn(p ResolveParams) (interface{}, error) { // try to resolve p.Source as a struct first sourceVal := reflect.ValueOf(p.Source) - if sourceVal.IsValid() && sourceVal.Type().Kind() == reflect.Ptr { - sourceVal = sourceVal.Elem() - } - if !sourceVal.IsValid() { + if sourceVal.IsValid() { + if sourceVal.Type().Kind() == reflect.Ptr { + sourceVal = sourceVal.Elem() + if !sourceVal.IsValid() { + return nil, nil + } + } + } else { return nil, nil } + if sourceVal.Type().Kind() == reflect.Struct { // try matching the field name first if v := sourceVal.FieldByName(p.Info.FieldName); v.IsValid() {