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