graphql 1.13.19 → 2.0.19

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.

Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +1 -1
  3. data/lib/generators/graphql/relay.rb +3 -17
  4. data/lib/generators/graphql/templates/schema.erb +3 -0
  5. data/lib/graphql/analysis/ast/field_usage.rb +3 -1
  6. data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -1
  7. data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
  8. data/lib/graphql/analysis/ast/query_depth.rb +0 -1
  9. data/lib/graphql/analysis/ast/visitor.rb +43 -36
  10. data/lib/graphql/analysis/ast.rb +2 -12
  11. data/lib/graphql/analysis.rb +0 -7
  12. data/lib/graphql/backtrace/table.rb +2 -20
  13. data/lib/graphql/backtrace/tracer.rb +2 -3
  14. data/lib/graphql/backtrace.rb +2 -8
  15. data/lib/graphql/dataloader/null_dataloader.rb +3 -1
  16. data/lib/graphql/dataloader/source.rb +9 -0
  17. data/lib/graphql/dataloader.rb +4 -1
  18. data/lib/graphql/dig.rb +1 -1
  19. data/lib/graphql/execution/errors.rb +12 -82
  20. data/lib/graphql/execution/interpreter/resolve.rb +26 -0
  21. data/lib/graphql/execution/interpreter/runtime.rb +162 -119
  22. data/lib/graphql/execution/interpreter.rb +187 -78
  23. data/lib/graphql/execution/lazy.rb +7 -21
  24. data/lib/graphql/execution/lookahead.rb +44 -40
  25. data/lib/graphql/execution/multiplex.rb +3 -174
  26. data/lib/graphql/execution.rb +11 -4
  27. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  28. data/lib/graphql/introspection/entry_points.rb +2 -15
  29. data/lib/graphql/introspection/type_type.rb +8 -1
  30. data/lib/graphql/introspection.rb +4 -3
  31. data/lib/graphql/language/document_from_schema_definition.rb +18 -35
  32. data/lib/graphql/language/lexer.rb +216 -1488
  33. data/lib/graphql/language/lexer.ri +744 -0
  34. data/lib/graphql/language/nodes.rb +41 -33
  35. data/lib/graphql/language/parser.rb +375 -363
  36. data/lib/graphql/language/parser.y +48 -43
  37. data/lib/graphql/language/printer.rb +37 -21
  38. data/lib/graphql/language/visitor.rb +191 -83
  39. data/lib/graphql/pagination/active_record_relation_connection.rb +0 -8
  40. data/lib/graphql/pagination/array_connection.rb +4 -2
  41. data/lib/graphql/pagination/connection.rb +31 -4
  42. data/lib/graphql/pagination/connections.rb +3 -28
  43. data/lib/graphql/pagination/relation_connection.rb +2 -0
  44. data/lib/graphql/query/context.rb +155 -196
  45. data/lib/graphql/query/input_validation_result.rb +1 -1
  46. data/lib/graphql/query/null_context.rb +0 -3
  47. data/lib/graphql/query/validation_pipeline.rb +10 -34
  48. data/lib/graphql/query/variables.rb +7 -20
  49. data/lib/graphql/query.rb +32 -42
  50. data/lib/graphql/railtie.rb +0 -104
  51. data/lib/graphql/rake_task/validate.rb +1 -1
  52. data/lib/graphql/rake_task.rb +29 -1
  53. data/lib/graphql/relay/range_add.rb +9 -20
  54. data/lib/graphql/relay.rb +0 -15
  55. data/lib/graphql/schema/addition.rb +7 -9
  56. data/lib/graphql/schema/argument.rb +36 -43
  57. data/lib/graphql/schema/build_from_definition.rb +32 -18
  58. data/lib/graphql/schema/directive/one_of.rb +12 -0
  59. data/lib/graphql/schema/directive/transform.rb +1 -1
  60. data/lib/graphql/schema/directive.rb +11 -22
  61. data/lib/graphql/schema/enum.rb +28 -39
  62. data/lib/graphql/schema/enum_value.rb +5 -25
  63. data/lib/graphql/schema/field/connection_extension.rb +4 -0
  64. data/lib/graphql/schema/field.rb +214 -327
  65. data/lib/graphql/schema/input_object.rb +56 -67
  66. data/lib/graphql/schema/interface.rb +0 -35
  67. data/lib/graphql/schema/introspection_system.rb +3 -8
  68. data/lib/graphql/schema/late_bound_type.rb +8 -2
  69. data/lib/graphql/schema/list.rb +0 -6
  70. data/lib/graphql/schema/loader.rb +1 -2
  71. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -19
  72. data/lib/graphql/schema/member/build_type.rb +5 -7
  73. data/lib/graphql/schema/member/has_arguments.rb +144 -53
  74. data/lib/graphql/schema/member/has_deprecation_reason.rb +3 -4
  75. data/lib/graphql/schema/member/has_directives.rb +71 -56
  76. data/lib/graphql/schema/member/has_fields.rb +15 -3
  77. data/lib/graphql/schema/member/has_interfaces.rb +47 -18
  78. data/lib/graphql/schema/member/has_validators.rb +31 -5
  79. data/lib/graphql/schema/member/relay_shortcuts.rb +28 -2
  80. data/lib/graphql/schema/member/type_system_helpers.rb +17 -0
  81. data/lib/graphql/schema/member/validates_input.rb +1 -1
  82. data/lib/graphql/schema/member.rb +0 -6
  83. data/lib/graphql/schema/mutation.rb +0 -9
  84. data/lib/graphql/schema/non_null.rb +1 -7
  85. data/lib/graphql/schema/object.rb +15 -52
  86. data/lib/graphql/schema/relay_classic_mutation.rb +53 -42
  87. data/lib/graphql/schema/resolver/has_payload_type.rb +20 -10
  88. data/lib/graphql/schema/resolver.rb +41 -42
  89. data/lib/graphql/schema/scalar.rb +7 -22
  90. data/lib/graphql/schema/subscription.rb +0 -7
  91. data/lib/graphql/schema/timeout.rb +24 -28
  92. data/lib/graphql/schema/type_membership.rb +3 -0
  93. data/lib/graphql/schema/union.rb +10 -17
  94. data/lib/graphql/schema/warden.rb +23 -6
  95. data/lib/graphql/schema/wrapper.rb +0 -5
  96. data/lib/graphql/schema.rb +240 -968
  97. data/lib/graphql/static_validation/all_rules.rb +1 -0
  98. data/lib/graphql/static_validation/base_visitor.rb +4 -21
  99. data/lib/graphql/static_validation/definition_dependencies.rb +7 -1
  100. data/lib/graphql/static_validation/error.rb +2 -2
  101. data/lib/graphql/static_validation/literal_validator.rb +19 -1
  102. data/lib/graphql/static_validation/rules/directives_are_defined.rb +11 -5
  103. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +12 -12
  104. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  105. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  106. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +12 -6
  107. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  108. data/lib/graphql/static_validation/validator.rb +3 -25
  109. data/lib/graphql/static_validation.rb +0 -2
  110. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -1
  111. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +38 -1
  112. data/lib/graphql/subscriptions/event.rb +3 -8
  113. data/lib/graphql/subscriptions/instrumentation.rb +0 -51
  114. data/lib/graphql/subscriptions.rb +32 -20
  115. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  116. data/lib/graphql/tracing/appoptics_trace.rb +231 -0
  117. data/lib/graphql/tracing/appsignal_trace.rb +66 -0
  118. data/lib/graphql/tracing/data_dog_trace.rb +148 -0
  119. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  120. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  121. data/lib/graphql/tracing/notifications_trace.rb +41 -0
  122. data/lib/graphql/tracing/platform_trace.rb +107 -0
  123. data/lib/graphql/tracing/platform_tracing.rb +26 -41
  124. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  125. data/lib/graphql/tracing/prometheus_tracing.rb +3 -3
  126. data/lib/graphql/tracing/scout_trace.rb +72 -0
  127. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  128. data/lib/graphql/tracing.rb +136 -40
  129. data/lib/graphql/type_kinds.rb +6 -3
  130. data/lib/graphql/types/iso_8601_date.rb +4 -1
  131. data/lib/graphql/types/iso_8601_date_time.rb +4 -0
  132. data/lib/graphql/types/relay/base_connection.rb +16 -6
  133. data/lib/graphql/types/relay/connection_behaviors.rb +5 -25
  134. data/lib/graphql/types/relay/default_relay.rb +5 -9
  135. data/lib/graphql/types/relay/edge_behaviors.rb +1 -4
  136. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  137. data/lib/graphql/types/relay.rb +0 -2
  138. data/lib/graphql/types/string.rb +1 -1
  139. data/lib/graphql/version.rb +1 -1
  140. data/lib/graphql.rb +11 -72
  141. metadata +31 -132
  142. data/lib/graphql/analysis/analyze_query.rb +0 -98
  143. data/lib/graphql/analysis/field_usage.rb +0 -45
  144. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  145. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  146. data/lib/graphql/analysis/query_complexity.rb +0 -88
  147. data/lib/graphql/analysis/query_depth.rb +0 -43
  148. data/lib/graphql/analysis/reducer_state.rb +0 -48
  149. data/lib/graphql/argument.rb +0 -131
  150. data/lib/graphql/authorization.rb +0 -82
  151. data/lib/graphql/backtrace/legacy_tracer.rb +0 -56
  152. data/lib/graphql/backwards_compatibility.rb +0 -61
  153. data/lib/graphql/base_type.rb +0 -232
  154. data/lib/graphql/boolean_type.rb +0 -2
  155. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  156. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  157. data/lib/graphql/compatibility/execution_specification.rb +0 -436
  158. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  159. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -215
  160. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -87
  161. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  162. data/lib/graphql/compatibility/query_parser_specification.rb +0 -266
  163. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -682
  164. data/lib/graphql/compatibility.rb +0 -5
  165. data/lib/graphql/define/assign_argument.rb +0 -12
  166. data/lib/graphql/define/assign_connection.rb +0 -13
  167. data/lib/graphql/define/assign_enum_value.rb +0 -18
  168. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  169. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  170. data/lib/graphql/define/assign_object_field.rb +0 -42
  171. data/lib/graphql/define/defined_object_proxy.rb +0 -53
  172. data/lib/graphql/define/instance_definable.rb +0 -255
  173. data/lib/graphql/define/no_definition_error.rb +0 -7
  174. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  175. data/lib/graphql/define/type_definer.rb +0 -31
  176. data/lib/graphql/define.rb +0 -31
  177. data/lib/graphql/deprecated_dsl.rb +0 -55
  178. data/lib/graphql/directive/deprecated_directive.rb +0 -2
  179. data/lib/graphql/directive/include_directive.rb +0 -2
  180. data/lib/graphql/directive/skip_directive.rb +0 -2
  181. data/lib/graphql/directive.rb +0 -107
  182. data/lib/graphql/enum_type.rb +0 -133
  183. data/lib/graphql/execution/execute.rb +0 -333
  184. data/lib/graphql/execution/flatten.rb +0 -40
  185. data/lib/graphql/execution/instrumentation.rb +0 -92
  186. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  187. data/lib/graphql/execution/typecast.rb +0 -50
  188. data/lib/graphql/field/resolve.rb +0 -59
  189. data/lib/graphql/field.rb +0 -226
  190. data/lib/graphql/float_type.rb +0 -2
  191. data/lib/graphql/function.rb +0 -128
  192. data/lib/graphql/id_type.rb +0 -2
  193. data/lib/graphql/input_object_type.rb +0 -138
  194. data/lib/graphql/int_type.rb +0 -2
  195. data/lib/graphql/interface_type.rb +0 -72
  196. data/lib/graphql/internal_representation/document.rb +0 -27
  197. data/lib/graphql/internal_representation/node.rb +0 -206
  198. data/lib/graphql/internal_representation/print.rb +0 -51
  199. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  200. data/lib/graphql/internal_representation/scope.rb +0 -88
  201. data/lib/graphql/internal_representation/visit.rb +0 -36
  202. data/lib/graphql/internal_representation.rb +0 -7
  203. data/lib/graphql/language/lexer.rl +0 -260
  204. data/lib/graphql/list_type.rb +0 -80
  205. data/lib/graphql/non_null_type.rb +0 -71
  206. data/lib/graphql/object_type.rb +0 -130
  207. data/lib/graphql/query/arguments.rb +0 -189
  208. data/lib/graphql/query/arguments_cache.rb +0 -24
  209. data/lib/graphql/query/executor.rb +0 -52
  210. data/lib/graphql/query/literal_input.rb +0 -136
  211. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  212. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  213. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  214. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  215. data/lib/graphql/query/serial_execution.rb +0 -40
  216. data/lib/graphql/relay/array_connection.rb +0 -83
  217. data/lib/graphql/relay/base_connection.rb +0 -189
  218. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  219. data/lib/graphql/relay/connection_resolve.rb +0 -43
  220. data/lib/graphql/relay/connection_type.rb +0 -54
  221. data/lib/graphql/relay/edge.rb +0 -27
  222. data/lib/graphql/relay/edge_type.rb +0 -19
  223. data/lib/graphql/relay/edges_instrumentation.rb +0 -39
  224. data/lib/graphql/relay/global_id_resolve.rb +0 -17
  225. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  226. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  227. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  228. data/lib/graphql/relay/mutation/result.rb +0 -38
  229. data/lib/graphql/relay/mutation.rb +0 -106
  230. data/lib/graphql/relay/node.rb +0 -39
  231. data/lib/graphql/relay/page_info.rb +0 -7
  232. data/lib/graphql/relay/relation_connection.rb +0 -188
  233. data/lib/graphql/relay/type_extensions.rb +0 -32
  234. data/lib/graphql/scalar_type.rb +0 -91
  235. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  236. data/lib/graphql/schema/default_parse_error.rb +0 -10
  237. data/lib/graphql/schema/default_type_error.rb +0 -17
  238. data/lib/graphql/schema/member/accepts_definition.rb +0 -164
  239. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -58
  240. data/lib/graphql/schema/member/instrumentation.rb +0 -131
  241. data/lib/graphql/schema/middleware_chain.rb +0 -82
  242. data/lib/graphql/schema/possible_types.rb +0 -44
  243. data/lib/graphql/schema/rescue_middleware.rb +0 -60
  244. data/lib/graphql/schema/timeout_middleware.rb +0 -88
  245. data/lib/graphql/schema/traversal.rb +0 -228
  246. data/lib/graphql/schema/validation.rb +0 -313
  247. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  248. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  249. data/lib/graphql/string_type.rb +0 -2
  250. data/lib/graphql/subscriptions/subscription_root.rb +0 -76
  251. data/lib/graphql/tracing/skylight_tracing.rb +0 -70
  252. data/lib/graphql/types/relay/node_field.rb +0 -24
  253. data/lib/graphql/types/relay/nodes_field.rb +0 -43
  254. data/lib/graphql/union_type.rb +0 -115
  255. data/lib/graphql/upgrader/member.rb +0 -937
  256. data/lib/graphql/upgrader/schema.rb +0 -38
