graphql 2.6.9 → 2.6.14

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.
Files changed (382) hide show
  1. checksums.yaml +4 -4
  2. data/.rdoc_options +4 -0
  3. data/lib/generators/graphql/core.rb +1 -0
  4. data/lib/generators/graphql/detailed_trace_generator.rb +1 -0
  5. data/lib/generators/graphql/enum_generator.rb +1 -0
  6. data/lib/generators/graphql/field_extractor.rb +1 -0
  7. data/lib/generators/graphql/input_generator.rb +1 -0
  8. data/lib/generators/graphql/install/mutation_root_generator.rb +1 -0
  9. data/lib/generators/graphql/install_generator.rb +1 -0
  10. data/lib/generators/graphql/interface_generator.rb +1 -0
  11. data/lib/generators/graphql/loader_generator.rb +8 -2
  12. data/lib/generators/graphql/mutation_create_generator.rb +8 -2
  13. data/lib/generators/graphql/mutation_delete_generator.rb +8 -2
  14. data/lib/generators/graphql/mutation_generator.rb +8 -2
  15. data/lib/generators/graphql/mutation_update_generator.rb +8 -2
  16. data/lib/generators/graphql/object_generator.rb +1 -0
  17. data/lib/generators/graphql/orm_mutations_base.rb +8 -2
  18. data/lib/generators/graphql/relay.rb +1 -0
  19. data/lib/generators/graphql/relay_generator.rb +1 -0
  20. data/lib/generators/graphql/scalar_generator.rb +1 -0
  21. data/lib/generators/graphql/type_generator.rb +38 -8
  22. data/lib/generators/graphql/union_generator.rb +1 -0
  23. data/lib/graphql/analysis/analyzer.rb +35 -9
  24. data/lib/graphql/analysis/field_usage.rb +1 -0
  25. data/lib/graphql/analysis/max_query_complexity.rb +3 -2
  26. data/lib/graphql/analysis/max_query_depth.rb +1 -0
  27. data/lib/graphql/analysis/query_complexity.rb +57 -20
  28. data/lib/graphql/analysis/query_depth.rb +17 -12
  29. data/lib/graphql/analysis/visitor.rb +79 -16
  30. data/lib/graphql/analysis.rb +23 -6
  31. data/lib/graphql/analysis_error.rb +1 -0
  32. data/lib/graphql/autoload.rb +30 -7
  33. data/lib/graphql/backtrace/table.rb +21 -5
  34. data/lib/graphql/backtrace/traced_error.rb +8 -3
  35. data/lib/graphql/backtrace.rb +14 -9
  36. data/lib/graphql/coercion_error.rb +1 -0
  37. data/lib/graphql/current.rb +44 -19
  38. data/lib/graphql/dashboard/application_controller.rb +1 -0
  39. data/lib/graphql/dashboard/detailed_traces.rb +1 -0
  40. data/lib/graphql/dashboard/installable.rb +1 -0
  41. data/lib/graphql/dashboard/landings_controller.rb +1 -0
  42. data/lib/graphql/dashboard/limiters.rb +1 -0
  43. data/lib/graphql/dashboard/operation_store.rb +1 -0
  44. data/lib/graphql/dashboard/statics_controller.rb +1 -0
  45. data/lib/graphql/dashboard/subscriptions.rb +1 -0
  46. data/lib/graphql/dashboard.rb +36 -22
  47. data/lib/graphql/dataloader/active_record_association_source.rb +1 -0
  48. data/lib/graphql/dataloader/active_record_source.rb +1 -0
  49. data/lib/graphql/dataloader/async_dataloader.rb +45 -16
  50. data/lib/graphql/dataloader/null_dataloader.rb +4 -3
  51. data/lib/graphql/dataloader/request.rb +8 -2
  52. data/lib/graphql/dataloader/request_all.rb +8 -2
  53. data/lib/graphql/dataloader/source.rb +127 -35
  54. data/lib/graphql/dataloader.rb +98 -44
  55. data/lib/graphql/date_encoding_error.rb +2 -1
  56. data/lib/graphql/dig.rb +12 -3
  57. data/lib/graphql/duration_encoding_error.rb +2 -1
  58. data/lib/graphql/execution/directive_checks.rb +8 -3
  59. data/lib/graphql/execution/errors.rb +20 -6
  60. data/lib/graphql/execution/field_resolve_step.rb +288 -168
  61. data/lib/graphql/execution/finalize.rb +12 -6
  62. data/lib/graphql/execution/input_values.rb +5 -2
  63. data/lib/graphql/execution/interpreter/argument_value.rb +17 -5
  64. data/lib/graphql/execution/interpreter/arguments.rb +24 -9
  65. data/lib/graphql/execution/interpreter/arguments_cache.rb +2 -1
  66. data/lib/graphql/execution/interpreter/execution_errors.rb +1 -0
  67. data/lib/graphql/execution/interpreter/handles_raw_value.rb +1 -0
  68. data/lib/graphql/execution/interpreter/resolve.rb +18 -8
  69. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +4 -1
  70. data/lib/graphql/execution/interpreter/runtime.rb +72 -25
  71. data/lib/graphql/execution/interpreter.rb +18 -7
  72. data/lib/graphql/execution/lazy/lazy_method_map.rb +21 -8
  73. data/lib/graphql/execution/lazy.rb +34 -10
  74. data/lib/graphql/execution/load_argument_step.rb +1 -0
  75. data/lib/graphql/execution/lookahead.rb +137 -54
  76. data/lib/graphql/execution/multiplex.rb +4 -4
  77. data/lib/graphql/execution/next.rb +7 -0
  78. data/lib/graphql/execution/prepare_object_step.rb +38 -13
  79. data/lib/graphql/execution/resolve_type_step.rb +2 -1
  80. data/lib/graphql/execution/runner.rb +32 -15
  81. data/lib/graphql/execution/selections_step.rb +3 -2
  82. data/lib/graphql/execution.rb +2 -2
  83. data/lib/graphql/execution_error.rb +19 -10
  84. data/lib/graphql/float_decoding_error.rb +14 -0
  85. data/lib/graphql/float_encoding_error.rb +33 -0
  86. data/lib/graphql/integer_decoding_error.rb +2 -1
  87. data/lib/graphql/integer_encoding_error.rb +8 -3
  88. data/lib/graphql/introspection/base_object.rb +3 -1
  89. data/lib/graphql/introspection/directive_location_enum.rb +1 -0
  90. data/lib/graphql/introspection/directive_type.rb +1 -0
  91. data/lib/graphql/introspection/dynamic_fields.rb +1 -0
  92. data/lib/graphql/introspection/entry_points.rb +1 -0
  93. data/lib/graphql/introspection/enum_value_type.rb +1 -0
  94. data/lib/graphql/introspection/field_type.rb +1 -0
  95. data/lib/graphql/introspection/input_value_type.rb +1 -0
  96. data/lib/graphql/introspection/introspection_query.rb +1 -0
  97. data/lib/graphql/introspection/schema_type.rb +1 -0
  98. data/lib/graphql/introspection/type_kind_enum.rb +1 -0
  99. data/lib/graphql/introspection/type_type.rb +1 -0
  100. data/lib/graphql/introspection.rb +1 -0
  101. data/lib/graphql/invalid_name_error.rb +1 -0
  102. data/lib/graphql/invalid_null_error.rb +19 -6
  103. data/lib/graphql/language/block_string.rb +2 -1
  104. data/lib/graphql/language/cache.rb +10 -4
  105. data/lib/graphql/language/comment.rb +1 -0
  106. data/lib/graphql/language/definition_slice.rb +1 -0
  107. data/lib/graphql/language/document_from_schema_definition.rb +9 -10
  108. data/lib/graphql/language/generation.rb +23 -9
  109. data/lib/graphql/language/lexer.rb +16 -8
  110. data/lib/graphql/language/nodes.rb +2094 -419
  111. data/lib/graphql/language/parser.rb +29 -18
  112. data/lib/graphql/language/printer.rb +31 -16
  113. data/lib/graphql/language/sanitized_printer.rb +16 -5
  114. data/lib/graphql/language/static_visitor.rb +19 -4
  115. data/lib/graphql/language/visitor.rb +51 -29
  116. data/lib/graphql/language.rb +15 -9
  117. data/lib/graphql/load_application_object_failed_error.rb +14 -5
  118. data/lib/graphql/name_validator.rb +1 -0
  119. data/lib/graphql/pagination/active_record_relation_connection.rb +1 -0
  120. data/lib/graphql/pagination/array_connection.rb +24 -6
  121. data/lib/graphql/pagination/connection.rb +178 -48
  122. data/lib/graphql/pagination/connections.rb +21 -14
  123. data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -0
  124. data/lib/graphql/pagination/relation_connection.rb +164 -27
  125. data/lib/graphql/pagination/sequel_dataset_connection.rb +1 -0
  126. data/lib/graphql/pagination.rb +1 -0
  127. data/lib/graphql/parse_error.rb +1 -0
  128. data/lib/graphql/query/context/scoped_context.rb +2 -1
  129. data/lib/graphql/query/context.rb +106 -35
  130. data/lib/graphql/query/fingerprint.rb +15 -7
  131. data/lib/graphql/query/input_validation_result.rb +1 -0
  132. data/lib/graphql/query/null_context.rb +1 -0
  133. data/lib/graphql/query/partial.rb +28 -16
  134. data/lib/graphql/query/result.rb +15 -5
  135. data/lib/graphql/query/validation_pipeline.rb +16 -6
  136. data/lib/graphql/query/variable_validation_error.rb +17 -1
  137. data/lib/graphql/query/variables.rb +9 -2
  138. data/lib/graphql/query.rb +195 -50
  139. data/lib/graphql/railtie.rb +7 -3
  140. data/lib/graphql/rake_task/validate.rb +72 -17
  141. data/lib/graphql/rake_task.rb +55 -23
  142. data/lib/graphql/relay/range_add.rb +32 -21
  143. data/lib/graphql/relay.rb +1 -0
  144. data/lib/graphql/rubocop/graphql/base_cop.rb +1 -0
  145. data/lib/graphql/rubocop/graphql/default_null_true.rb +9 -6
  146. data/lib/graphql/rubocop/graphql/default_required_true.rb +9 -6
  147. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +12 -8
  148. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +9 -5
  149. data/lib/graphql/rubocop.rb +1 -0
  150. data/lib/graphql/runtime_error.rb +1 -0
  151. data/lib/graphql/runtime_type_error.rb +1 -0
  152. data/lib/graphql/schema/addition.rb +69 -50
  153. data/lib/graphql/schema/always_visible.rb +1 -0
  154. data/lib/graphql/schema/argument.rb +279 -45
  155. data/lib/graphql/schema/base_64_encoder.rb +2 -2
  156. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -0
  157. data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
  158. data/lib/graphql/schema/build_from_definition.rb +507 -178
  159. data/lib/graphql/schema/built_in_types.rb +1 -0
  160. data/lib/graphql/schema/directive/deprecated.rb +1 -0
  161. data/lib/graphql/schema/directive/feature.rb +39 -22
  162. data/lib/graphql/schema/directive/flagged.rb +6 -1
  163. data/lib/graphql/schema/directive/include.rb +1 -0
  164. data/lib/graphql/schema/directive/one_of.rb +1 -0
  165. data/lib/graphql/schema/directive/skip.rb +1 -0
  166. data/lib/graphql/schema/directive/specified_by.rb +1 -0
  167. data/lib/graphql/schema/directive/transform.rb +17 -8
  168. data/lib/graphql/schema/directive.rb +33 -7
  169. data/lib/graphql/schema/enum.rb +99 -38
  170. data/lib/graphql/schema/enum_value.rb +21 -13
  171. data/lib/graphql/schema/field/connection_extension.rb +10 -2
  172. data/lib/graphql/schema/field/scope_extension.rb +1 -0
  173. data/lib/graphql/schema/field.rb +622 -110
  174. data/lib/graphql/schema/field_extension.rb +89 -34
  175. data/lib/graphql/schema/find_inherited_value.rb +5 -3
  176. data/lib/graphql/schema/finder.rb +22 -8
  177. data/lib/graphql/schema/has_single_input_argument.rb +39 -6
  178. data/lib/graphql/schema/input_object.rb +40 -13
  179. data/lib/graphql/schema/interface.rb +33 -17
  180. data/lib/graphql/schema/introspection_system.rb +7 -3
  181. data/lib/graphql/schema/late_bound_type.rb +2 -2
  182. data/lib/graphql/schema/list.rb +15 -4
  183. data/lib/graphql/schema/loader.rb +23 -12
  184. data/lib/graphql/schema/member/base_dsl_methods.rb +58 -12
  185. data/lib/graphql/schema/member/build_type.rb +21 -7
  186. data/lib/graphql/schema/member/graphql_type_names.rb +10 -6
  187. data/lib/graphql/schema/member/has_arguments.rb +112 -49
  188. data/lib/graphql/schema/member/has_ast_node.rb +1 -0
  189. data/lib/graphql/schema/member/has_authorization.rb +5 -0
  190. data/lib/graphql/schema/member/has_dataloader.rb +91 -34
  191. data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -2
  192. data/lib/graphql/schema/member/has_directives.rb +45 -11
  193. data/lib/graphql/schema/member/has_fields.rb +151 -70
  194. data/lib/graphql/schema/member/has_interfaces.rb +8 -2
  195. data/lib/graphql/schema/member/has_path.rb +14 -5
  196. data/lib/graphql/schema/member/has_unresolved_type_error.rb +1 -0
  197. data/lib/graphql/schema/member/has_validators.rb +19 -4
  198. data/lib/graphql/schema/member/relay_shortcuts.rb +10 -2
  199. data/lib/graphql/schema/member/scoped.rb +14 -3
  200. data/lib/graphql/schema/member/type_system_helpers.rb +36 -6
  201. data/lib/graphql/schema/member/validates_input.rb +1 -0
  202. data/lib/graphql/schema/member.rb +9 -2
  203. data/lib/graphql/schema/mutation.rb +50 -46
  204. data/lib/graphql/schema/non_null.rb +21 -5
  205. data/lib/graphql/schema/object.rb +44 -15
  206. data/lib/graphql/schema/printer.rb +52 -31
  207. data/lib/graphql/schema/ractor_shareable.rb +6 -2
  208. data/lib/graphql/schema/relay_classic_mutation.rb +3 -3
  209. data/lib/graphql/schema/resolver/has_payload_type.rb +29 -7
  210. data/lib/graphql/schema/resolver.rb +156 -45
  211. data/lib/graphql/schema/scalar.rb +1 -0
  212. data/lib/graphql/schema/subscription.rb +67 -28
  213. data/lib/graphql/schema/timeout.rb +65 -25
  214. data/lib/graphql/schema/type_expression.rb +14 -5
  215. data/lib/graphql/schema/type_membership.rb +29 -10
  216. data/lib/graphql/schema/union.rb +4 -2
  217. data/lib/graphql/schema/unique_within_type.rb +24 -5
  218. data/lib/graphql/schema/validator/all_validator.rb +17 -9
  219. data/lib/graphql/schema/validator/allow_blank_validator.rb +8 -2
  220. data/lib/graphql/schema/validator/allow_null_validator.rb +8 -2
  221. data/lib/graphql/schema/validator/exclusion_validator.rb +14 -5
  222. data/lib/graphql/schema/validator/format_validator.rb +21 -10
  223. data/lib/graphql/schema/validator/inclusion_validator.rb +15 -6
  224. data/lib/graphql/schema/validator/length_validator.rb +23 -12
  225. data/lib/graphql/schema/validator/numericality_validator.rb +29 -16
  226. data/lib/graphql/schema/validator/required_validator.rb +45 -31
  227. data/lib/graphql/schema/validator.rb +89 -25
  228. data/lib/graphql/schema/visibility/migration.rb +14 -7
  229. data/lib/graphql/schema/visibility/profile.rb +73 -19
  230. data/lib/graphql/schema/visibility/visit.rb +12 -10
  231. data/lib/graphql/schema/visibility.rb +24 -20
  232. data/lib/graphql/schema/warden.rb +117 -31
  233. data/lib/graphql/schema/wrapper.rb +4 -1
  234. data/lib/graphql/schema.rb +1052 -304
  235. data/lib/graphql/static_validation/all_rules.rb +2 -1
  236. data/lib/graphql/static_validation/base_visitor.rb +59 -9
  237. data/lib/graphql/static_validation/definition_dependencies.rb +27 -7
  238. data/lib/graphql/static_validation/error.rb +3 -0
  239. data/lib/graphql/static_validation/interpreter_visitor.rb +1 -0
  240. data/lib/graphql/static_validation/literal_validator.rb +1 -0
  241. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -0
  242. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +1 -0
  243. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +3 -0
  244. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +1 -0
  245. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -0
  246. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +1 -0
  247. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -0
  248. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +1 -0
  249. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +3 -0
  250. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +1 -0
  251. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +3 -0
  252. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +1 -0
  253. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +9 -1
  254. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +1 -0
  255. data/lib/graphql/static_validation/rules/fields_will_merge.rb +355 -157
  256. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +14 -2
  257. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +3 -0
  258. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +1 -0
  259. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -0
  260. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +1 -0
  261. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +3 -0
  262. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +1 -0
  263. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +3 -0
  264. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +1 -0
  265. data/lib/graphql/static_validation/rules/fragments_are_named.rb +3 -0
  266. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +1 -0
  267. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +3 -0
  268. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +1 -0
  269. data/lib/graphql/static_validation/rules/fragments_are_used.rb +3 -0
  270. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +1 -0
  271. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +3 -0
  272. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +1 -0
  273. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +3 -0
  274. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +1 -0
  275. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +3 -0
  276. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +1 -0
  277. data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +1 -0
  278. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +4 -0
  279. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +1 -0
  280. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +3 -0
  281. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +1 -0
  282. data/lib/graphql/static_validation/rules/query_root_exists.rb +3 -0
  283. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +1 -0
  284. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -1
  285. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +1 -0
  286. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +4 -0
  287. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +1 -0
  288. data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +43 -5
  289. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +1 -0
  290. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +3 -0
  291. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +1 -0
  292. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -0
  293. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +1 -0
  294. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +3 -0
  295. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +1 -0
  296. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +207 -51
  297. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +1 -0
  298. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +3 -0
  299. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +1 -0
  300. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +6 -3
  301. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +1 -0
  302. data/lib/graphql/static_validation/validation_context.rb +3 -2
  303. data/lib/graphql/static_validation/validation_timeout_error.rb +1 -0
  304. data/lib/graphql/static_validation/validator.rb +41 -16
  305. data/lib/graphql/static_validation.rb +1 -0
  306. data/lib/graphql/string_encoding_error.rb +1 -0
  307. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +85 -65
  308. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  309. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +1 -0
  310. data/lib/graphql/subscriptions/event.rb +25 -6
  311. data/lib/graphql/subscriptions/serialize.rb +89 -23
  312. data/lib/graphql/subscriptions.rb +172 -46
  313. data/lib/graphql/testing/helpers.rb +17 -4
  314. data/lib/graphql/testing/mock_action_cable.rb +55 -33
  315. data/lib/graphql/testing.rb +1 -0
  316. data/lib/graphql/tracing/active_support_notifications_trace.rb +17 -9
  317. data/lib/graphql/tracing/active_support_notifications_tracing.rb +2 -1
  318. data/lib/graphql/tracing/appoptics_trace.rb +2 -1
  319. data/lib/graphql/tracing/appoptics_tracing.rb +2 -1
  320. data/lib/graphql/tracing/appsignal_trace.rb +16 -7
  321. data/lib/graphql/tracing/appsignal_tracing.rb +7 -3
  322. data/lib/graphql/tracing/call_legacy_tracers.rb +1 -0
  323. data/lib/graphql/tracing/data_dog_trace.rb +17 -6
  324. data/lib/graphql/tracing/data_dog_tracing.rb +10 -3
  325. data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +1 -0
  326. data/lib/graphql/tracing/detailed_trace/memory_backend.rb +1 -0
  327. data/lib/graphql/tracing/detailed_trace/redis_backend.rb +1 -0
  328. data/lib/graphql/tracing/detailed_trace.rb +105 -42
  329. data/lib/graphql/tracing/legacy_hooks_trace.rb +5 -0
  330. data/lib/graphql/tracing/legacy_trace.rb +1 -0
  331. data/lib/graphql/tracing/monitor_trace.rb +17 -11
  332. data/lib/graphql/tracing/new_relic_trace.rb +17 -8
  333. data/lib/graphql/tracing/new_relic_tracing.rb +7 -3
  334. data/lib/graphql/tracing/notifications_trace.rb +11 -8
  335. data/lib/graphql/tracing/notifications_tracing.rb +23 -7
  336. data/lib/graphql/tracing/null_trace.rb +1 -0
  337. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +1 -0
  338. data/lib/graphql/tracing/perfetto_trace.rb +41 -19
  339. data/lib/graphql/tracing/platform_trace.rb +3 -1
  340. data/lib/graphql/tracing/platform_tracing.rb +16 -7
  341. data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +1 -0
  342. data/lib/graphql/tracing/prometheus_trace.rb +22 -13
  343. data/lib/graphql/tracing/prometheus_tracing.rb +1 -0
  344. data/lib/graphql/tracing/scout_trace.rb +10 -4
  345. data/lib/graphql/tracing/scout_tracing.rb +7 -3
  346. data/lib/graphql/tracing/sentry_trace.rb +25 -6
  347. data/lib/graphql/tracing/statsd_trace.rb +12 -6
  348. data/lib/graphql/tracing/statsd_tracing.rb +7 -1
  349. data/lib/graphql/tracing/trace.rb +231 -58
  350. data/lib/graphql/tracing.rb +25 -9
  351. data/lib/graphql/type_kinds.rb +2 -1
  352. data/lib/graphql/types/big_int.rb +1 -0
  353. data/lib/graphql/types/boolean.rb +1 -0
  354. data/lib/graphql/types/float.rb +19 -4
  355. data/lib/graphql/types/id.rb +1 -0
  356. data/lib/graphql/types/int.rb +2 -1
  357. data/lib/graphql/types/iso_8601_date.rb +21 -4
  358. data/lib/graphql/types/iso_8601_date_time.rb +33 -6
  359. data/lib/graphql/types/iso_8601_duration.rb +42 -9
  360. data/lib/graphql/types/json.rb +1 -0
  361. data/lib/graphql/types/relay/base_connection.rb +38 -32
  362. data/lib/graphql/types/relay/base_edge.rb +15 -9
  363. data/lib/graphql/types/relay/connection_behaviors.rb +19 -3
  364. data/lib/graphql/types/relay/edge_behaviors.rb +17 -4
  365. data/lib/graphql/types/relay/has_node_field.rb +6 -1
  366. data/lib/graphql/types/relay/has_nodes_field.rb +6 -1
  367. data/lib/graphql/types/relay/node.rb +1 -0
  368. data/lib/graphql/types/relay/node_behaviors.rb +5 -1
  369. data/lib/graphql/types/relay/page_info.rb +1 -0
  370. data/lib/graphql/types/relay/page_info_behaviors.rb +1 -0
  371. data/lib/graphql/types/relay.rb +4 -3
  372. data/lib/graphql/types/string.rb +1 -0
  373. data/lib/graphql/types.rb +1 -0
  374. data/lib/graphql/unauthorized_enum_value_error.rb +4 -1
  375. data/lib/graphql/unauthorized_error.rb +11 -4
  376. data/lib/graphql/unauthorized_field_error.rb +4 -1
  377. data/lib/graphql/unresolved_type_error.rb +16 -5
  378. data/lib/graphql/version.rb +2 -1
  379. data/lib/graphql.rb +39 -9
  380. data/readme.md +1 -1
  381. metadata +91 -5
  382. data/.yardopts +0 -5
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class FieldResolveStep
6
+ # Only these built-in fields on Relay connection and edge types return already-scoped items.
7
+ # Custom fields on those types must still be authorized normally.
8
+ SCOPED_RELAY_FIELD_NAMES = [:node, :nodes, :edges].freeze
9
+
5
10
  def initialize(parent_type:, runner:, key:, selections_step:)
