graphql 1.13.12 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graphql might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install_generator.rb +1 -1
- data/lib/generators/graphql/relay.rb +3 -17
- data/lib/generators/graphql/templates/schema.erb +3 -0
- data/lib/graphql/analysis/ast/field_usage.rb +3 -1
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/analysis/ast/query_depth.rb +0 -1
- data/lib/graphql/analysis/ast/visitor.rb +43 -36
- data/lib/graphql/analysis/ast.rb +2 -12
- data/lib/graphql/analysis.rb +0 -7
- data/lib/graphql/backtrace/table.rb +2 -20
- data/lib/graphql/backtrace/trace.rb +96 -0
- data/lib/graphql/backtrace/tracer.rb +2 -3
- data/lib/graphql/backtrace.rb +7 -8
- data/lib/graphql/dataloader/null_dataloader.rb +3 -1
- data/lib/graphql/dataloader/source.rb +9 -0
- data/lib/graphql/dataloader.rb +4 -1
- data/lib/graphql/dig.rb +1 -1
- data/lib/graphql/execution/errors.rb +12 -82
- data/lib/graphql/execution/interpreter/arguments.rb +1 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -3
- data/lib/graphql/execution/interpreter/resolve.rb +26 -0
- data/lib/graphql/execution/interpreter/runtime.rb +300 -222
- data/lib/graphql/execution/interpreter.rb +187 -78
- data/lib/graphql/execution/lazy.rb +7 -21
- data/lib/graphql/execution/lookahead.rb +44 -40
- data/lib/graphql/execution/multiplex.rb +3 -174
- data/lib/graphql/execution.rb +11 -4
- data/lib/graphql/filter.rb +7 -2
- data/lib/graphql/introspection/directive_type.rb +2 -2
- data/lib/graphql/introspection/dynamic_fields.rb +3 -8
- data/lib/graphql/introspection/entry_points.rb +2 -15
- data/lib/graphql/introspection/field_type.rb +1 -1
- data/lib/graphql/introspection/schema_type.rb +2 -2
- data/lib/graphql/introspection/type_type.rb +13 -6
- data/lib/graphql/introspection.rb +4 -3
- data/lib/graphql/language/document_from_schema_definition.rb +43 -44
- data/lib/graphql/language/lexer.rb +216 -1488
- data/lib/graphql/language/nodes.rb +66 -40
- data/lib/graphql/language/parser.rb +539 -510
- data/lib/graphql/language/parser.y +53 -44
- data/lib/graphql/language/printer.rb +37 -21
- data/lib/graphql/language/visitor.rb +191 -83
- data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
- data/lib/graphql/pagination/array_connection.rb +4 -2
- data/lib/graphql/pagination/connection.rb +33 -6
- data/lib/graphql/pagination/connections.rb +3 -28
- data/lib/graphql/pagination/relation_connection.rb +2 -0
- data/lib/graphql/query/context.rb +156 -196
- data/lib/graphql/query/input_validation_result.rb +10 -1
- data/lib/graphql/query/null_context.rb +1 -4
- data/lib/graphql/query/validation_pipeline.rb +12 -37
- data/lib/graphql/query/variable_validation_error.rb +2 -2
- data/lib/graphql/query/variables.rb +35 -21
- data/lib/graphql/query.rb +39 -46
- data/lib/graphql/railtie.rb +0 -104
- data/lib/graphql/rake_task/validate.rb +1 -1
- data/lib/graphql/rake_task.rb +29 -1
- data/lib/graphql/relay/range_add.rb +9 -20
- data/lib/graphql/relay.rb +0 -15
- data/lib/graphql/schema/addition.rb +7 -9
- data/lib/graphql/schema/argument.rb +38 -47
- data/lib/graphql/schema/build_from_definition.rb +47 -21
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/transform.rb +1 -1
- data/lib/graphql/schema/directive.rb +12 -23
- data/lib/graphql/schema/enum.rb +29 -41
- data/lib/graphql/schema/enum_value.rb +2 -25
- data/lib/graphql/schema/field/connection_extension.rb +4 -0
- data/lib/graphql/schema/field.rb +256 -349
- data/lib/graphql/schema/field_extension.rb +1 -4
- data/lib/graphql/schema/find_inherited_value.rb +2 -7
- data/lib/graphql/schema/input_object.rb +57 -69
- data/lib/graphql/schema/interface.rb +0 -35
- data/lib/graphql/schema/introspection_system.rb +3 -8
- data/lib/graphql/schema/late_bound_type.rb +8 -2
- data/lib/graphql/schema/list.rb +18 -9
- data/lib/graphql/schema/loader.rb +1 -2
- data/lib/graphql/schema/member/base_dsl_methods.rb +17 -19
- data/lib/graphql/schema/member/build_type.rb +5 -7
- data/lib/graphql/schema/member/has_arguments.rb +147 -56
- data/lib/graphql/schema/member/has_ast_node.rb +12 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
- data/lib/graphql/schema/member/has_directives.rb +81 -61
- data/lib/graphql/schema/member/has_fields.rb +97 -40
- data/lib/graphql/schema/member/has_interfaces.rb +49 -10
- data/lib/graphql/schema/member/has_validators.rb +32 -6
- data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +0 -6
- data/lib/graphql/schema/mutation.rb +0 -9
- data/lib/graphql/schema/non_null.rb +3 -9
- data/lib/graphql/schema/object.rb +15 -52
- data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
- data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
- data/lib/graphql/schema/resolver.rb +43 -44
- data/lib/graphql/schema/scalar.rb +8 -23
- data/lib/graphql/schema/subscription.rb +0 -7
- data/lib/graphql/schema/timeout.rb +24 -28
- data/lib/graphql/schema/type_membership.rb +3 -0
- data/lib/graphql/schema/union.rb +10 -17
- data/lib/graphql/schema/validator.rb +1 -1
- data/lib/graphql/schema/warden.rb +37 -9
- data/lib/graphql/schema/wrapper.rb +0 -5
- data/lib/graphql/schema.rb +265 -968
- data/lib/graphql/static_validation/all_rules.rb +1 -0
- data/lib/graphql/static_validation/base_visitor.rb +4 -21
- data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
- data/lib/graphql/static_validation/error.rb +2 -2
- data/lib/graphql/static_validation/literal_validator.rb +19 -1
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +12 -4
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +2 -2
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
- data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +3 -25
- data/lib/graphql/static_validation.rb +0 -2
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
- data/lib/graphql/subscriptions/event.rb +3 -8
- data/lib/graphql/subscriptions/instrumentation.rb +0 -51
- data/lib/graphql/subscriptions.rb +32 -20
- data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
- data/lib/graphql/tracing/appoptics_trace.rb +231 -0
- data/lib/graphql/tracing/appsignal_trace.rb +77 -0
- data/lib/graphql/tracing/data_dog_trace.rb +148 -0
- data/lib/graphql/tracing/data_dog_tracing.rb +21 -2
- data/lib/graphql/tracing/legacy_trace.rb +65 -0
- data/lib/graphql/tracing/new_relic_trace.rb +75 -0
- data/lib/graphql/tracing/notifications_trace.rb +42 -0
- data/lib/graphql/tracing/platform_trace.rb +109 -0
- data/lib/graphql/tracing/platform_tracing.rb +33 -43
- data/lib/graphql/tracing/prometheus_trace.rb +89 -0
- data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +1 -1
- data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
- data/lib/graphql/tracing/scout_trace.rb +72 -0
- data/lib/graphql/tracing/statsd_trace.rb +56 -0
- data/lib/graphql/tracing/trace.rb +75 -0
- data/lib/graphql/tracing.rb +16 -40
- data/lib/graphql/type_kinds.rb +6 -3
- data/lib/graphql/types/iso_8601_date.rb +4 -1
- data/lib/graphql/types/iso_8601_date_time.rb +4 -0
- data/lib/graphql/types/relay/base_connection.rb +16 -6
- data/lib/graphql/types/relay/connection_behaviors.rb +29 -27
- data/lib/graphql/types/relay/edge_behaviors.rb +16 -5
- data/lib/graphql/types/relay/node_behaviors.rb +12 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +7 -2
- data/lib/graphql/types/relay.rb +0 -3
- data/lib/graphql/types/string.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +17 -74
- metadata +33 -133
- data/lib/graphql/analysis/analyze_query.rb +0 -98
- data/lib/graphql/analysis/field_usage.rb +0 -45
- data/lib/graphql/analysis/max_query_complexity.rb +0 -26
- data/lib/graphql/analysis/max_query_depth.rb +0 -26
- data/lib/graphql/analysis/query_complexity.rb +0 -88
- data/lib/graphql/analysis/query_depth.rb +0 -43
- data/lib/graphql/analysis/reducer_state.rb +0 -48
- data/lib/graphql/argument.rb +0 -131
- data/lib/graphql/authorization.rb +0 -82
- data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
- data/lib/graphql/backwards_compatibility.rb +0 -61
- data/lib/graphql/base_type.rb +0 -232
- data/lib/graphql/boolean_type.rb +0 -2
- data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
- data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
- data/lib/graphql/compatibility/execution_specification.rb +0 -436
- data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
- data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
- data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
- data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
- data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
- data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
- data/lib/graphql/compatibility.rb +0 -5
- data/lib/graphql/define/assign_argument.rb +0 -12
- data/lib/graphql/define/assign_connection.rb +0 -13
- data/lib/graphql/define/assign_enum_value.rb +0 -18
- data/lib/graphql/define/assign_global_id_field.rb +0 -11
- data/lib/graphql/define/assign_mutation_function.rb +0 -34
- data/lib/graphql/define/assign_object_field.rb +0 -42
- data/lib/graphql/define/defined_object_proxy.rb +0 -53
- data/lib/graphql/define/instance_definable.rb +0 -255
- data/lib/graphql/define/no_definition_error.rb +0 -7
- data/lib/graphql/define/non_null_with_bang.rb +0 -16
- data/lib/graphql/define/type_definer.rb +0 -31
- data/lib/graphql/define.rb +0 -31
- data/lib/graphql/deprecated_dsl.rb +0 -55
- data/lib/graphql/directive/deprecated_directive.rb +0 -2
- data/lib/graphql/directive/include_directive.rb +0 -2
- data/lib/graphql/directive/skip_directive.rb +0 -2
- data/lib/graphql/directive.rb +0 -107
- data/lib/graphql/enum_type.rb +0 -133
- data/lib/graphql/execution/execute.rb +0 -333
- data/lib/graphql/execution/flatten.rb +0 -40
- data/lib/graphql/execution/instrumentation.rb +0 -92
- data/lib/graphql/execution/lazy/resolve.rb +0 -91
- data/lib/graphql/execution/typecast.rb +0 -50
- data/lib/graphql/field/resolve.rb +0 -59
- data/lib/graphql/field.rb +0 -226
- data/lib/graphql/float_type.rb +0 -2
- data/lib/graphql/function.rb +0 -128
- data/lib/graphql/id_type.rb +0 -2
- data/lib/graphql/input_object_type.rb +0 -138
- data/lib/graphql/int_type.rb +0 -2
- data/lib/graphql/interface_type.rb +0 -72
- data/lib/graphql/internal_representation/document.rb +0 -27
- data/lib/graphql/internal_representation/node.rb +0 -206
- data/lib/graphql/internal_representation/print.rb +0 -51
- data/lib/graphql/internal_representation/rewrite.rb +0 -184
- data/lib/graphql/internal_representation/scope.rb +0 -88
- data/lib/graphql/internal_representation/visit.rb +0 -36
- data/lib/graphql/internal_representation.rb +0 -7
- data/lib/graphql/language/lexer.rl +0 -260
- data/lib/graphql/list_type.rb +0 -80
- data/lib/graphql/non_null_type.rb +0 -71
- data/lib/graphql/object_type.rb +0 -130
- data/lib/graphql/query/arguments.rb +0 -189
- data/lib/graphql/query/arguments_cache.rb +0 -24
- data/lib/graphql/query/executor.rb +0 -52
- data/lib/graphql/query/literal_input.rb +0 -136
- data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
- data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
- data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
- data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
- data/lib/graphql/query/serial_execution.rb +0 -40
- data/lib/graphql/relay/array_connection.rb +0 -83
- data/lib/graphql/relay/base_connection.rb +0 -189
- data/lib/graphql/relay/connection_instrumentation.rb +0 -54
- data/lib/graphql/relay/connection_resolve.rb +0 -43
- data/lib/graphql/relay/connection_type.rb +0 -54
- data/lib/graphql/relay/edge.rb +0 -27
- data/lib/graphql/relay/edge_type.rb +0 -19
- data/lib/graphql/relay/edges_instrumentation.rb +0 -39
- data/lib/graphql/relay/global_id_resolve.rb +0 -17
- data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
- data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
- data/lib/graphql/relay/mutation/resolve.rb +0 -56
- data/lib/graphql/relay/mutation/result.rb +0 -38
- data/lib/graphql/relay/mutation.rb +0 -106
- data/lib/graphql/relay/node.rb +0 -39
- data/lib/graphql/relay/page_info.rb +0 -7
- data/lib/graphql/relay/relation_connection.rb +0 -188
- data/lib/graphql/relay/type_extensions.rb +0 -32
- data/lib/graphql/scalar_type.rb +0 -91
- data/lib/graphql/schema/catchall_middleware.rb +0 -35
- data/lib/graphql/schema/default_parse_error.rb +0 -10
- data/lib/graphql/schema/default_type_error.rb +0 -17
- data/lib/graphql/schema/member/accepts_definition.rb +0 -164
- data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
- data/lib/graphql/schema/member/instrumentation.rb +0 -131
- data/lib/graphql/schema/middleware_chain.rb +0 -82
- data/lib/graphql/schema/possible_types.rb +0 -44
- data/lib/graphql/schema/rescue_middleware.rb +0 -60
- data/lib/graphql/schema/timeout_middleware.rb +0 -88
- data/lib/graphql/schema/traversal.rb +0 -228
- data/lib/graphql/schema/validation.rb +0 -313
- data/lib/graphql/static_validation/default_visitor.rb +0 -15
- data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
- data/lib/graphql/string_type.rb +0 -2
- data/lib/graphql/subscriptions/subscription_root.rb +0 -76
- data/lib/graphql/tracing/skylight_tracing.rb +0 -70
- data/lib/graphql/types/relay/default_relay.rb +0 -31
- data/lib/graphql/types/relay/node_field.rb +0 -24
- data/lib/graphql/types/relay/nodes_field.rb +0 -43
- data/lib/graphql/union_type.rb +0 -115
- data/lib/graphql/upgrader/member.rb +0 -937
- data/lib/graphql/upgrader/schema.rb +0 -38
@@ -8,6 +8,18 @@ module GraphQL
|
|
8
8
|
#
|
9
9
|
# @api private
|
10
10
|
class Runtime
|
11
|
+
class CurrentState
|
12
|
+
def initialize
|
13
|
+
@current_object = nil
|
14
|
+
@current_field = nil
|
15
|
+
@current_arguments = nil
|
16
|
+
@current_result_name = nil
|
17
|
+
@current_result = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :current_result, :current_result_name,
|
21
|
+
:current_arguments, :current_field, :current_object
|
22
|
+
end
|
11
23
|
|
12
24
|
module GraphQLResult
|
13
25
|
def initialize(result_name, parent_result)
|
@@ -20,6 +32,15 @@ module GraphQL
|
|
20
32
|
@graphql_metadata = nil
|
21
33
|
end
|
22
34
|
|
35
|
+
def path
|
36
|
+
@path ||= build_path([])
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_path(path_array)
|
40
|
+
graphql_result_name && path_array.unshift(graphql_result_name)
|
41
|
+
@graphql_parent ? @graphql_parent.build_path(path_array) : path_array
|
42
|
+
end
|
43
|
+
|
23
44
|
attr_accessor :graphql_dead
|
24
45
|
attr_reader :graphql_parent, :graphql_result_name
|
25
46
|
|
@@ -45,7 +66,7 @@ module GraphQL
|
|
45
66
|
|
46
67
|
attr_accessor :graphql_merged_into
|
47
68
|
|
48
|
-
def
|
69
|
+
def set_leaf(key, value)
|
49
70
|
# This is a hack.
|
50
71
|
# Basically, this object is merged into the root-level result at some point.
|
51
72
|
# But the problem is, some lazies are created whose closures retain reference to _this_
|
@@ -55,23 +76,27 @@ module GraphQL
|
|
55
76
|
# In order to return a proper partial result (eg, for a directive), we have to update this object, too.
|
56
77
|
# Yowza.
|
57
78
|
if (t = @graphql_merged_into)
|
58
|
-
t
|
79
|
+
t.set_leaf(key, value)
|
59
80
|
end
|
60
81
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# then create the metadata hash if necessary. It will be kept up-to-date after this.
|
65
|
-
(@graphql_metadata ||= @graphql_result_data.dup)[key] = value
|
66
|
-
else
|
67
|
-
@graphql_result_data[key] = value
|
68
|
-
# keep this up-to-date if it's been initialized
|
69
|
-
@graphql_metadata && @graphql_metadata[key] = value
|
70
|
-
end
|
82
|
+
@graphql_result_data[key] = value
|
83
|
+
# keep this up-to-date if it's been initialized
|
84
|
+
@graphql_metadata && @graphql_metadata[key] = value
|
71
85
|
|
72
86
|
value
|
73
87
|
end
|
74
88
|
|
89
|
+
def set_child_result(key, value)
|
90
|
+
if (t = @graphql_merged_into)
|
91
|
+
t.set_child_result(key, value)
|
92
|
+
end
|
93
|
+
@graphql_result_data[key] = value.graphql_result_data
|
94
|
+
# If we encounter some part of this response that requires metadata tracking,
|
95
|
+
# then create the metadata hash if necessary. It will be kept up-to-date after this.
|
96
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[key] = value
|
97
|
+
value
|
98
|
+
end
|
99
|
+
|
75
100
|
def delete(key)
|
76
101
|
@graphql_metadata && @graphql_metadata.delete(key)
|
77
102
|
@graphql_result_data.delete(key)
|
@@ -92,6 +117,29 @@ module GraphQL
|
|
92
117
|
def [](k)
|
93
118
|
(@graphql_metadata || @graphql_result_data)[k]
|
94
119
|
end
|
120
|
+
|
121
|
+
def merge_into(into_result)
|
122
|
+
self.each do |key, value|
|
123
|
+
case value
|
124
|
+
when GraphQLResultHash
|
125
|
+
next_into = into_result[key]
|
126
|
+
if next_into
|
127
|
+
value.merge_into(next_into)
|
128
|
+
else
|
129
|
+
into_result.set_child_result(key, value)
|
130
|
+
end
|
131
|
+
when GraphQLResultArray
|
132
|
+
# There's no special handling of arrays because currently, there's no way to split the execution
|
133
|
+
# of a list over several concurrent flows.
|
134
|
+
next_result.set_child_result(key, value)
|
135
|
+
else
|
136
|
+
# We have to assume that, since this passed the `fields_will_merge` selection,
|
137
|
+
# that the old and new values are the same.
|
138
|
+
into_result.set_leaf(key, value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
@graphql_merged_into = into_result
|
142
|
+
end
|
95
143
|
end
|
96
144
|
|
97
145
|
class GraphQLResultArray
|
@@ -114,19 +162,25 @@ module GraphQL
|
|
114
162
|
@graphql_result_data.delete_at(delete_at_index)
|
115
163
|
end
|
116
164
|
|
117
|
-
def
|
165
|
+
def set_leaf(idx, value)
|
118
166
|
if @skip_indices
|
119
167
|
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < idx }
|
120
168
|
idx -= offset_by
|
121
169
|
end
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
@graphql_result_data[idx] = value
|
127
|
-
@graphql_metadata && @graphql_metadata[idx] = value
|
128
|
-
end
|
170
|
+
@graphql_result_data[idx] = value
|
171
|
+
@graphql_metadata && @graphql_metadata[idx] = value
|
172
|
+
value
|
173
|
+
end
|
129
174
|
|
175
|
+
def set_child_result(idx, value)
|
176
|
+
if @skip_indices
|
177
|
+
offset_by = @skip_indices.count { |skipped_idx| skipped_idx < idx }
|
178
|
+
idx -= offset_by
|
179
|
+
end
|
180
|
+
@graphql_result_data[idx] = value.graphql_result_data
|
181
|
+
# If we encounter some part of this response that requires metadata tracking,
|
182
|
+
# then create the metadata hash if necessary. It will be kept up-to-date after this.
|
183
|
+
(@graphql_metadata ||= @graphql_result_data.dup)[idx] = value
|
130
184
|
value
|
131
185
|
end
|
132
186
|
|
@@ -148,13 +202,15 @@ module GraphQL
|
|
148
202
|
# @return [GraphQL::Query::Context]
|
149
203
|
attr_reader :context
|
150
204
|
|
151
|
-
def initialize(query:)
|
205
|
+
def initialize(query:, lazies_at_depth:)
|
152
206
|
@query = query
|
153
207
|
@dataloader = query.multiplex.dataloader
|
208
|
+
@lazies_at_depth = lazies_at_depth
|
154
209
|
@schema = query.schema
|
155
210
|
@context = query.context
|
156
211
|
@multiplex_context = query.multiplex.context
|
157
|
-
|
212
|
+
# Start this off empty:
|
213
|
+
Thread.current[:__graphql_runtime_info] = nil
|
158
214
|
@response = GraphQLResultHash.new(nil, nil)
|
159
215
|
# Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
|
160
216
|
@runtime_directive_names = []
|
@@ -198,8 +254,9 @@ module GraphQL
|
|
198
254
|
root_operation = query.selected_operation
|
199
255
|
root_op_type = root_operation.operation_type || "query"
|
200
256
|
root_type = schema.root_type_for_operation(root_op_type)
|
201
|
-
|
202
|
-
|
257
|
+
st = get_current_runtime_state
|
258
|
+
st.current_object = query.root_value
|
259
|
+
st.current_result = @response
|
203
260
|
object_proxy = authorized_new(root_type, query.root_value, context)
|
204
261
|
object_proxy = schema.sync_lazy(object_proxy)
|
205
262
|
|
@@ -226,11 +283,12 @@ module GraphQL
|
|
226
283
|
end
|
227
284
|
|
228
285
|
@dataloader.append_job {
|
229
|
-
|
286
|
+
st = get_current_runtime_state
|
287
|
+
st.current_object = query.root_value
|
288
|
+
st.current_result = selection_response
|
289
|
+
|
230
290
|
call_method_on_directives(:resolve, object_proxy, selections.graphql_directives) do
|
231
291
|
evaluate_selections(
|
232
|
-
path,
|
233
|
-
context.scoped_context,
|
234
292
|
object_proxy,
|
235
293
|
root_type,
|
236
294
|
root_op_type == "mutation",
|
@@ -244,32 +302,7 @@ module GraphQL
|
|
244
302
|
end
|
245
303
|
end
|
246
304
|
end
|
247
|
-
|
248
|
-
delete_interpreter_context(:current_field)
|
249
|
-
delete_interpreter_context(:current_object)
|
250
|
-
delete_interpreter_context(:current_arguments)
|
251
|
-
nil
|
252
|
-
end
|
253
|
-
|
254
|
-
# @return [void]
|
255
|
-
def deep_merge_selection_result(from_result, into_result)
|
256
|
-
from_result.each do |key, value|
|
257
|
-
if !into_result.key?(key)
|
258
|
-
into_result[key] = value
|
259
|
-
else
|
260
|
-
case value
|
261
|
-
when GraphQLResultHash
|
262
|
-
deep_merge_selection_result(value, into_result[key])
|
263
|
-
else
|
264
|
-
# We have to assume that, since this passed the `fields_will_merge` selection,
|
265
|
-
# that the old and new values are the same.
|
266
|
-
# There's no special handling of arrays because currently, there's no way to split the execution
|
267
|
-
# of a list over several concurrent flows.
|
268
|
-
into_result[key] = value
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
from_result.graphql_merged_into = into_result
|
305
|
+
delete_all_interpreter_context
|
273
306
|
nil
|
274
307
|
end
|
275
308
|
|
@@ -346,22 +379,25 @@ module GraphQL
|
|
346
379
|
selections_to_run || selections_by_name
|
347
380
|
end
|
348
381
|
|
349
|
-
NO_ARGS =
|
382
|
+
NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
|
350
383
|
|
351
384
|
# @return [void]
|
352
|
-
def evaluate_selections(
|
353
|
-
|
385
|
+
def evaluate_selections(owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
386
|
+
st = get_current_runtime_state
|
387
|
+
st.current_object = owner_object
|
388
|
+
st.current_result_name = nil
|
389
|
+
st.current_result = selections_result
|
354
390
|
|
355
391
|
finished_jobs = 0
|
356
392
|
enqueued_jobs = gathered_selections.size
|
357
393
|
gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
|
358
394
|
@dataloader.append_job {
|
359
395
|
evaluate_selection(
|
360
|
-
|
396
|
+
result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_selection, selections_result, parent_object
|
361
397
|
)
|
362
398
|
finished_jobs += 1
|
363
399
|
if target_result && finished_jobs == enqueued_jobs
|
364
|
-
|
400
|
+
selections_result.merge_into(target_result)
|
365
401
|
end
|
366
402
|
}
|
367
403
|
end
|
@@ -369,10 +405,8 @@ module GraphQL
|
|
369
405
|
selections_result
|
370
406
|
end
|
371
407
|
|
372
|
-
attr_reader :progress_path
|
373
|
-
|
374
408
|
# @return [void]
|
375
|
-
def evaluate_selection(
|
409
|
+
def evaluate_selection(result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_field, selections_result, parent_object) # rubocop:disable Metrics/ParameterLists
|
376
410
|
return if dead_result?(selections_result)
|
377
411
|
# As a performance optimization, the hash key will be a `Node` if
|
378
412
|
# there's only one selection of the field. But if there are multiple
|
@@ -400,22 +434,22 @@ module GraphQL
|
|
400
434
|
raise "Invariant: no field for #{owner_type}.#{field_name}"
|
401
435
|
end
|
402
436
|
end
|
403
|
-
return_type = field_defn.type
|
404
437
|
|
405
|
-
|
406
|
-
next_path << result_name
|
407
|
-
next_path.freeze
|
438
|
+
return_type = field_defn.type
|
408
439
|
|
409
440
|
# This seems janky, but we need to know
|
410
441
|
# the field's return type at this path in order
|
411
442
|
# to propagate `null`
|
412
|
-
|
443
|
+
return_type_non_null = return_type.non_null?
|
444
|
+
if return_type_non_null
|
413
445
|
(selections_result.graphql_non_null_field_names ||= []).push(result_name)
|
414
446
|
end
|
415
447
|
# Set this before calling `run_with_directives`, so that the directive can have the latest path
|
416
|
-
|
448
|
+
st = get_current_runtime_state
|
449
|
+
st.current_field = field_defn
|
450
|
+
st.current_result = selections_result
|
451
|
+
st.current_result_name = result_name
|
417
452
|
|
418
|
-
context.scoped_context = scoped_context
|
419
453
|
object = owner_object
|
420
454
|
|
421
455
|
if is_introspection
|
@@ -425,27 +459,34 @@ module GraphQL
|
|
425
459
|
total_args_count = field_defn.arguments(context).size
|
426
460
|
if total_args_count == 0
|
427
461
|
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
428
|
-
|
462
|
+
if field_defn.extras.size == 0
|
463
|
+
evaluate_selection_with_resolved_keyword_args(
|
464
|
+
NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null
|
465
|
+
)
|
466
|
+
else
|
467
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
|
468
|
+
end
|
429
469
|
else
|
430
|
-
# TODO remove all arguments(...) usages?
|
431
470
|
@query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
|
432
|
-
evaluate_selection_with_args(resolved_arguments, field_defn,
|
471
|
+
evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type_non_null)
|
433
472
|
end
|
434
473
|
end
|
435
474
|
end
|
436
475
|
|
437
|
-
def evaluate_selection_with_args(arguments, field_defn,
|
438
|
-
|
439
|
-
return_type = field_defn.type
|
440
|
-
after_lazy(arguments, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
|
476
|
+
def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null) # rubocop:disable Metrics/ParameterLists
|
477
|
+
after_lazy(arguments, owner: owner_type, field: field_defn, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result) do |resolved_arguments|
|
441
478
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
442
|
-
continue_value(
|
479
|
+
continue_value(resolved_arguments, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
|
443
480
|
next
|
444
481
|
end
|
445
482
|
|
446
|
-
kwarg_arguments = if
|
447
|
-
|
448
|
-
|
483
|
+
kwarg_arguments = if field_defn.extras.empty?
|
484
|
+
if resolved_arguments.empty?
|
485
|
+
# We can avoid allocating the `{ Symbol => Object }` hash in this case
|
486
|
+
NO_ARGS
|
487
|
+
else
|
488
|
+
resolved_arguments.keyword_arguments
|
489
|
+
end
|
449
490
|
else
|
450
491
|
# Bundle up the extras, then make a new arguments instance
|
451
492
|
# that includes the extras, too.
|
@@ -455,9 +496,9 @@ module GraphQL
|
|
455
496
|
when :ast_node
|
456
497
|
extra_args[:ast_node] = ast_node
|
457
498
|
when :execution_errors
|
458
|
-
extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node,
|
499
|
+
extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node, current_path)
|
459
500
|
when :path
|
460
|
-
extra_args[:path] =
|
501
|
+
extra_args[:path] = current_path
|
461
502
|
when :lookahead
|
462
503
|
if !field_ast_nodes
|
463
504
|
field_ast_nodes = [ast_node]
|
@@ -472,10 +513,6 @@ module GraphQL
|
|
472
513
|
# Use this flag to tell Interpreter::Arguments to add itself
|
473
514
|
# to the keyword args hash _before_ freezing everything.
|
474
515
|
extra_args[:argument_details] = :__arguments_add_self
|
475
|
-
when :irep_node
|
476
|
-
# This is used by `__typename` in order to support the legacy runtime,
|
477
|
-
# but it has no use here (and it's always `nil`).
|
478
|
-
# Stop adding it here to avoid the overhead of `.merge_extras` below.
|
479
516
|
when :parent
|
480
517
|
extra_args[:parent] = parent_object
|
481
518
|
else
|
@@ -488,57 +525,70 @@ module GraphQL
|
|
488
525
|
resolved_arguments.keyword_arguments
|
489
526
|
end
|
490
527
|
|
491
|
-
|
528
|
+
evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null)
|
529
|
+
end
|
530
|
+
end
|
492
531
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
532
|
+
def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null) # rubocop:disable Metrics/ParameterLists
|
533
|
+
st = get_current_runtime_state
|
534
|
+
st.current_field = field_defn
|
535
|
+
st.current_object = object
|
536
|
+
st.current_arguments = resolved_arguments
|
537
|
+
st.current_result_name = result_name
|
538
|
+
st.current_result = selection_result
|
539
|
+
# Optimize for the case that field is selected only once
|
540
|
+
if field_ast_nodes.nil? || field_ast_nodes.size == 1
|
541
|
+
next_selections = ast_node.selections
|
542
|
+
directives = ast_node.directives
|
543
|
+
else
|
544
|
+
next_selections = []
|
545
|
+
directives = []
|
546
|
+
field_ast_nodes.each { |f|
|
547
|
+
next_selections.concat(f.selections)
|
548
|
+
directives.concat(f.directives)
|
549
|
+
}
|
550
|
+
end
|
551
|
+
|
552
|
+
field_result = call_method_on_directives(:resolve, object, directives) do
|
553
|
+
# Actually call the field resolver and capture the result
|
554
|
+
app_result = begin
|
555
|
+
query.current_trace.execute_field(field: field_defn, ast_node: ast_node, query: query, object: object, arguments: kwarg_arguments) do
|
556
|
+
field_defn.resolve(object, kwarg_arguments, context)
|
516
557
|
end
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
558
|
+
rescue GraphQL::ExecutionError => err
|
559
|
+
err
|
560
|
+
rescue StandardError => err
|
561
|
+
begin
|
562
|
+
query.handle_or_reraise(err)
|
563
|
+
rescue GraphQL::ExecutionError => ex_err
|
564
|
+
ex_err
|
522
565
|
end
|
523
566
|
end
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
530
|
-
else
|
531
|
-
# Return this from `after_lazy` because it might be another lazy that needs to be resolved
|
532
|
-
field_result
|
567
|
+
after_lazy(app_result, owner: owner_type, field: field_defn, ast_node: ast_node, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
|
568
|
+
continue_value = continue_value(inner_result, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
|
569
|
+
if HALT != continue_value
|
570
|
+
continue_field(continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
|
571
|
+
end
|
533
572
|
end
|
534
573
|
end
|
574
|
+
|
575
|
+
# If this field is a root mutation field, immediately resolve
|
576
|
+
# all of its child fields before moving on to the next root mutation field.
|
577
|
+
# (Subselections of this mutation will still be resolved level-by-level.)
|
578
|
+
if is_eager_field
|
579
|
+
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
580
|
+
else
|
581
|
+
# Return this from `after_lazy` because it might be another lazy that needs to be resolved
|
582
|
+
field_result
|
583
|
+
end
|
535
584
|
end
|
536
585
|
|
586
|
+
|
537
587
|
def dead_result?(selection_result)
|
538
|
-
selection_result.graphql_dead || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
|
588
|
+
selection_result.graphql_dead # || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
|
539
589
|
end
|
540
590
|
|
541
|
-
def set_result(selection_result, result_name, value)
|
591
|
+
def set_result(selection_result, result_name, value, is_child_result)
|
542
592
|
if !dead_result?(selection_result)
|
543
593
|
if value.nil? &&
|
544
594
|
( # there are two conditions under which `nil` is not allowed in the response:
|
@@ -558,11 +608,13 @@ module GraphQL
|
|
558
608
|
if parent.nil? # This is a top-level result hash
|
559
609
|
@response = nil
|
560
610
|
else
|
561
|
-
set_result(parent, name_in_parent, nil)
|
611
|
+
set_result(parent, name_in_parent, nil, false)
|
562
612
|
set_graphql_dead(selection_result)
|
563
613
|
end
|
614
|
+
elsif is_child_result
|
615
|
+
selection_result.set_child_result(result_name, value)
|
564
616
|
else
|
565
|
-
selection_result
|
617
|
+
selection_result.set_leaf(result_name, value)
|
566
618
|
end
|
567
619
|
end
|
568
620
|
end
|
@@ -582,18 +634,29 @@ module GraphQL
|
|
582
634
|
end
|
583
635
|
end
|
584
636
|
|
637
|
+
def current_path
|
638
|
+
st = get_current_runtime_state
|
639
|
+
result = st.current_result
|
640
|
+
path = result && result.path
|
641
|
+
if path && (rn = st.current_result_name)
|
642
|
+
path = path.dup
|
643
|
+
path.push(rn)
|
644
|
+
end
|
645
|
+
path
|
646
|
+
end
|
647
|
+
|
585
648
|
HALT = Object.new
|
586
|
-
def continue_value(
|
649
|
+
def continue_value(value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
|
587
650
|
case value
|
588
651
|
when nil
|
589
652
|
if is_non_null
|
590
|
-
set_result(selection_result, result_name, nil) do
|
653
|
+
set_result(selection_result, result_name, nil, false) do
|
591
654
|
# This block is called if `result_name` is not dead. (Maybe a previous invalid nil caused it be marked dead.)
|
592
655
|
err = parent_type::InvalidNullError.new(parent_type, field, value)
|
593
656
|
schema.type_error(err, context)
|
594
657
|
end
|
595
658
|
else
|
596
|
-
set_result(selection_result, result_name, nil)
|
659
|
+
set_result(selection_result, result_name, nil, false)
|
597
660
|
end
|
598
661
|
HALT
|
599
662
|
when GraphQL::Error
|
@@ -602,14 +665,24 @@ module GraphQL
|
|
602
665
|
# every time.
|
603
666
|
if value.is_a?(GraphQL::ExecutionError)
|
604
667
|
if selection_result.nil? || !dead_result?(selection_result)
|
605
|
-
value.path ||=
|
668
|
+
value.path ||= current_path
|
606
669
|
value.ast_node ||= ast_node
|
607
670
|
context.errors << value
|
608
671
|
if selection_result
|
609
|
-
set_result(selection_result, result_name, nil)
|
672
|
+
set_result(selection_result, result_name, nil, false)
|
610
673
|
end
|
611
674
|
end
|
612
675
|
HALT
|
676
|
+
elsif value.is_a?(GraphQL::UnauthorizedFieldError)
|
677
|
+
value.field ||= field
|
678
|
+
# this hook might raise & crash, or it might return
|
679
|
+
# a replacement value
|
680
|
+
next_value = begin
|
681
|
+
schema.unauthorized_field(value)
|
682
|
+
rescue GraphQL::ExecutionError => err
|
683
|
+
err
|
684
|
+
end
|
685
|
+
continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
|
613
686
|
elsif value.is_a?(GraphQL::UnauthorizedError)
|
614
687
|
# this hook might raise & crash, or it might return
|
615
688
|
# a replacement value
|
@@ -618,8 +691,8 @@ module GraphQL
|
|
618
691
|
rescue GraphQL::ExecutionError => err
|
619
692
|
err
|
620
693
|
end
|
621
|
-
continue_value(
|
622
|
-
elsif GraphQL::Execution::
|
694
|
+
continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
|
695
|
+
elsif GraphQL::Execution::SKIP == value
|
623
696
|
# It's possible a lazy was already written here
|
624
697
|
case selection_result
|
625
698
|
when GraphQLResultHash
|
@@ -644,15 +717,15 @@ module GraphQL
|
|
644
717
|
if selection_result.nil? || !dead_result?(selection_result)
|
645
718
|
value.each_with_index do |error, index|
|
646
719
|
error.ast_node ||= ast_node
|
647
|
-
error.path ||=
|
720
|
+
error.path ||= current_path + (list_type_at_all ? [index] : [])
|
648
721
|
context.errors << error
|
649
722
|
end
|
650
723
|
if selection_result
|
651
724
|
if list_type_at_all
|
652
725
|
result_without_errors = value.map { |v| v.is_a?(GraphQL::ExecutionError) ? nil : v }
|
653
|
-
set_result(selection_result, result_name, result_without_errors)
|
726
|
+
set_result(selection_result, result_name, result_without_errors, false)
|
654
727
|
else
|
655
|
-
set_result(selection_result, result_name, nil)
|
728
|
+
set_result(selection_result, result_name, nil, false)
|
656
729
|
end
|
657
730
|
end
|
658
731
|
end
|
@@ -662,7 +735,7 @@ module GraphQL
|
|
662
735
|
end
|
663
736
|
when GraphQL::Execution::Interpreter::RawValue
|
664
737
|
# Write raw value directly to the response without resolving nested objects
|
665
|
-
set_result(selection_result, result_name, value.resolve)
|
738
|
+
set_result(selection_result, result_name, value.resolve, false)
|
666
739
|
HALT
|
667
740
|
else
|
668
741
|
value
|
@@ -677,7 +750,7 @@ module GraphQL
|
|
677
750
|
# Location information from `path` and `ast_node`.
|
678
751
|
#
|
679
752
|
# @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
|
680
|
-
def continue_field(
|
753
|
+
def continue_field(value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
|
681
754
|
if current_type.non_null?
|
682
755
|
current_type = current_type.of_type
|
683
756
|
is_non_null = true
|
@@ -685,25 +758,33 @@ module GraphQL
|
|
685
758
|
|
686
759
|
case current_type.kind.name
|
687
760
|
when "SCALAR", "ENUM"
|
688
|
-
r =
|
689
|
-
|
761
|
+
r = begin
|
762
|
+
current_type.coerce_result(value, context)
|
763
|
+
rescue StandardError => err
|
764
|
+
schema.handle_or_reraise(context, err)
|
765
|
+
end
|
766
|
+
set_result(selection_result, result_name, r, false)
|
690
767
|
r
|
691
768
|
when "UNION", "INTERFACE"
|
692
|
-
resolved_type_or_lazy
|
693
|
-
|
769
|
+
resolved_type_or_lazy = resolve_type(current_type, value)
|
770
|
+
after_lazy(resolved_type_or_lazy, owner: current_type, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |resolved_type_result|
|
771
|
+
if resolved_type_result.is_a?(Array) && resolved_type_result.length == 2
|
772
|
+
resolved_type, resolved_value = resolved_type_result
|
773
|
+
else
|
774
|
+
resolved_type = resolved_type_result
|
775
|
+
resolved_value = value
|
776
|
+
end
|
694
777
|
|
695
|
-
after_lazy(resolved_type_or_lazy, owner: current_type, path: path, ast_node: ast_node, scoped_context: context.scoped_context, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |resolved_type|
|
696
778
|
possible_types = query.possible_types(current_type)
|
697
|
-
|
698
779
|
if !possible_types.include?(resolved_type)
|
699
780
|
parent_type = field.owner_type
|
700
781
|
err_class = current_type::UnresolvedTypeError
|
701
782
|
type_error = err_class.new(resolved_value, field, parent_type, resolved_type, possible_types)
|
702
783
|
schema.type_error(type_error, context)
|
703
|
-
set_result(selection_result, result_name, nil)
|
784
|
+
set_result(selection_result, result_name, nil, false)
|
704
785
|
nil
|
705
786
|
else
|
706
|
-
continue_field(
|
787
|
+
continue_field(resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result)
|
707
788
|
end
|
708
789
|
end
|
709
790
|
when "OBJECT"
|
@@ -712,11 +793,11 @@ module GraphQL
|
|
712
793
|
rescue GraphQL::ExecutionError => err
|
713
794
|
err
|
714
795
|
end
|
715
|
-
after_lazy(object_proxy, owner: current_type,
|
716
|
-
continue_value = continue_value(
|
796
|
+
after_lazy(object_proxy, owner: current_type, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result) do |inner_object|
|
797
|
+
continue_value = continue_value(inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
|
717
798
|
if HALT != continue_value
|
718
799
|
response_hash = GraphQLResultHash.new(result_name, selection_result)
|
719
|
-
set_result(selection_result, result_name, response_hash)
|
800
|
+
set_result(selection_result, result_name, response_hash, true)
|
720
801
|
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
721
802
|
# There are two possibilities for `gathered_selections`:
|
722
803
|
# 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
|
@@ -734,11 +815,15 @@ module GraphQL
|
|
734
815
|
this_result = response_hash
|
735
816
|
final_result = nil
|
736
817
|
end
|
737
|
-
|
818
|
+
# reset this mutable state
|
819
|
+
# Unset `result_name` here because it's already included in the new response hash
|
820
|
+
st = get_current_runtime_state
|
821
|
+
st.current_object = continue_value
|
822
|
+
st.current_result_name = nil
|
823
|
+
st.current_result = this_result
|
824
|
+
|
738
825
|
call_method_on_directives(:resolve, continue_value, selections.graphql_directives) do
|
739
826
|
evaluate_selections(
|
740
|
-
path,
|
741
|
-
context.scoped_context,
|
742
827
|
continue_value,
|
743
828
|
current_type,
|
744
829
|
false,
|
@@ -756,53 +841,60 @@ module GraphQL
|
|
756
841
|
inner_type = current_type.of_type
|
757
842
|
# This is true for objects, unions, and interfaces
|
758
843
|
use_dataloader_job = !inner_type.unwrap.kind.input?
|
844
|
+
inner_type_non_null = inner_type.non_null?
|
759
845
|
response_list = GraphQLResultArray.new(result_name, selection_result)
|
760
|
-
response_list.graphql_non_null_list_items =
|
761
|
-
set_result(selection_result, result_name, response_list)
|
762
|
-
|
846
|
+
response_list.graphql_non_null_list_items = inner_type_non_null
|
847
|
+
set_result(selection_result, result_name, response_list, true)
|
763
848
|
idx = 0
|
764
|
-
|
765
|
-
begin
|
849
|
+
list_value = begin
|
766
850
|
value.each do |inner_value|
|
767
|
-
break if dead_result?(response_list)
|
768
|
-
next_path = path.dup
|
769
|
-
next_path << idx
|
770
851
|
this_idx = idx
|
771
|
-
next_path.freeze
|
772
852
|
idx += 1
|
773
853
|
if use_dataloader_job
|
774
854
|
@dataloader.append_job do
|
775
|
-
resolve_list_item(inner_value, inner_type,
|
855
|
+
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
|
776
856
|
end
|
777
857
|
else
|
778
|
-
resolve_list_item(inner_value, inner_type,
|
858
|
+
resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
|
779
859
|
end
|
780
860
|
end
|
861
|
+
|
862
|
+
response_list
|
781
863
|
rescue NoMethodError => err
|
782
864
|
# Ruby 2.2 doesn't have NoMethodError#receiver, can't check that one in this case. (It's been EOL since 2017.)
|
783
865
|
if err.name == :each && (err.respond_to?(:receiver) ? err.receiver == value : true)
|
784
866
|
# This happens when the GraphQL schema doesn't match the implementation. Help the dev debug.
|
785
|
-
raise ListResultFailedError.new(value: value, field: field, path:
|
867
|
+
raise ListResultFailedError.new(value: value, field: field, path: current_path)
|
786
868
|
else
|
787
869
|
# This was some other NoMethodError -- let it bubble to reveal the real error.
|
788
870
|
raise
|
789
871
|
end
|
872
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
|
873
|
+
ex_err
|
874
|
+
rescue StandardError => err
|
875
|
+
begin
|
876
|
+
query.handle_or_reraise(err)
|
877
|
+
rescue GraphQL::ExecutionError => ex_err
|
878
|
+
ex_err
|
879
|
+
end
|
790
880
|
end
|
791
881
|
|
792
|
-
|
882
|
+
continue_value(list_value, owner_type, field, inner_type.non_null?, ast_node, result_name, selection_result)
|
793
883
|
else
|
794
884
|
raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
|
795
885
|
end
|
796
886
|
end
|
797
887
|
|
798
|
-
def resolve_list_item(inner_value, inner_type,
|
799
|
-
|
888
|
+
def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
|
889
|
+
st = get_current_runtime_state
|
890
|
+
st.current_result_name = this_idx
|
891
|
+
st.current_result = response_list
|
800
892
|
call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
|
801
893
|
# This will update `response_list` with the lazy
|
802
|
-
after_lazy(inner_value, owner: inner_type,
|
803
|
-
continue_value = continue_value(
|
894
|
+
after_lazy(inner_value, owner: inner_type, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
|
895
|
+
continue_value = continue_value(inner_inner_value, owner_type, field, inner_type_non_null, ast_node, this_idx, response_list)
|
804
896
|
if HALT != continue_value
|
805
|
-
continue_field(
|
897
|
+
continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
|
806
898
|
end
|
807
899
|
end
|
808
900
|
end
|
@@ -819,12 +911,8 @@ module GraphQL
|
|
819
911
|
yield
|
820
912
|
else
|
821
913
|
dir_defn = @schema_directives.fetch(dir_node.name)
|
822
|
-
if !dir_defn.is_a?(Class)
|
823
|
-
dir_defn = dir_defn.type_class || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
|
824
|
-
end
|
825
914
|
raw_dir_args = arguments(nil, dir_defn, dir_node)
|
826
915
|
dir_args = continue_value(
|
827
|
-
@context[:current_path], # path
|
828
916
|
raw_dir_args, # value
|
829
917
|
dir_defn, # parent_type
|
830
918
|
nil, # field
|
@@ -847,7 +935,7 @@ module GraphQL
|
|
847
935
|
# Check {Schema::Directive.include?} for each directive that's present
|
848
936
|
def directives_include?(node, graphql_object, parent_type)
|
849
937
|
node.directives.each do |dir_node|
|
850
|
-
dir_defn = @schema_directives.fetch(dir_node.name)
|
938
|
+
dir_defn = @schema_directives.fetch(dir_node.name)
|
851
939
|
args = arguments(graphql_object, dir_defn, dir_node)
|
852
940
|
if !dir_defn.include?(graphql_object, args, context)
|
853
941
|
return false
|
@@ -856,50 +944,43 @@ module GraphQL
|
|
856
944
|
true
|
857
945
|
end
|
858
946
|
|
859
|
-
def
|
860
|
-
|
861
|
-
@context[:current_object] = @interpreter_context[:current_object] = object
|
862
|
-
end
|
863
|
-
if field
|
864
|
-
@context[:current_field] = @interpreter_context[:current_field] = field
|
865
|
-
end
|
866
|
-
if arguments
|
867
|
-
@context[:current_arguments] = @interpreter_context[:current_arguments] = arguments
|
868
|
-
end
|
869
|
-
if path
|
870
|
-
@context[:current_path] = @interpreter_context[:current_path] = path
|
871
|
-
end
|
947
|
+
def get_current_runtime_state
|
948
|
+
Thread.current[:__graphql_runtime_info] ||= CurrentState.new
|
872
949
|
end
|
873
950
|
|
874
951
|
# @param obj [Object] Some user-returned value that may want to be batched
|
875
|
-
# @param path [Array<String>]
|
876
952
|
# @param field [GraphQL::Schema::Field]
|
877
953
|
# @param eager [Boolean] Set to `true` for mutation root fields only
|
878
954
|
# @param trace [Boolean] If `false`, don't wrap this with field tracing
|
879
955
|
# @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
|
880
|
-
def after_lazy(lazy_obj, owner:, field:,
|
956
|
+
def after_lazy(lazy_obj, owner:, field:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, trace: true, &block)
|
881
957
|
if lazy?(lazy_obj)
|
882
|
-
|
883
|
-
|
884
|
-
|
958
|
+
orig_result = result
|
959
|
+
lazy = GraphQL::Execution::Lazy.new(field: field) do
|
960
|
+
st = get_current_runtime_state
|
961
|
+
st.current_object = owner_object
|
962
|
+
st.current_field = field
|
963
|
+
st.current_arguments = arguments
|
964
|
+
st.current_result_name = result_name
|
965
|
+
st.current_result = orig_result
|
885
966
|
# Wrap the execution of _this_ method with tracing,
|
886
967
|
# but don't wrap the continuation below
|
887
968
|
inner_obj = begin
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
query.trace("execute_field_lazy", {owner: owner, field: field, path: path, query: query, object: owner_object, arguments: arguments, ast_node: ast_node}) do
|
892
|
-
schema.sync_lazy(lazy_obj)
|
893
|
-
end
|
894
|
-
else
|
895
|
-
schema.sync_lazy(lazy_obj)
|
896
|
-
end
|
897
|
-
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
|
898
|
-
err
|
969
|
+
if trace
|
970
|
+
query.current_trace.execute_field_lazy(field: field, query: query, object: owner_object, arguments: arguments, ast_node: ast_node) do
|
971
|
+
schema.sync_lazy(lazy_obj)
|
899
972
|
end
|
973
|
+
else
|
974
|
+
schema.sync_lazy(lazy_obj)
|
900
975
|
end
|
901
|
-
rescue GraphQL::ExecutionError => ex_err
|
976
|
+
rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
|
902
977
|
ex_err
|
978
|
+
rescue StandardError => err
|
979
|
+
begin
|
980
|
+
query.handle_or_reraise(err)
|
981
|
+
rescue GraphQL::ExecutionError => ex_err
|
982
|
+
ex_err
|
983
|
+
end
|
903
984
|
end
|
904
985
|
yield(inner_obj)
|
905
986
|
end
|
@@ -907,11 +988,17 @@ module GraphQL
|
|
907
988
|
if eager
|
908
989
|
lazy.value
|
909
990
|
else
|
910
|
-
set_result(result, result_name, lazy)
|
991
|
+
set_result(result, result_name, lazy, false)
|
992
|
+
current_depth = 0
|
993
|
+
while result
|
994
|
+
current_depth += 1
|
995
|
+
result = result.graphql_parent
|
996
|
+
end
|
997
|
+
@lazies_at_depth[current_depth] << lazy
|
911
998
|
lazy
|
912
999
|
end
|
913
1000
|
else
|
914
|
-
|
1001
|
+
# Don't need to reset state here because it _wasn't_ lazy.
|
915
1002
|
yield(lazy_obj)
|
916
1003
|
end
|
917
1004
|
end
|
@@ -925,27 +1012,18 @@ module GraphQL
|
|
925
1012
|
end
|
926
1013
|
end
|
927
1014
|
|
928
|
-
|
929
|
-
|
930
|
-
def set_interpreter_context(key, value)
|
931
|
-
@interpreter_context[key] = value
|
932
|
-
@context[key] = value
|
933
|
-
end
|
934
|
-
|
935
|
-
def delete_interpreter_context(key)
|
936
|
-
@interpreter_context.delete(key)
|
937
|
-
@context.delete(key)
|
1015
|
+
def delete_all_interpreter_context
|
1016
|
+
Thread.current[:__graphql_runtime_info] = nil
|
938
1017
|
end
|
939
1018
|
|
940
|
-
def resolve_type(type, value
|
941
|
-
|
942
|
-
resolved_type, resolved_value = query.trace("resolve_type", trace_payload) do
|
1019
|
+
def resolve_type(type, value)
|
1020
|
+
resolved_type, resolved_value = query.current_trace.resolve_type(query: query, type: type, object: value) do
|
943
1021
|
query.resolve_type(type, value)
|
944
1022
|
end
|
945
1023
|
|
946
1024
|
if lazy?(resolved_type)
|
947
1025
|
GraphQL::Execution::Lazy.new do
|
948
|
-
query.
|
1026
|
+
query.current_trace.resolve_type_lazy(query: query, type: type, object: value) do
|
949
1027
|
schema.sync_lazy(resolved_type)
|
950
1028
|
end
|
951
1029
|
end
|