@@ -20,6 +20,15 @@ module GraphQL
20
20
  @graphql_metadata = nil
21
21
  end
22
22
 
23
+ def path
24
+ @path ||= build_path([])
25
+ end
26
+
27
+ def build_path(path_array)
28
+ graphql_result_name && path_array.unshift(graphql_result_name)
29
+ @graphql_parent ? @graphql_parent.build_path(path_array) : path_array
30
+ end
31
+
23
32
  attr_accessor :graphql_dead
24
33
  attr_reader :graphql_parent, :graphql_result_name
25
34
 
@@ -148,13 +157,24 @@ module GraphQL
148
157
  # @return [GraphQL::Query::Context]
149
158
  attr_reader :context
150
159
 
151
- def initialize(query:)
160
+ def thread_info
161
+ info = Thread.current[:__graphql_runtime_info]
162
+ if !info
163
+ new_ti = {}
164
+ info = Thread.current[:__graphql_runtime_info] = new_ti
165
+ end
166
+ info
167
+ end
168
+
169
+ def initialize(query:, lazies_at_depth:)
152
170
  @query = query
153
171
  @dataloader = query.multiplex.dataloader
172
+ @lazies_at_depth = lazies_at_depth
154
173
  @schema = query.schema
155
174
  @context = query.context
