executor.go

  1package graphql
  2
  3import (
  4	"context"
  5	"errors"
  6	"fmt"
  7	"reflect"
  8	"strings"
  9
 10	"github.com/graphql-go/graphql/gqlerrors"
 11	"github.com/graphql-go/graphql/language/ast"
 12)
 13
 14type ExecuteParams struct {
 15	Schema        Schema
 16	Root          interface{}
 17	AST           *ast.Document
 18	OperationName string
 19	Args          map[string]interface{}
 20
 21	// Context may be provided to pass application-specific per-request
 22	// information to resolve functions.
 23	Context context.Context
 24}
 25
 26func Execute(p ExecuteParams) (result *Result) {
 27	// Use background context if no context was provided
 28	ctx := p.Context
 29	if ctx == nil {
 30		ctx = context.Background()
 31	}
 32
 33	resultChannel := make(chan *Result)
 34
 35	go func(out chan<- *Result, done <-chan struct{}) {
 36		result := &Result{}
 37
 38		exeContext, err := buildExecutionContext(buildExecutionCtxParams{
 39			Schema:        p.Schema,
 40			Root:          p.Root,
 41			AST:           p.AST,
 42			OperationName: p.OperationName,
 43			Args:          p.Args,
 44			Errors:        nil,
 45			Result:        result,
 46			Context:       p.Context,
 47		})
 48
 49		if err != nil {
 50			result.Errors = append(result.Errors, gqlerrors.FormatError(err))
 51			select {
 52			case out <- result:
 53			case <-done:
 54			}
 55			return
 56		}
 57
 58		defer func() {
 59			if r := recover(); r != nil {
 60				var err error
 61				if r, ok := r.(error); ok {
 62					err = gqlerrors.FormatError(r)
 63				}
 64				exeContext.Errors = append(exeContext.Errors, gqlerrors.FormatError(err))
 65				result.Errors = exeContext.Errors
 66				select {
 67				case out <- result:
 68				case <-done:
 69				}
 70			}
 71		}()
 72
 73		result = executeOperation(executeOperationParams{
 74			ExecutionContext: exeContext,
 75			Root:             p.Root,
 76			Operation:        exeContext.Operation,
 77		})
 78		select {
 79		case out <- result:
 80		case <-done:
 81		}
 82
 83	}(resultChannel, ctx.Done())
 84
 85	select {
 86	case <-ctx.Done():
 87		result = &Result{}
 88		result.Errors = append(result.Errors, gqlerrors.FormatError(ctx.Err()))
 89	case r := <-resultChannel:
 90		result = r
 91	}
 92	return
 93}
 94
 95type buildExecutionCtxParams struct {
 96	Schema        Schema
 97	Root          interface{}
 98	AST           *ast.Document
 99	OperationName string
100	Args          map[string]interface{}
101	Errors        []gqlerrors.FormattedError
102	Result        *Result
103	Context       context.Context
104}
105
106type executionContext struct {
107	Schema         Schema
108	Fragments      map[string]ast.Definition
109	Root           interface{}
110	Operation      ast.Definition
111	VariableValues map[string]interface{}
112	Errors         []gqlerrors.FormattedError
113	Context        context.Context
114}
115
116func buildExecutionContext(p buildExecutionCtxParams) (*executionContext, error) {
117	eCtx := &executionContext{}
118	var operation *ast.OperationDefinition
119	fragments := map[string]ast.Definition{}
120
121	for _, definition := range p.AST.Definitions {
122		switch definition := definition.(type) {
123		case *ast.OperationDefinition:
124			if (p.OperationName == "") && operation != nil {
125				return nil, errors.New("Must provide operation name if query contains multiple operations.")
126			}
127			if p.OperationName == "" || definition.GetName() != nil && definition.GetName().Value == p.OperationName {
128				operation = definition
129			}
130		case *ast.FragmentDefinition:
131			key := ""
132			if definition.GetName() != nil && definition.GetName().Value != "" {
133				key = definition.GetName().Value
134			}
135			fragments[key] = definition
136		default:
137			return nil, fmt.Errorf("GraphQL cannot execute a request containing a %v", definition.GetKind())
138		}
139	}
140
141	if operation == nil {
142		if p.OperationName != "" {
143			return nil, fmt.Errorf(`Unknown operation named "%v".`, p.OperationName)
144		}
145		return nil, fmt.Errorf(`Must provide an operation.`)
146	}
147
148	variableValues, err := getVariableValues(p.Schema, operation.GetVariableDefinitions(), p.Args)
149	if err != nil {
150		return nil, err
151	}
152
153	eCtx.Schema = p.Schema
154	eCtx.Fragments = fragments
155	eCtx.Root = p.Root
156	eCtx.Operation = operation
157	eCtx.VariableValues = variableValues
158	eCtx.Errors = p.Errors
159	eCtx.Context = p.Context
160	return eCtx, nil
161}
162
163type executeOperationParams struct {
164	ExecutionContext *executionContext
165	Root             interface{}
166	Operation        ast.Definition
167}
168
169func executeOperation(p executeOperationParams) *Result {
170	operationType, err := getOperationRootType(p.ExecutionContext.Schema, p.Operation)
171	if err != nil {
172		return &Result{Errors: gqlerrors.FormatErrors(err)}
173	}
174
175	fields := collectFields(collectFieldsParams{
176		ExeContext:   p.ExecutionContext,
177		RuntimeType:  operationType,
178		SelectionSet: p.Operation.GetSelectionSet(),
179	})
180
181	executeFieldsParams := executeFieldsParams{
182		ExecutionContext: p.ExecutionContext,
183		ParentType:       operationType,
184		Source:           p.Root,
185		Fields:           fields,
186	}
187
188	if p.Operation.GetOperation() == ast.OperationTypeMutation {
189		return executeFieldsSerially(executeFieldsParams)
190	}
191	return executeFields(executeFieldsParams)
192
193}
194
195// Extracts the root type of the operation from the schema.
196func getOperationRootType(schema Schema, operation ast.Definition) (*Object, error) {
197	if operation == nil {
198		return nil, errors.New("Can only execute queries and mutations")
199	}
200
201	switch operation.GetOperation() {
202	case ast.OperationTypeQuery:
203		return schema.QueryType(), nil
204	case ast.OperationTypeMutation:
205		mutationType := schema.MutationType()
206		if mutationType.PrivateName == "" {
207			return nil, gqlerrors.NewError(
208				"Schema is not configured for mutations",
209				[]ast.Node{operation},
210				"",
211				nil,
212				[]int{},
213				nil,
214			)
215		}
216		return mutationType, nil
217	case ast.OperationTypeSubscription:
218		subscriptionType := schema.SubscriptionType()
219		if subscriptionType.PrivateName == "" {
220			return nil, gqlerrors.NewError(
221				"Schema is not configured for subscriptions",
222				[]ast.Node{operation},
223				"",
224				nil,
225				[]int{},
226				nil,
227			)
228		}
229		return subscriptionType, nil
230	default:
231		return nil, gqlerrors.NewError(
232			"Can only execute queries, mutations and subscription",
233			[]ast.Node{operation},
234			"",
235			nil,
236			[]int{},
237			nil,
238		)
239	}
240}
241
242type executeFieldsParams struct {
243	ExecutionContext *executionContext
244	ParentType       *Object
245	Source           interface{}
246	Fields           map[string][]*ast.Field
247}
248
249// Implements the "Evaluating selection sets" section of the spec for "write" mode.
250func executeFieldsSerially(p executeFieldsParams) *Result {
251	if p.Source == nil {
252		p.Source = map[string]interface{}{}
253	}
254	if p.Fields == nil {
255		p.Fields = map[string][]*ast.Field{}
256	}
257
258	finalResults := map[string]interface{}{}
259	for responseName, fieldASTs := range p.Fields {
260		resolved, state := resolveField(p.ExecutionContext, p.ParentType, p.Source, fieldASTs)
261		if state.hasNoFieldDefs {
262			continue
263		}
264		finalResults[responseName] = resolved
265	}
266
267	return &Result{
268		Data:   finalResults,
269		Errors: p.ExecutionContext.Errors,
270	}
271}
272
273// Implements the "Evaluating selection sets" section of the spec for "read" mode.
274func executeFields(p executeFieldsParams) *Result {
275	if p.Source == nil {
276		p.Source = map[string]interface{}{}
277	}
278	if p.Fields == nil {
279		p.Fields = map[string][]*ast.Field{}
280	}
281
282	finalResults := map[string]interface{}{}
283	for responseName, fieldASTs := range p.Fields {
284		resolved, state := resolveField(p.ExecutionContext, p.ParentType, p.Source, fieldASTs)
285		if state.hasNoFieldDefs {
286			continue
287		}
288		finalResults[responseName] = resolved
289	}
290
291	return &Result{
292		Data:   finalResults,
293		Errors: p.ExecutionContext.Errors,
294	}
295}
296
297type collectFieldsParams struct {
298	ExeContext           *executionContext
299	RuntimeType          *Object // previously known as OperationType
300	SelectionSet         *ast.SelectionSet
301	Fields               map[string][]*ast.Field
302	VisitedFragmentNames map[string]bool
303}
304
305// Given a selectionSet, adds all of the fields in that selection to
306// the passed in map of fields, and returns it at the end.
307// CollectFields requires the "runtime type" of an object. For a field which
308// returns and Interface or Union type, the "runtime type" will be the actual
309// Object type returned by that field.
310func collectFields(p collectFieldsParams) map[string][]*ast.Field {
311
312	fields := p.Fields
313	if fields == nil {
314		fields = map[string][]*ast.Field{}
315	}
316	if p.VisitedFragmentNames == nil {
317		p.VisitedFragmentNames = map[string]bool{}
318	}
319	if p.SelectionSet == nil {
320		return fields
321	}
322	for _, iSelection := range p.SelectionSet.Selections {
323		switch selection := iSelection.(type) {
324		case *ast.Field:
325			if !shouldIncludeNode(p.ExeContext, selection.Directives) {
326				continue
327			}
328			name := getFieldEntryKey(selection)
329			if _, ok := fields[name]; !ok {
330				fields[name] = []*ast.Field{}
331			}
332			fields[name] = append(fields[name], selection)
333		case *ast.InlineFragment:
334
335			if !shouldIncludeNode(p.ExeContext, selection.Directives) ||
336				!doesFragmentConditionMatch(p.ExeContext, selection, p.RuntimeType) {
337				continue
338			}
339			innerParams := collectFieldsParams{
340				ExeContext:           p.ExeContext,
341				RuntimeType:          p.RuntimeType,
342				SelectionSet:         selection.SelectionSet,
343				Fields:               fields,
344				VisitedFragmentNames: p.VisitedFragmentNames,
345			}
346			collectFields(innerParams)
347		case *ast.FragmentSpread:
348			fragName := ""
349			if selection.Name != nil {
350				fragName = selection.Name.Value
351			}
352			if visited, ok := p.VisitedFragmentNames[fragName]; (ok && visited) ||
353				!shouldIncludeNode(p.ExeContext, selection.Directives) {
354				continue
355			}
356			p.VisitedFragmentNames[fragName] = true
357			fragment, hasFragment := p.ExeContext.Fragments[fragName]
358			if !hasFragment {
359				continue
360			}
361
362			if fragment, ok := fragment.(*ast.FragmentDefinition); ok {
363				if !doesFragmentConditionMatch(p.ExeContext, fragment, p.RuntimeType) {
364					continue
365				}
366				innerParams := collectFieldsParams{
367					ExeContext:           p.ExeContext,
368					RuntimeType:          p.RuntimeType,
369					SelectionSet:         fragment.GetSelectionSet(),
370					Fields:               fields,
371					VisitedFragmentNames: p.VisitedFragmentNames,
372				}
373				collectFields(innerParams)
374			}
375		}
376	}
377	return fields
378}
379
380// Determines if a field should be included based on the @include and @skip
381// directives, where @skip has higher precedence than @include.
382func shouldIncludeNode(eCtx *executionContext, directives []*ast.Directive) bool {
383
384	defaultReturnValue := true
385
386	var skipAST *ast.Directive
387	var includeAST *ast.Directive
388	for _, directive := range directives {
389		if directive == nil || directive.Name == nil {
390			continue
391		}
392		if directive.Name.Value == SkipDirective.Name {
393			skipAST = directive
394			break
395		}
396	}
397	if skipAST != nil {
398		argValues, err := getArgumentValues(
399			SkipDirective.Args,
400			skipAST.Arguments,
401			eCtx.VariableValues,
402		)
403		if err != nil {
404			return defaultReturnValue
405		}
406		if skipIf, ok := argValues["if"].(bool); ok {
407			if skipIf == true {
408				return false
409			}
410		}
411	}
412	for _, directive := range directives {
413		if directive == nil || directive.Name == nil {
414			continue
415		}
416		if directive.Name.Value == IncludeDirective.Name {
417			includeAST = directive
418			break
419		}
420	}
421	if includeAST != nil {
422		argValues, err := getArgumentValues(
423			IncludeDirective.Args,
424			includeAST.Arguments,
425			eCtx.VariableValues,
426		)
427		if err != nil {
428			return defaultReturnValue
429		}
430		if includeIf, ok := argValues["if"].(bool); ok {
431			if includeIf == false {
432				return false
433			}
434		}
435	}
436	return defaultReturnValue
437}
438
439// Determines if a fragment is applicable to the given type.
440func doesFragmentConditionMatch(eCtx *executionContext, fragment ast.Node, ttype *Object) bool {
441
442	switch fragment := fragment.(type) {
443	case *ast.FragmentDefinition:
444		typeConditionAST := fragment.TypeCondition
445		if typeConditionAST == nil {
446			return true
447		}
448		conditionalType, err := typeFromAST(eCtx.Schema, typeConditionAST)
449		if err != nil {
450			return false
451		}
452		if conditionalType == ttype {
453			return true
454		}
455		if conditionalType.Name() == ttype.Name() {
456			return true
457		}
458		if conditionalType, ok := conditionalType.(*Interface); ok {
459			return eCtx.Schema.IsPossibleType(conditionalType, ttype)
460		}
461		if conditionalType, ok := conditionalType.(*Union); ok {
462			return eCtx.Schema.IsPossibleType(conditionalType, ttype)
463		}
464	case *ast.InlineFragment:
465		typeConditionAST := fragment.TypeCondition
466		if typeConditionAST == nil {
467			return true
468		}
469		conditionalType, err := typeFromAST(eCtx.Schema, typeConditionAST)
470		if err != nil {
471			return false
472		}
473		if conditionalType == ttype {
474			return true
475		}
476		if conditionalType.Name() == ttype.Name() {
477			return true
478		}
479		if conditionalType, ok := conditionalType.(*Interface); ok {
480			return eCtx.Schema.IsPossibleType(conditionalType, ttype)
481		}
482		if conditionalType, ok := conditionalType.(*Union); ok {
483			return eCtx.Schema.IsPossibleType(conditionalType, ttype)
484		}
485	}
486
487	return false
488}
489
490// Implements the logic to compute the key of a given field’s entry
491func getFieldEntryKey(node *ast.Field) string {
492
493	if node.Alias != nil && node.Alias.Value != "" {
494		return node.Alias.Value
495	}
496	if node.Name != nil && node.Name.Value != "" {
497		return node.Name.Value
498	}
499	return ""
500}
501
502// Internal resolveField state
503type resolveFieldResultState struct {
504	hasNoFieldDefs bool
505}
506
507// Resolves the field on the given source object. In particular, this
508// figures out the value that the field returns by calling its resolve function,
509// then calls completeValue to complete promises, serialize scalars, or execute
510// the sub-selection-set for objects.
511func resolveField(eCtx *executionContext, parentType *Object, source interface{}, fieldASTs []*ast.Field) (result interface{}, resultState resolveFieldResultState) {
512	// catch panic from resolveFn
513	var returnType Output
514	defer func() (interface{}, resolveFieldResultState) {
515		if r := recover(); r != nil {
516
517			var err error
518			if r, ok := r.(string); ok {
519				err = NewLocatedError(
520					fmt.Sprintf("%v", r),
521					FieldASTsToNodeASTs(fieldASTs),
522				)
523			}
524			if r, ok := r.(error); ok {
525				err = gqlerrors.FormatError(r)
526			}
527			// send panic upstream
528			if _, ok := returnType.(*NonNull); ok {
529				panic(gqlerrors.FormatError(err))
530			}
531			eCtx.Errors = append(eCtx.Errors, gqlerrors.FormatError(err))
532			return result, resultState
533		}
534		return result, resultState
535	}()
536
537	fieldAST := fieldASTs[0]
538	fieldName := ""
539	if fieldAST.Name != nil {
540		fieldName = fieldAST.Name.Value
541	}
542
543	fieldDef := getFieldDef(eCtx.Schema, parentType, fieldName)
544	if fieldDef == nil {
545		resultState.hasNoFieldDefs = true
546		return nil, resultState
547	}
548	returnType = fieldDef.Type
549	resolveFn := fieldDef.Resolve
550	if resolveFn == nil {
551		resolveFn = DefaultResolveFn
552	}
553
554	// Build a map of arguments from the field.arguments AST, using the
555	// variables scope to fulfill any variable references.
556	// TODO: find a way to memoize, in case this field is within a List type.
557	args, _ := getArgumentValues(fieldDef.Args, fieldAST.Arguments, eCtx.VariableValues)
558
559	info := ResolveInfo{
560		FieldName:      fieldName,
561		FieldASTs:      fieldASTs,
562		ReturnType:     returnType,
563		ParentType:     parentType,
564		Schema:         eCtx.Schema,
565		Fragments:      eCtx.Fragments,
566		RootValue:      eCtx.Root,
567		Operation:      eCtx.Operation,
568		VariableValues: eCtx.VariableValues,
569	}
570
571	var resolveFnError error
572
573	result, resolveFnError = resolveFn(ResolveParams{
574		Source:  source,
575		Args:    args,
576		Info:    info,
577		Context: eCtx.Context,
578	})
579
580	if resolveFnError != nil {
581		panic(gqlerrors.FormatError(resolveFnError))
582	}
583
584	completed := completeValueCatchingError(eCtx, returnType, fieldASTs, info, result)
585	return completed, resultState
586}
587
588func completeValueCatchingError(eCtx *executionContext, returnType Type, fieldASTs []*ast.Field, info ResolveInfo, result interface{}) (completed interface{}) {
589	// catch panic
590	defer func() interface{} {
591		if r := recover(); r != nil {
592			//send panic upstream
593			if _, ok := returnType.(*NonNull); ok {
594				panic(r)
595			}
596			if err, ok := r.(gqlerrors.FormattedError); ok {
597				eCtx.Errors = append(eCtx.Errors, err)
598			}
599			return completed
600		}
601		return completed
602	}()
603
604	if returnType, ok := returnType.(*NonNull); ok {
605		completed := completeValue(eCtx, returnType, fieldASTs, info, result)
606		return completed
607	}
608	completed = completeValue(eCtx, returnType, fieldASTs, info, result)
609	return completed
610}
611
612func completeValue(eCtx *executionContext, returnType Type, fieldASTs []*ast.Field, info ResolveInfo, result interface{}) interface{} {
613
614	resultVal := reflect.ValueOf(result)
615	if resultVal.IsValid() && resultVal.Type().Kind() == reflect.Func {
616		if propertyFn, ok := result.(func() interface{}); ok {
617			return propertyFn()
618		}
619		err := gqlerrors.NewFormattedError("Error resolving func. Expected `func() interface{}` signature")
620		panic(gqlerrors.FormatError(err))
621	}
622
623	// If field type is NonNull, complete for inner type, and throw field error
624	// if result is null.
625	if returnType, ok := returnType.(*NonNull); ok {
626		completed := completeValue(eCtx, returnType.OfType, fieldASTs, info, result)
627		if completed == nil {
628			err := NewLocatedError(
629				fmt.Sprintf("Cannot return null for non-nullable field %v.%v.", info.ParentType, info.FieldName),
630				FieldASTsToNodeASTs(fieldASTs),
631			)
632			panic(gqlerrors.FormatError(err))
633		}
634		return completed
635	}
636
637	// If result value is null-ish (null, undefined, or NaN) then return null.
638	if isNullish(result) {
639		return nil
640	}
641
642	// If field type is List, complete each item in the list with the inner type
643	if returnType, ok := returnType.(*List); ok {
644		return completeListValue(eCtx, returnType, fieldASTs, info, result)
645	}
646
647	// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
648	// returning null if serialization is not possible.
649	if returnType, ok := returnType.(*Scalar); ok {
650		return completeLeafValue(returnType, result)
651	}
652	if returnType, ok := returnType.(*Enum); ok {
653		return completeLeafValue(returnType, result)
654	}
655
656	// If field type is an abstract type, Interface or Union, determine the
657	// runtime Object type and complete for that type.
658	if returnType, ok := returnType.(*Union); ok {
659		return completeAbstractValue(eCtx, returnType, fieldASTs, info, result)
660	}
661	if returnType, ok := returnType.(*Interface); ok {
662		return completeAbstractValue(eCtx, returnType, fieldASTs, info, result)
663	}
664
665	// If field type is Object, execute and complete all sub-selections.
666	if returnType, ok := returnType.(*Object); ok {
667		return completeObjectValue(eCtx, returnType, fieldASTs, info, result)
668	}
669
670	// Not reachable. All possible output types have been considered.
671	err := invariantf(false,
672		`Cannot complete value of unexpected type "%v."`, returnType)
673
674	if err != nil {
675		panic(gqlerrors.FormatError(err))
676	}
677	return nil
678}
679
680// completeAbstractValue completes value of an Abstract type (Union / Interface) by determining the runtime type
681// of that value, then completing based on that type.
682func completeAbstractValue(eCtx *executionContext, returnType Abstract, fieldASTs []*ast.Field, info ResolveInfo, result interface{}) interface{} {
683
684	var runtimeType *Object
685
686	resolveTypeParams := ResolveTypeParams{
687		Value:   result,
688		Info:    info,
689		Context: eCtx.Context,
690	}
691	if unionReturnType, ok := returnType.(*Union); ok && unionReturnType.ResolveType != nil {
692		runtimeType = unionReturnType.ResolveType(resolveTypeParams)
693	} else if interfaceReturnType, ok := returnType.(*Interface); ok && interfaceReturnType.ResolveType != nil {
694		runtimeType = interfaceReturnType.ResolveType(resolveTypeParams)
695	} else {
696		runtimeType = defaultResolveTypeFn(resolveTypeParams, returnType)
697	}
698
699	err := invariant(runtimeType != nil,
700		fmt.Sprintf(`Abstract type %v must resolve to an Object type at runtime `+
701			`for field %v.%v with value "%v", received "%v".`,
702			returnType, info.ParentType, info.FieldName, result, runtimeType),
703	)
704	if err != nil {
705		panic(err)
706	}
707
708	if !eCtx.Schema.IsPossibleType(returnType, runtimeType) {
709		panic(gqlerrors.NewFormattedError(
710			fmt.Sprintf(`Runtime Object type "%v" is not a possible type `+
711				`for "%v".`, runtimeType, returnType),
712		))
713	}
714
715	return completeObjectValue(eCtx, runtimeType, fieldASTs, info, result)
716}
717
718// completeObjectValue complete an Object value by executing all sub-selections.
719func completeObjectValue(eCtx *executionContext, returnType *Object, fieldASTs []*ast.Field, info ResolveInfo, result interface{}) interface{} {
720
721	// If there is an isTypeOf predicate function, call it with the
722	// current result. If isTypeOf returns false, then raise an error rather
723	// than continuing execution.
724	if returnType.IsTypeOf != nil {
725		p := IsTypeOfParams{
726			Value:   result,
727			Info:    info,
728			Context: eCtx.Context,
729		}
730		if !returnType.IsTypeOf(p) {
731			panic(gqlerrors.NewFormattedError(
732				fmt.Sprintf(`Expected value of type "%v" but got: %T.`, returnType, result),
733			))
734		}
735	}
736
737	// Collect sub-fields to execute to complete this value.
738	subFieldASTs := map[string][]*ast.Field{}
739	visitedFragmentNames := map[string]bool{}
740	for _, fieldAST := range fieldASTs {
741		if fieldAST == nil {
742			continue
743		}
744		selectionSet := fieldAST.SelectionSet
745		if selectionSet != nil {
746			innerParams := collectFieldsParams{
747				ExeContext:           eCtx,
748				RuntimeType:          returnType,
749				SelectionSet:         selectionSet,
750				Fields:               subFieldASTs,
751				VisitedFragmentNames: visitedFragmentNames,
752			}
753			subFieldASTs = collectFields(innerParams)
754		}
755	}
756	executeFieldsParams := executeFieldsParams{
757		ExecutionContext: eCtx,
758		ParentType:       returnType,
759		Source:           result,
760		Fields:           subFieldASTs,
761	}
762	results := executeFields(executeFieldsParams)
763
764	return results.Data
765
766}
767
768// completeLeafValue complete a leaf value (Scalar / Enum) by serializing to a valid value, returning nil if serialization is not possible.
769func completeLeafValue(returnType Leaf, result interface{}) interface{} {
770	serializedResult := returnType.Serialize(result)
771	if isNullish(serializedResult) {
772		return nil
773	}
774	return serializedResult
775}
776
777// completeListValue complete a list value by completing each item in the list with the inner type
778func completeListValue(eCtx *executionContext, returnType *List, fieldASTs []*ast.Field, info ResolveInfo, result interface{}) interface{} {
779	resultVal := reflect.ValueOf(result)
780	parentTypeName := ""
781	if info.ParentType != nil {
782		parentTypeName = info.ParentType.Name()
783	}
784	err := invariantf(
785		resultVal.IsValid() && resultVal.Type().Kind() == reflect.Slice,
786		"User Error: expected iterable, but did not find one "+
787			"for field %v.%v.", parentTypeName, info.FieldName)
788
789	if err != nil {
790		panic(gqlerrors.FormatError(err))
791	}
792
793	itemType := returnType.OfType
794	completedResults := []interface{}{}
795	for i := 0; i < resultVal.Len(); i++ {
796		val := resultVal.Index(i).Interface()
797		completedItem := completeValueCatchingError(eCtx, itemType, fieldASTs, info, val)
798		completedResults = append(completedResults, completedItem)
799	}
800	return completedResults
801}
802
803// defaultResolveTypeFn If a resolveType function is not given, then a default resolve behavior is
804// used which tests each possible type for the abstract type by calling
805// isTypeOf for the object being coerced, returning the first type that matches.
806func defaultResolveTypeFn(p ResolveTypeParams, abstractType Abstract) *Object {
807	possibleTypes := p.Info.Schema.PossibleTypes(abstractType)
808	for _, possibleType := range possibleTypes {
809		if possibleType.IsTypeOf == nil {
810			continue
811		}
812		isTypeOfParams := IsTypeOfParams{
813			Value:   p.Value,
814			Info:    p.Info,
815			Context: p.Context,
816		}
817		if res := possibleType.IsTypeOf(isTypeOfParams); res {
818			return possibleType
819		}
820	}
821	return nil
822}
823
824// FieldResolver is used in DefaultResolveFn when the the source value implements this interface.
825type FieldResolver interface {
826	// Resolve resolves the value for the given ResolveParams. It has the same semantics as FieldResolveFn.
827	Resolve(p ResolveParams) (interface{}, error)
828}
829
830// defaultResolveFn If a resolve function is not given, then a default resolve behavior is used
831// which takes the property of the source object of the same name as the field
832// and returns it as the result, or if it's a function, returns the result
833// of calling that function.
834func DefaultResolveFn(p ResolveParams) (interface{}, error) {
835	// try to resolve p.Source as a struct first
836	sourceVal := reflect.ValueOf(p.Source)
837	if sourceVal.IsValid() && sourceVal.Type().Kind() == reflect.Ptr {
838		sourceVal = sourceVal.Elem()
839	}
840	if !sourceVal.IsValid() {
841		return nil, nil
842	}
843
844	// Check if value implements 'Resolver' interface
845	if resolver, ok := sourceVal.Interface().(FieldResolver); ok {
846		return resolver.Resolve(p)
847	}
848
849	if sourceVal.Type().Kind() == reflect.Struct {
850		for i := 0; i < sourceVal.NumField(); i++ {
851			valueField := sourceVal.Field(i)
852			typeField := sourceVal.Type().Field(i)
853			// try matching the field name first
854			if typeField.Name == p.Info.FieldName {
855				return valueField.Interface(), nil
856			}
857			tag := typeField.Tag
858			checkTag := func(tagName string) bool {
859				t := tag.Get(tagName)
860				tOptions := strings.Split(t, ",")
861				if len(tOptions) == 0 {
862					return false
863				}
864				if tOptions[0] != p.Info.FieldName {
865					return false
866				}
867				return true
868			}
869			if checkTag("json") || checkTag("graphql") {
870				return valueField.Interface(), nil
871			} else {
872				continue
873			}
874		}
875		return nil, nil
876	}
877
878	// try p.Source as a map[string]interface
879	if sourceMap, ok := p.Source.(map[string]interface{}); ok {
880		property := sourceMap[p.Info.FieldName]
881		val := reflect.ValueOf(property)
882		if val.IsValid() && val.Type().Kind() == reflect.Func {
883			// try type casting the func to the most basic func signature
884			// for more complex signatures, user have to define ResolveFn
885			if propertyFn, ok := property.(func() interface{}); ok {
886				return propertyFn(), nil
887			}
888		}
889		return property, nil
890	}
891
892	// last resort, return nil
893	return nil, nil
894}
895
896// This method looks up the field on the given type definition.
897// It has special casing for the two introspection fields, __schema
898// and __typename. __typename is special because it can always be
899// queried as a field, even in situations where no other fields
900// are allowed, like on a Union. __schema could get automatically
901// added to the query type, but that would require mutating type
902// definitions, which would cause issues.
903func getFieldDef(schema Schema, parentType *Object, fieldName string) *FieldDefinition {
904
905	if parentType == nil {
906		return nil
907	}
908
909	if fieldName == SchemaMetaFieldDef.Name &&
910		schema.QueryType() == parentType {
911		return SchemaMetaFieldDef
912	}
913	if fieldName == TypeMetaFieldDef.Name &&
914		schema.QueryType() == parentType {
915		return TypeMetaFieldDef
916	}
917	if fieldName == TypeNameMetaFieldDef.Name {
918		return TypeNameMetaFieldDef
919	}
920	return parentType.Fields()[fieldName]
921}