6
11
  @selections_step = selections_step
7
12
  @key = key
@@ -21,6 +26,8 @@ module GraphQL
21
26
  @finish_extension_idx = nil
22
27
  @was_scoped = nil
23
28
  @pending_steps = nil
29
+ @field_authorization_objects = @field_authorization_results = @field_authorization_errors = nil
30
+ @field_authorization_next_idx = @field_authorization_pending = nil
24
31
  @arguments_without_loads = @post_processors = @directive_finalizers = nil
25
32
  end
26
33
 
@@ -89,6 +96,12 @@ module GraphQL
89
96
  finish_extensions
90
97
  elsif @field_results
91
98
  build_results
99
+ elsif @field_authorization_results
100
+ if @field_authorization_next_idx < @field_authorization_objects.size
101
+ authorize_next_field_object
102
+ else
103
+ finish_field_authorizations
104
+ end
92
105
  elsif @arguments
93
106
  execute_field
94
107
  else
@@ -113,7 +126,7 @@ module GraphQL
113
126
  @runner.add_finalizer(@selections_step.query, result, key, err)
114
127
  if !err.is_a?(GraphQL::Execution::Skip)
115
128
  field_type = return_type
116
- should_propagate_null = field_type.non_null?
129
+ should_propagate_null = field_type.non_null? #: bool
117
130
  while (should_propagate_null == false && field_type.kind.wraps?)