156
175
  @multiplex_context = query.multiplex.context
157
- @interpreter_context = @context.namespace(:interpreter)
176
+ # Start this off empty:
177
+ Thread.current[:__graphql_runtime_info] = nil
158
178
  @response = GraphQLResultHash.new(nil, nil)
159
179
  # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
160
180
  @runtime_directive_names = []
@@ -198,8 +218,7 @@ module GraphQL
198
218
  root_operation = query.selected_operation
199
219
  root_op_type = root_operation.operation_type || "query"
200
220
  root_type = schema.root_type_for_operation(root_op_type)
201
- path = []
202
- set_all_interpreter_context(query.root_value, nil, nil, path)
221
+ set_all_interpreter_context(query.root_value, nil, nil, nil, @response)
203
222
  object_proxy = authorized_new(root_type, query.root_value, context)
204
223
  object_proxy = schema.sync_lazy(object_proxy)
205
224
 
@@ -226,11 +245,9 @@ module GraphQL
226
245
  end
227
246
 
228
247
  @dataloader.append_job {
229
- set_all_interpreter_context(query.root_value, nil, nil, path)
248
+ set_all_interpreter_context(query.root_value, nil, nil, nil, selection_response)
230
249
  call_method_on_directives(:resolve, object_proxy, selections.graphql_directives) do
231
250
  evaluate_selections(
232
- path,
233
- context.scoped_context,
234
251
  object_proxy,
235
252
  root_type,
236
253
  root_op_type == "mutation",
@@ -244,10 +261,7 @@ module GraphQL
244
261
  end
245
262
  end
246
263
  end
247
- delete_interpreter_context(:current_path)
248
- delete_interpreter_context(:current_field)
249
- delete_interpreter_context(:current_object)
250
- delete_interpreter_context(:current_arguments)
264
+ delete_all_interpreter_context
251
265
  nil
252
266
  end
253
267
 
@@ -349,15 +363,15 @@ module GraphQL
349
363
  NO_ARGS = {}.freeze
350
364
 
351
365
  # @return [void]
352
- def evaluate_selections(path, scoped_context, owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object) # rubocop:disable Metrics/ParameterLists
353
- set_all_interpreter_context(owner_object, nil, nil, path)
366
+ def evaluate_selections(owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object) # rubocop:disable Metrics/ParameterLists
367
+ set_all_interpreter_context(owner_object, nil, nil, nil, selections_result)
354
368
 
355
369
  finished_jobs = 0
356
370
  enqueued_jobs = gathered_selections.size
357
371
  gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
358
372
  @dataloader.append_job {
359
373
  evaluate_selection(
360
- path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_selection, selections_result, parent_object
374
+ result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_selection, selections_result, parent_object
361
375
  )
362
376
  finished_jobs += 1
363
377
  if target_result && finished_jobs == enqueued_jobs
@@ -369,10 +383,8 @@ module GraphQL
369
383
  selections_result
370
384
  end
371
385
 
372
- attr_reader :progress_path
373
-
374
386
  # @return [void]
375
- def evaluate_selection(path, result_name, field_ast_nodes_or_ast_node, scoped_context, owner_object, owner_type, is_eager_field, selections_result, parent_object) # rubocop:disable Metrics/ParameterLists
387
+ 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
388
  return if dead_result?(selections_result)
377
389
  # As a performance optimization, the hash key will be a `Node` if
378
390
  # there's only one selection of the field. But if there are multiple
@@ -403,10 +415,6 @@ module GraphQL
403
415
 
404
416
  return_type = field_defn.type
405
417
 
406
- next_path = path.dup
407
- next_path << result_name
408
- next_path.freeze
409
-
410
418
  # This seems janky, but we need to know
411
419
  # the field's return type at this path in order
412
420
  # to propagate `null`
@@ -414,9 +422,7 @@ module GraphQL
414
422
  (selections_result.graphql_non_null_field_names ||= []).push(result_name)
415
423
  end
416
424
  # Set this before calling `run_with_directives`, so that the directive can have the latest path
417
- set_all_interpreter_context(nil, field_defn, nil, next_path)
418
-
419
- context.scoped_context = scoped_context
425
+ set_all_interpreter_context(nil, field_defn, nil, result_name, selections_result)
420
426
  object = owner_object
421
427
 
422
428
  if is_introspection
@@ -426,20 +432,19 @@ module GraphQL
426
432
  total_args_count = field_defn.arguments(context).size
427
433
  if total_args_count == 0
428
434
  resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
429
- evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
435
+ 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)
430
436
  else
431
437
  # TODO remove all arguments(...) usages?
432
438
  @query.arguments_cache.dataload_for(ast_node, field_defn, object) do |resolved_arguments|
433
- evaluate_selection_with_args(resolved_arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selections_result, parent_object, return_type)
439
+ 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)
434
440
  end
435
441
  end
436
442
  end
437
443
 
438
- def evaluate_selection_with_args(arguments, field_defn, next_path, ast_node, field_ast_nodes, scoped_context, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type) # rubocop:disable Metrics/ParameterLists
439
- context.scoped_context = scoped_context
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|
444
+ 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) # rubocop:disable Metrics/ParameterLists
445
+ 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
446
  if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
