Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6329,3 +6329,96 @@ query Q {
}
})
}

// https://github.com/graph-gophers/graphql-go/issues/763
type issue763ThingResolver interface {
Alpha(ctx context.Context, args struct {
Query *string
Limit *int32
}) (string, error)
Beta(ctx context.Context, args struct{ Query *string }) (string, error)
}

type issue763ConcreteThingResolver struct{}

// sorts before Alpha, shifting method indices on the concrete type to reproduce #763
func (r *issue763ConcreteThingResolver) AaExtra() string {
return ""
}

func (r *issue763ConcreteThingResolver) Alpha(_ context.Context, args struct {
Query *string
Limit *int32
},
) (string, error) {
return "alpha", nil
}

func (r *issue763ConcreteThingResolver) Beta(_ context.Context, args struct{ Query *string }) (string, error) {
return "beta", nil
}

type issueRootResolver763 struct{}

func (r *issueRootResolver763) Thing() (issue763ThingResolver, error) {
return &issue763ConcreteThingResolver{}, nil
}

func TestInterfaceResolverMethodIndex(t *testing.T) {
t.Parallel()

gqltesting.RunTest(t, &gqltesting.Test{
Schema: graphql.MustParseSchema(`
type Query { thing: Thing! }
type Thing {
alpha(query: String, limit: Int): String!
beta(query: String): String!
}
`, &issueRootResolver763{}),
Query: `{ thing { beta(query: "test") } }`,
ExpectedResult: `{"thing":{"beta":"beta"}}`,
})
}

type issue763ListUnionNodeResolver interface {
Label(ctx context.Context, args struct{ Query *string }) (string, error)
}

type issue763ListUnionConcreteNodeResolver struct{}

// sorts before Label, shifting method indices on the concrete type to reproduce #763
func (r *issue763ListUnionConcreteNodeResolver) AaExtra() string {
return ""
}

func (r *issue763ListUnionConcreteNodeResolver) Label(_ context.Context, args struct{ Query *string }) (string, error) {
return "label:" + *args.Query, nil
}

type issue763ListUnionSearchResultResolver struct{}

func (r *issue763ListUnionSearchResultResolver) ToNodeImpl() (issue763ListUnionNodeResolver, bool) {
return &issue763ListUnionConcreteNodeResolver{}, true
}

type issue763ListUnionRootResolver struct{}

func (r *issue763ListUnionRootResolver) Search() ([]*issue763ListUnionSearchResultResolver, error) {
return []*issue763ListUnionSearchResultResolver{{}}, nil
}

func TestIssue763InterfaceMethodIndexInListUnion(t *testing.T) {
t.Parallel()

gqltesting.RunTest(t, &gqltesting.Test{
Schema: graphql.MustParseSchema(`
type Query { search: [Search!]! }
union Search = NodeImpl
type NodeImpl {
label(query: String): String!
}
`, &issue763ListUnionRootResolver{}),
Query: `{ search { ... on NodeImpl { label(query: "x") } } }`,
ExpectedResult: `{"search":[{"label":"label:x"}]}`,
})
}
7 changes: 3 additions & 4 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type fieldToExec struct {
out *bytes.Buffer
}

func (f *fieldToExec) resolve(ctx context.Context) (output any, err error) {
func (f *fieldToExec) resolve(ctx context.Context) (reflect.Value, error) {
return f.field.Resolve(ctx, f.resolver)
}

Expand Down Expand Up @@ -271,7 +271,8 @@ func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f
if len(f.sels) > 0 && !r.DisableFieldSelections {
ctx = selections.With(traceCtx, f.sels)
}
res, resolverErr := f.resolve(ctx)
var resolverErr error
result, resolverErr = f.resolve(ctx)
if resolverErr != nil {
err := errors.Errorf("%s", resolverErr)
err.Path = path.toSlice()
Expand All @@ -282,8 +283,6 @@ func execFieldSelection(ctx context.Context, r *Request, s *resolvable.Schema, f
return err
}

result = reflect.ValueOf(res)

return nil
}()

Expand Down
14 changes: 7 additions & 7 deletions internal/exec/resolvable/resolvable.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (f *Field) UseMethodResolver() bool {
return f.MethodIndex != -1 || f.IsFieldFunc
}

func (f *Field) Resolve(ctx context.Context, resolver reflect.Value, args map[string]any, packedArgs reflect.Value) (output any, err error) {
func (f *Field) Resolve(ctx context.Context, resolver reflect.Value, args map[string]any, packedArgs reflect.Value) (reflect.Value, error) {
if len(f.Implementations) > 0 {
for _, impl := range f.Implementations {
out := resolver.Method(impl.MethodIndex).Call(nil)
Expand All @@ -77,10 +77,10 @@ func (f *Field) Resolve(ctx context.Context, resolver reflect.Value, args map[st
return f.resolve(ctx, resolver, args, packedArgs)
}

func (f *Field) resolve(ctx context.Context, resolver reflect.Value, args map[string]any, packedArgs reflect.Value) (output any, err error) {
func (f *Field) resolve(ctx context.Context, resolver reflect.Value, args map[string]any, packedArgs reflect.Value) (reflect.Value, error) {
if !f.UseMethodResolver() {
if len(f.FieldIndex) == 0 {
return nil, fmt.Errorf("missing resolver for field %q", f.Name)
return reflect.Value{}, fmt.Errorf("missing resolver for field %q", f.Name)
}
res := resolver

Expand All @@ -89,7 +89,7 @@ func (f *Field) resolve(ctx context.Context, resolver reflect.Value, args map[st
res = res.Elem()
}

return res.FieldByIndex(f.FieldIndex).Interface(), nil
return res.FieldByIndex(f.FieldIndex), nil
}

var in []reflect.Value
Expand All @@ -103,7 +103,7 @@ func (f *Field) resolve(ctx context.Context, resolver reflect.Value, args map[st
if !packedArgs.IsValid() {
packed, packErr := f.ArgsPacker.Pack(args)
if packErr != nil {
return nil, packErr
return reflect.Value{}, packErr
}
packedArgs = packed
}
Expand All @@ -123,10 +123,10 @@ func (f *Field) resolve(ctx context.Context, resolver reflect.Value, args map[st

if f.HasError && !callOut[1].IsNil() {
resolverErr := callOut[1].Interface().(error)
return result.Interface(), resolverErr
return result, resolverErr
}

return result.Interface(), nil
return result, nil
}

type TypeAssertion struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/exec/selected/selected.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type SchemaField struct {
FixedResult reflect.Value
}

func (f *SchemaField) Resolve(ctx context.Context, resolver reflect.Value) (output any, err error) {
func (f *SchemaField) Resolve(ctx context.Context, resolver reflect.Value) (reflect.Value, error) {
return f.Field.Resolve(ctx, resolver, f.Args, f.PackedArgs)
}

Expand Down