118
131
  field_type = field_type.of_type
119
132
  should_propagate_null = field_type.non_null?
@@ -126,10 +139,10 @@ module GraphQL
126
139
  end
127
140
 
128
141
  def propagate_nulls
129
- propagating_null = true
142
+ propagating_null = true #: bool
130
143
  highest_nulled_depth = path.size
131
- highest_list_depth = nil
132
- current_field_step = self
144
+ highest_list_depth = nil #: Integer?
145
+ current_field_step = self #: FieldResolveStep?
133
146
  while current_field_step && current_field_step.field_definition
134
147
  return_type = current_field_step.field_definition.type
135
148
  if propagating_null && return_type.non_null?
@@ -146,7 +159,7 @@ module GraphQL
146
159
  end
147
160
 
148
161
  if highest_list_depth.nil? || highest_nulled_depth <= highest_list_depth
149
- kill_field_step = self
162
+ kill_field_step = self #: FieldResolveStep?
150
163
  while kill_field_step && kill_field_step.field_definition && highest_nulled_depth <= kill_field_step.path.size
151
164
  kill_field_step.selections_step.killed = true
152
165
  kill_field_step = kill_field_step.selections_step.field_resolve_step
@@ -238,153 +251,30 @@ module GraphQL
238
251
  end
239
252
 