442
- continue_value(next_path, resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
447
+ continue_value(resolved_arguments, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
443
448
  next
444
449
  end
445
450
 
@@ -455,9 +460,9 @@ module GraphQL
455
460
  when :ast_node
456
461
  extra_args[:ast_node] = ast_node
457
462
  when :execution_errors
458
- extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node, next_path)
463
+ extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node, current_path)
459
464
  when :path
460
- extra_args[:path] = next_path
465
+ extra_args[:path] = current_path
461
466
  when :lookahead
462
467
  if !field_ast_nodes
463
468
  field_ast_nodes = [ast_node]
@@ -472,10 +477,6 @@ module GraphQL
472
477
  # Use this flag to tell Interpreter::Arguments to add itself
473
478
  # to the keyword args hash _before_ freezing everything.
474
479
  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
480
  when :parent
480
481
  extra_args[:parent] = parent_object
481
482
  else
@@ -488,7 +489,7 @@ module GraphQL
488
489
  resolved_arguments.keyword_arguments
489
490
  end
490
491
 
491
- set_all_interpreter_context(nil, nil, resolved_arguments, nil)
492
+ set_all_interpreter_context(nil, nil, resolved_arguments, result_name, selection_result)
492
493
 
493
494
  # Optimize for the case that field is selected only once
