From 9c3123cd8aa72ced2bd6e9c7ceac424367589971 Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Tue, 27 Nov 2018 19:26:02 +1100 Subject: [PATCH 1/3] Add a benchmark go test -benchtime=5s -bench=. -benchmem goos: linux goarch: amd64 pkg: github.com/99designs/gqlgen/example/starwars BenchmarkSimpleQueryNoArgs-8 200000 32680 ns/op 6357 B/op 126 allocs/op PASS ok github.com/99designs/gqlgen/example/starwars 9.901s --- .gitignore | 2 ++ example/starwars/benchmarks_test.go | 30 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 example/starwars/benchmarks_test.go diff --git a/.gitignore b/.gitignore index a9712beb0bc..c0ff0ef28b9 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ /codegen/gen .idea/ +*.test +*.out diff --git a/example/starwars/benchmarks_test.go b/example/starwars/benchmarks_test.go new file mode 100644 index 00000000000..8386b7963f0 --- /dev/null +++ b/example/starwars/benchmarks_test.go @@ -0,0 +1,30 @@ +package starwars + +import ( + "net/http/httptest" + "strings" + "testing" + + "github.com/99designs/gqlgen/handler" +) + +func BenchmarkSimpleQueryNoArgs(b *testing.B) { + server := handler.GraphQL(NewExecutableSchema(NewResolver())) + + q := `{"query":"{ search(text:\"Luke\") { ... on Human { starships { name } } } }"}` + + var body strings.Reader + r := httptest.NewRequest("POST", "/graphql", &body) + + b.ResetTimer() + rec := httptest.NewRecorder() + for i := 0; i < b.N; i++ { + body.Reset(q) + rec.Body.Reset() + server.ServeHTTP(rec, r) + if rec.Body.String() != `{"data":{"search":[{"starships":[{"name":"X-Wing"},{"name":"Imperial shuttle"}]}]}}` { + b.Fatalf("Unexpected response") + } + + } +} From b66090325046aefb5b5606f421de49a74181de0f Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Tue, 27 Nov 2018 19:27:19 +1100 Subject: [PATCH 2/3] Remove strconv.Quote call in hot path to avoid some allocs go test -benchtime=5s -bench=. -benchmem goos: linux goarch: amd64 pkg: github.com/99designs/gqlgen/example/starwars BenchmarkSimpleQueryNoArgs-8 200000 32125 ns/op 6277 B/op 118 allocs/op PASS ok github.com/99designs/gqlgen/example/starwars 9.768s --- graphql/jsonw.go | 3 +-- graphql/string.go | 59 +++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/graphql/jsonw.go b/graphql/jsonw.go index c112444a7e6..c087f63bd0d 100644 --- a/graphql/jsonw.go +++ b/graphql/jsonw.go @@ -2,7 +2,6 @@ package graphql import ( "io" - "strconv" ) var nullLit = []byte(`null`) @@ -56,7 +55,7 @@ func (m *OrderedMap) MarshalGQL(writer io.Writer) { if i != 0 { writer.Write(comma) } - io.WriteString(writer, strconv.Quote(key)) + writeQuotedString(writer, key) writer.Write(colon) m.Values[i].MarshalGQL(writer) } diff --git a/graphql/string.go b/graphql/string.go index d5fb32947dc..7c1b7d95775 100644 --- a/graphql/string.go +++ b/graphql/string.go @@ -10,37 +10,42 @@ const encodeHex = "0123456789ABCDEF" func MarshalString(s string) Marshaler { return WriterFunc(func(w io.Writer) { - start := 0 - io.WriteString(w, `"`) - - for i, c := range s { - if c < 0x20 || c == '\\' || c == '"' { - io.WriteString(w, s[start:i]) - - switch c { - case '\t': - io.WriteString(w, `\t`) - case '\r': - io.WriteString(w, `\r`) - case '\n': - io.WriteString(w, `\n`) - case '\\': - io.WriteString(w, `\\`) - case '"': - io.WriteString(w, `\"`) - default: - io.WriteString(w, `\u00`) - w.Write([]byte{encodeHex[c>>4], encodeHex[c&0xf]}) - } - - start = i + 1 + writeQuotedString(w, s) + }) +} + +func writeQuotedString(w io.Writer, s string) { + start := 0 + io.WriteString(w, `"`) + + for i, c := range s { + if c < 0x20 || c == '\\' || c == '"' { + io.WriteString(w, s[start:i]) + + switch c { + case '\t': + io.WriteString(w, `\t`) + case '\r': + io.WriteString(w, `\r`) + case '\n': + io.WriteString(w, `\n`) + case '\\': + io.WriteString(w, `\\`) + case '"': + io.WriteString(w, `\"`) + default: + io.WriteString(w, `\u00`) + w.Write([]byte{encodeHex[c>>4], encodeHex[c&0xf]}) } + + start = i + 1 } + } - io.WriteString(w, s[start:]) - io.WriteString(w, `"`) - }) + io.WriteString(w, s[start:]) + io.WriteString(w, `"`) } + func UnmarshalString(v interface{}) (string, error) { switch v := v.(type) { case string: From e4584ea307c11d1d32eac068521afc560fdb3834 Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Sat, 8 Dec 2018 13:11:32 +1100 Subject: [PATCH 3/3] Avoid unnessicary goroutines goos: linux goarch: amd64 pkg: github.com/99designs/gqlgen/example/starwars BenchmarkSimpleQueryNoArgs-8 300000 25093 ns/op 6453 B/op 114 allocs/op PASS ok github.com/99designs/gqlgen/example/starwars 10.807s --- codegen/templates/data.go | 4 +- codegen/templates/field.gotpl | 12 +- codegen/templates/object.gotpl | 24 +- codegen/testserver/generated.go | 331 ++++++++++----------- example/chat/generated.go | 87 +++--- example/config/generated.go | 86 ++---- example/dataloader/generated.go | 129 ++++---- example/scalars/generated.go | 102 +++---- example/selection/generated.go | 65 ++-- example/starwars/generated.go | 255 +++++++--------- example/todo/generated.go | 87 +++--- example/type-system-extension/generated.go | 77 ++--- graphql/fieldset.go | 63 ++++ graphql/jsonw.go | 30 -- graphql/jsonw_test.go | 30 +- integration/generated.go | 165 +++++----- 16 files changed, 687 insertions(+), 860 deletions(-) create mode 100644 graphql/fieldset.go diff --git a/codegen/templates/data.go b/codegen/templates/data.go index d3098aaae14..7eb66cb5932 100644 --- a/codegen/templates/data.go +++ b/codegen/templates/data.go @@ -2,12 +2,12 @@ package templates var data = map[string]string{ "args.gotpl": "\targs := map[string]interface{}{}\n\t{{- range $i, $arg := . }}\n\t\tvar arg{{$i}} {{$arg.Signature }}\n\t\tif tmp, ok := rawArgs[{{$arg.GQLName|quote}}]; ok {\n\t\t\tvar err error\n\t\t\t{{$arg.Unmarshal (print \"arg\" $i) \"tmp\" }}\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\targs[{{$arg.GQLName|quote}}] = arg{{$i}}\n\t{{- end }}\n\treturn args, nil\n", - "field.gotpl": "{{ $field := . }}\n{{ $object := $field.Object }}\n\n{{- if $object.Stream }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {\n\t\t{{- if $field.Args }}\n\t\t\trawArgs := field.ArgumentMap(ec.Variables)\n\t\t\targs, err := {{ $field.ArgsFunc }}(rawArgs)\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t{{- end }}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tField: field,\n\t\t})\n\t\t// FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259\n\t\t// and Tracer stack\n\t\trctx := ctx\n\t\tresults, err := ec.resolvers.{{ $field.ShortInvocation }}\n\t\tif err != nil {\n\t\t\tec.Error(ctx, err)\n\t\t\treturn nil\n\t\t}\n\t\treturn func() graphql.Marshaler {\n\t\t\tres, ok := <-results\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tvar out graphql.OrderedMap\n\t\t\tout.Add(field.Alias, func() graphql.Marshaler { {{ $field.WriteJson }} }())\n\t\t\treturn &out\n\t\t}\n\t}\n{{ else }}\n\t// nolint: vetshadow\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField, {{if not $object.Root}}obj *{{$object.FullName}}{{end}}) graphql.Marshaler {\n\t\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\t\tdefer func () { ec.Tracer.EndFieldExecution(ctx) }()\n\t\t{{- if $field.Args }}\n\t\t\trawArgs := field.ArgumentMap(ec.Variables)\n\t\t\targs, err := {{ $field.ArgsFunc }}(rawArgs)\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\treturn graphql.Null\n\t\t\t}\n\t\t{{- end }}\n\t\trctx := &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t\tArgs: {{if $field.Args }}args{{else}}nil{{end}},\n\t\t\tField: field,\n\t\t}\n\t\tctx = graphql.WithResolverContext(ctx, rctx)\n\t\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\t\tresTmp := ec.FieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {\n\t\t\tctx = rctx // use context from middleware stack in children\n\t\t\t{{- if $field.IsResolver }}\n\t\t\t\treturn ec.resolvers.{{ $field.ShortInvocation }}\n\t\t\t{{- else if $field.IsMethod }}\n\t\t\t\t{{- if $field.NoErr }}\n\t\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})\n\t\t\t\t{{- end }}\n\t\t\t{{- else if $field.IsVariable }}\n\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil\n\t\t\t{{- end }}\n\t\t})\n\t\tif resTmp == nil {\n\t\t\t{{- if $field.ASTType.NonNull }}\n\t\t\t\tif !ec.HasError(rctx) {\n\t\t\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t\t\t}\n\t\t\t{{- end }}\n\t\t\treturn graphql.Null\n\t\t}\n\t\tres := resTmp.({{$field.Signature}})\n\t\trctx.Result = res\n\t\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\t\t{{ $field.WriteJson }}\n\t}\n{{ end }}\n", + "field.gotpl": "{{ $field := . }}\n{{ $object := $field.Object }}\n\n{{- if $object.Stream }}\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {\n\t\t{{- if $field.Args }}\n\t\t\trawArgs := field.ArgumentMap(ec.Variables)\n\t\t\targs, err := {{ $field.ArgsFunc }}(rawArgs)\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t{{- end }}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tField: field,\n\t\t})\n\t\t// FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259\n\t\t// and Tracer stack\n\t\trctx := ctx\n\t\tresults, err := ec.resolvers.{{ $field.ShortInvocation }}\n\t\tif err != nil {\n\t\t\tec.Error(ctx, err)\n\t\t\treturn nil\n\t\t}\n\t\treturn func() graphql.Marshaler {\n\t\t\tres, ok := <-results\n\t\t\tif !ok {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn graphql.WriterFunc(func(w io.Writer) {\n\t\t\t\tw.Write([]byte{'{'})\n\t\t\t\tgraphql.MarshalString(field.Alias).MarshalGQL(w)\n\t\t\t\tw.Write([]byte{':'})\n\t\t\t\tfunc() graphql.Marshaler {\n\t\t\t\t\t{{ $field.WriteJson }}\n\t\t\t\t}().MarshalGQL(w)\n\t\t\t\tw.Write([]byte{'}'})\n\t\t\t})\n\t\t}\n\t}\n{{ else }}\n\t// nolint: vetshadow\n\tfunc (ec *executionContext) _{{$object.GQLType}}_{{$field.GQLName}}(ctx context.Context, field graphql.CollectedField, {{if not $object.Root}}obj *{{$object.FullName}}{{end}}) graphql.Marshaler {\n\t\tctx = ec.Tracer.StartFieldExecution(ctx, field)\n\t\tdefer func () { ec.Tracer.EndFieldExecution(ctx) }()\n\t\t{{- if $field.Args }}\n\t\t\trawArgs := field.ArgumentMap(ec.Variables)\n\t\t\targs, err := {{ $field.ArgsFunc }}(rawArgs)\n\t\t\tif err != nil {\n\t\t\t\tec.Error(ctx, err)\n\t\t\t\treturn graphql.Null\n\t\t\t}\n\t\t{{- end }}\n\t\trctx := &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t\tArgs: {{if $field.Args }}args{{else}}nil{{end}},\n\t\t\tField: field,\n\t\t}\n\t\tctx = graphql.WithResolverContext(ctx, rctx)\n\t\tctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)\n\t\tresTmp := ec.FieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {\n\t\t\tctx = rctx // use context from middleware stack in children\n\t\t\t{{- if $field.IsResolver }}\n\t\t\t\treturn ec.resolvers.{{ $field.ShortInvocation }}\n\t\t\t{{- else if $field.IsMethod }}\n\t\t\t\t{{- if $field.NoErr }}\n\t\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil\n\t\t\t\t{{- else }}\n\t\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})\n\t\t\t\t{{- end }}\n\t\t\t{{- else if $field.IsVariable }}\n\t\t\t\treturn {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil\n\t\t\t{{- end }}\n\t\t})\n\t\tif resTmp == nil {\n\t\t\t{{- if $field.ASTType.NonNull }}\n\t\t\t\tif !ec.HasError(rctx) {\n\t\t\t\t\tec.Errorf(ctx, \"must not be null\")\n\t\t\t\t}\n\t\t\t{{- end }}\n\t\t\treturn graphql.Null\n\t\t}\n\t\tres := resTmp.({{$field.Signature}})\n\t\trctx.Result = res\n\t\tctx = ec.Tracer.StartFieldChildExecution(ctx)\n\t\t{{ $field.WriteJson }}\n\t}\n{{ end }}\n", "generated.gotpl": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n\t%%%IMPORTS%%%\n\n\t{{ reserveImport \"context\" }}\n\t{{ reserveImport \"fmt\" }}\n\t{{ reserveImport \"io\" }}\n\t{{ reserveImport \"strconv\" }}\n\t{{ reserveImport \"time\" }}\n\t{{ reserveImport \"sync\" }}\n\t{{ reserveImport \"errors\" }}\n\t{{ reserveImport \"bytes\" }}\n\n\t{{ reserveImport \"github.com/vektah/gqlparser\" }}\n\t{{ reserveImport \"github.com/vektah/gqlparser/ast\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql/introspection\" }}\n)\n\n// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.\nfunc NewExecutableSchema(cfg Config) graphql.ExecutableSchema {\n\treturn &executableSchema{\n\t\tresolvers: cfg.Resolvers,\n\t\tdirectives: cfg.Directives,\n\t\tcomplexity: cfg.Complexity,\n\t}\n}\n\ntype Config struct {\n\tResolvers ResolverRoot\n\tDirectives DirectiveRoot\n\tComplexity ComplexityRoot\n}\n\ntype ResolverRoot interface {\n{{- range $object := .Objects -}}\n\t{{ if $object.HasResolvers -}}\n\t\t{{$object.GQLType}}() {{$object.GQLType}}Resolver\n\t{{ end }}\n{{- end }}\n}\n\ntype DirectiveRoot struct {\n{{ range $directive := .Directives }}\n\t{{ $directive.Declaration }}\n{{ end }}\n}\n\ntype ComplexityRoot struct {\n{{ range $object := .Objects }}\n\t{{ if not $object.IsReserved -}}\n\t\t{{ $object.GQLType|toCamel }} struct {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ if not $field.IsReserved -}}\n\t\t\t\t{{ $field.GQLName|toCamel }} {{ $field.ComplexitySignature }}\n\t\t\t{{ end }}\n\t\t{{- end }}\n\t\t}\n\t{{- end }}\n{{ end }}\n}\n\n{{ range $object := .Objects -}}\n\t{{ if $object.HasResolvers }}\n\t\ttype {{$object.GQLType}}Resolver interface {\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{ $field.ShortResolverDeclaration }}\n\t\t{{ end }}\n\t\t}\n\t{{- end }}\n{{- end }}\n\n{{ range $object := .Objects -}}\n\t{{ range $field := $object.Fields -}}\n\t\t{{ if $field.Args }}\n\t\t\tfunc {{ $field.ArgsFunc }}(rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\t\t\t{{ template \"args.gotpl\" $field.Args }}\n\t\t\t}\n\t\t{{ end }}\n\t{{ end }}\n{{- end }}\n\n{{ range $directive := .Directives }}\n\t{{ if $directive.Args }}\n\t\tfunc {{ $directive.ArgsFunc }}(rawArgs map[string]interface{}) (map[string]interface{}, error) {\n\t\t{{ template \"args.gotpl\" $directive.Args }}\n\t\t}\n\t{{ end }}\n{{ end }}\n\ntype executableSchema struct {\n\tresolvers ResolverRoot\n\tdirectives DirectiveRoot\n\tcomplexity ComplexityRoot\n}\n\nfunc (e *executableSchema) Schema() *ast.Schema {\n\treturn parsedSchema\n}\n\nfunc (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {\n\tswitch typeName + \".\" + field {\n\t{{ range $object := .Objects }}\n\t\t{{ if not $object.IsReserved }}\n\t\t\t{{ range $field := $object.Fields }}\n\t\t\t\t{{ if not $field.IsReserved }}\n\t\t\t\t\tcase \"{{$object.GQLType}}.{{$field.GQLName}}\":\n\t\t\t\t\t\tif e.complexity.{{$object.GQLType|toCamel}}.{{$field.GQLName|toCamel}} == nil {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\t{{ if $field.Args }}\n\t\t\t\t\t\t\targs, err := {{ $field.ArgsFunc }}(rawArgs)\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn 0, false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t{{ end }}\n\t\t\t\t\t\treturn e.complexity.{{$object.GQLType|toCamel}}.{{$field.GQLName|toCamel}}(childComplexity{{if $field.Args}}, {{$field.ComplexityArgs}} {{end}}), true\n\t\t\t\t{{ end }}\n\t\t\t{{ end }}\n\t\t{{ end }}\n\t{{ end }}\n\t}\n\treturn 0, false\n}\n\nfunc (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .QueryRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.QueryRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t\tExtensions: ec.Extensions,\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"queries are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {\n\t{{- if .MutationRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\tdata := ec._{{.MutationRoot.GQLType}}(ctx, op.SelectionSet)\n\t\t\tvar buf bytes.Buffer\n\t\t\tdata.MarshalGQL(&buf)\n\t\t\treturn buf.Bytes()\n\t\t})\n\n\t\treturn &graphql.Response{\n\t\t\tData: buf,\n\t\t\tErrors: ec.Errors,\n\t\t\tExtensions: ec.Extensions,\n\t\t}\n\t{{- else }}\n\t\treturn graphql.ErrorResponse(ctx, \"mutations are not supported\")\n\t{{- end }}\n}\n\nfunc (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {\n\t{{- if .SubscriptionRoot }}\n\t\tec := executionContext{graphql.GetRequestContext(ctx), e}\n\n\t\tnext := ec._{{.SubscriptionRoot.GQLType}}(ctx, op.SelectionSet)\n\t\tif ec.Errors != nil {\n\t\t\treturn graphql.OneShot(&graphql.Response{Data: []byte(\"null\"), Errors: ec.Errors})\n\t\t}\n\n\t\tvar buf bytes.Buffer\n\t\treturn func() *graphql.Response {\n\t\t\tbuf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {\n\t\t\t\tbuf.Reset()\n\t\t\t\tdata := next()\n\n\t\t\t\tif data == nil {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdata.MarshalGQL(&buf)\n\t\t\t\treturn buf.Bytes()\n\t\t\t})\n\n\t\t\tif buf == nil {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\treturn &graphql.Response{\n\t\t\t\tData: buf,\n\t\t\t\tErrors: ec.Errors,\n\t\t\t\tExtensions: ec.Extensions,\n\t\t\t}\n\t\t}\n\t{{- else }}\n\t\treturn graphql.OneShot(graphql.ErrorResponse(ctx, \"subscriptions are not supported\"))\n\t{{- end }}\n}\n\ntype executionContext struct {\n\t*graphql.RequestContext\n\t*executableSchema\n}\n\n{{- range $object := .Objects }}\n\t{{ template \"object.gotpl\" $object }}\n\n\t{{- range $field := $object.Fields }}\n\t\t{{ template \"field.gotpl\" $field }}\n\t{{ end }}\n{{- end}}\n\n{{- range $interface := .Interfaces }}\n\t{{ template \"interface.gotpl\" $interface }}\n{{- end }}\n\n{{- range $input := .Inputs }}\n\t{{ template \"input.gotpl\" $input }}\n{{- end }}\n\nfunc (ec *executionContext) FieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) (ret interface{}) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tec.Error(ctx, ec.Recover(ctx, r))\n\t\t\tret = nil\n\t\t}\n\t}()\n\t{{- if .Directives }}\n\trctx := graphql.GetResolverContext(ctx)\n\tfor _, d := range rctx.Field.Definition.Directives {\n\t\tswitch d.Name {\n\t\t{{- range $directive := .Directives }}\n\t\tcase \"{{$directive.Name}}\":\n\t\t\tif ec.directives.{{$directive.Name|ucFirst}} != nil {\n\t\t\t\t{{- if $directive.Args }}\n\t\t\t\t\trawArgs := d.ArgumentMap(ec.Variables)\n\t\t\t\t\targs, err := {{ $directive.ArgsFunc }}(rawArgs)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tec.Error(ctx, err)\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\t\t\t\t{{- end }}\n\t\t\t\tn := next\n\t\t\t\tnext = func(ctx context.Context) (interface{}, error) {\n\t\t\t\t\treturn ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}})\n\t\t\t\t}\n\t\t\t}\n\t\t{{- end }}\n\t\t}\n\t}\n\t{{- end }}\n\tres, err := ec.ResolverMiddleware(ctx, next)\n\tif err != nil {\n\t\tec.Error(ctx, err)\n\t\treturn nil\n\t}\n\treturn res\n}\n\nfunc (ec *executionContext) introspectSchema() (*introspection.Schema, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapSchema(parsedSchema), nil\n}\n\nfunc (ec *executionContext) introspectType(name string) (*introspection.Type, error) {\n\tif ec.DisableIntrospection {\n\t\treturn nil, errors.New(\"introspection disabled\")\n\t}\n\treturn introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil\n}\n\nvar parsedSchema = gqlparser.MustLoadSchema(\n\t{{- range $filename, $schema := .SchemaRaw }}\n\t\t&ast.Source{Name: {{$filename|quote}}, Input: {{$schema|rawQuote}}},\n\t{{- end }}\n)\n", "input.gotpl": "\t{{- if .IsMarshaled }}\n\tfunc Unmarshal{{ .GQLType }}(v interface{}) ({{.FullName}}, error) {\n\t\tvar it {{.FullName}}\n\t\tvar asMap = v.(map[string]interface{})\n\t\t{{ range $field := .Fields}}\n\t\t\t{{- if $field.Default}}\n\t\t\t\tif _, present := asMap[{{$field.GQLName|quote}}] ; !present {\n\t\t\t\t\tasMap[{{$field.GQLName|quote}}] = {{ $field.Default | dump }}\n\t\t\t\t}\n\t\t\t{{- end}}\n\t\t{{- end }}\n\n\t\tfor k, v := range asMap {\n\t\t\tswitch k {\n\t\t\t{{- range $field := .Fields }}\n\t\t\tcase {{$field.GQLName|quote}}:\n\t\t\t\tvar err error\n\t\t\t\t{{ $field.Unmarshal (print \"it.\" $field.GoFieldName) \"v\" }}\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn it, err\n\t\t\t\t}\n\t\t\t{{- end }}\n\t\t\t}\n\t\t}\n\n\t\treturn it, nil\n\t}\n\t{{- end }}\n", "interface.gotpl": "{{- $interface := . }}\n\nfunc (ec *executionContext) _{{$interface.GQLType}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.FullName}}) graphql.Marshaler {\n\tswitch obj := (*obj).(type) {\n\tcase nil:\n\t\treturn graphql.Null\n\t{{- range $implementor := $interface.Implementors }}\n\t\t{{- if $implementor.ValueReceiver }}\n\t\t\tcase {{$implementor.FullName}}:\n\t\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, &obj)\n\t\t{{- end}}\n\t\tcase *{{$implementor.FullName}}:\n\t\t\treturn ec._{{$implementor.GQLType}}(ctx, sel, obj)\n\t{{- end }}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unexpected type %T\", obj))\n\t}\n}\n", "models.gotpl": "// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\npackage {{ .PackageName }}\n\nimport (\n\t%%%IMPORTS%%%\n\n\t{{ reserveImport \"context\" }}\n\t{{ reserveImport \"fmt\" }}\n\t{{ reserveImport \"io\" }}\n\t{{ reserveImport \"strconv\" }}\n\t{{ reserveImport \"time\" }}\n\t{{ reserveImport \"sync\" }}\n\t{{ reserveImport \"errors\" }}\n\t{{ reserveImport \"bytes\" }}\n\n\t{{ reserveImport \"github.com/vektah/gqlparser\" }}\n\t{{ reserveImport \"github.com/vektah/gqlparser/ast\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql/introspection\" }}\n)\n\n{{ range $model := .Models }}\n\t{{with .Description}} {{.|prefixLines \"// \"}} {{end}}\n\t{{- if .IsInterface }}\n\t\ttype {{.GoType}} interface {\n\t\t\tIs{{.GoType}}()\n\t\t}\n\t{{- else }}\n\t\ttype {{.GoType}} struct {\n\t\t\t{{- range $field := .Fields }}\n\t\t\t\t{{- with .Description}}\n\t\t\t\t\t{{.|prefixLines \"// \"}}\n\t\t\t\t{{- end}}\n\t\t\t\t{{- if $field.GoFieldName }}\n\t\t\t\t\t{{ $field.GoFieldName }} {{$field.Signature}} `json:\"{{$field.GQLName}}\"`\n\t\t\t\t{{- else }}\n\t\t\t\t\t{{ $field.GoFKName }} {{$field.GoFKType}}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t}\n\n\t\t{{- range $iface := .Implements }}\n\t\t\tfunc ({{$model.GoType}}) Is{{$iface.GoType}}() {}\n\t\t{{- end }}\n\n\t{{- end }}\n{{- end}}\n\n{{ range $enum := .Enums }}\n\t{{with .Description}}{{.|prefixLines \"// \"}} {{end}}\n\ttype {{.GoType}} string\n\tconst (\n\t{{- range $value := .Values}}\n\t\t{{- with .Description}}\n\t\t\t{{.|prefixLines \"// \"}}\n\t\t{{- end}}\n\t\t{{$enum.GoType}}{{ .Name|toCamel }} {{$enum.GoType}} = {{.Name|quote}}\n\t{{- end }}\n\t)\n\n\tfunc (e {{.GoType}}) IsValid() bool {\n\t\tswitch e {\n\t\tcase {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.GoType }}{{ $element.Name|toCamel }}{{end}}:\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tfunc (e {{.GoType}}) String() string {\n\t\treturn string(e)\n\t}\n\n\tfunc (e *{{.GoType}}) UnmarshalGQL(v interface{}) error {\n\t\tstr, ok := v.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"enums must be strings\")\n\t\t}\n\n\t\t*e = {{.GoType}}(str)\n\t\tif !e.IsValid() {\n\t\t\treturn fmt.Errorf(\"%s is not a valid {{.GQLType}}\", str)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfunc (e {{.GoType}}) MarshalGQL(w io.Writer) {\n\t\tfmt.Fprint(w, strconv.Quote(e.String()))\n\t}\n\n{{- end }}\n", - "object.gotpl": "{{ $object := . }}\n\nvar {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}}\n\n// nolint: gocyclo, errcheck, gas, goconst\n{{- if .Stream }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {\n\tfields := graphql.CollectFields(ctx, sel, {{$object.GQLType|lcFirst}}Implementors)\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: {{$object.GQLType|quote}},\n\t})\n\tif len(fields) != 1 {\n\t\tec.Errorf(ctx, \"must subscribe to exactly one stream\")\n\t\treturn nil\n\t}\n\n\tswitch fields[0].Name {\n\t{{- range $field := $object.Fields }}\n\tcase \"{{$field.GQLName}}\":\n\t\treturn ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, fields[0])\n\t{{- end }}\n\tdefault:\n\t\tpanic(\"unknown field \" + strconv.Quote(fields[0].Name))\n\t}\n}\n{{- else }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler {\n\tfields := graphql.CollectFields(ctx, sel, {{$object.GQLType|lcFirst}}Implementors)\n\t{{if $object.Root}}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t})\n\t{{end}}\n\n\t{{if $object.IsConcurrent}} var wg sync.WaitGroup {{end}}\n\tout := graphql.NewOrderedMap(len(fields))\n\tinvalid := false\n\tfor i, field := range fields {\n\t\tout.Keys[i] = field.Alias\n\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString({{$object.GQLType|quote}})\n\t\t{{- range $field := $object.Fields }}\n\t\tcase \"{{$field.GQLName}}\":\n\t\t\t{{- if $field.IsConcurrent }}\n\t\t\t\twg.Add(1)\n\t\t\t\tgo func(i int, field graphql.CollectedField) {\n\t\t\t{{- end }}\n\t\t\t\tout.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})\n\t\t\t\t{{- if $field.ASTType.NonNull }}\n\t\t\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\t\t\tinvalid = true\n\t\t\t\t\t}\n\t\t\t\t{{- end }}\n\t\t\t{{- if $field.IsConcurrent }}\n\t\t\t\t\twg.Done()\n\t\t\t\t}(i, field)\n\t\t\t{{- end }}\n\t\t{{- end }}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\t{{if $object.IsConcurrent}} wg.Wait() {{end}}\n\tif invalid { return graphql.Null }\n\treturn out\n}\n{{- end }}\n", + "object.gotpl": "{{ $object := . }}\n\nvar {{ $object.GQLType|lcFirst}}Implementors = {{$object.Implementors}}\n\n// nolint: gocyclo, errcheck, gas, goconst\n{{- if .Stream }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {\n\tfields := graphql.CollectFields(ctx, sel, {{$object.GQLType|lcFirst}}Implementors)\n\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\tObject: {{$object.GQLType|quote}},\n\t})\n\tif len(fields) != 1 {\n\t\tec.Errorf(ctx, \"must subscribe to exactly one stream\")\n\t\treturn nil\n\t}\n\n\tswitch fields[0].Name {\n\t{{- range $field := $object.Fields }}\n\tcase \"{{$field.GQLName}}\":\n\t\treturn ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, fields[0])\n\t{{- end }}\n\tdefault:\n\t\tpanic(\"unknown field \" + strconv.Quote(fields[0].Name))\n\t}\n}\n{{- else }}\nfunc (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.SelectionSet{{if not $object.Root}}, obj *{{$object.FullName}} {{end}}) graphql.Marshaler {\n\tfields := graphql.CollectFields(ctx, sel, {{$object.GQLType|lcFirst}}Implementors)\n\t{{if $object.Root}}\n\t\tctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{\n\t\t\tObject: {{$object.GQLType|quote}},\n\t\t})\n\t{{end}}\n\n\tout := graphql.NewFieldSet(fields)\n\tinvalid := false\n\tfor i, field := range fields {\n\t\tswitch field.Name {\n\t\tcase \"__typename\":\n\t\t\tout.Values[i] = graphql.MarshalString({{$object.GQLType|quote}})\n\t\t{{- range $field := $object.Fields }}\n\t\tcase \"{{$field.GQLName}}\":\n\t\t\t{{- if $field.IsConcurrent }}\n\t\t\t\tfield := field\n\t\t\t\tout.Concurrently(i, func() (res graphql.Marshaler) {\n\t\t\t\t\tres = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})\n\t\t\t\t\t{{- if $field.ASTType.NonNull }}\n\t\t\t\t\t\tif res == graphql.Null {\n\t\t\t\t\t\t\tinvalid = true\n\t\t\t\t\t\t}\n\t\t\t\t\t{{- end }}\n\t\t\t\t\treturn res\n\t\t\t\t})\n\t\t\t{{- else }}\n\t\t\t\tout.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}})\n\t\t\t\t{{- if $field.ASTType.NonNull }}\n\t\t\t\t\tif out.Values[i] == graphql.Null {\n\t\t\t\t\t\tinvalid = true\n\t\t\t\t\t}\n\t\t\t\t{{- end }}\n\t\t\t{{- end }}\n\t\t{{- end }}\n\t\tdefault:\n\t\t\tpanic(\"unknown field \" + strconv.Quote(field.Name))\n\t\t}\n\t}\n\tout.Dispatch()\n\tif invalid { return graphql.Null }\n\treturn out\n}\n{{- end }}\n", "resolver.gotpl": "package {{ .PackageName }}\n\nimport (\n\t%%%IMPORTS%%%\n\n\t{{ reserveImport \"context\" }}\n\t{{ reserveImport \"fmt\" }}\n\t{{ reserveImport \"io\" }}\n\t{{ reserveImport \"strconv\" }}\n\t{{ reserveImport \"time\" }}\n\t{{ reserveImport \"sync\" }}\n\t{{ reserveImport \"errors\" }}\n\t{{ reserveImport \"bytes\" }}\n\n\t{{ reserveImport \"github.com/99designs/gqlgen/handler\" }}\n\t{{ reserveImport \"github.com/vektah/gqlparser\" }}\n\t{{ reserveImport \"github.com/vektah/gqlparser/ast\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/graphql/introspection\" }}\n)\n\ntype {{.ResolverType}} struct {}\n\n{{ range $object := .Objects -}}\n\t{{- if $object.HasResolvers -}}\n\t\tfunc (r *{{$.ResolverType}}) {{$object.GQLType}}() {{ $object.ResolverInterface.FullName }} {\n\t\t\treturn &{{lcFirst $object.GQLType}}Resolver{r}\n\t\t}\n\t{{ end -}}\n{{ end }}\n\n{{ range $object := .Objects -}}\n\t{{- if $object.HasResolvers -}}\n\t\ttype {{lcFirst $object.GQLType}}Resolver struct { *Resolver }\n\n\t\t{{ range $field := $object.Fields -}}\n\t\t\t{{- if $field.IsResolver -}}\n\t\t\tfunc (r *{{lcFirst $object.GQLType}}Resolver) {{ $field.ShortResolverDeclaration }} {\n\t\t\t\tpanic(\"not implemented\")\n\t\t\t}\n\t\t\t{{ end -}}\n\t\t{{ end -}}\n\t{{ end -}}\n{{ end }}\n", "server.gotpl": "package main\n\nimport (\n\t%%%IMPORTS%%%\n\n\t{{ reserveImport \"context\" }}\n\t{{ reserveImport \"log\" }}\n\t{{ reserveImport \"net/http\" }}\n\t{{ reserveImport \"os\" }}\n\t{{ reserveImport \"github.com/99designs/gqlgen/handler\" }}\n)\n\nconst defaultPort = \"8080\"\n\nfunc main() {\n\tport := os.Getenv(\"PORT\")\n\tif port == \"\" {\n\t\tport = defaultPort\n\t}\n\n\thttp.Handle(\"/\", handler.Playground(\"GraphQL playground\", \"/query\"))\n\thttp.Handle(\"/query\", handler.GraphQL({{ lookupImport .ExecPackageName }}.NewExecutableSchema({{ lookupImport .ExecPackageName}}.Config{Resolvers: &{{ lookupImport .ResolverPackageName}}.Resolver{}})))\n\n\tlog.Printf(\"connect to http://localhost:%s/ for GraphQL playground\", port)\n\tlog.Fatal(http.ListenAndServe(\":\" + port, nil))\n}\n", } diff --git a/codegen/templates/field.gotpl b/codegen/templates/field.gotpl index 3df847fa980..0d2c07368cc 100644 --- a/codegen/templates/field.gotpl +++ b/codegen/templates/field.gotpl @@ -27,9 +27,15 @@ if !ok { return nil } - var out graphql.OrderedMap - out.Add(field.Alias, func() graphql.Marshaler { {{ $field.WriteJson }} }()) - return &out + return graphql.WriterFunc(func(w io.Writer) { + w.Write([]byte{'{'}) + graphql.MarshalString(field.Alias).MarshalGQL(w) + w.Write([]byte{':'}) + func() graphql.Marshaler { + {{ $field.WriteJson }} + }().MarshalGQL(w) + w.Write([]byte{'}'}) + }) } } {{ else }} diff --git a/codegen/templates/object.gotpl b/codegen/templates/object.gotpl index e98cbe1ee55..135f4f21f31 100644 --- a/codegen/templates/object.gotpl +++ b/codegen/templates/object.gotpl @@ -32,37 +32,39 @@ func (ec *executionContext) _{{$object.GQLType}}(ctx context.Context, sel ast.Se }) {{end}} - {{if $object.IsConcurrent}} var wg sync.WaitGroup {{end}} - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString({{$object.GQLType|quote}}) {{- range $field := $object.Fields }} case "{{$field.GQLName}}": {{- if $field.IsConcurrent }} - wg.Add(1) - go func(i int, field graphql.CollectedField) { - {{- end }} + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}}) + {{- if $field.ASTType.NonNull }} + if res == graphql.Null { + invalid = true + } + {{- end }} + return res + }) + {{- else }} out.Values[i] = ec._{{$object.GQLType}}_{{$field.GQLName}}(ctx, field{{if not $object.Root}}, obj{{end}}) {{- if $field.ASTType.NonNull }} if out.Values[i] == graphql.Null { invalid = true } {{- end }} - {{- if $field.IsConcurrent }} - wg.Done() - }(i, field) {{- end }} {{- end }} default: panic("unknown field " + strconv.Quote(field.Name)) } } - {{if $object.IsConcurrent}} wg.Wait() {{end}} + out.Dispatch() if invalid { return graphql.Null } return out } diff --git a/codegen/testserver/generated.go b/codegen/testserver/generated.go index 3f97c620b14..b0f5764ff80 100644 --- a/codegen/testserver/generated.go +++ b/codegen/testserver/generated.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "io" "strconv" "sync" @@ -939,11 +940,9 @@ var circleImplementors = []string{"Circle", "Shape"} func (ec *executionContext) _Circle(ctx context.Context, sel ast.SelectionSet, obj *Circle) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, circleImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Circle") @@ -955,7 +954,7 @@ func (ec *executionContext) _Circle(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1016,11 +1015,9 @@ var embeddedPointerImplementors = []string{"EmbeddedPointer"} func (ec *executionContext) _EmbeddedPointer(ctx context.Context, sel ast.SelectionSet, obj *EmbeddedPointerModel) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, embeddedPointerImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("EmbeddedPointer") @@ -1032,7 +1029,7 @@ func (ec *executionContext) _EmbeddedPointer(ctx context.Context, sel ast.Select panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1093,11 +1090,9 @@ var errorImplementors = []string{"Error"} func (ec *executionContext) _Error(ctx context.Context, sel ast.SelectionSet, obj *Error) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, errorImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Error") @@ -1122,7 +1117,7 @@ func (ec *executionContext) _Error(ctx context.Context, sel ast.SelectionSet, ob panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1247,26 +1242,23 @@ var forcedResolverImplementors = []string{"ForcedResolver"} func (ec *executionContext) _ForcedResolver(ctx context.Context, sel ast.SelectionSet, obj *ForcedResolver) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, forcedResolverImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("ForcedResolver") case "field": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._ForcedResolver_field(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._ForcedResolver_field(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1308,11 +1300,9 @@ var innerObjectImplementors = []string{"InnerObject"} func (ec *executionContext) _InnerObject(ctx context.Context, sel ast.SelectionSet, obj *InnerObject) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, innerObjectImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("InnerObject") @@ -1325,7 +1315,7 @@ func (ec *executionContext) _InnerObject(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1365,11 +1355,9 @@ var invalidIdentifierImplementors = []string{"InvalidIdentifier"} func (ec *executionContext) _InvalidIdentifier(ctx context.Context, sel ast.SelectionSet, obj *invalid_packagename.InvalidIdentifier) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, invalidIdentifierImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("InvalidIdentifier") @@ -1382,7 +1370,7 @@ func (ec *executionContext) _InvalidIdentifier(ctx context.Context, sel ast.Sele panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1422,11 +1410,9 @@ var itImplementors = []string{"It"} func (ec *executionContext) _It(ctx context.Context, sel ast.SelectionSet, obj *introspection1.It) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, itImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("It") @@ -1439,7 +1425,7 @@ func (ec *executionContext) _It(ctx context.Context, sel ast.SelectionSet, obj * panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1479,43 +1465,40 @@ var modelMethodsImplementors = []string{"ModelMethods"} func (ec *executionContext) _ModelMethods(ctx context.Context, sel ast.SelectionSet, obj *ModelMethods) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, modelMethodsImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("ModelMethods") case "resolverField": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._ModelMethods_resolverField(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._ModelMethods_resolverField(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "noContext": out.Values[i] = ec._ModelMethods_noContext(ctx, field, obj) if out.Values[i] == graphql.Null { invalid = true } case "withContext": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._ModelMethods_withContext(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._ModelMethods_withContext(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1609,11 +1592,9 @@ var outerObjectImplementors = []string{"OuterObject"} func (ec *executionContext) _OuterObject(ctx context.Context, sel ast.SelectionSet, obj *OuterObject) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, outerObjectImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("OuterObject") @@ -1626,7 +1607,7 @@ func (ec *executionContext) _OuterObject(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1671,111 +1652,108 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "invalidIdentifier": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_invalidIdentifier(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_invalidIdentifier(ctx, field) + return res + }) case "collision": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_collision(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_collision(ctx, field) + return res + }) case "mapInput": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_mapInput(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_mapInput(ctx, field) + return res + }) case "recursive": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_recursive(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_recursive(ctx, field) + return res + }) case "nestedInputs": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_nestedInputs(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_nestedInputs(ctx, field) + return res + }) case "nestedOutputs": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_nestedOutputs(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_nestedOutputs(ctx, field) + return res + }) case "keywords": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_keywords(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_keywords(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "shapes": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_shapes(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_shapes(ctx, field) + return res + }) case "errorBubble": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_errorBubble(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_errorBubble(ctx, field) + return res + }) case "modelMethods": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_modelMethods(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_modelMethods(ctx, field) + return res + }) case "valid": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_valid(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_valid(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "user": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_user(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_user(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "nullableArg": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_nullableArg(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_nullableArg(ctx, field) + return res + }) case "keywordArgs": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_keywordArgs(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_keywordArgs(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -1784,7 +1762,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -2393,11 +2371,9 @@ var rectangleImplementors = []string{"Rectangle", "Shape"} func (ec *executionContext) _Rectangle(ctx context.Context, sel ast.SelectionSet, obj *Rectangle) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, rectangleImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Rectangle") @@ -2411,7 +2387,7 @@ func (ec *executionContext) _Rectangle(ctx context.Context, sel ast.SelectionSet panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -2530,9 +2506,15 @@ func (ec *executionContext) _Subscription_updated(ctx context.Context, field gra if !ok { return nil } - var out graphql.OrderedMap - out.Add(field.Alias, func() graphql.Marshaler { return graphql.MarshalString(res) }()) - return &out + return graphql.WriterFunc(func(w io.Writer) { + w.Write([]byte{'{'}) + graphql.MarshalString(field.Alias).MarshalGQL(w) + w.Write([]byte{':'}) + func() graphql.Marshaler { + return graphql.MarshalString(res) + }().MarshalGQL(w) + w.Write([]byte{'}'}) + }) } } @@ -2553,9 +2535,15 @@ func (ec *executionContext) _Subscription_initPayload(ctx context.Context, field if !ok { return nil } - var out graphql.OrderedMap - out.Add(field.Alias, func() graphql.Marshaler { return graphql.MarshalString(res) }()) - return &out + return graphql.WriterFunc(func(w io.Writer) { + w.Write([]byte{'{'}) + graphql.MarshalString(field.Alias).MarshalGQL(w) + w.Write([]byte{':'}) + func() graphql.Marshaler { + return graphql.MarshalString(res) + }().MarshalGQL(w) + w.Write([]byte{'}'}) + }) } } @@ -2565,12 +2553,9 @@ var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, userImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("User") @@ -2580,19 +2565,19 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj invalid = true } case "friends": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._User_friends(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._User_friends(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -2692,11 +2677,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -2721,7 +2704,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -2881,11 +2864,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -2907,7 +2888,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3026,11 +3007,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -3062,7 +3041,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3276,11 +3255,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -3302,7 +3279,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3429,11 +3406,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -3460,7 +3435,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3686,11 +3661,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -3719,7 +3692,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/chat/generated.go b/example/chat/generated.go index d1bb62f7d3d..4f4682c0e3b 100644 --- a/example/chat/generated.go +++ b/example/chat/generated.go @@ -6,6 +6,7 @@ import ( "bytes" "context" "errors" + "io" "strconv" "sync" "time" @@ -356,11 +357,9 @@ var chatroomImplementors = []string{"Chatroom"} func (ec *executionContext) _Chatroom(ctx context.Context, sel ast.SelectionSet, obj *Chatroom) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, chatroomImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Chatroom") @@ -378,7 +377,7 @@ func (ec *executionContext) _Chatroom(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -478,11 +477,9 @@ var messageImplementors = []string{"Message"} func (ec *executionContext) _Message(ctx context.Context, sel ast.SelectionSet, obj *Message) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, messageImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Message") @@ -510,7 +507,7 @@ func (ec *executionContext) _Message(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -635,11 +632,9 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) Object: "Mutation", }) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Mutation") @@ -652,7 +647,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -703,21 +698,18 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "room": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_room(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_room(ctx, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -726,7 +718,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -876,11 +868,16 @@ func (ec *executionContext) _Subscription_messageAdded(ctx context.Context, fiel if !ok { return nil } - var out graphql.OrderedMap - out.Add(field.Alias, func() graphql.Marshaler { - return ec._Message(ctx, field.Selections, &res) - }()) - return &out + return graphql.WriterFunc(func(w io.Writer) { + w.Write([]byte{'{'}) + graphql.MarshalString(field.Alias).MarshalGQL(w) + w.Write([]byte{':'}) + func() graphql.Marshaler { + + return ec._Message(ctx, field.Selections, &res) + }().MarshalGQL(w) + w.Write([]byte{'}'}) + }) } } @@ -890,11 +887,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -919,7 +914,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1079,11 +1074,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -1105,7 +1098,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1224,11 +1217,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1260,7 +1251,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1474,11 +1465,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1500,7 +1489,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1627,11 +1616,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1658,7 +1645,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1884,11 +1871,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1917,7 +1902,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/config/generated.go b/example/config/generated.go index f408b8e5fa3..c9e36cd03a3 100644 --- a/example/config/generated.go +++ b/example/config/generated.go @@ -269,11 +269,9 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) Object: "Mutation", }) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Mutation") @@ -286,7 +284,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -337,24 +335,21 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "todos": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_todos(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_todos(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -363,7 +358,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -500,24 +495,21 @@ var todoImplementors = []string{"Todo"} func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *Todo) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, todoImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Todo") case "id": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Todo_id(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Todo_id(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "databaseId": out.Values[i] = ec._Todo_databaseId(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -542,7 +534,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -691,11 +683,9 @@ var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *User) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, userImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("User") @@ -713,7 +703,7 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -780,11 +770,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -809,7 +797,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -969,11 +957,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -995,7 +981,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1114,11 +1100,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1150,7 +1134,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1364,11 +1348,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1390,7 +1372,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1517,11 +1499,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1548,7 +1528,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1774,11 +1754,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1807,7 +1785,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/dataloader/generated.go b/example/dataloader/generated.go index a3d4f0ffdb2..ba3a3d6e45a 100644 --- a/example/dataloader/generated.go +++ b/example/dataloader/generated.go @@ -360,11 +360,9 @@ var addressImplementors = []string{"Address"} func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, obj *Address) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, addressImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Address") @@ -387,7 +385,7 @@ func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -481,12 +479,9 @@ var customerImplementors = []string{"Customer"} func (ec *executionContext) _Customer(ctx context.Context, sel ast.SelectionSet, obj *Customer) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, customerImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Customer") @@ -501,22 +496,22 @@ func (ec *executionContext) _Customer(ctx context.Context, sel ast.SelectionSet, invalid = true } case "address": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Customer_address(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Customer_address(ctx, field, obj) + return res + }) case "orders": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Customer_orders(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Customer_orders(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -669,11 +664,9 @@ var itemImplementors = []string{"Item"} func (ec *executionContext) _Item(ctx context.Context, sel ast.SelectionSet, obj *Item) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, itemImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Item") @@ -686,7 +679,7 @@ func (ec *executionContext) _Item(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -726,12 +719,9 @@ var orderImplementors = []string{"Order"} func (ec *executionContext) _Order(ctx context.Context, sel ast.SelectionSet, obj *Order) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, orderImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Order") @@ -751,16 +741,16 @@ func (ec *executionContext) _Order(ctx context.Context, sel ast.SelectionSet, ob invalid = true } case "items": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Order_items(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Order_items(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -915,33 +905,30 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "customers": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_customers(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_customers(ctx, field) + return res + }) case "torture1d": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_torture1d(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_torture1d(ctx, field) + return res + }) case "torture2d": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_torture2d(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_torture2d(ctx, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -950,7 +937,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1241,11 +1228,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -1270,7 +1255,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1430,11 +1415,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -1456,7 +1439,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1575,11 +1558,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1611,7 +1592,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1825,11 +1806,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1851,7 +1830,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1978,11 +1957,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -2009,7 +1986,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -2235,11 +2212,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -2268,7 +2243,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/scalars/generated.go b/example/scalars/generated.go index af67c2b40dd..c05d47525c4 100644 --- a/example/scalars/generated.go +++ b/example/scalars/generated.go @@ -299,11 +299,9 @@ var addressImplementors = []string{"Address"} func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, obj *model.Address) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, addressImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Address") @@ -318,7 +316,7 @@ func (ec *executionContext) _Address(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -390,30 +388,27 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "user": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_user(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_user(ctx, field) + return res + }) case "search": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_search(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_search(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -422,7 +417,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -600,12 +595,9 @@ var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *model.User) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, userImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("User") @@ -627,23 +619,23 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj invalid = true } case "primitiveResolver": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._User_primitiveResolver(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._User_primitiveResolver(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "customResolver": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._User_customResolver(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._User_customResolver(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "address": out.Values[i] = ec._User_address(ctx, field, obj) case "tier": @@ -652,7 +644,7 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -873,11 +865,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -902,7 +892,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1062,11 +1052,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -1088,7 +1076,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1207,11 +1195,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1243,7 +1229,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1457,11 +1443,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1483,7 +1467,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1610,11 +1594,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1641,7 +1623,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1867,11 +1849,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1900,7 +1880,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/selection/generated.go b/example/selection/generated.go index b8f99c7e32c..5e6f8c53bd3 100644 --- a/example/selection/generated.go +++ b/example/selection/generated.go @@ -223,11 +223,9 @@ var likeImplementors = []string{"Like", "Event"} func (ec *executionContext) _Like(ctx context.Context, sel ast.SelectionSet, obj *Like) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, likeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Like") @@ -249,7 +247,7 @@ func (ec *executionContext) _Like(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -382,11 +380,9 @@ var postImplementors = []string{"Post", "Event"} func (ec *executionContext) _Post(ctx context.Context, sel ast.SelectionSet, obj *Post) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, postImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Post") @@ -408,7 +404,7 @@ func (ec *executionContext) _Post(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -545,21 +541,18 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "events": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_events(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_events(ctx, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -568,7 +561,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -702,11 +695,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -731,7 +722,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -891,11 +882,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -917,7 +906,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1036,11 +1025,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1072,7 +1059,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1286,11 +1273,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1312,7 +1297,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1439,11 +1424,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1470,7 +1453,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1696,11 +1679,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1729,7 +1710,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/starwars/generated.go b/example/starwars/generated.go index a58a5750e6b..9c38be96a51 100644 --- a/example/starwars/generated.go +++ b/example/starwars/generated.go @@ -828,12 +828,9 @@ var droidImplementors = []string{"Droid", "Character"} func (ec *executionContext) _Droid(ctx context.Context, sel ast.SelectionSet, obj *Droid) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, droidImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Droid") @@ -848,20 +845,20 @@ func (ec *executionContext) _Droid(ctx context.Context, sel ast.SelectionSet, ob invalid = true } case "friends": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Droid_friends(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Droid_friends(ctx, field, obj) + return res + }) case "friendsConnection": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Droid_friendsConnection(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Droid_friendsConnection(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "appearsIn": out.Values[i] = ec._Droid_appearsIn(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -873,7 +870,7 @@ func (ec *executionContext) _Droid(ctx context.Context, sel ast.SelectionSet, ob panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1091,12 +1088,9 @@ var friendsConnectionImplementors = []string{"FriendsConnection"} func (ec *executionContext) _FriendsConnection(ctx context.Context, sel ast.SelectionSet, obj *FriendsConnection) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, friendsConnectionImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("FriendsConnection") @@ -1106,17 +1100,17 @@ func (ec *executionContext) _FriendsConnection(ctx context.Context, sel ast.Sele invalid = true } case "edges": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._FriendsConnection_edges(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._FriendsConnection_edges(ctx, field, obj) + return res + }) case "friends": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._FriendsConnection_friends(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._FriendsConnection_friends(ctx, field, obj) + return res + }) case "pageInfo": out.Values[i] = ec._FriendsConnection_pageInfo(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -1126,7 +1120,7 @@ func (ec *executionContext) _FriendsConnection(ctx context.Context, sel ast.Sele panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1308,11 +1302,9 @@ var friendsEdgeImplementors = []string{"FriendsEdge"} func (ec *executionContext) _FriendsEdge(ctx context.Context, sel ast.SelectionSet, obj *FriendsEdge) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, friendsEdgeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("FriendsEdge") @@ -1327,7 +1319,7 @@ func (ec *executionContext) _FriendsEdge(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1392,12 +1384,9 @@ var humanImplementors = []string{"Human", "Character"} func (ec *executionContext) _Human(ctx context.Context, sel ast.SelectionSet, obj *Human) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, humanImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Human") @@ -1419,36 +1408,36 @@ func (ec *executionContext) _Human(ctx context.Context, sel ast.SelectionSet, ob case "mass": out.Values[i] = ec._Human_mass(ctx, field, obj) case "friends": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Human_friends(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Human_friends(ctx, field, obj) + return res + }) case "friendsConnection": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Human_friendsConnection(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Human_friendsConnection(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "appearsIn": out.Values[i] = ec._Human_appearsIn(ctx, field, obj) if out.Values[i] == graphql.Null { invalid = true } case "starships": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Human_starships(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Human_starships(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -1760,11 +1749,9 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) Object: "Mutation", }) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Mutation") @@ -1774,7 +1761,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1822,11 +1809,9 @@ var pageInfoImplementors = []string{"PageInfo"} func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *PageInfo) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, pageInfoImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("PageInfo") @@ -1849,7 +1834,7 @@ func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1947,63 +1932,60 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "hero": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_hero(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_hero(ctx, field) + return res + }) case "reviews": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_reviews(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_reviews(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "search": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_search(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_search(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "character": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_character(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_character(ctx, field) + return res + }) case "droid": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_droid(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_droid(ctx, field) + return res + }) case "human": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_human(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_human(ctx, field) + return res + }) case "starship": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_starship(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_starship(ctx, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -2012,7 +1994,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -2388,11 +2370,9 @@ var reviewImplementors = []string{"Review"} func (ec *executionContext) _Review(ctx context.Context, sel ast.SelectionSet, obj *Review) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, reviewImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Review") @@ -2409,7 +2389,7 @@ func (ec *executionContext) _Review(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -2501,12 +2481,9 @@ var starshipImplementors = []string{"Starship"} func (ec *executionContext) _Starship(ctx context.Context, sel ast.SelectionSet, obj *Starship) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, starshipImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Starship") @@ -2521,14 +2498,14 @@ func (ec *executionContext) _Starship(ctx context.Context, sel ast.SelectionSet, invalid = true } case "length": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Starship_length(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Starship_length(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "history": out.Values[i] = ec._Starship_history(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -2538,7 +2515,7 @@ func (ec *executionContext) _Starship(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -2683,11 +2660,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -2712,7 +2687,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -2872,11 +2847,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -2898,7 +2871,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3017,11 +2990,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -3053,7 +3024,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3267,11 +3238,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -3293,7 +3262,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3420,11 +3389,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -3451,7 +3418,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -3677,11 +3644,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -3710,7 +3675,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/todo/generated.go b/example/todo/generated.go index 2fbe0d159e9..4e70d88ac18 100644 --- a/example/todo/generated.go +++ b/example/todo/generated.go @@ -322,11 +322,9 @@ func (ec *executionContext) _MyMutation(ctx context.Context, sel ast.SelectionSe Object: "MyMutation", }) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("MyMutation") @@ -341,7 +339,7 @@ func (ec *executionContext) _MyMutation(ctx context.Context, sel ast.SelectionSe panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -427,36 +425,33 @@ func (ec *executionContext) _MyQuery(ctx context.Context, sel ast.SelectionSet) Object: "MyQuery", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("MyQuery") case "todo": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._MyQuery_todo(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._MyQuery_todo(ctx, field) + return res + }) case "lastTodo": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._MyQuery_lastTodo(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._MyQuery_lastTodo(ctx, field) + return res + }) case "todos": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._MyQuery_todos(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._MyQuery_todos(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "__type": out.Values[i] = ec._MyQuery___type(ctx, field) case "__schema": @@ -465,7 +460,7 @@ func (ec *executionContext) _MyQuery(ctx context.Context, sel ast.SelectionSet) panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -666,11 +661,9 @@ var todoImplementors = []string{"Todo"} func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *Todo) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, todoImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Todo") @@ -693,7 +686,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -787,11 +780,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -816,7 +807,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -976,11 +967,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -1002,7 +991,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1121,11 +1110,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1157,7 +1144,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1371,11 +1358,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1397,7 +1382,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1524,11 +1509,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1555,7 +1538,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1781,11 +1764,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1814,7 +1795,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/example/type-system-extension/generated.go b/example/type-system-extension/generated.go index 065da51a593..1372ad097fe 100644 --- a/example/type-system-extension/generated.go +++ b/example/type-system-extension/generated.go @@ -281,11 +281,9 @@ func (ec *executionContext) _MyMutation(ctx context.Context, sel ast.SelectionSe Object: "MyMutation", }) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("MyMutation") @@ -298,7 +296,7 @@ func (ec *executionContext) _MyMutation(ctx context.Context, sel ast.SelectionSe panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -349,30 +347,27 @@ func (ec *executionContext) _MyQuery(ctx context.Context, sel ast.SelectionSet) Object: "MyQuery", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("MyQuery") case "todos": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._MyQuery_todos(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._MyQuery_todos(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "todo": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._MyQuery_todo(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._MyQuery_todo(ctx, field) + return res + }) case "__type": out.Values[i] = ec._MyQuery___type(ctx, field) case "__schema": @@ -381,7 +376,7 @@ func (ec *executionContext) _MyQuery(ctx context.Context, sel ast.SelectionSet) panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -553,11 +548,9 @@ var todoImplementors = []string{"Todo", "Node"} func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *Todo) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, todoImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Todo") @@ -585,7 +578,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -706,11 +699,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -735,7 +726,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -895,11 +886,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -921,7 +910,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1040,11 +1029,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1076,7 +1063,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1290,11 +1277,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1316,7 +1301,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1443,11 +1428,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1474,7 +1457,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1700,11 +1683,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1733,7 +1714,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } diff --git a/graphql/fieldset.go b/graphql/fieldset.go new file mode 100644 index 00000000000..351e266fdb3 --- /dev/null +++ b/graphql/fieldset.go @@ -0,0 +1,63 @@ +package graphql + +import ( + "io" + "sync" +) + +type FieldSet struct { + fields []CollectedField + Values []Marshaler + delayed []delayedResult +} + +type delayedResult struct { + i int + f func() Marshaler +} + +func NewFieldSet(fields []CollectedField) *FieldSet { + return &FieldSet{ + fields: fields, + Values: make([]Marshaler, len(fields)), + } +} + +func (m *FieldSet) Concurrently(i int, f func() Marshaler) { + m.delayed = append(m.delayed, delayedResult{i: i, f: f}) +} + +func (m *FieldSet) Dispatch() { + if len(m.delayed) == 1 { + // only one concurrent task, no need to spawn a goroutine or deal create waitgroups + d := m.delayed[0] + m.Values[d.i] = d.f() + } else if len(m.delayed) > 1 { + // more than one concurrent task, use the main goroutine to do one, only spawn goroutines for the others + + var wg sync.WaitGroup + for _, d := range m.delayed[1:] { + wg.Add(1) + go func(d delayedResult) { + m.Values[d.i] = d.f() + wg.Done() + }(d) + } + + m.Values[m.delayed[0].i] = m.delayed[0].f() + wg.Wait() + } +} + +func (m *FieldSet) MarshalGQL(writer io.Writer) { + writer.Write(openBrace) + for i, field := range m.fields { + if i != 0 { + writer.Write(comma) + } + writeQuotedString(writer, field.Alias) + writer.Write(colon) + m.Values[i].MarshalGQL(writer) + } + writer.Write(closeBrace) +} diff --git a/graphql/jsonw.go b/graphql/jsonw.go index c087f63bd0d..db95d8e4419 100644 --- a/graphql/jsonw.go +++ b/graphql/jsonw.go @@ -26,42 +26,12 @@ type Unmarshaler interface { UnmarshalGQL(v interface{}) error } -type OrderedMap struct { - Keys []string - Values []Marshaler -} - type WriterFunc func(writer io.Writer) func (f WriterFunc) MarshalGQL(w io.Writer) { f(w) } -func NewOrderedMap(len int) *OrderedMap { - return &OrderedMap{ - Keys: make([]string, len), - Values: make([]Marshaler, len), - } -} - -func (m *OrderedMap) Add(key string, value Marshaler) { - m.Keys = append(m.Keys, key) - m.Values = append(m.Values, value) -} - -func (m *OrderedMap) MarshalGQL(writer io.Writer) { - writer.Write(openBrace) - for i, key := range m.Keys { - if i != 0 { - writer.Write(comma) - } - writeQuotedString(writer, key) - writer.Write(colon) - m.Values[i].MarshalGQL(writer) - } - writer.Write(closeBrace) -} - type Array []Marshaler func (a Array) MarshalGQL(writer io.Writer) { diff --git a/graphql/jsonw_test.go b/graphql/jsonw_test.go index 00f01cf57b7..856f1b9cdde 100644 --- a/graphql/jsonw_test.go +++ b/graphql/jsonw_test.go @@ -5,13 +5,19 @@ import ( "testing" "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/ast" ) func TestJsonWriter(t *testing.T) { - obj := &OrderedMap{} - obj.Add("test", MarshalInt(10)) + obj := NewFieldSet([]CollectedField{ + {Field: &ast.Field{Alias: "test"}}, + {Field: &ast.Field{Alias: "array"}}, + {Field: &ast.Field{Alias: "emptyArray"}}, + {Field: &ast.Field{Alias: "child"}}, + }) + obj.Values[0] = MarshalInt(10) - obj.Add("array", &Array{ + obj.Values[1] = &Array{ MarshalInt(1), MarshalString("2"), MarshalBoolean(true), @@ -19,17 +25,21 @@ func TestJsonWriter(t *testing.T) { Null, MarshalFloat(1.3), True, - }) + } - obj.Add("emptyArray", &Array{}) + obj.Values[2] = &Array{} - child2 := &OrderedMap{} - child2.Add("child", Null) + child2 := NewFieldSet([]CollectedField{ + {Field: &ast.Field{Alias: "child"}}, + }) + child2.Values[0] = Null - child1 := &OrderedMap{} - child1.Add("child", child2) + child1 := NewFieldSet([]CollectedField{ + {Field: &ast.Field{Alias: "child"}}, + }) + child1.Values[0] = child2 - obj.Add("child", child1) + obj.Values[3] = child1 b := &bytes.Buffer{} obj.MarshalGQL(b) diff --git a/integration/generated.go b/integration/generated.go index 008cf1959ab..83a4a42cc48 100644 --- a/integration/generated.go +++ b/integration/generated.go @@ -322,44 +322,41 @@ var elementImplementors = []string{"Element"} func (ec *executionContext) _Element(ctx context.Context, sel ast.SelectionSet, obj *models.Element) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, elementImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Element") case "child": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Element_child(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Element_child(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "error": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Element_error(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Element_error(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "mismatched": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Element_mismatched(ctx, field, obj) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Element_mismatched(ctx, field, obj) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -464,54 +461,51 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr Object: "Query", }) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") case "path": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_path(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_path(ctx, field) + return res + }) case "date": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_date(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_date(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "viewer": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_viewer(ctx, field) - wg.Done() - }(i, field) + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_viewer(ctx, field) + return res + }) case "jsonEncoding": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_jsonEncoding(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_jsonEncoding(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "error": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._Query_error(ctx, field) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._Query_error(ctx, field) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -520,7 +514,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -780,12 +774,9 @@ var userImplementors = []string{"User"} func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *remote_api.User) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, userImplementors) - var wg sync.WaitGroup - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("User") @@ -795,19 +786,19 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj invalid = true } case "likes": - wg.Add(1) - go func(i int, field graphql.CollectedField) { - out.Values[i] = ec._User_likes(ctx, field, obj) - if out.Values[i] == graphql.Null { + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + res = ec._User_likes(ctx, field, obj) + if res == graphql.Null { invalid = true } - wg.Done() - }(i, field) + return res + }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - wg.Wait() + out.Dispatch() if invalid { return graphql.Null } @@ -883,11 +874,9 @@ var viewerImplementors = []string{"Viewer"} func (ec *executionContext) _Viewer(ctx context.Context, sel ast.SelectionSet, obj *models.Viewer) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, viewerImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Viewer") @@ -897,7 +886,7 @@ func (ec *executionContext) _Viewer(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -939,11 +928,9 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __DirectiveImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") @@ -968,7 +955,7 @@ func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1128,11 +1115,9 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __EnumValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") @@ -1154,7 +1139,7 @@ func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionS panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1273,11 +1258,9 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __FieldImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") @@ -1309,7 +1292,7 @@ func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1523,11 +1506,9 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __InputValueImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") @@ -1549,7 +1530,7 @@ func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.Selection panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1676,11 +1657,9 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __SchemaImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") @@ -1707,7 +1686,7 @@ func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null } @@ -1933,11 +1912,9 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ctx, sel, __TypeImplementors) - out := graphql.NewOrderedMap(len(fields)) + out := graphql.NewFieldSet(fields) invalid := false for i, field := range fields { - out.Keys[i] = field.Alias - switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") @@ -1966,7 +1943,7 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o panic("unknown field " + strconv.Quote(field.Name)) } } - + out.Dispatch() if invalid { return graphql.Null }