240
253
  if @runner.authorizes?(@field_definition, ctx)
241
- authorized_objects = []
242
- authorized_results = []
243
- l = objects.size
244
- i = 0
245
- while i < l
246
- o = objects[i]
247
- err = nil
248
- begin
249
- field_authed = @field_definition.authorized?(o, @arguments, ctx)
250
- if @runner.resolves_lazies && @runner.lazy?(field_authed)
251
- # TODO batch this properly...
252
- field_authed = sync(field_authed)
253
- end
254
- rescue GraphQL::UnauthorizedFieldError => field_auth_err
255
- err = field_auth_err
256
- err.field ||= @field_definition
257
- field_authed = false
258
- end
259
-
260
- if field_authed
261
- authorized_results << @results[i]
262
- authorized_objects << o
263
- else
264
- begin
265
- err ||= GraphQL::UnauthorizedFieldError.new(object: o, type: @parent_type, context: ctx, field: @field_definition)
266
- new_obj = query.schema.unauthorized_field(err)
267
- if !new_obj.nil?
268
- authorized_objects << new_obj
269
- authorized_results << @results[i]
270
- end
271
- rescue GraphQL::ExecutionError => exec_err
272
- add_graphql_error(@results[i], key, exec_err)
273
- end
274
- end
275
- i += 1
276
- end
277
-
278
- if authorized_objects.size == 0
254
+ @field_authorization_objects = objects
255
+ @field_authorization_results = Array.new(objects.size)
256
+ @field_authorization_next_idx = 0
257
+ if objects.size > 1 && !@runner.dataloader.is_a?(GraphQL::Dataloader::NullDataloader)
258
+ # Enqueue this step once per object, so Dataloader sources loaded by `authorized?` batch across objects.
259
+ # Each call authorizes the next object; see `authorize_next_field_object`.
260
+ @field_authorization_pending = objects.size
261
+ objects.size.times { @runner.dataloader.append_job(self) }
279
262
  return