494
495
  if field_ast_nodes.nil? || field_ast_nodes.size == 1
@@ -506,18 +507,22 @@ module GraphQL
506
507
  field_result = call_method_on_directives(:resolve, object, directives) do
507
508
  # Actually call the field resolver and capture the result
508
509
  app_result = begin
509
- query.with_error_handling do
510
- query.trace("execute_field", {owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, query: query, object: object, arguments: kwarg_arguments}) do
511
- field_defn.resolve(object, kwarg_arguments, context)
512
- end
510
+ query.current_trace.execute_field(field: field_defn, ast_node: ast_node, query: query, object: object, arguments: kwarg_arguments) do
511
+ field_defn.resolve(object, kwarg_arguments, context)
513
512
  end
514
513
  rescue GraphQL::ExecutionError => err
515
514
  err
515
+ rescue StandardError => err
516
+ begin
517
+ query.handle_or_reraise(err)
518
+ rescue GraphQL::ExecutionError => ex_err
519
+ ex_err
520
+ end
516
521
  end
517
- after_lazy(app_result, owner: owner_type, field: field_defn, path: next_path, ast_node: ast_node, scoped_context: context.scoped_context, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result) do |inner_result|
518
- continue_value = continue_value(next_path, inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
522
+ 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|
523
+ continue_value = continue_value(inner_result, owner_type, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
519
524
  if HALT != continue_value
520
- continue_field(next_path, continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
525
+ continue_field(continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result)
521
526
  end
522
527
  end
523
528
  end
@@ -582,8 +587,30 @@ module GraphQL
582
587
  end
583
588
  end
584
589
 
590
+ def current_path
591
+ ti = thread_info
592
+ path = ti &&
593
+ (result = ti[:current_result]) &&
594
+ (result.path)
595
+ if path && (rn = ti[:current_result_name])
596
+ path = path.dup
597
+ path.push(rn)
598
+ end
599
+ path
600
+ end
601
+
602
+ def current_depth
603
+ ti = thread_info
604
+ depth = 1
605
+ result = ti[:current_result]
606
+ while (result = result.graphql_parent)
607
+ depth += 1
608
+ end
609
+ depth
610
+ end
611
+
585
612
  HALT = Object.new
586
- def continue_value(path, value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
613
+ def continue_value(value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
587
614
  case value
588
615
  when nil
589
616
  if is_non_null
@@ -602,7 +629,7 @@ module GraphQL
602
629
  # every time.
603
630
  if value.is_a?(GraphQL::ExecutionError)
604
631
  if selection_result.nil? || !dead_result?(selection_result)
605
- value.path ||= path
632
+ value.path ||= current_path
606
633
  value.ast_node ||= ast_node
607
634
  context.errors << value
608
635
  if selection_result
@@ -610,6 +637,16 @@ module GraphQL
610
637
  end
611
638
  end
612
639
  HALT
640
+ elsif value.is_a?(GraphQL::UnauthorizedFieldError)
641
+ value.field ||= field
642
+ # this hook might raise & crash, or it might return
643
+ # a replacement value
644
+ next_value = begin
645
+ schema.unauthorized_field(value)
646
+ rescue GraphQL::ExecutionError => err
647
+ err
648
+ end
649
+ continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
613
650
  elsif value.is_a?(GraphQL::UnauthorizedError)
614
651
  # this hook might raise & crash, or it might return
615
652
  # a replacement value
@@ -618,8 +655,8 @@ module GraphQL
618
655
  rescue GraphQL::ExecutionError => err
619
656
  err
620
657
  end
621
- continue_value(path, next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
622
- elsif GraphQL::Execution::Execute::SKIP == value
658
+ continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
659
+ elsif GraphQL::Execution::SKIP == value
623
660
  # It's possible a lazy was already written here
624
661
  case selection_result
625
662
  when GraphQLResultHash
@@ -644,7 +681,7 @@ module GraphQL
644
681
  if selection_result.nil? || !dead_result?(selection_result)
645
682
  value.each_with_index do |error, index|
646
683
  error.ast_node ||= ast_node
647
- error.path ||= path + (list_type_at_all ? [index] : [])
684
+ error.path ||= current_path + (list_type_at_all ? [index] : [])
648
685
  context.errors << error
649
686
  end
650
687
  if selection_result
@@ -677,7 +714,7 @@ module GraphQL
677
714
  # Location information from `path` and `ast_node`.
678
715
  #
679
716
  # @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
680
- def continue_field(path, value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
717
+ 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
718
  if current_type.non_null?
682
719
  current_type = current_type.of_type
683
720
  is_non_null = true
@@ -685,16 +722,24 @@ module GraphQL
685
722
 
686
723
  case current_type.kind.name
687
724
  when "SCALAR", "ENUM"
688
- r = current_type.coerce_result(value, context)
725
+ r = begin
726
+ current_type.coerce_result(value, context)
727
+ rescue StandardError => err
728
+ schema.handle_or_reraise(context, err)
729
+ end
689
730
  set_result(selection_result, result_name, r)
690
731
  r
691
732
  when "UNION", "INTERFACE"
692
- resolved_type_or_lazy, resolved_value = resolve_type(current_type, value, path)
693
- resolved_value ||= value
733
+ resolved_type_or_lazy = resolve_type(current_type, value)
734
+ 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|
735
+ if resolved_type_result.is_a?(Array) && resolved_type_result.length == 2
736
+ resolved_type, resolved_value = resolved_type_result
737
+ else
738
+ resolved_type = resolved_type_result
739
+ resolved_value = value
740
+ end
694
741
 
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
742
  possible_types = query.possible_types(current_type)
697
-
698
743
  if !possible_types.include?(resolved_type)
699
744
  parent_type = field.owner_type
700
745
  err_class = current_type::UnresolvedTypeError
@@ -703,7 +748,7 @@ module GraphQL
703
748
  set_result(selection_result, result_name, nil)
704
749
  nil
705
750
  else
706
- continue_field(path, resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result)
751
+ continue_field(resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result)
707
752
  end
708
753
  end
709
754
  when "OBJECT"
@@ -712,8 +757,8 @@ module GraphQL
712
757
  rescue GraphQL::ExecutionError => err
713
758
  err
714
759
  end
715
- after_lazy(object_proxy, 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 |inner_object|
716
- continue_value = continue_value(path, inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
760
+ 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|
761
+ continue_value = continue_value(inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
717
762
  if HALT != continue_value
718
763
  response_hash = GraphQLResultHash.new(result_name, selection_result)
719
764
  set_result(selection_result, result_name, response_hash)
@@ -734,11 +779,10 @@ module GraphQL
734
779
  this_result = response_hash
735
780
  final_result = nil
736
781
  end
737
- set_all_interpreter_context(continue_value, nil, nil, path) # reset this mutable state
782
+ # Don't pass `result_name` here because it's already included in the new response hash
783
+ set_all_interpreter_context(continue_value, nil, nil, nil, this_result) # reset this mutable state
738
784
  call_method_on_directives(:resolve, continue_value, selections.graphql_directives) do
739
785
  evaluate_selections(
740
- path,
741
- context.scoped_context,
742
786
  continue_value,
743
787
  current_type,
744
788
  false,
@@ -759,50 +803,55 @@ module GraphQL
759
803
  response_list = GraphQLResultArray.new(result_name, selection_result)
760
804
  response_list.graphql_non_null_list_items = inner_type.non_null?
761
805
  set_result(selection_result, result_name, response_list)
762
-
763
806
  idx = 0
764
- scoped_context = context.scoped_context
765
- begin
807
+ list_value = begin
766
808
  value.each do |inner_value|
767
809
  break if dead_result?(response_list)
768
- next_path = path.dup
769
- next_path << idx
770
810
  this_idx = idx
771
- next_path.freeze
772
811
  idx += 1
773
812
  if use_dataloader_job
774
813
  @dataloader.append_job do
775
- resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
814
+ resolve_list_item(inner_value, inner_type, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
776
815
  end
777
816
  else
778
- resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
817
+ resolve_list_item(inner_value, inner_type, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type)
779
818
  end
780
819
  end
820
+
821
+ response_list
781
822
  rescue NoMethodError => err
782
823
  # Ruby 2.2 doesn't have NoMethodError#receiver, can't check that one in this case. (It's been EOL since 2017.)
783
824
  if err.name == :each && (err.respond_to?(:receiver) ? err.receiver == value : true)
784
825
  # This happens when the GraphQL schema doesn't match the implementation. Help the dev debug.
785
- raise ListResultFailedError.new(value: value, field: field, path: path)
826
+ raise ListResultFailedError.new(value: value, field: field, path: current_path)
786
827
  else
787
828
  # This was some other NoMethodError -- let it bubble to reveal the real error.
788
829
  raise
789
830
  end
831
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
832
+ ex_err
833
+ rescue StandardError => err
834
+ begin
835
+ query.handle_or_reraise(err)
836
+ rescue GraphQL::ExecutionError => ex_err
837
+ ex_err
838
+ end
790
839
  end
791
840
 
792
- response_list
841
+ continue_value(list_value, owner_type, field, inner_type.non_null?, ast_node, result_name, selection_result)
793
842
  else
794
843
  raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
795
844
  end
796
845
  end
797
846
 
798
- def resolve_list_item(inner_value, inner_type, next_path, ast_node, scoped_context, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
799
- set_all_interpreter_context(nil, nil, nil, next_path)
847
+ def resolve_list_item(inner_value, inner_type, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type) # rubocop:disable Metrics/ParameterLists
848
+ set_all_interpreter_context(nil, nil, nil, this_idx, response_list)
800
849
  call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
801
850
  # This will update `response_list` with the lazy
802
- after_lazy(inner_value, owner: inner_type, path: next_path, ast_node: ast_node, scoped_context: scoped_context, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list) do |inner_inner_value|
803
- continue_value = continue_value(next_path, inner_inner_value, owner_type, field, inner_type.non_null?, ast_node, this_idx, response_list)
851
+ 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|
852
+ continue_value = continue_value(inner_inner_value, owner_type, field, inner_type.non_null?, ast_node, this_idx, response_list)
804
853
  if HALT != continue_value
805
- continue_field(next_path, continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
854
+ continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list)
806
855
  end
807
856
  end
808
857
  end
@@ -819,12 +868,8 @@ module GraphQL
819
868
  yield
820
869
  else
821
870
  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
871
  raw_dir_args = arguments(nil, dir_defn, dir_node)
826
872
  dir_args = continue_value(
827
- @context[:current_path], # path
828
873
  raw_dir_args, # value
829
874
  dir_defn, # parent_type
830
875
  nil, # field
@@ -847,7 +892,7 @@ module GraphQL
847
892
  # Check {Schema::Directive.include?} for each directive that's present
848
893
  def directives_include?(node, graphql_object, parent_type)
849
894
  node.directives.each do |dir_node|
850
- dir_defn = @schema_directives.fetch(dir_node.name).type_class || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
895
+ dir_defn = @schema_directives.fetch(dir_node.name)
851
896
  args = arguments(graphql_object, dir_defn, dir_node)
852
897
  if !dir_defn.include?(graphql_object, args, context)
853
898
  return false
@@ -856,50 +901,50 @@ module GraphQL
856
901
  true
857
902
  end
858
903
 
859
- def set_all_interpreter_context(object, field, arguments, path)
904
+ def set_all_interpreter_context(object, field, arguments, result_name, result)
905
+ ti = thread_info
860
906
  if object
861
- @context[:current_object] = @interpreter_context[:current_object] = object
907
+ ti[:current_object] = object
862
908
  end
863
909
  if field
864
- @context[:current_field] = @interpreter_context[:current_field] = field
910
+ ti[:current_field] = field
865
911
  end
866
912
  if arguments
867
- @context[:current_arguments] = @interpreter_context[:current_arguments] = arguments
913
+ ti[:current_arguments] = arguments
868
914
  end
869
- if path
870
- @context[:current_path] = @interpreter_context[:current_path] = path
915
+ ti[:current_result_name] = result_name
916
+ if result
917
+ ti[:current_result] = result
871
918
  end
872
919
  end
873
920
 
874
921
  # @param obj [Object] Some user-returned value that may want to be batched
875
- # @param path [Array<String>]
876
922
  # @param field [GraphQL::Schema::Field]
877
923
  # @param eager [Boolean] Set to `true` for mutation root fields only
878
924
  # @param trace [Boolean] If `false`, don't wrap this with field tracing
879
925
  # @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:, path:, scoped_context:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, trace: true, &block)
926
+ def after_lazy(lazy_obj, owner:, field:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, trace: true, &block)
881
927
  if lazy?(lazy_obj)
882
- lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
883
- set_all_interpreter_context(owner_object, field, arguments, path)
884
- context.scoped_context = scoped_context
928
+ lazy = GraphQL::Execution::Lazy.new(field: field) do
929
+ set_all_interpreter_context(owner_object, field, arguments, result_name, result)
885
930
  # Wrap the execution of _this_ method with tracing,
886
931
  # but don't wrap the continuation below
887
932
  inner_obj = begin
888
- query.with_error_handling do
889
- begin
890
- if trace
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
933
+ if trace
934
+ query.current_trace.execute_field_lazy(field: field, query: query, object: owner_object, arguments: arguments, ast_node: ast_node) do
935
+ schema.sync_lazy(lazy_obj)
899
936
  end
937
+ else
938
+ schema.sync_lazy(lazy_obj)
900
939
  end
901
- rescue GraphQL::ExecutionError => ex_err
940
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
902
941
  ex_err
942
+ rescue StandardError => err
943
+ begin
944
+ query.handle_or_reraise(err)
945
+ rescue GraphQL::ExecutionError => ex_err
946
+ ex_err
947
+ end
903
948
  end
904
949
  yield(inner_obj)
905
950
  end
@@ -908,10 +953,11 @@ module GraphQL
908
953
  lazy.value
909
954
  else
910
955
  set_result(result, result_name, lazy)
956
+ @lazies_at_depth[current_depth] << lazy
911
957
  lazy
912
958
  end
913
959
  else
914
- set_all_interpreter_context(owner_object, field, arguments, path)
960
+ set_all_interpreter_context(owner_object, field, arguments, result_name, result)
915
961
  yield(lazy_obj)
916
962
  end
917
963
  end
@@ -925,27 +971,24 @@ module GraphQL
925
971
  end
926
972
  end
927
973
 
928
- # Set this pair in the Query context, but also in the interpeter namespace,
929
- # for compatibility.
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)
974
+ def delete_all_interpreter_context
975
+ if (ti = thread_info)
976
+ ti.delete(:current_result)
977
+ ti.delete(:current_result_name)
978
+ ti.delete(:current_field)
979
+ ti.delete(:current_object)
980
+ ti.delete(:current_arguments)
981
+ end
938
982
  end
939
983
 
940
- def resolve_type(type, value, path)
941
- trace_payload = { context: context, type: type, object: value, path: path }
942
- resolved_type, resolved_value = query.trace("resolve_type", trace_payload) do
984
+ def resolve_type(type, value)
985
+ resolved_type, resolved_value = query.current_trace.resolve_type(query: query, type: type, object: value) do
943
986
  query.resolve_type(type, value)
944
987
  end
945
988
 
946
989
  if lazy?(resolved_type)
947
990
  GraphQL::Execution::Lazy.new do
948
- query.trace("resolve_type_lazy", trace_payload) do
991
+ query.current_trace.resolve_type_lazy(query: query, type: type, object: value) do
949
992
  schema.sync_lazy(resolved_type)
950
993
  end
951
994
  end