280
263
  end
281
- @results = authorized_results
264
+ objects.size.times { |idx| authorize_field_at(idx, ctx) }
265
+ authorized_objects = collect_field_authorizations
266
+ return if authorized_objects.nil?
282
267
  else
283
268
  authorized_objects = objects
284
269
  end
285
270
 
286
- if @parent_type.default_relay? && authorized_objects.all? { |o| o.respond_to?(:was_authorized_by_scope_items?) && o.was_authorized_by_scope_items? }
287
- @was_scoped = true
288
- end
289
-
290
- query.current_trace.begin_execute_field(@field_definition, authorized_objects, @arguments, query)
291
-
292
- if @runner.uses_runtime_directives
293
- if @ast_nodes.nil? || @ast_nodes.size == 1
294
- directives = if !@ast_node.directives.empty?
295
- @ast_node.directives
296
- else
297
- nil
298
- end
299
- else
300
- directives = nil
301
- @ast_nodes.each do |n|
302
- if (d = n.directives).any? # rubocop:disable Development/NoneWithoutBlockCop
303
- directives ||= []
304
- directives.concat(d)
305
- end
306
- end
307
- end
308
-
309
- if directives
310
- directives.each do |dir_node|
311
- if (dir_defn = @runner.runtime_directives[dir_node.name])
312
- dir_args, errors = @runner.input_values[query].argument_values(dir_defn, dir_node.arguments, self) # rubocop:disable Development/ContextIsPassedCop
313
- if errors
314
- @results.each { |r| r.delete(@key) }
315
- errors.each { |e| e.ast_node = dir_node }
316
- build_errors_result(errors, nil)
317
- return
318
- else
319
- begin
320
- dir_defn.validate!(dir_args, query.context)
321
- if !(result = dir_defn.resolve_field(ast_nodes, @parent_type, field_definition, authorized_objects, dir_args, ctx)).nil?
322
- if result.is_a?(Finalizer)
323
- result.path = path
324
- @directive_finalizers ||= []
325
- @directive_finalizers << result
326
- end
327
-
328
- if result.is_a?(PostProcessor)
329
- @post_processors ||= []
330
- @post_processors << result
331
- end
332
-
333
- if result.is_a?(HaltExecution)
334
- @directive_finalizers&.each { |f|
335
- @selections_step.results.each { |r| @runner.add_finalizer(query, r, key, f) }
336
- }
337
- return
338
- end
339
- end
340
- rescue GraphQL::RuntimeError => err
341
- err.ast_node = dir_node
342
- raise
343
- end
344
- end
345
- end
346
- end
347
- end
348
- end
349
-
350
- has_extensions = @field_definition.extensions.size > 0
351
- if has_extensions
352
- @extended = GraphQL::Schema::Field::ExtendedState.new(@arguments, authorized_objects)
353
- @field_results = @field_definition.run_next_extensions_before_resolve(authorized_objects, @arguments, ctx, @extended) do |objs, args|
354
- if (added_extras = @extended.added_extras)
355
- args = args.dup
356
- added_extras.each { |e| args.delete(e) }
357
- end
358
- resolve_batch(objs, ctx, args)
359
- end
360
- @finish_extension_idx = 0
361
- else
362
- @field_results = resolve_batch(authorized_objects, ctx, @arguments)
363
- end
364
-
365
- query.current_trace.end_execute_field(@field_definition, authorized_objects, @arguments, query, @field_results)
366
-
367
- if any_lazy_results?
368
- @runner.dataloader.lazy_at_depth(path.size, self)
369
- elsif @pending_steps.nil? || @pending_steps.empty?
370
- if has_extensions
371
- finish_extensions
372
- else
373
- build_results
374
- end
375
- end
376
- rescue GraphQL::ExecutionError => err
377
- build_errors_result(nil, err)
378
- rescue StandardError => stderr
379
- begin
380
- @selections_step.query.handle_or_reraise(stderr, field: @field_definition, arguments: @arguments, object: nil)
381
- rescue GraphQL::ExecutionError => err
382
- add_graphql_error(@results[0], key, err)
383
- end
271
+ execute_authorized_field(authorized_objects)
272
+ rescue StandardError => err
273
+ handle_execute_field_error(err)
384
274
  end
385
275
 
386
276
  def any_lazy_results?
387
- lazies = false
277
+ lazies = false #: bool
388
278
  if @runner.resolves_lazies # TODO extract this
389
279
  @field_results.each do |field_result|
390
280
  if @runner.lazy?(field_result)
@@ -414,11 +304,15 @@ module GraphQL
414
304
  case ext
415
305
  when Schema::Field::ConnectionExtension
416
306
  conns = ctx.schema.connections
307
+ lookahead = @arguments[:lookahead]
308
+ # The memo omits the extension's extras (`:lookahead`)
309
+ conn_arguments = memos[@finish_extension_idx] || @arguments
417
310
  @field_results.map!.each_with_index do |value, idx|
418
311
  object = @extended.object[idx]
419
- conn = conns.populate_connection(@field_definition, object, value, @arguments, ctx)
312
+ conn = conns.populate_connection(@field_definition, object, value, conn_arguments, ctx)
420
313
  if conn
421
314
  conn.was_authorized_by_scope_items = @was_scoped
315
+ conn.lookahead ||= lookahead
422
316
  end
423
317
  conn
424
318
  rescue GraphQL::RuntimeError => err
@@ -510,7 +404,7 @@ module GraphQL
510
404
  def build_leaf_result(result_h, result_key, field_result, return_type, ctx, is_from_array)
511
405
  if field_result.nil?
512
406
  if return_type.non_null?
513
- add_non_null_error(is_from_array)
407
+ add_non_null_error(is_from_array, return_type: return_type)
514
408
  else
515
409
  nil
516
410
  end
@@ -527,7 +421,7 @@ module GraphQL
527
421
  end
528
422
 
529
423
  inner_type = return_type.of_type
530
- result_a = Array.new(field_result.size)
424
+ result_a = field_result.is_a?(Array) ? Array.new(field_result.size) : []
531
425
  field_result.each_with_index do |item, idx|
532
426
  result_a[idx] = build_leaf_result(result_a, idx, item, inner_type, ctx, true)
533
427
  end
@@ -605,8 +499,14 @@ module GraphQL
605
499
  end
606
500
  end
607
501
 
608
- def add_non_null_error(is_from_array)
609
- err = @parent_type::InvalidNullError.new(@parent_type, @field_definition, ast_nodes, is_from_array: is_from_array, path: path)
502
+ def add_non_null_error(is_from_array, return_type: nil)
503
+ if is_from_array && return_type
504
+ list_type = @field_definition.type
505
+ list_type = list_type.of_type if list_type.non_null?
506
+ # Preserve existing messages for single-level lists.
507
+ element_type = return_type.of_type if list_type.of_type.list?
508
+ end
509
+ err = @parent_type.const_get(:InvalidNullError).new(@parent_type, @field_definition, ast_nodes, is_from_array: is_from_array, path: path, element_type: element_type)
610
510
  nn_result = @runner.schema.type_error(err, @selections_step.query.context)
611
511
  if nn_result.nil?
612
512
  propagate_nulls
@@ -620,6 +520,207 @@ module GraphQL
620
520
 
621
521
  private
622
522
 
523
+ def execute_authorized_field(authorized_objects)
524
+ query = @selections_step.query
525
+ ctx = query.context
526
+
527
+ if @parent_type.default_relay? && SCOPED_RELAY_FIELD_NAMES.include?(@field_definition.original_name) && authorized_objects.all? { |o| o.respond_to?(:was_authorized_by_scope_items?) && o.was_authorized_by_scope_items? }
528
+ @was_scoped = true
529
+ end
530
+
531
+ query.current_trace.begin_execute_field(@field_definition, authorized_objects, @arguments, query)
532
+
533
+ if @runner.uses_runtime_directives
534
+ if @ast_nodes.nil? || @ast_nodes.size == 1
535
+ directives = if !@ast_node.directives.empty?
536
+ @ast_node.directives
537
+ else
538
+ nil
539
+ end
540
+ else
541
+ directives = nil #: Array[untyped]?
542
+ @ast_nodes.each do |n|
543
+ if (d = n.directives).any? # rubocop:disable Development/NoneWithoutBlockCop
544
+ directives ||= []
545
+ directives.concat(d)
546
+ end
547
+ end
548
+ end
549
+
550
+ if directives
551
+ directives.each do |dir_node|
552
+ if (dir_defn = @runner.runtime_directives[dir_node.name])
553
+ dir_args, errors = @runner.input_values[query].argument_values(dir_defn, dir_node.arguments, self) # rubocop:disable Development/ContextIsPassedCop
554
+ if errors
555
+ @results.each { |r| r.delete(@key) }
556
+ errors.each { |e| e.ast_node = dir_node }
557
+ build_errors_result(errors, nil)
558
+ return
559
+ else
560
+ begin
561
+ dir_defn.validate!(dir_args, query.context)
562
+ if !(result = dir_defn.resolve_field(ast_nodes, @parent_type, field_definition, authorized_objects, dir_args, ctx)).nil?
563
+ if result.is_a?(Finalizer)
564
+ result.path = path
565
+ @directive_finalizers ||= []
566
+ @directive_finalizers << result
567
+ end
568
+
569
+ if result.is_a?(PostProcessor)
570
+ @post_processors ||= []
571
+ @post_processors << result
572
+ end
573
+
574
+ if result.is_a?(HaltExecution)
575
+ @directive_finalizers&.each { |f|
576
+ @selections_step.results.each { |r| @runner.add_finalizer(query, r, key, f) }
577
+ }
578
+ return
579
+ end
580
+ end
581
+ rescue GraphQL::RuntimeError => err
582
+ err.ast_node = dir_node
583
+ raise
584
+ end
585
+ end
586
+ end
587
+ end
588
+ end
589
+ end
590
+
591
+ has_extensions = @field_definition.extensions.size > 0
592
+ if has_extensions
593
+ @extended = GraphQL::Schema::Field::ExtendedState.new(@arguments, authorized_objects)
594
+ @field_results = @field_definition.run_next_extensions_before_resolve(authorized_objects, @arguments, ctx, @extended) do |objs, args|
595
+ if (added_extras = @extended.added_extras)
596
+ args = args.dup
597
+ added_extras.each { |e| args.delete(e) }
598
+ end
599
+ resolve_batch(objs, ctx, args)
600
+ end
601
+ @finish_extension_idx = 0
602
+ else
603
+ @field_results = resolve_batch(authorized_objects, ctx, @arguments)
604
+ end
605
+
606
+ query.current_trace.end_execute_field(@field_definition, authorized_objects, @arguments, query, @field_results)
607
+
608
+ if any_lazy_results?
609
+ @runner.dataloader.lazy_at_depth(path.size, self)
610
+ elsif @pending_steps.nil? || @pending_steps.empty?
611
+ if has_extensions
612
+ finish_extensions
613
+ else
614
+ build_results
615
+ end
616
+ end
617
+ rescue StandardError => err
618
+ handle_execute_field_error(err)
619
+ end
620
+
621
+ def handle_execute_field_error(err)
622
+ if @field_authorization_objects
623
+ clear_field_authorizations
624
+ end
625
+ if err.is_a?(GraphQL::ExecutionError)
626
+ build_errors_result(nil, err)
627
+ else
628
+ begin
629
+ @selections_step.query.handle_or_reraise(err, field: @field_definition, arguments: @arguments, object: nil)
630
+ rescue GraphQL::ExecutionError => exec_err
631
+ add_graphql_error(@results[0], key, exec_err)
632
+ end
633
+ end
634
+ end
635
+
636
+ # Stores the (possibly synced) +authorized?+ result for the object at +idx+.
637
+ # A GraphQL::UnauthorizedFieldError raised by +authorized?+ is stored in +@field_authorization_errors+.
638
+ def authorize_field_at(idx, ctx)
639
+ field_authed = @field_definition.authorized?(@field_authorization_objects[idx], @arguments, ctx)
640
+ if @runner.resolves_lazies && @runner.lazy?(field_authed)
641
+ field_authed = sync(field_authed)
642
+ end
643
+ @field_authorization_results[idx] = field_authed
644
+ rescue GraphQL::UnauthorizedFieldError => field_auth_err
645
+ field_auth_err.field ||= @field_definition
646
+ (@field_authorization_errors ||= {})[idx] = field_auth_err
647
+ end
648
+
649
+ # Runs once for each time this step was enqueued for field authorization.
650
+ # The index is taken before +authorized?+ runs, so it's still correct if this Fiber pauses.
651
+ # When the last object is done, the step is enqueued again to call +finish_field_authorizations+.
652
+ def authorize_next_field_object
653
+ idx = @field_authorization_next_idx
654
+ @field_authorization_next_idx += 1
655
+ begin
656
+ authorize_field_at(idx, @selections_step.query.context)
657
+ rescue StandardError => err
658
+ (@field_authorization_errors ||= {})[idx] = err
659
+ end
660
+ @field_authorization_pending -= 1
661
+ if @field_authorization_pending == 0
662
+ @runner.add_step(self)
663
+ end
664
+ end
665
+
666
+ def finish_field_authorizations
667
+ if (errors = @field_authorization_errors)
668
+ @field_authorization_objects.size.times do |idx|
669
+ err = errors[idx]
670
+ if err && !err.is_a?(GraphQL::UnauthorizedFieldError)
671
+ raise err
672
+ end
673
+ end
674
+ end
675
+ authorized_objects = collect_field_authorizations
676
+ if authorized_objects
677
+ execute_authorized_field(authorized_objects)
678
+ end
679
+ rescue StandardError => err
680
+ handle_execute_field_error(err)
681
+ end
682
+
683
+ def clear_field_authorizations
684
+ @field_authorization_objects = @field_authorization_results = @field_authorization_errors = nil
685
+ @field_authorization_next_idx = @field_authorization_pending = nil
686
+ end
687
+
688
+ # Applies +unauthorized_field+ for denied objects, in object order.
689
+ # Returns the objects to resolve, or +nil+ if none are left.
690
+ def collect_field_authorizations
691
+ objects = @field_authorization_objects
692
+ auth_results = @field_authorization_results
693
+ errors = @field_authorization_errors
694
+ clear_field_authorizations
695
+ ctx = @selections_step.query.context
696
+ authorized_objects = []
697
+ authorized_results = []
698
+ objects.each_with_index do |o, i|
699
+ err = errors && errors[i]
700
+ if !err && auth_results[i]
701
+ authorized_results << @results[i]
702
+ authorized_objects << o
703
+ else
704
+ begin
705
+ err ||= GraphQL::UnauthorizedFieldError.new(object: o, type: @parent_type, context: ctx, field: @field_definition)
706
+ new_obj = ctx.schema.unauthorized_field(err)
707
+ if !new_obj.nil?
708
+ authorized_objects << new_obj
709
+ authorized_results << @results[i]
710
+ end
711
+ rescue GraphQL::ExecutionError => exec_err
712
+ add_graphql_error(@results[i], key, exec_err)
713
+ end
714
+ end
715
+ end
716
+
717
+ if authorized_objects.size == 0
718
+ return nil
719
+ end
720
+ @results = authorized_results
721
+ authorized_objects
722
+ end
723
+
623
724
  def build_graphql_result(graphql_result, key, field_result, return_type, is_nn, is_list, is_from_array) # rubocop:disable Metrics/ParameterLists
624
725
  if field_result.nil?
625
726
  if is_nn
@@ -645,11 +746,18 @@ module GraphQL
645
746
  list_result = graphql_result[key] = []
646
747
  @directive_finalizers&.each { |f| @runner.add_finalizer(@selections_step.query, list_result, nil, f) }
647
748
  i = 0
648
- s = field_result.size
649
- while i < s
650
- inner_f_r = field_result[i]
651
- build_graphql_result(list_result, i, inner_f_r, inner_type, inner_type_nn, inner_type_l, true)
652
- i += 1
749
+ if field_result.is_a?(Array)
750
+ s = field_result.size
751
+ while i < s
752
+ inner_f_r = field_result[i]
753
+ build_graphql_result(list_result, i, inner_f_r, inner_type, inner_type_nn, inner_type_l, true)
754
+ i += 1
755
+ end
756
+ else
757
+ field_result.each do |inner_f_r|
758
+ build_graphql_result(list_result, i, inner_f_r, inner_type, inner_type_nn, inner_type_l, true)
759
+ i += 1
760
+ end
653
761
  end
654
762
  elsif @runner.resolves_lazies || (
655
763
  @static_type.kind.object? ?
@@ -690,25 +798,25 @@ module GraphQL
690
798
  when :resolve_batch
691
799
  begin
692
800
  method_receiver.public_send(@field_definition.execution_mode_key, objects, context, **args_hash)
693
- rescue GraphQL::ExecutionError => exec_err
694
- error_instance_array(objects.size, exec_err)
695
- rescue StandardError => stderr
801
+ rescue GraphQL::ExecutionError => batch_err
802
+ error_instance_array(objects.size, batch_err)
803
+ rescue StandardError => batch_stderr
696
804
  begin
697
- context.query.handle_or_reraise(stderr, field: @field_definition, arguments: @arguments, object: nil)
698
- rescue GraphQL::ExecutionError => exec_err
699
- error_instance_array(objects.size, exec_err)
805
+ context.query.handle_or_reraise(batch_stderr, field: @field_definition, arguments: @arguments, object: nil)
806
+ rescue GraphQL::ExecutionError => batch_err
807
+ error_instance_array(objects.size, batch_err)
700
808
  end
701
809
  end
702
810
  when :resolve_static
703
811
  result = begin
704
812
  method_receiver.public_send(@field_definition.execution_mode_key, context, **args_hash)
705
- rescue GraphQL::ExecutionError => err
706
- err
707
- rescue StandardError => stderr
813
+ rescue GraphQL::ExecutionError => static_err
814
+ static_err
815
+ rescue StandardError => static_stderr
708
816
  begin
709
- context.query.handle_or_reraise(stderr, field: @field_definition, arguments: @arguments, object: nil)
710
- rescue GraphQL::ExecutionError => err
711
- err
817
+ context.query.handle_or_reraise(static_stderr, field: @field_definition, arguments: @arguments, object: nil)
818
+ rescue GraphQL::ExecutionError => static_err
819
+ static_err
712
820
  end
713
821
  end
714
822
  Array.new(objects.size, result)
@@ -744,7 +852,8 @@ module GraphQL
744
852
  when :dig
745
853
  objects.map { |o| o.dig(*@field_definition.execution_mode_key) }
746
854
  when :dataload
747
- if (k = @field_definition.execution_mode_key).is_a?(Class)
855
+ k = @field_definition.execution_mode_key
856
+ results = if k.is_a?(Class)
748
857
  context.dataload_all(k, objects)
749
858
  elsif (source_class = k[:with])
750
859
  if (batch_args = k[:by])
@@ -764,6 +873,12 @@ module GraphQL
764
873
  else
765
874
  raise ArgumentError, "Unexpected `dataload: ...` configuration: #{k.inspect}"
766
875
  end
876
+ method = k.is_a?(Hash) ? k[:method] : nil
877
+ if method
878
+ results.map { |r| r&.public_send(method) }
879
+ else
880
+ results
881
+ end
767
882
  when :resolver_class
768
883
  results = Array.new(objects.size, nil)
769
884
  ps = @pending_steps ||= []
@@ -779,8 +894,13 @@ module GraphQL
779
894
  end
780
895
  results
781
896
  when :resolve_legacy_instance_method
782
- @selections_step.graphql_objects.map do |obj_inst|
783
- obj_inst.public_send(@field_definition.execution_mode_key, **args_hash)
897
+ graphql_objects = if objects.equal?(@selections_step.objects)
898
+ @selections_step.graphql_objects
899
+ else
900
+ objects.map { |object| @parent_type.scoped_new(object, context) }
901
+ end
902
+ graphql_objects.map do |graphql_object|
903
+ graphql_object.public_send(@field_definition.execution_mode_key, **args_hash)
784
904
  rescue GraphQL::ExecutionError => exec_err
785
905
  exec_err
786
906
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class Finalize
@@ -39,11 +40,16 @@ module GraphQL
39
40
  tf[key] = err
40
41
  @finalizers_count += 1
41
42
  elsif value_at_key.is_a?(Array)
42
- value_at_key.each_with_index do |el, idx|
43
- if el.equal?(err)
44
- tf = @finalizers[value_at_key] ||= {}.compare_by_identity
45
- tf[idx] = err
46
- @finalizers_count += 1
43
+ pending_arrays = [value_at_key]
44
+ while (array = pending_arrays.pop)
45
+ array.each_with_index do |el, idx|
46
+ if el.equal?(err)
47
+ array_tf = @finalizers[array] ||= {}.compare_by_identity
48
+ array_tf[idx] = err
49
+ @finalizers_count += 1
50
+ elsif el.is_a?(Array)
51
+ pending_arrays << el
52
+ end
47
53
  end
48
54
  end
49
55
  end
@@ -175,7 +181,7 @@ module GraphQL
175
181
  inner_type = inner_type.of_type
176
182
  end
177
183
 
178
- new_invalid_null = false
184
+ new_invalid_null = false #: bool
179
185
 
180
186
  if (f = finalizers(result_arr, nil))
181
187
  run_finalizers(@current_result_path.dup, f, result_arr, nil)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
  module GraphQL
3
4
  module Execution
4
5
  class InputValues
@@ -38,7 +39,7 @@ module GraphQL
38
39
  def argument_values(owner_defn, argument_nodes, field_resolve_step)
39
40
  arg_defns = @query.types.arguments(owner_defn)
40
41
  argument_values = {}
41
- errors = nil
42
+ errors = nil #: untyped
42
43
 
43
44
  arg_defns.each do |argument_definition|
44
45
  arg_ruby_key = argument_definition.keyword
@@ -182,7 +183,9 @@ module GraphQL
182
183
  arg_value = begin
183
184
  argument_definition.prepare_value(nil, arg_value, context: @query.context)
184
185
  rescue StandardError => err
185
- @runner.schema.handle_or_reraise(@query.context, err, object: nil, arguments: argument_values, field: field_resolve_step&.field_definition)
186
+ handled_err = @runner.schema.handle_or_reraise(@query.context, err, object: nil, arguments: argument_values, field: field_resolve_step&.field_definition)
187
+ raise handled_err if handled_err.is_a?(GraphQL::RuntimeError)
188
+ handled_err
186
189
  end
187
190
  end
188
191