graphql 1.9.0 → 2.1.1

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 (723) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +12 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +4 -0
  9. data/lib/generators/graphql/install_generator.rb +49 -9
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +66 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +8 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +10 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +10 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +4 -0
  25. data/lib/generators/graphql/templates/base_field.erb +9 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +5 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +6 -0
  28. data/lib/generators/graphql/templates/base_object.erb +5 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  30. data/lib/generators/graphql/templates/base_union.erb +4 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +23 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +4 -0
  36. data/lib/generators/graphql/templates/mutation.erb +5 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +11 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +5 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +27 -27
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/ast/analyzer.rb +41 -12
  49. data/lib/graphql/analysis/ast/field_usage.rb +32 -3
  50. data/lib/graphql/analysis/ast/max_query_complexity.rb +4 -5
  51. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  52. data/lib/graphql/analysis/ast/query_complexity.rb +182 -66
  53. data/lib/graphql/analysis/ast/query_depth.rb +15 -26
  54. data/lib/graphql/analysis/ast/visitor.rb +83 -62
  55. data/lib/graphql/analysis/ast.rb +23 -20
  56. data/lib/graphql/analysis.rb +0 -7
  57. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  58. data/lib/graphql/backtrace/table.rb +37 -16
  59. data/lib/graphql/backtrace/trace.rb +96 -0
  60. data/lib/graphql/backtrace/traced_error.rb +0 -1
  61. data/lib/graphql/backtrace/tracer.rb +39 -9
  62. data/lib/graphql/backtrace.rb +22 -18
  63. data/lib/graphql/coercion_error.rb +8 -0
  64. data/lib/graphql/dataloader/null_dataloader.rb +24 -0
  65. data/lib/graphql/dataloader/request.rb +19 -0
  66. data/lib/graphql/dataloader/request_all.rb +19 -0
  67. data/lib/graphql/dataloader/source.rb +195 -0
  68. data/lib/graphql/dataloader.rb +320 -0
  69. data/lib/graphql/date_encoding_error.rb +16 -0
  70. data/lib/graphql/deprecation.rb +9 -0
  71. data/lib/graphql/dig.rb +1 -1
  72. data/lib/graphql/execution/directive_checks.rb +2 -2
  73. data/lib/graphql/execution/errors.rb +93 -0
  74. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  75. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  76. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  77. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  78. data/lib/graphql/execution/interpreter/resolve.rb +62 -24
  79. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +170 -0
  80. data/lib/graphql/execution/interpreter/runtime.rb +695 -392
  81. data/lib/graphql/execution/interpreter.rb +199 -74
  82. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  83. data/lib/graphql/execution/lazy.rb +11 -21
  84. data/lib/graphql/execution/lookahead.rb +110 -150
  85. data/lib/graphql/execution/multiplex.rb +6 -148
  86. data/lib/graphql/execution.rb +12 -4
  87. data/lib/graphql/execution_error.rb +3 -2
  88. data/lib/graphql/integer_decoding_error.rb +17 -0
  89. data/lib/graphql/integer_encoding_error.rb +26 -2
  90. data/lib/graphql/introspection/base_object.rb +2 -5
  91. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  92. data/lib/graphql/introspection/directive_type.rb +12 -6
  93. data/lib/graphql/introspection/dynamic_fields.rb +3 -8
  94. data/lib/graphql/introspection/entry_points.rb +6 -18
  95. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  96. data/lib/graphql/introspection/field_type.rb +9 -5
  97. data/lib/graphql/introspection/input_value_type.rb +41 -7
  98. data/lib/graphql/introspection/introspection_query.rb +6 -92
  99. data/lib/graphql/introspection/schema_type.rb +13 -12
  100. data/lib/graphql/introspection/type_type.rb +34 -17
  101. data/lib/graphql/introspection.rb +100 -0
  102. data/lib/graphql/invalid_null_error.rb +18 -0
  103. data/lib/graphql/language/block_string.rb +50 -23
  104. data/lib/graphql/language/cache.rb +37 -0
  105. data/lib/graphql/language/definition_slice.rb +21 -10
  106. data/lib/graphql/language/document_from_schema_definition.rb +153 -87
  107. data/lib/graphql/language/lexer.rb +249 -1450
  108. data/lib/graphql/language/nodes.rb +152 -142
  109. data/lib/graphql/language/parser.rb +1036 -953
  110. data/lib/graphql/language/parser.y +159 -120
  111. data/lib/graphql/language/printer.rb +342 -154
  112. data/lib/graphql/language/sanitized_printer.rb +220 -0
  113. data/lib/graphql/language/static_visitor.rb +167 -0
  114. data/lib/graphql/language/token.rb +2 -2
  115. data/lib/graphql/language/visitor.rb +196 -140
  116. data/lib/graphql/language.rb +4 -1
  117. data/lib/graphql/load_application_object_failed_error.rb +22 -0
  118. data/lib/graphql/name_validator.rb +2 -7
  119. data/lib/graphql/pagination/active_record_relation_connection.rb +77 -0
  120. data/lib/graphql/pagination/array_connection.rb +79 -0
  121. data/lib/graphql/pagination/connection.rb +275 -0
  122. data/lib/graphql/pagination/connections.rb +135 -0
  123. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  124. data/lib/graphql/pagination/relation_connection.rb +228 -0
  125. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  126. data/lib/graphql/pagination.rb +6 -0
  127. data/lib/graphql/parse_error.rb +0 -1
  128. data/lib/graphql/query/context/scoped_context.rb +101 -0
  129. data/lib/graphql/query/context.rb +157 -187
  130. data/lib/graphql/query/fingerprint.rb +26 -0
  131. data/lib/graphql/query/input_validation_result.rb +33 -7
  132. data/lib/graphql/query/null_context.rb +21 -14
  133. data/lib/graphql/query/validation_pipeline.rb +17 -38
  134. data/lib/graphql/query/variable_validation_error.rb +17 -3
  135. data/lib/graphql/query/variables.rb +49 -14
  136. data/lib/graphql/query.rb +142 -61
  137. data/lib/graphql/railtie.rb +6 -102
  138. data/lib/graphql/rake_task/validate.rb +5 -2
  139. data/lib/graphql/rake_task.rb +42 -20
  140. data/lib/graphql/relay/range_add.rb +17 -10
  141. data/lib/graphql/relay.rb +0 -15
  142. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  143. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  144. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  145. data/lib/graphql/rubocop.rb +4 -0
  146. data/lib/graphql/schema/addition.rb +271 -0
  147. data/lib/graphql/schema/always_visible.rb +10 -0
  148. data/lib/graphql/schema/argument.rb +301 -32
  149. data/lib/graphql/schema/base_64_bp.rb +3 -2
  150. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  151. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  152. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  153. data/lib/graphql/schema/build_from_definition.rb +349 -203
  154. data/lib/graphql/schema/built_in_types.rb +5 -5
  155. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  156. data/lib/graphql/schema/directive/feature.rb +2 -2
  157. data/lib/graphql/schema/directive/flagged.rb +57 -0
  158. data/lib/graphql/schema/directive/include.rb +2 -2
  159. data/lib/graphql/schema/directive/one_of.rb +12 -0
  160. data/lib/graphql/schema/directive/skip.rb +2 -2
  161. data/lib/graphql/schema/directive/specified_by.rb +14 -0
  162. data/lib/graphql/schema/directive/transform.rb +14 -2
  163. data/lib/graphql/schema/directive.rb +134 -15
  164. data/lib/graphql/schema/enum.rb +137 -39
  165. data/lib/graphql/schema/enum_value.rb +17 -23
  166. data/lib/graphql/schema/field/connection_extension.rb +36 -20
  167. data/lib/graphql/schema/field/scope_extension.rb +15 -5
  168. data/lib/graphql/schema/field.rb +570 -334
  169. data/lib/graphql/schema/field_extension.rb +88 -4
  170. data/lib/graphql/schema/find_inherited_value.rb +31 -0
  171. data/lib/graphql/schema/finder.rb +16 -14
  172. data/lib/graphql/schema/has_single_input_argument.rb +156 -0
  173. data/lib/graphql/schema/input_object.rb +190 -48
  174. data/lib/graphql/schema/interface.rb +24 -49
  175. data/lib/graphql/schema/introspection_system.rb +109 -36
  176. data/lib/graphql/schema/late_bound_type.rb +9 -2
  177. data/lib/graphql/schema/list.rb +61 -3
  178. data/lib/graphql/schema/loader.rb +146 -97
  179. data/lib/graphql/schema/member/base_dsl_methods.rb +45 -51
  180. data/lib/graphql/schema/member/build_type.rb +34 -17
  181. data/lib/graphql/schema/member/has_arguments.rb +385 -10
  182. data/lib/graphql/schema/member/has_ast_node.rb +32 -0
  183. data/lib/graphql/schema/member/has_deprecation_reason.rb +24 -0
  184. data/lib/graphql/schema/member/has_directives.rb +118 -0
  185. data/lib/graphql/schema/member/has_fields.rb +180 -35
  186. data/lib/graphql/schema/member/has_interfaces.rb +143 -0
  187. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  188. data/lib/graphql/schema/member/has_validators.rb +57 -0
  189. data/lib/graphql/schema/member/relay_shortcuts.rb +47 -2
  190. data/lib/graphql/schema/member/scoped.rb +19 -0
  191. data/lib/graphql/schema/member/type_system_helpers.rb +20 -3
  192. data/lib/graphql/schema/member/validates_input.rb +33 -0
  193. data/lib/graphql/schema/member.rb +11 -6
  194. data/lib/graphql/schema/mutation.rb +4 -9
  195. data/lib/graphql/schema/non_null.rb +34 -4
  196. data/lib/graphql/schema/object.rb +55 -64
  197. data/lib/graphql/schema/printer.rb +26 -40
  198. data/lib/graphql/schema/relay_classic_mutation.rb +13 -80
  199. data/lib/graphql/schema/resolver/has_payload_type.rb +53 -12
  200. data/lib/graphql/schema/resolver.rb +182 -162
  201. data/lib/graphql/schema/scalar.rb +40 -15
  202. data/lib/graphql/schema/subscription.rb +85 -27
  203. data/lib/graphql/schema/timeout.rb +119 -0
  204. data/lib/graphql/schema/type_expression.rb +21 -13
  205. data/lib/graphql/schema/type_membership.rb +51 -0
  206. data/lib/graphql/schema/union.rb +69 -15
  207. data/lib/graphql/schema/unique_within_type.rb +1 -2
  208. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  209. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  210. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  211. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  212. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  213. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  214. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  215. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  216. data/lib/graphql/schema/validator.rb +171 -0
  217. data/lib/graphql/schema/warden.rb +330 -59
  218. data/lib/graphql/schema/wrapper.rb +0 -5
  219. data/lib/graphql/schema.rb +985 -858
  220. data/lib/graphql/static_validation/all_rules.rb +4 -1
  221. data/lib/graphql/static_validation/base_visitor.rb +33 -32
  222. data/lib/graphql/static_validation/definition_dependencies.rb +28 -14
  223. data/lib/graphql/static_validation/error.rb +3 -1
  224. data/lib/graphql/static_validation/literal_validator.rb +71 -28
  225. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  226. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  227. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  228. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  229. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -6
  230. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +14 -14
  231. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  232. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +15 -7
  233. data/lib/graphql/static_validation/rules/fields_will_merge.rb +107 -57
  234. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  235. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  236. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  237. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  238. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  239. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid.rb +66 -0
  240. data/lib/graphql/static_validation/rules/one_of_input_objects_are_valid_error.rb +29 -0
  241. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  242. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  243. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +6 -4
  244. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +22 -10
  245. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +13 -7
  246. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  247. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  248. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  249. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  250. data/lib/graphql/static_validation/validation_context.rb +17 -7
  251. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  252. data/lib/graphql/static_validation/validator.rb +32 -20
  253. data/lib/graphql/static_validation.rb +1 -3
  254. data/lib/graphql/string_encoding_error.rb +13 -3
  255. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +134 -24
  256. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  257. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +58 -0
  258. data/lib/graphql/subscriptions/event.rb +90 -27
  259. data/lib/graphql/subscriptions/instrumentation.rb +0 -47
  260. data/lib/graphql/subscriptions/serialize.rb +53 -6
  261. data/lib/graphql/subscriptions.rb +147 -62
  262. data/lib/graphql/tracing/active_support_notifications_trace.rb +16 -0
  263. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  264. data/lib/graphql/tracing/appoptics_trace.rb +251 -0
  265. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  266. data/lib/graphql/tracing/appsignal_trace.rb +77 -0
  267. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  268. data/lib/graphql/tracing/data_dog_trace.rb +196 -0
  269. data/lib/graphql/tracing/data_dog_tracing.rb +53 -2
  270. data/lib/graphql/tracing/legacy_trace.rb +69 -0
  271. data/lib/graphql/tracing/new_relic_trace.rb +75 -0
  272. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  273. data/lib/graphql/tracing/notifications_trace.rb +45 -0
  274. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  275. data/lib/graphql/tracing/platform_trace.rb +118 -0
  276. data/lib/graphql/tracing/platform_tracing.rb +77 -31
  277. data/lib/graphql/tracing/prometheus_trace.rb +89 -0
  278. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +5 -2
  279. data/lib/graphql/tracing/prometheus_tracing.rb +11 -3
  280. data/lib/graphql/tracing/scout_trace.rb +72 -0
  281. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  282. data/lib/graphql/tracing/statsd_trace.rb +56 -0
  283. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  284. data/lib/graphql/tracing/trace.rb +75 -0
  285. data/lib/graphql/tracing.rb +24 -67
  286. data/lib/graphql/type_kinds.rb +6 -3
  287. data/lib/graphql/types/big_int.rb +23 -0
  288. data/lib/graphql/types/int.rb +11 -3
  289. data/lib/graphql/types/iso_8601_date.rb +45 -0
  290. data/lib/graphql/types/iso_8601_date_time.rb +36 -8
  291. data/lib/graphql/types/json.rb +25 -0
  292. data/lib/graphql/types/relay/base_connection.rb +18 -90
  293. data/lib/graphql/types/relay/base_edge.rb +2 -36
  294. data/lib/graphql/types/relay/connection_behaviors.rb +193 -0
  295. data/lib/graphql/types/relay/edge_behaviors.rb +82 -0
  296. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  297. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  298. data/lib/graphql/types/relay/node.rb +2 -4
  299. data/lib/graphql/types/relay/node_behaviors.rb +25 -0
  300. data/lib/graphql/types/relay/page_info.rb +2 -14
  301. data/lib/graphql/types/relay/page_info_behaviors.rb +30 -0
  302. data/lib/graphql/types/relay.rb +10 -5
  303. data/lib/graphql/types/string.rb +8 -2
  304. data/lib/graphql/types.rb +3 -0
  305. data/lib/graphql/unauthorized_error.rb +3 -3
  306. data/lib/graphql/unauthorized_field_error.rb +1 -1
  307. data/lib/graphql/unresolved_type_error.rb +2 -2
  308. data/lib/graphql/version.rb +1 -1
  309. data/lib/graphql.rb +68 -54
  310. data/readme.md +4 -7
  311. metadata +150 -822
  312. data/lib/graphql/analysis/analyze_query.rb +0 -91
  313. data/lib/graphql/analysis/field_usage.rb +0 -45
  314. data/lib/graphql/analysis/max_query_complexity.rb +0 -26
  315. data/lib/graphql/analysis/max_query_depth.rb +0 -26
  316. data/lib/graphql/analysis/query_complexity.rb +0 -88
  317. data/lib/graphql/analysis/query_depth.rb +0 -56
  318. data/lib/graphql/analysis/reducer_state.rb +0 -48
  319. data/lib/graphql/argument.rb +0 -153
  320. data/lib/graphql/authorization.rb +0 -82
  321. data/lib/graphql/backwards_compatibility.rb +0 -60
  322. data/lib/graphql/base_type.rb +0 -226
  323. data/lib/graphql/boolean_type.rb +0 -2
  324. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +0 -53
  325. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +0 -200
  326. data/lib/graphql/compatibility/execution_specification.rb +0 -435
  327. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +0 -111
  328. data/lib/graphql/compatibility/lazy_execution_specification.rb +0 -213
  329. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -91
  330. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +0 -79
  331. data/lib/graphql/compatibility/query_parser_specification.rb +0 -264
  332. data/lib/graphql/compatibility/schema_parser_specification.rb +0 -680
  333. data/lib/graphql/compatibility.rb +0 -5
  334. data/lib/graphql/define/assign_argument.rb +0 -12
  335. data/lib/graphql/define/assign_connection.rb +0 -13
  336. data/lib/graphql/define/assign_enum_value.rb +0 -18
  337. data/lib/graphql/define/assign_global_id_field.rb +0 -11
  338. data/lib/graphql/define/assign_mutation_function.rb +0 -34
  339. data/lib/graphql/define/assign_object_field.rb +0 -42
  340. data/lib/graphql/define/defined_object_proxy.rb +0 -50
  341. data/lib/graphql/define/instance_definable.rb +0 -300
  342. data/lib/graphql/define/no_definition_error.rb +0 -7
  343. data/lib/graphql/define/non_null_with_bang.rb +0 -16
  344. data/lib/graphql/define/type_definer.rb +0 -31
  345. data/lib/graphql/define.rb +0 -31
  346. data/lib/graphql/deprecated_dsl.rb +0 -42
  347. data/lib/graphql/directive/deprecated_directive.rb +0 -13
  348. data/lib/graphql/directive/include_directive.rb +0 -2
  349. data/lib/graphql/directive/skip_directive.rb +0 -2
  350. data/lib/graphql/directive.rb +0 -104
  351. data/lib/graphql/enum_type.rb +0 -193
  352. data/lib/graphql/execution/execute.rb +0 -319
  353. data/lib/graphql/execution/flatten.rb +0 -40
  354. data/lib/graphql/execution/instrumentation.rb +0 -92
  355. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  356. data/lib/graphql/execution/lazy/resolve.rb +0 -91
  357. data/lib/graphql/execution/typecast.rb +0 -50
  358. data/lib/graphql/field/resolve.rb +0 -59
  359. data/lib/graphql/field.rb +0 -330
  360. data/lib/graphql/filter.rb +0 -53
  361. data/lib/graphql/float_type.rb +0 -2
  362. data/lib/graphql/function.rb +0 -153
  363. data/lib/graphql/id_type.rb +0 -2
  364. data/lib/graphql/input_object_type.rb +0 -153
  365. data/lib/graphql/int_type.rb +0 -2
  366. data/lib/graphql/interface_type.rb +0 -86
  367. data/lib/graphql/internal_representation/document.rb +0 -27
  368. data/lib/graphql/internal_representation/node.rb +0 -206
  369. data/lib/graphql/internal_representation/print.rb +0 -51
  370. data/lib/graphql/internal_representation/rewrite.rb +0 -184
  371. data/lib/graphql/internal_representation/scope.rb +0 -88
  372. data/lib/graphql/internal_representation/visit.rb +0 -36
  373. data/lib/graphql/internal_representation.rb +0 -7
  374. data/lib/graphql/language/lexer.rl +0 -236
  375. data/lib/graphql/list_type.rb +0 -80
  376. data/lib/graphql/literal_validation_error.rb +0 -6
  377. data/lib/graphql/non_null_type.rb +0 -81
  378. data/lib/graphql/object_type.rb +0 -141
  379. data/lib/graphql/query/arguments.rb +0 -179
  380. data/lib/graphql/query/arguments_cache.rb +0 -25
  381. data/lib/graphql/query/executor.rb +0 -53
  382. data/lib/graphql/query/literal_input.rb +0 -115
  383. data/lib/graphql/query/serial_execution/field_resolution.rb +0 -92
  384. data/lib/graphql/query/serial_execution/operation_resolution.rb +0 -19
  385. data/lib/graphql/query/serial_execution/selection_resolution.rb +0 -23
  386. data/lib/graphql/query/serial_execution/value_resolution.rb +0 -87
  387. data/lib/graphql/query/serial_execution.rb +0 -39
  388. data/lib/graphql/relay/array_connection.rb +0 -85
  389. data/lib/graphql/relay/base_connection.rb +0 -172
  390. data/lib/graphql/relay/connection_instrumentation.rb +0 -54
  391. data/lib/graphql/relay/connection_resolve.rb +0 -43
  392. data/lib/graphql/relay/connection_type.rb +0 -40
  393. data/lib/graphql/relay/edge.rb +0 -27
  394. data/lib/graphql/relay/edge_type.rb +0 -18
  395. data/lib/graphql/relay/edges_instrumentation.rb +0 -40
  396. data/lib/graphql/relay/global_id_resolve.rb +0 -18
  397. data/lib/graphql/relay/mongo_relation_connection.rb +0 -50
  398. data/lib/graphql/relay/mutation/instrumentation.rb +0 -23
  399. data/lib/graphql/relay/mutation/resolve.rb +0 -56
  400. data/lib/graphql/relay/mutation/result.rb +0 -38
  401. data/lib/graphql/relay/mutation.rb +0 -190
  402. data/lib/graphql/relay/node.rb +0 -36
  403. data/lib/graphql/relay/page_info.rb +0 -7
  404. data/lib/graphql/relay/relation_connection.rb +0 -186
  405. data/lib/graphql/relay/type_extensions.rb +0 -30
  406. data/lib/graphql/scalar_type.rb +0 -135
  407. data/lib/graphql/schema/catchall_middleware.rb +0 -35
  408. data/lib/graphql/schema/default_parse_error.rb +0 -10
  409. data/lib/graphql/schema/default_type_error.rb +0 -15
  410. data/lib/graphql/schema/member/accepts_definition.rb +0 -152
  411. data/lib/graphql/schema/member/cached_graphql_definition.rb +0 -26
  412. data/lib/graphql/schema/member/instrumentation.rb +0 -121
  413. data/lib/graphql/schema/middleware_chain.rb +0 -82
  414. data/lib/graphql/schema/possible_types.rb +0 -39
  415. data/lib/graphql/schema/rescue_middleware.rb +0 -55
  416. data/lib/graphql/schema/timeout_middleware.rb +0 -85
  417. data/lib/graphql/schema/traversal.rb +0 -228
  418. data/lib/graphql/schema/validation.rb +0 -286
  419. data/lib/graphql/static_validation/default_visitor.rb +0 -15
  420. data/lib/graphql/static_validation/no_validate_visitor.rb +0 -10
  421. data/lib/graphql/static_validation/type_stack.rb +0 -216
  422. data/lib/graphql/string_type.rb +0 -2
  423. data/lib/graphql/subscriptions/subscription_root.rb +0 -66
  424. data/lib/graphql/tracing/skylight_tracing.rb +0 -61
  425. data/lib/graphql/types/relay/base_field.rb +0 -22
  426. data/lib/graphql/types/relay/base_interface.rb +0 -29
  427. data/lib/graphql/types/relay/base_object.rb +0 -26
  428. data/lib/graphql/types/relay/node_field.rb +0 -43
  429. data/lib/graphql/types/relay/nodes_field.rb +0 -45
  430. data/lib/graphql/union_type.rb +0 -100
  431. data/lib/graphql/upgrader/member.rb +0 -899
  432. data/lib/graphql/upgrader/schema.rb +0 -37
  433. data/spec/dummy/Gemfile +0 -12
  434. data/spec/dummy/Gemfile.lock +0 -157
  435. data/spec/dummy/README.md +0 -24
  436. data/spec/dummy/Rakefile +0 -7
  437. data/spec/dummy/app/assets/config/manifest.js +0 -1
  438. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  439. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  440. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  441. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  442. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  443. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  444. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  445. data/spec/dummy/app/jobs/application_job.rb +0 -3
  446. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  447. data/spec/dummy/app/views/pages/show.html +0 -16
  448. data/spec/dummy/bin/bundle +0 -4
  449. data/spec/dummy/bin/rails +0 -5
  450. data/spec/dummy/bin/rake +0 -5
  451. data/spec/dummy/bin/setup +0 -31
  452. data/spec/dummy/bin/update +0 -27
  453. data/spec/dummy/bin/yarn +0 -12
  454. data/spec/dummy/config/application.rb +0 -30
  455. data/spec/dummy/config/boot.rb +0 -4
  456. data/spec/dummy/config/cable.yml +0 -10
  457. data/spec/dummy/config/environment.rb +0 -6
  458. data/spec/dummy/config/environments/development.rb +0 -40
  459. data/spec/dummy/config/environments/production.rb +0 -76
  460. data/spec/dummy/config/environments/test.rb +0 -37
  461. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  462. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  463. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  464. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  465. data/spec/dummy/config/initializers/inflections.rb +0 -17
  466. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  467. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  468. data/spec/dummy/config/locales/en.yml +0 -33
  469. data/spec/dummy/config/puma.rb +0 -57
  470. data/spec/dummy/config/routes.rb +0 -4
  471. data/spec/dummy/config/secrets.yml +0 -32
  472. data/spec/dummy/config.ru +0 -6
  473. data/spec/dummy/log/test.log +0 -199
  474. data/spec/dummy/package.json +0 -5
  475. data/spec/dummy/public/404.html +0 -67
  476. data/spec/dummy/public/422.html +0 -67
  477. data/spec/dummy/public/500.html +0 -66
  478. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  479. data/spec/dummy/public/apple-touch-icon.png +0 -0
  480. data/spec/dummy/public/favicon.ico +0 -0
  481. data/spec/dummy/public/robots.txt +0 -1
  482. data/spec/dummy/test/application_system_test_case.rb +0 -6
  483. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  484. data/spec/dummy/test/test_helper.rb +0 -4
  485. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  486. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  487. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  488. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  489. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  490. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  491. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  492. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  493. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  494. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  495. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  496. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  497. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  498. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  499. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  500. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  501. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  502. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  503. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  504. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  505. data/spec/fixtures/upgrader/account.original.rb +0 -19
  506. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  507. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  508. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  509. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  510. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  511. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  512. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  513. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  514. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  515. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  516. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  517. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  518. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  519. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  520. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  521. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  522. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  523. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  524. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  525. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  526. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  527. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  528. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  529. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  530. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  531. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  532. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  533. data/spec/graphql/analysis/ast_spec.rb +0 -269
  534. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  535. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  536. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  537. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  538. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  539. data/spec/graphql/argument_spec.rb +0 -159
  540. data/spec/graphql/authorization_spec.rb +0 -901
  541. data/spec/graphql/backtrace_spec.rb +0 -206
  542. data/spec/graphql/base_type_spec.rb +0 -171
  543. data/spec/graphql/boolean_type_spec.rb +0 -21
  544. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  545. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  546. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  547. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  548. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  549. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  550. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  551. data/spec/graphql/directive_spec.rb +0 -295
  552. data/spec/graphql/enum_type_spec.rb +0 -158
  553. data/spec/graphql/execution/execute_spec.rb +0 -303
  554. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  555. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  556. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  557. data/spec/graphql/execution/lazy_spec.rb +0 -240
  558. data/spec/graphql/execution/lookahead_spec.rb +0 -363
  559. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  560. data/spec/graphql/execution/typecast_spec.rb +0 -47
  561. data/spec/graphql/execution_error_spec.rb +0 -325
  562. data/spec/graphql/field_spec.rb +0 -246
  563. data/spec/graphql/float_type_spec.rb +0 -16
  564. data/spec/graphql/function_spec.rb +0 -129
  565. data/spec/graphql/id_type_spec.rb +0 -33
  566. data/spec/graphql/input_object_type_spec.rb +0 -25
  567. data/spec/graphql/int_type_spec.rb +0 -35
  568. data/spec/graphql/interface_type_spec.rb +0 -196
  569. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  570. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  571. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  572. data/spec/graphql/introspection/input_value_type_spec.rb +0 -105
  573. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  574. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  575. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  576. data/spec/graphql/language/block_string_spec.rb +0 -70
  577. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  578. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  579. data/spec/graphql/language/equality_spec.rb +0 -84
  580. data/spec/graphql/language/generation_spec.rb +0 -38
  581. data/spec/graphql/language/lexer_spec.rb +0 -135
  582. data/spec/graphql/language/nodes_spec.rb +0 -67
  583. data/spec/graphql/language/parser_spec.rb +0 -175
  584. data/spec/graphql/language/printer_spec.rb +0 -215
  585. data/spec/graphql/language/visitor_spec.rb +0 -400
  586. data/spec/graphql/list_type_spec.rb +0 -57
  587. data/spec/graphql/non_null_type_spec.rb +0 -48
  588. data/spec/graphql/object_type_spec.rb +0 -197
  589. data/spec/graphql/query/arguments_spec.rb +0 -346
  590. data/spec/graphql/query/context_spec.rb +0 -292
  591. data/spec/graphql/query/executor_spec.rb +0 -314
  592. data/spec/graphql/query/literal_input_spec.rb +0 -91
  593. data/spec/graphql/query/result_spec.rb +0 -29
  594. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  595. data/spec/graphql/query_spec.rb +0 -800
  596. data/spec/graphql/rake_task_spec.rb +0 -59
  597. data/spec/graphql/scalar_type_spec.rb +0 -66
  598. data/spec/graphql/schema/argument_spec.rb +0 -127
  599. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  600. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  601. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  602. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  603. data/spec/graphql/schema/enum_spec.rb +0 -83
  604. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  605. data/spec/graphql/schema/field_extension_spec.rb +0 -115
  606. data/spec/graphql/schema/field_spec.rb +0 -301
  607. data/spec/graphql/schema/finder_spec.rb +0 -135
  608. data/spec/graphql/schema/input_object_spec.rb +0 -238
  609. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  610. data/spec/graphql/schema/interface_spec.rb +0 -215
  611. data/spec/graphql/schema/introspection_system_spec.rb +0 -47
  612. data/spec/graphql/schema/list_spec.rb +0 -46
  613. data/spec/graphql/schema/loader_spec.rb +0 -286
  614. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  615. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  616. data/spec/graphql/schema/member/scoped_spec.rb +0 -177
  617. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  618. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  619. data/spec/graphql/schema/mutation_spec.rb +0 -150
  620. data/spec/graphql/schema/non_null_spec.rb +0 -46
  621. data/spec/graphql/schema/object_spec.rb +0 -244
  622. data/spec/graphql/schema/printer_spec.rb +0 -869
  623. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -234
  624. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -74
  625. data/spec/graphql/schema/resolver_spec.rb +0 -640
  626. data/spec/graphql/schema/scalar_spec.rb +0 -101
  627. data/spec/graphql/schema/subscription_spec.rb +0 -416
  628. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  629. data/spec/graphql/schema/traversal_spec.rb +0 -222
  630. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  631. data/spec/graphql/schema/union_spec.rb +0 -72
  632. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  633. data/spec/graphql/schema/validation_spec.rb +0 -355
  634. data/spec/graphql/schema/warden_spec.rb +0 -926
  635. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  636. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  637. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  638. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  639. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  640. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  641. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  642. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  643. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  644. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  645. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  646. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  647. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  648. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  649. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  650. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  651. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  652. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  653. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  654. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -58
  655. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  656. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  657. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  658. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  659. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  660. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  661. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  662. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  663. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  664. data/spec/graphql/string_type_spec.rb +0 -80
  665. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  666. data/spec/graphql/subscriptions_spec.rb +0 -502
  667. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -63
  668. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -137
  669. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  670. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  671. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  672. data/spec/graphql/tracing_spec.rb +0 -52
  673. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  674. data/spec/graphql/union_type_spec.rb +0 -211
  675. data/spec/graphql/upgrader/member_spec.rb +0 -583
  676. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  677. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  678. data/spec/integration/mongoid/spec_helper.rb +0 -2
  679. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  680. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  681. data/spec/integration/rails/data.rb +0 -110
  682. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  683. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  684. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  685. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  686. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  687. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  688. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  689. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  690. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  691. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  692. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  693. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  694. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  695. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  696. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  697. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  698. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  699. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  700. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  701. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  702. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  703. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  704. data/spec/integration/rails/graphql/schema_spec.rb +0 -476
  705. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  706. data/spec/integration/rails/spec_helper.rb +0 -25
  707. data/spec/integration/tmp/app/graphql/types/family_type.rb +0 -9
  708. data/spec/spec_helper.rb +0 -116
  709. data/spec/support/dummy/data.rb +0 -45
  710. data/spec/support/dummy/schema.rb +0 -492
  711. data/spec/support/error_bubbling_helpers.rb +0 -23
  712. data/spec/support/global_id.rb +0 -23
  713. data/spec/support/jazz.rb +0 -759
  714. data/spec/support/lazy_helpers.rb +0 -192
  715. data/spec/support/magic_cards/schema.graphql +0 -33
  716. data/spec/support/minimum_input_object.rb +0 -21
  717. data/spec/support/new_relic.rb +0 -27
  718. data/spec/support/parser/filename_example.graphql +0 -5
  719. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  720. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  721. data/spec/support/skylight.rb +0 -39
  722. data/spec/support/star_wars/schema.rb +0 -465
  723. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require "graphql/execution/interpreter/runtime/graphql_result"
2
3
 
3
4
  module GraphQL
4
5
  module Execution
@@ -8,61 +9,156 @@ module GraphQL
8
9
  #
9
10
  # @api private
10
11
  class Runtime
12
+ class CurrentState
13
+ def initialize
14
+ @current_object = nil
15
+ @current_field = nil
16
+ @current_arguments = nil
17
+ @current_result_name = nil
18
+ @current_result = nil
19
+ @was_authorized_by_scope_items = nil
20
+ end
21
+
22
+ attr_accessor :current_result, :current_result_name,
23
+ :current_arguments, :current_field, :current_object, :was_authorized_by_scope_items
24
+ end
25
+
11
26
  # @return [GraphQL::Query]
12
27
  attr_reader :query
13
28
 
14
- # @return [Class]
29
+ # @return [Class<GraphQL::Schema>]
15
30
  attr_reader :schema
16
31
 
17
32
  # @return [GraphQL::Query::Context]
18
33
  attr_reader :context
19
34
 
20
- def initialize(query:, response:)
35
+ def initialize(query:, lazies_at_depth:)
21
36
  @query = query
37
+ @current_trace = query.current_trace
38
+ @dataloader = query.multiplex.dataloader
39
+ @lazies_at_depth = lazies_at_depth
22
40
  @schema = query.schema
23
41
  @context = query.context
24
- @interpreter_context = @context.namespace(:interpreter)
25
- @response = response
26
- @dead_paths = {}
27
- @types_at_paths = {}
28
- # A cache of { Class => { String => Schema::Field } }
29
- # Which assumes that MyObject.get_field("myField") will return the same field
30
- # during the lifetime of a query
31
- @fields_cache = Hash.new { |h, k| h[k] = {} }
42
+ @response = GraphQLResultHash.new(nil, nil, false)
43
+ # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
44
+ @runtime_directive_names = []
45
+ noop_resolve_owner = GraphQL::Schema::Directive.singleton_class
46
+ @schema_directives = schema.directives
47
+ @schema_directives.each do |name, dir_defn|
48
+ if dir_defn.method(:resolve).owner != noop_resolve_owner
49
+ @runtime_directive_names << name
50
+ end
51
+ end
52
+ # { Class => Boolean }
53
+ @lazy_cache = {}
54
+ @lazy_cache.compare_by_identity
55
+
56
+ @gathered_selections_cache = Hash.new { |h, k|
57
+ cache = {}
58
+ cache.compare_by_identity
59
+ h[k] = cache
60
+ }
61
+ @gathered_selections_cache.compare_by_identity
32
62
  end
33
63
 
34
- def final_value
35
- @response.final_value
64
+ def final_result
65
+ @response && @response.graphql_result_data
36
66
  end
37
67
 
38
68
  def inspect
39
69
  "#<#{self.class.name} response=#{@response.inspect}>"
40
70
  end
41
71
 
72
+ def tap_or_each(obj_or_array)
73
+ if obj_or_array.is_a?(Array)
74
+ obj_or_array.each do |item|
75
+ yield(item, true)
76
+ end
77
+ else
78
+ yield(obj_or_array, false)
79
+ end
80
+ end
81
+
42
82
  # This _begins_ the execution. Some deferred work
43
83
  # might be stored up in lazies.
44
84
  # @return [void]
45
85
  def run_eager
46
86
  root_operation = query.selected_operation
47
87
  root_op_type = root_operation.operation_type || "query"
48
- legacy_root_type = schema.root_type_for_operation(root_op_type)
49
- root_type = legacy_root_type.metadata[:type_class] || raise("Invariant: type must be class-based: #{legacy_root_type}")
50
- object_proxy = root_type.authorized_new(query.root_value, context)
51
- object_proxy = schema.sync_lazy(object_proxy)
52
- path = []
53
- evaluate_selections(path, object_proxy, root_type, root_operation.selections, root_operation_type: root_op_type)
88
+ root_type = schema.root_type_for_operation(root_op_type)
89
+
90
+ st = get_current_runtime_state
91
+ st.current_object = query.root_value
92
+ st.current_result = @response
93
+ runtime_object = root_type.wrap(query.root_value, context)
94
+ runtime_object = schema.sync_lazy(runtime_object)
95
+
96
+ if runtime_object.nil?
97
+ # Root .authorized? returned false.
98
+ @response = nil
99
+ else
100
+ call_method_on_directives(:resolve, runtime_object, root_operation.directives) do # execute query level directives
101
+ gathered_selections = gather_selections(runtime_object, root_type, nil, root_operation.selections)
102
+ # This is kind of a hack -- `gathered_selections` is an Array if any of the selections
103
+ # require isolation during execution (because of runtime directives). In that case,
104
+ # make a new, isolated result hash for writing the result into. (That isolated response
105
+ # is eventually merged back into the main response)
106
+ #
107
+ # Otherwise, `gathered_selections` is a hash of selections which can be
108
+ # directly evaluated and the results can be written right into the main response hash.
109
+ tap_or_each(gathered_selections) do |selections, is_selection_array|
110
+ if is_selection_array
111
+ selection_response = GraphQLResultHash.new(nil, nil, false)
112
+ final_response = @response
113
+ else
114
+ selection_response = @response
115
+ final_response = nil
116
+ end
117
+
118
+ @dataloader.append_job {
119
+ st = get_current_runtime_state
120
+ st.current_object = query.root_value
121
+ st.current_result_name = nil
122
+ st.current_result = selection_response
123
+ # This is a less-frequent case; use a fast check since it's often not there.
124
+ if (directives = selections[:graphql_directives])
125
+ selections.delete(:graphql_directives)
126
+ end
127
+ call_method_on_directives(:resolve, runtime_object, directives) do
128
+ evaluate_selections(
129
+ runtime_object,
130
+ root_type,
131
+ root_op_type == "mutation",
132
+ selections,
133
+ selection_response,
134
+ final_response,
135
+ nil,
136
+ st,
137
+ )
138
+ end
139
+ }
140
+ end
141
+ end
142
+ end
54
143
  nil
55
144
  end
56
145
 
57
- def gather_selections(owner_object, owner_type, selections, selections_by_name)
146
+ def gather_selections(owner_object, owner_type, ast_node_for_caching, selections, selections_to_run = nil, selections_by_name = nil)
147
+ if ast_node_for_caching && (cached_selections = @gathered_selections_cache[ast_node_for_caching][owner_type])
148
+ return cached_selections
149
+ end
150
+ selections_by_name ||= {} # allocate this default here so we check the cache first
151
+
152
+ should_cache = true
153
+
58
154
  selections.each do |node|
59
155
  # Skip gathering this if the directive says so
60
156
  if !directives_include?(node, owner_object, owner_type)
157
+ should_cache = false
61
158
  next
62
159
  end
63
160
 
64
- case node
65
- when GraphQL::Language::Nodes::Field
161
+ if node.is_a?(GraphQL::Language::Nodes::Field)
66
162
  response_key = node.alias || node.name
67
163
  selections = selections_by_name[response_key]
68
164
  # if there was already a selection of this field,
@@ -78,177 +174,388 @@ module GraphQL
78
174
  # No selection was found for this field yet
79
175
  selections_by_name[response_key] = node
80
176
  end
81
- when GraphQL::Language::Nodes::InlineFragment
82
- if node.type
83
- type_defn = schema.types[node.type.name]
84
- type_defn = type_defn.metadata[:type_class]
85
- # Faster than .map{}.include?()
86
- query.warden.possible_types(type_defn).each do |t|
87
- if t.metadata[:type_class] == owner_type
88
- gather_selections(owner_object, owner_type, node.selections, selections_by_name)
89
- break
90
- end
177
+ else
178
+ # This is an InlineFragment or a FragmentSpread
179
+ if @runtime_directive_names.any? && node.directives.any? { |d| @runtime_directive_names.include?(d.name) }
180
+ next_selections = {}
181
+ next_selections[:graphql_directives] = node.directives
182
+ should_cache = false
183
+ if selections_to_run
184
+ selections_to_run << next_selections
185
+ else
186
+ selections_to_run = []
187
+ selections_to_run << selections_by_name
188
+ selections_to_run << next_selections
91
189
  end
92
190
  else
93
- # it's an untyped fragment, definitely continue
94
- gather_selections(owner_object, owner_type, node.selections, selections_by_name)
191
+ next_selections = selections_by_name
95
192
  end
96
- when GraphQL::Language::Nodes::FragmentSpread
97
- fragment_def = query.fragments[node.name]
98
- type_defn = schema.types[fragment_def.type.name]
99
- type_defn = type_defn.metadata[:type_class]
100
- schema.possible_types(type_defn).each do |t|
101
- if t.metadata[:type_class] == owner_type
102
- gather_selections(owner_object, owner_type, fragment_def.selections, selections_by_name)
103
- break
193
+
194
+ case node
195
+ when GraphQL::Language::Nodes::InlineFragment
196
+ if node.type
197
+ type_defn = schema.get_type(node.type.name, context)
198
+
199
+ if query.warden.possible_types(type_defn).include?(owner_type)
200
+ gather_selections(owner_object, owner_type, nil, node.selections, selections_to_run, next_selections)
201
+ end
202
+ else
203
+ # it's an untyped fragment, definitely continue
204
+ gather_selections(owner_object, owner_type, nil, node.selections, selections_to_run, next_selections)
104
205
  end
206
+ when GraphQL::Language::Nodes::FragmentSpread
207
+ fragment_def = query.fragments[node.name]
208
+ type_defn = query.get_type(fragment_def.type.name)
209
+ if query.warden.possible_types(type_defn).include?(owner_type)
210
+ gather_selections(owner_object, owner_type, nil, fragment_def.selections, selections_to_run, next_selections)
211
+ end
212
+ else
213
+ raise "Invariant: unexpected selection class: #{node.class}"
105
214
  end
106
- else
107
- raise "Invariant: unexpected selection class: #{node.class}"
108
215
  end
109
216
  end
217
+ result = selections_to_run || selections_by_name
218
+ if should_cache
219
+ @gathered_selections_cache[ast_node_for_caching][owner_type] = result
220
+ end
221
+ result
110
222
  end
111
223
 
112
- def evaluate_selections(path, owner_object, owner_type, selections, root_operation_type: nil)
113
- selections_by_name = {}
114
- gather_selections(owner_object, owner_type, selections, selections_by_name)
115
- selections_by_name.each do |result_name, field_ast_nodes_or_ast_node|
116
- # As a performance optimization, the hash key will be a `Node` if
117
- # there's only one selection of the field. But if there are multiple
118
- # selections of the field, it will be an Array of nodes
119
- if field_ast_nodes_or_ast_node.is_a?(Array)
120
- field_ast_nodes = field_ast_nodes_or_ast_node
121
- ast_node = field_ast_nodes.first
122
- else
123
- field_ast_nodes = nil
124
- ast_node = field_ast_nodes_or_ast_node
125
- end
126
- field_name = ast_node.name
127
- field_defn = @fields_cache[owner_type][field_name] ||= owner_type.get_field(field_name)
128
- is_introspection = false
129
- if field_defn.nil?
130
- field_defn = if owner_type == schema.query.metadata[:type_class] && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
131
- is_introspection = true
132
- entry_point_field.metadata[:type_class]
133
- elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
134
- is_introspection = true
135
- dynamic_field.metadata[:type_class]
136
- else
137
- raise "Invariant: no field for #{owner_type}.#{field_name}"
224
+ NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
225
+
226
+ # @return [void]
227
+ def evaluate_selections(owner_object, owner_type, is_eager_selection, gathered_selections, selections_result, target_result, parent_object, runtime_state) # rubocop:disable Metrics/ParameterLists
228
+ finished_jobs = 0
229
+ enqueued_jobs = gathered_selections.size
230
+ gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
231
+ @dataloader.append_job {
232
+ runtime_state = get_current_runtime_state
233
+ evaluate_selection(
234
+ result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_selection, selections_result, parent_object, runtime_state
235
+ )
236
+ finished_jobs += 1
237
+ if target_result && finished_jobs == enqueued_jobs
238
+ selections_result.merge_into(target_result)
138
239
  end
240
+ }
241
+ # Field resolution may pause the fiber,
242
+ # so it wouldn't get to the `Resolve` call that happens below.
243
+ # So instead trigger a run from this outer context.
244
+ if is_eager_selection
245
+ @dataloader.clear_cache
246
+ @dataloader.run
247
+ @dataloader.clear_cache
139
248
  end
249
+ end
140
250
 
141
- return_type = resolve_if_late_bound_type(field_defn.type)
251
+ selections_result
252
+ end
142
253
 
143
- next_path = path.dup
144
- next_path << result_name
145
- next_path.freeze
254
+ # @return [void]
255
+ def evaluate_selection(result_name, field_ast_nodes_or_ast_node, owner_object, owner_type, is_eager_field, selections_result, parent_object, runtime_state) # rubocop:disable Metrics/ParameterLists
256
+ return if dead_result?(selections_result)
257
+ # As a performance optimization, the hash key will be a `Node` if
258
+ # there's only one selection of the field. But if there are multiple
259
+ # selections of the field, it will be an Array of nodes
260
+ if field_ast_nodes_or_ast_node.is_a?(Array)
261
+ field_ast_nodes = field_ast_nodes_or_ast_node
262
+ ast_node = field_ast_nodes.first
263
+ else
264
+ field_ast_nodes = nil
265
+ ast_node = field_ast_nodes_or_ast_node
266
+ end
267
+ field_name = ast_node.name
268
+ field_defn = query.warden.get_field(owner_type, field_name)
146
269
 
147
- # This seems janky, but we need to know
148
- # the field's return type at this path in order
149
- # to propagate `null`
150
- set_type_at_path(next_path, return_type)
151
- # Set this before calling `run_with_directives`, so that the directive can have the latest path
152
- @interpreter_context[:current_path] = next_path
153
- @interpreter_context[:current_field] = field_defn
270
+ # Set this before calling `run_with_directives`, so that the directive can have the latest path
271
+ runtime_state.current_field = field_defn
272
+ runtime_state.current_result = selections_result
273
+ runtime_state.current_result_name = result_name
154
274
 
155
- object = owner_object
275
+ if field_defn.dynamic_introspection
276
+ owner_object = field_defn.owner.wrap(owner_object, context)
277
+ end
156
278
 
157
- if is_introspection
158
- object = field_defn.owner.authorized_new(object, context)
279
+ return_type = field_defn.type
280
+ if !field_defn.any_arguments?
281
+ resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
282
+ if field_defn.extras.size == 0
283
+ evaluate_selection_with_resolved_keyword_args(
284
+ NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, return_type.non_null?, runtime_state
285
+ )
286
+ else
287
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, runtime_state)
159
288
  end
289
+ else
290
+ @query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
291
+ runtime_state = get_current_runtime_state # This might be in a different fiber
292
+ evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, owner_object, is_eager_field, result_name, selections_result, parent_object, return_type, runtime_state)
293
+ end
294
+ end
295
+ end
160
296
 
297
+ 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, runtime_state) # rubocop:disable Metrics/ParameterLists
298
+ after_lazy(arguments, field: field_defn, ast_node: ast_node, owner_object: object, arguments: arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |resolved_arguments, runtime_state|
299
+ return_type_non_null = return_type.non_null?
300
+ if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
301
+ continue_value(resolved_arguments, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
302
+ next
303
+ end
161
304
 
162
- kwarg_arguments = arguments(object, field_defn, ast_node)
163
- # It might turn out that making arguments for every field is slow.
164
- # If we have to cache them, we'll need a more subtle approach here.
165
- field_defn.extras.each do |extra|
166
- case extra
167
- when :ast_node
168
- kwarg_arguments[:ast_node] = ast_node
169
- when :execution_errors
170
- kwarg_arguments[:execution_errors] = ExecutionErrors.new(context, ast_node, next_path)
171
- when :path
172
- kwarg_arguments[:path] = next_path
173
- when :lookahead
174
- if !field_ast_nodes
175
- field_ast_nodes = [ast_node]
176
- end
177
- kwarg_arguments[:lookahead] = Execution::Lookahead.new(
178
- query: query,
179
- ast_nodes: field_ast_nodes,
180
- field: field_defn,
181
- )
305
+ kwarg_arguments = if field_defn.extras.empty?
306
+ if resolved_arguments.empty?
307
+ # We can avoid allocating the `{ Symbol => Object }` hash in this case
308
+ NO_ARGS
182
309
  else
183
- kwarg_arguments[extra] = field_defn.fetch_extra(extra, context)
310
+ resolved_arguments.keyword_arguments
184
311
  end
185
- end
186
-
187
- # Optimize for the case that field is selected only once
188
- if field_ast_nodes.nil? || field_ast_nodes.size == 1
189
- next_selections = ast_node.selections
190
312
  else
191
- next_selections = []
192
- field_ast_nodes.each { |f| next_selections.concat(f.selections) }
313
+ # Bundle up the extras, then make a new arguments instance
314
+ # that includes the extras, too.
315
+ extra_args = {}
316
+ field_defn.extras.each do |extra|
317
+ case extra
318
+ when :ast_node
319
+ extra_args[:ast_node] = ast_node
320
+ when :execution_errors
321
+ extra_args[:execution_errors] = ExecutionErrors.new(context, ast_node, current_path)
322
+ when :path
323
+ extra_args[:path] = current_path
324
+ when :lookahead
325
+ if !field_ast_nodes
326
+ field_ast_nodes = [ast_node]
327
+ end
328
+
329
+ extra_args[:lookahead] = Execution::Lookahead.new(
330
+ query: query,
331
+ ast_nodes: field_ast_nodes,
332
+ field: field_defn,
333
+ )
334
+ when :argument_details
335
+ # Use this flag to tell Interpreter::Arguments to add itself
336
+ # to the keyword args hash _before_ freezing everything.
337
+ extra_args[:argument_details] = :__arguments_add_self
338
+ when :parent
339
+ extra_args[:parent] = parent_object
340
+ else
341
+ extra_args[extra] = field_defn.fetch_extra(extra, context)
342
+ end
343
+ end
344
+ if extra_args.any?
345
+ resolved_arguments = resolved_arguments.merge_extras(extra_args)
346
+ end
347
+ resolved_arguments.keyword_arguments
193
348
  end
194
349
 
195
- field_result = resolve_with_directives(object, ast_node) do
196
- # Actually call the field resolver and capture the result
197
- app_result = query.trace("execute_field", {field: field_defn, path: next_path}) do
350
+ evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state)
351
+ end
352
+ end
353
+
354
+ def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_type, object, is_eager_field, result_name, selection_result, parent_object, return_type, return_type_non_null, runtime_state) # rubocop:disable Metrics/ParameterLists
355
+ runtime_state.current_field = field_defn
356
+ runtime_state.current_object = object
357
+ runtime_state.current_arguments = resolved_arguments
358
+ runtime_state.current_result_name = result_name
359
+ runtime_state.current_result = selection_result
360
+ # Optimize for the case that field is selected only once
361
+ if field_ast_nodes.nil? || field_ast_nodes.size == 1
362
+ next_selections = ast_node.selections
363
+ directives = ast_node.directives
364
+ else
365
+ next_selections = []
366
+ directives = []
367
+ field_ast_nodes.each { |f|
368
+ next_selections.concat(f.selections)
369
+ directives.concat(f.directives)
370
+ }
371
+ end
372
+
373
+ field_result = call_method_on_directives(:resolve, object, directives) do
374
+ # Actually call the field resolver and capture the result
375
+ app_result = begin
376
+ @current_trace.execute_field(field: field_defn, ast_node: ast_node, query: query, object: object, arguments: kwarg_arguments) do
198
377
  field_defn.resolve(object, kwarg_arguments, context)
199
378
  end
200
- after_lazy(app_result, field: field_defn, path: next_path) do |inner_result|
201
- continue_value = continue_value(next_path, inner_result, field_defn, return_type.non_null?, ast_node)
202
- if HALT != continue_value
203
- continue_field(next_path, continue_value, field_defn, return_type, ast_node, next_selections, false)
204
- end
379
+ rescue GraphQL::ExecutionError => err
380
+ err
381
+ rescue StandardError => err
382
+ begin
383
+ query.handle_or_reraise(err)
384
+ rescue GraphQL::ExecutionError => ex_err
385
+ ex_err
386
+ end
387
+ end
388
+ after_lazy(app_result, field: field_defn, ast_node: ast_node, owner_object: object, arguments: resolved_arguments, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_result, runtime_state|
389
+ continue_value = continue_value(inner_result, owner_type, field_defn, return_type_non_null, ast_node, result_name, selection_result)
390
+ if HALT != continue_value
391
+ was_scoped = runtime_state.was_authorized_by_scope_items
392
+ runtime_state.was_authorized_by_scope_items = nil
393
+ continue_field(continue_value, owner_type, field_defn, return_type, ast_node, next_selections, false, object, resolved_arguments, result_name, selection_result, was_scoped, runtime_state)
205
394
  end
206
395
  end
396
+ end
397
+
398
+ # If this field is a root mutation field, immediately resolve
399
+ # all of its child fields before moving on to the next root mutation field.
400
+ # (Subselections of this mutation will still be resolved level-by-level.)
401
+ if is_eager_field
402
+ Interpreter::Resolve.resolve_all([field_result], @dataloader)
403
+ else
404
+ # Return this from `after_lazy` because it might be another lazy that needs to be resolved
405
+ field_result
406
+ end
407
+ end
408
+
409
+
410
+ def dead_result?(selection_result)
411
+ selection_result.graphql_dead # || ((parent = selection_result.graphql_parent) && parent.graphql_dead)
412
+ end
207
413
 
208
- # If this field is a root mutation field, immediately resolve
209
- # all of its child fields before moving on to the next root mutation field.
210
- # (Subselections of this mutation will still be resolved level-by-level.)
211
- if root_operation_type == "mutation"
212
- Interpreter::Resolve.resolve_all([field_result])
414
+ def set_result(selection_result, result_name, value, is_child_result, is_non_null)
415
+ if !dead_result?(selection_result)
416
+ if value.nil? && is_non_null
417
+ # This is an invalid nil that should be propagated
418
+ # One caller of this method passes a block,
419
+ # namely when application code returns a `nil` to GraphQL and it doesn't belong there.
420
+ # The other possibility for reaching here is when a field returns an ExecutionError, so we write
421
+ # `nil` to the response, not knowing whether it's an invalid `nil` or not.
422
+ # (And in that case, we don't have to call the schema's handler, since it's not a bug in the application.)
423
+ # TODO the code is trying to tell me something.
424
+ yield if block_given?
425
+ parent = selection_result.graphql_parent
426
+ if parent.nil? # This is a top-level result hash
427
+ @response = nil
428
+ else
429
+ name_in_parent = selection_result.graphql_result_name
430
+ is_non_null_in_parent = selection_result.graphql_is_non_null_in_parent
431
+ set_result(parent, name_in_parent, nil, false, is_non_null_in_parent)
432
+ set_graphql_dead(selection_result)
433
+ end
434
+ elsif is_child_result
435
+ selection_result.set_child_result(result_name, value)
213
436
  else
214
- field_result
437
+ selection_result.set_leaf(result_name, value)
215
438
  end
216
439
  end
217
440
  end
218
441
 
442
+ # Mark this node and any already-registered children as dead,
443
+ # so that it accepts no more writes.
444
+ def set_graphql_dead(selection_result)
445
+ case selection_result
446
+ when GraphQLResultArray
447
+ selection_result.graphql_dead = true
448
+ selection_result.values.each { |v| set_graphql_dead(v) }
449
+ when GraphQLResultHash
450
+ selection_result.graphql_dead = true
451
+ selection_result.each { |k, v| set_graphql_dead(v) }
452
+ else
453
+ # It's a scalar, no way to mark it dead.
454
+ end
455
+ end
456
+
457
+ def current_path
458
+ st = get_current_runtime_state
459
+ result = st.current_result
460
+ path = result && result.path
461
+ if path && (rn = st.current_result_name)
462
+ path = path.dup
463
+ path.push(rn)
464
+ end
465
+ path
466
+ end
467
+
219
468
  HALT = Object.new
220
- def continue_value(path, value, field, is_non_null, ast_node)
221
- if value.nil?
469
+ def continue_value(value, parent_type, field, is_non_null, ast_node, result_name, selection_result) # rubocop:disable Metrics/ParameterLists
470
+ case value
471
+ when nil
222
472
  if is_non_null
223
- err = GraphQL::InvalidNullError.new(field.owner, field, value)
224
- write_invalid_null_in_response(path, err)
473
+ set_result(selection_result, result_name, nil, false, is_non_null) do
474
+ # This block is called if `result_name` is not dead. (Maybe a previous invalid nil caused it be marked dead.)
475
+ err = parent_type::InvalidNullError.new(parent_type, field, value)
476
+ schema.type_error(err, context)
477
+ end
225
478
  else
226
- write_in_response(path, nil)
479
+ set_result(selection_result, result_name, nil, false, is_non_null)
227
480
  end
228
481
  HALT
229
- elsif value.is_a?(GraphQL::ExecutionError)
230
- value.path ||= path
231
- value.ast_node ||= ast_node
232
- write_execution_errors_in_response(path, [value])
233
- HALT
234
- elsif value.is_a?(Array) && value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
235
- value.each do |v|
236
- v.path ||= path
237
- v.ast_node ||= ast_node
482
+ when GraphQL::Error
483
+ # Handle these cases inside a single `when`
484
+ # to avoid the overhead of checking three different classes
485
+ # every time.
486
+ if value.is_a?(GraphQL::ExecutionError)
487
+ if selection_result.nil? || !dead_result?(selection_result)
488
+ value.path ||= current_path
489
+ value.ast_node ||= ast_node
490
+ context.errors << value
491
+ if selection_result
492
+ set_result(selection_result, result_name, nil, false, is_non_null)
493
+ end
494
+ end
495
+ HALT
496
+ elsif value.is_a?(GraphQL::UnauthorizedFieldError)
497
+ value.field ||= field
498
+ # this hook might raise & crash, or it might return
499
+ # a replacement value
500
+ next_value = begin
501
+ schema.unauthorized_field(value)
502
+ rescue GraphQL::ExecutionError => err
503
+ err
504
+ end
505
+ continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
506
+ elsif value.is_a?(GraphQL::UnauthorizedError)
507
+ # this hook might raise & crash, or it might return
508
+ # a replacement value
509
+ next_value = begin
510
+ schema.unauthorized_object(value)
511
+ rescue GraphQL::ExecutionError => err
512
+ err
513
+ end
514
+ continue_value(next_value, parent_type, field, is_non_null, ast_node, result_name, selection_result)
515
+ elsif GraphQL::Execution::SKIP == value
516
+ # It's possible a lazy was already written here
517
+ case selection_result
518
+ when GraphQLResultHash
519
+ selection_result.delete(result_name)
520
+ when GraphQLResultArray
521
+ selection_result.graphql_skip_at(result_name)
522
+ when nil
523
+ # this can happen with directives
524
+ else
525
+ raise "Invariant: unexpected result class #{selection_result.class} (#{selection_result.inspect})"
526
+ end
527
+ HALT
528
+ else
529
+ # What could this actually _be_? Anyhow,
530
+ # preserve the default behavior of doing nothing with it.
531
+ value
238
532
  end
239
- write_execution_errors_in_response(path, value)
240
- HALT
241
- elsif value.is_a?(GraphQL::UnauthorizedError)
242
- # this hook might raise & crash, or it might return
243
- # a replacement value
244
- next_value = begin
245
- schema.unauthorized_object(value)
246
- rescue GraphQL::ExecutionError => err
247
- err
533
+ when Array
534
+ # It's an array full of execution errors; add them all.
535
+ if value.any? && value.all? { |v| v.is_a?(GraphQL::ExecutionError) }
536
+ list_type_at_all = (field && (field.type.list?))
537
+ if selection_result.nil? || !dead_result?(selection_result)
538
+ value.each_with_index do |error, index|
539
+ error.ast_node ||= ast_node
540
+ error.path ||= current_path + (list_type_at_all ? [index] : [])
541
+ context.errors << error
542
+ end
543
+ if selection_result
544
+ if list_type_at_all
545
+ result_without_errors = value.map { |v| v.is_a?(GraphQL::ExecutionError) ? nil : v }
546
+ set_result(selection_result, result_name, result_without_errors, false, is_non_null)
547
+ else
548
+ set_result(selection_result, result_name, nil, false, is_non_null)
549
+ end
550
+ end
551
+ end
552
+ HALT
553
+ else
554
+ value
248
555
  end
249
-
250
- continue_value(path, next_value, field, is_non_null, ast_node)
251
- elsif GraphQL::Execution::Execute::SKIP == value
556
+ when GraphQL::Execution::Interpreter::RawValue
557
+ # Write raw value directly to the response without resolving nested objects
558
+ set_result(selection_result, result_name, value.resolve, false, is_non_null)
252
559
  HALT
253
560
  else
254
561
  value
@@ -263,92 +570,188 @@ module GraphQL
263
570
  # Location information from `path` and `ast_node`.
264
571
  #
265
572
  # @return [Lazy, Array, Hash, Object] Lazy, Array, and Hash are all traversed to resolve lazy values later
266
- def continue_field(path, value, field, type, ast_node, next_selections, is_non_null)
267
- case type.kind.name
573
+ def continue_field(value, owner_type, field, current_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result, was_scoped, runtime_state) # rubocop:disable Metrics/ParameterLists
574
+ if current_type.non_null?
575
+ current_type = current_type.of_type
576
+ is_non_null = true
577
+ end
578
+
579
+ case current_type.kind.name
268
580
  when "SCALAR", "ENUM"
269
- r = type.coerce_result(value, context)
270
- write_in_response(path, r)
581
+ r = begin
582
+ current_type.coerce_result(value, context)
583
+ rescue StandardError => err
584
+ schema.handle_or_reraise(context, err)
585
+ end
586
+ set_result(selection_result, result_name, r, false, is_non_null)
271
587
  r
272
588
  when "UNION", "INTERFACE"
273
- resolved_type_or_lazy = query.resolve_type(type, value)
274
- after_lazy(resolved_type_or_lazy, path: path, field: field) do |resolved_type|
275
- possible_types = query.possible_types(type)
589
+ resolved_type_or_lazy = resolve_type(current_type, value)
590
+ after_lazy(resolved_type_or_lazy, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |resolved_type_result, runtime_state|
591
+ if resolved_type_result.is_a?(Array) && resolved_type_result.length == 2
592
+ resolved_type, resolved_value = resolved_type_result
593
+ else
594
+ resolved_type = resolved_type_result
595
+ resolved_value = value
596
+ end
276
597
 
598
+ possible_types = query.possible_types(current_type)
277
599
  if !possible_types.include?(resolved_type)
278
- parent_type = field.owner
279
- type_error = GraphQL::UnresolvedTypeError.new(value, field, parent_type, resolved_type, possible_types)
600
+ parent_type = field.owner_type
601
+ err_class = current_type::UnresolvedTypeError
602
+ type_error = err_class.new(resolved_value, field, parent_type, resolved_type, possible_types)
280
603
  schema.type_error(type_error, context)
281
- write_in_response(path, nil)
604
+ set_result(selection_result, result_name, nil, false, is_non_null)
282
605
  nil
283
606
  else
284
- resolved_type = resolved_type.metadata[:type_class]
285
- continue_field(path, value, field, resolved_type, ast_node, next_selections, is_non_null)
607
+ continue_field(resolved_value, owner_type, field, resolved_type, ast_node, next_selections, is_non_null, owner_object, arguments, result_name, selection_result, was_scoped, runtime_state)
286
608
  end
287
609
  end
288
610
  when "OBJECT"
289
611
  object_proxy = begin
290
- type.authorized_new(value, context)
612
+ was_scoped ? current_type.wrap_scoped(value, context) : current_type.wrap(value, context)
291
613
  rescue GraphQL::ExecutionError => err
292
614
  err
293
615
  end
294
- after_lazy(object_proxy, path: path, field: field) do |inner_object|
295
- continue_value = continue_value(path, inner_object, field, is_non_null, ast_node)
616
+ after_lazy(object_proxy, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, trace: false, result_name: result_name, result: selection_result, runtime_state: runtime_state) do |inner_object, runtime_state|
617
+ continue_value = continue_value(inner_object, owner_type, field, is_non_null, ast_node, result_name, selection_result)
296
618
  if HALT != continue_value
297
- response_hash = {}
298
- write_in_response(path, response_hash)
299
- evaluate_selections(path, continue_value, type, next_selections)
300
- response_hash
619
+ response_hash = GraphQLResultHash.new(result_name, selection_result, is_non_null)
620
+ set_result(selection_result, result_name, response_hash, true, is_non_null)
621
+
622
+ gathered_selections = gather_selections(continue_value, current_type, ast_node, next_selections)
623
+ # There are two possibilities for `gathered_selections`:
624
+ # 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
625
+ # This case is handled below, and the result can be written right into the main `response_hash` above.
626
+ # In this case, `gathered_selections` is a hash of selections.
627
+ # 2. Some selections of this object have runtime directives that may or may not modify execution.
628
+ # That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
629
+ # eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
630
+ # (Technically, it's possible that one of those entries _doesn't_ require isolation.)
631
+ tap_or_each(gathered_selections) do |selections, is_selection_array|
632
+ if is_selection_array
633
+ this_result = GraphQLResultHash.new(result_name, selection_result, is_non_null)
634
+ final_result = response_hash
635
+ else
636
+ this_result = response_hash
637
+ final_result = nil
638
+ end
639
+ # reset this mutable state
640
+ # Unset `result_name` here because it's already included in the new response hash
641
+ runtime_state.current_object = continue_value
642
+ runtime_state.current_result_name = nil
643
+ runtime_state.current_result = this_result
644
+ # This is a less-frequent case; use a fast check since it's often not there.
645
+ if (directives = selections[:graphql_directives])
646
+ selections.delete(:graphql_directives)
647
+ end
648
+ call_method_on_directives(:resolve, continue_value, directives) do
649
+ evaluate_selections(
650
+ continue_value,
651
+ current_type,
652
+ false,
653
+ selections,
654
+ this_result,
655
+ final_result,
656
+ owner_object.object,
657
+ runtime_state,
658
+ )
659
+ this_result
660
+ end
661
+ end
301
662
  end
302
663
  end
303
664
  when "LIST"
304
- response_list = []
305
- write_in_response(path, response_list)
306
- inner_type = type.of_type
307
- idx = 0
308
- value.each do |inner_value|
309
- next_path = path.dup
310
- next_path << idx
311
- next_path.freeze
312
- idx += 1
313
- set_type_at_path(next_path, inner_type)
314
- # This will update `response_list` with the lazy
315
- after_lazy(inner_value, path: next_path, field: field) do |inner_inner_value|
316
- # reset `is_non_null` here and below, because the inner type will have its own nullability constraint
317
- continue_value = continue_value(next_path, inner_inner_value, field, false, ast_node)
318
- if HALT != continue_value
319
- continue_field(next_path, continue_value, field, inner_type, ast_node, next_selections, false)
665
+ inner_type = current_type.of_type
666
+ # This is true for objects, unions, and interfaces
667
+ use_dataloader_job = !inner_type.unwrap.kind.input?
668
+ inner_type_non_null = inner_type.non_null?
669
+ response_list = GraphQLResultArray.new(result_name, selection_result, is_non_null)
670
+ set_result(selection_result, result_name, response_list, true, is_non_null)
671
+ idx = nil
672
+ list_value = begin
673
+ value.each do |inner_value|
674
+ idx ||= 0
675
+ this_idx = idx
676
+ idx += 1
677
+ if use_dataloader_job
678
+ @dataloader.append_job do
679
+ resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped, runtime_state)
680
+ end
681
+ else
682
+ resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped, runtime_state)
320
683
  end
321
684
  end
685
+
686
+ response_list
687
+ rescue NoMethodError => err
688
+ # Ruby 2.2 doesn't have NoMethodError#receiver, can't check that one in this case. (It's been EOL since 2017.)
689
+ if err.name == :each && (err.respond_to?(:receiver) ? err.receiver == value : true)
690
+ # This happens when the GraphQL schema doesn't match the implementation. Help the dev debug.
691
+ raise ListResultFailedError.new(value: value, field: field, path: current_path)
692
+ else
693
+ # This was some other NoMethodError -- let it bubble to reveal the real error.
694
+ raise
695
+ end
696
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
697
+ ex_err
698
+ rescue StandardError => err
699
+ begin
700
+ query.handle_or_reraise(err)
701
+ rescue GraphQL::ExecutionError => ex_err
702
+ ex_err
703
+ end
322
704
  end
323
- response_list
324
- when "NON_NULL"
325
- inner_type = type.of_type
326
- # For fields like `__schema: __Schema!`
327
- inner_type = resolve_if_late_bound_type(inner_type)
328
- # Don't `set_type_at_path` because we want the static type,
329
- # we're going to use that to determine whether a `nil` should be propagated or not.
330
- continue_field(path, value, field, inner_type, ast_node, next_selections, true)
705
+ # Detect whether this error came while calling `.each` (before `idx` is set) or while running list *items* (after `idx` is set)
706
+ error_is_non_null = idx.nil? ? is_non_null : inner_type.non_null?
707
+ continue_value(list_value, owner_type, field, error_is_non_null, ast_node, result_name, selection_result)
331
708
  else
332
- raise "Invariant: Unhandled type kind #{type.kind} (#{type})"
709
+ raise "Invariant: Unhandled type kind #{current_type.kind} (#{current_type})"
710
+ end
711
+ end
712
+
713
+ def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, next_selections, owner_type, was_scoped, runtime_state) # rubocop:disable Metrics/ParameterLists
714
+ runtime_state.current_result_name = this_idx
715
+ runtime_state.current_result = response_list
716
+ call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
717
+ # This will update `response_list` with the lazy
718
+ after_lazy(inner_value, ast_node: ast_node, field: field, owner_object: owner_object, arguments: arguments, result_name: this_idx, result: response_list, runtime_state: runtime_state) do |inner_inner_value, runtime_state|
719
+ continue_value = continue_value(inner_inner_value, owner_type, field, inner_type_non_null, ast_node, this_idx, response_list)
720
+ if HALT != continue_value
721
+ continue_field(continue_value, owner_type, field, inner_type, ast_node, next_selections, false, owner_object, arguments, this_idx, response_list, was_scoped, runtime_state)
722
+ end
723
+ end
333
724
  end
334
725
  end
335
726
 
336
- def resolve_with_directives(object, ast_node)
337
- run_directive(object, ast_node, 0) { yield }
727
+ def call_method_on_directives(method_name, object, directives, &block)
728
+ return yield if directives.nil? || directives.empty?
729
+ run_directive(method_name, object, directives, 0, &block)
338
730
  end
339
731
 
340
- def run_directive(object, ast_node, idx)
341
- dir_node = ast_node.directives[idx]
732
+ def run_directive(method_name, object, directives, idx, &block)
733
+ dir_node = directives[idx]
342
734
  if !dir_node
343
735
  yield
344
736
  else
345
- dir_defn = schema.directives.fetch(dir_node.name)
346
- if !dir_defn.is_a?(Class)
347
- dir_defn = dir_defn.metadata[:type_class] || raise("Only class-based directives are supported (not `@#{dir_node.name}`)")
348
- end
349
- dir_args = arguments(nil, dir_defn, dir_node)
350
- dir_defn.resolve(object, dir_args, context) do
351
- run_directive(object, ast_node, idx + 1) { yield }
737
+ dir_defn = @schema_directives.fetch(dir_node.name)
738
+ raw_dir_args = arguments(nil, dir_defn, dir_node)
739
+ dir_args = continue_value(
740
+ raw_dir_args, # value
741
+ dir_defn, # parent_type
742
+ nil, # field
743
+ false, # is_non_null
744
+ dir_node, # ast_node
745
+ nil, # result_name
746
+ nil, # selection_result
747
+ )
748
+
749
+ if dir_args == HALT
750
+ nil
751
+ else
752
+ dir_defn.public_send(method_name, object, dir_args, context) do
753
+ run_directive(method_name, object, directives, idx + 1, &block)
754
+ end
352
755
  end
353
756
  end
354
757
  end
@@ -356,7 +759,7 @@ module GraphQL
356
759
  # Check {Schema::Directive.include?} for each directive that's present
357
760
  def directives_include?(node, graphql_object, parent_type)
358
761
  node.directives.each do |dir_node|
359
- dir_defn = schema.directives.fetch(dir_node.name).metadata[:type_class] || raise("Only class-based directives are supported (not #{dir_node.name.inspect})")
762
+ dir_defn = @schema_directives.fetch(dir_node.name)
360
763
  args = arguments(graphql_object, dir_defn, dir_node)
361
764
  if !dir_defn.include?(graphql_object, args, context)
362
765
  return false
@@ -365,231 +768,131 @@ module GraphQL
365
768
  true
366
769
  end
367
770
 
368
- def resolve_if_late_bound_type(type)
369
- if type.is_a?(GraphQL::Schema::LateBoundType)
370
- query.warden.get_type(type.name).metadata[:type_class]
771
+ def get_current_runtime_state
772
+ current_state = Thread.current[:__graphql_runtime_info] ||= begin
773
+ per_query_state = {}
774
+ per_query_state.compare_by_identity
775
+ per_query_state
776
+ end
777
+
778
+ current_state[@query] ||= CurrentState.new
779
+ end
780
+
781
+ def minimal_after_lazy(value, &block)
782
+ if lazy?(value)
783
+ GraphQL::Execution::Lazy.new do
784
+ result = @schema.sync_lazy(value)
785
+ # The returned result might also be lazy, so check it, too
786
+ minimal_after_lazy(result, &block)
787
+ end
371
788
  else
372
- type
789
+ yield(value)
373
790
  end
374
791
  end
375
792
 
376
793
  # @param obj [Object] Some user-returned value that may want to be batched
377
- # @param path [Array<String>]
378
794
  # @param field [GraphQL::Schema::Field]
379
795
  # @param eager [Boolean] Set to `true` for mutation root fields only
796
+ # @param trace [Boolean] If `false`, don't wrap this with field tracing
380
797
  # @return [GraphQL::Execution::Lazy, Object] If loading `object` will be deferred, it's a wrapper over it.
381
- def after_lazy(obj, field:, path:, eager: false)
382
- @interpreter_context[:current_path] = path
383
- @interpreter_context[:current_field] = field
384
- if schema.lazy?(obj)
385
- lazy = GraphQL::Execution::Lazy.new(path: path, field: field) do
386
- @interpreter_context[:current_path] = path
387
- @interpreter_context[:current_field] = field
798
+ def after_lazy(lazy_obj, field:, owner_object:, arguments:, ast_node:, result:, result_name:, eager: false, runtime_state:, trace: true, &block)
799
+ if lazy?(lazy_obj)
800
+ orig_result = result
801
+ was_authorized_by_scope_items = runtime_state.was_authorized_by_scope_items
802
+ lazy = GraphQL::Execution::Lazy.new(field: field) do
803
+ # This block might be called in a new fiber;
804
+ # In that case, this will initialize a new state
805
+ # to avoid conflicting with the parent fiber.
806
+ runtime_state = get_current_runtime_state
807
+ runtime_state.current_object = owner_object
808
+ runtime_state.current_field = field
809
+ runtime_state.current_arguments = arguments
810
+ runtime_state.current_result_name = result_name
811
+ runtime_state.current_result = orig_result
812
+ runtime_state.was_authorized_by_scope_items = was_authorized_by_scope_items
388
813
  # Wrap the execution of _this_ method with tracing,
389
814
  # but don't wrap the continuation below
390
- inner_obj = query.trace("execute_field_lazy", {field: field, path: path}) do
815
+ inner_obj = begin
816
+ if trace
817
+ @current_trace.execute_field_lazy(field: field, query: query, object: owner_object, arguments: arguments, ast_node: ast_node) do
818
+ schema.sync_lazy(lazy_obj)
819
+ end
820
+ else
821
+ schema.sync_lazy(lazy_obj)
822
+ end
823
+ rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => ex_err
824
+ ex_err
825
+ rescue StandardError => err
391
826
  begin
392
- schema.sync_lazy(obj)
393
- rescue GraphQL::ExecutionError, GraphQL::UnauthorizedError => err
394
- yield(err)
827
+ query.handle_or_reraise(err)
828
+ rescue GraphQL::ExecutionError => ex_err
829
+ ex_err
395
830
  end
396
831
  end
397
- after_lazy(inner_obj, field: field, path: path, eager: eager) do |really_inner_obj|
398
- yield(really_inner_obj)
399
- end
832
+ yield(inner_obj, runtime_state)
400
833
  end
401
834
 
402
835
  if eager
403
836
  lazy.value
404
837
  else
405
- write_in_response(path, lazy)
838
+ set_result(result, result_name, lazy, false, false) # is_non_null is irrelevant here
839
+ current_depth = 0
840
+ while result
841
+ current_depth += 1
842
+ result = result.graphql_parent
843
+ end
844
+ @lazies_at_depth[current_depth] << lazy
406
845
  lazy
407
846
  end
408
847
  else
409
- yield(obj)
410
- end
411
- end
412
-
413
- def each_argument_pair(ast_args_or_hash)
414
- case ast_args_or_hash
415
- when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
416
- ast_args_or_hash.arguments.each do |arg|
417
- yield(arg.name, arg.value)
418
- end
419
- when Hash
420
- ast_args_or_hash.each do |key, value|
421
- normalized_name = GraphQL::Schema::Member::BuildType.camelize(key.to_s)
422
- yield(normalized_name, value)
423
- end
424
- else
425
- raise "Invariant, unexpected #{ast_args_or_hash.inspect}"
848
+ # Don't need to reset state here because it _wasn't_ lazy.
849
+ yield(lazy_obj, runtime_state)
426
850
  end
427
851
  end
428
852
 
429
- def arguments(graphql_object, arg_owner, ast_node_or_hash)
430
- kwarg_arguments = {}
431
- arg_defns = arg_owner.arguments
432
- each_argument_pair(ast_node_or_hash) do |arg_name, arg_value|
433
- arg_defn = arg_defns[arg_name]
434
- # Need to distinguish between client-provided `nil`
435
- # and nothing-at-all
436
- is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_value)
437
- if is_present
438
- # This doesn't apply to directives, which are legacy
439
- # Can remove this when Skip and Include use classes or something.
440
- if graphql_object
441
- value = arg_defn.prepare_value(graphql_object, value)
442
- end
443
- kwarg_arguments[arg_defn.keyword] = value
444
- end
445
- end
446
- arg_defns.each do |name, arg_defn|
447
- if arg_defn.default_value? && !kwarg_arguments.key?(arg_defn.keyword)
448
- _is_present, value = arg_to_value(graphql_object, arg_defn.type, arg_defn.default_value)
449
- kwarg_arguments[arg_defn.keyword] = value
450
- end
451
- end
452
- kwarg_arguments
453
- end
454
-
455
- # Get a Ruby-ready value from a client query.
456
- # @param graphql_object [Object] The owner of the field whose argument this is
457
- # @param arg_type [Class, GraphQL::Schema::NonNull, GraphQL::Schema::List]
458
- # @param ast_value [GraphQL::Language::Nodes::VariableIdentifier, String, Integer, Float, Boolean]
459
- # @return [Array(is_present, value)]
460
- def arg_to_value(graphql_object, arg_type, ast_value)
461
- if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
462
- # If it's not here, it will get added later
463
- if query.variables.key?(ast_value.name)
464
- return true, query.variables[ast_value.name]
465
- else
466
- return false, nil
467
- end
468
- elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
469
- return true, nil
470
- elsif arg_type.is_a?(GraphQL::Schema::NonNull)
471
- arg_to_value(graphql_object, arg_type.of_type, ast_value)
472
- elsif arg_type.is_a?(GraphQL::Schema::List)
473
- # Treat a single value like a list
474
- arg_value = Array(ast_value)
475
- list = []
476
- arg_value.map do |inner_v|
477
- _present, value = arg_to_value(graphql_object, arg_type.of_type, inner_v)
478
- list << value
479
- end
480
- return true, list
481
- elsif arg_type.is_a?(Class) && arg_type < GraphQL::Schema::InputObject
482
- # For these, `prepare` is applied during `#initialize`.
483
- # Pass `nil` so it will be skipped in `#arguments`.
484
- # What a mess.
485
- args = arguments(nil, arg_type, ast_value)
486
- # We're not tracking defaults_used, but for our purposes
487
- # we compare the value to the default value.
488
- return true, arg_type.new(ruby_kwargs: args, context: context, defaults_used: nil)
853
+ def arguments(graphql_object, arg_owner, ast_node)
854
+ if arg_owner.arguments_statically_coercible?
855
+ query.arguments_for(ast_node, arg_owner)
489
856
  else
490
- flat_value = flatten_ast_value(ast_value)
491
- return true, arg_type.coerce_input(flat_value, context)
857
+ # The arguments must be prepared in the context of the given object
858
+ query.arguments_for(ast_node, arg_owner, parent_object: graphql_object)
492
859
  end
493
860
  end
494
861
 
495
- def flatten_ast_value(v)
496
- case v
497
- when GraphQL::Language::Nodes::Enum
498
- v.name
499
- when GraphQL::Language::Nodes::InputObject
500
- h = {}
501
- v.arguments.each do |arg|
502
- h[arg.name] = flatten_ast_value(arg.value)
862
+ def delete_all_interpreter_context
863
+ per_query_state = Thread.current[:__graphql_runtime_info]
864
+ if per_query_state
865
+ per_query_state.delete(@query)
866
+ if per_query_state.size == 0
867
+ Thread.current[:__graphql_runtime_info] = nil
503
868
  end
504
- h
505
- when Array
506
- v.map { |v2| flatten_ast_value(v2) }
507
- when GraphQL::Language::Nodes::VariableIdentifier
508
- flatten_ast_value(query.variables[v.name])
509
- else
510
- v
511
869
  end
870
+ nil
512
871
  end
513
872
 
514
- def write_invalid_null_in_response(path, invalid_null_error)
515
- if !dead_path?(path)
516
- schema.type_error(invalid_null_error, context)
517
- write_in_response(path, nil)
518
- add_dead_path(path)
873
+ def resolve_type(type, value)
874
+ resolved_type, resolved_value = @current_trace.resolve_type(query: query, type: type, object: value) do
875
+ query.resolve_type(type, value)
519
876
  end
520
- end
521
877
 
522
- def write_execution_errors_in_response(path, errors)
523
- if !dead_path?(path)
524
- errors.each do |v|
525
- context.errors << v
878
+ if lazy?(resolved_type)
879
+ GraphQL::Execution::Lazy.new do
880
+ @current_trace.resolve_type_lazy(query: query, type: type, object: value) do
881
+ schema.sync_lazy(resolved_type)
882
+ end
526
883
  end
527
- write_in_response(path, nil)
528
- add_dead_path(path)
529
- end
530
- end
531
-
532
- def write_in_response(path, value)
533
- if dead_path?(path)
534
- return
535
884
  else
536
- if value.nil? && path.any? && type_at(path).non_null?
537
- # This nil is invalid, try writing it at the previous spot
538
- propagate_path = path[0..-2]
539
- write_in_response(propagate_path, value)
540
- add_dead_path(propagate_path)
541
- else
542
- @response.write(path, value)
543
- end
544
- end
545
- end
546
-
547
- # To propagate nulls, we have to know what the field type was
548
- # at previous parts of the response.
549
- # This hash matches the response
550
- def type_at(path)
551
- t = @types_at_paths
552
- path.each do |part|
553
- t = t[part] || (raise("Invariant: #{part.inspect} not found in #{t}"))
554
- end
555
- t = t[:__type]
556
- t
557
- end
558
-
559
- def set_type_at_path(path, type)
560
- types = @types_at_paths
561
- path.each do |part|
562
- types = types[part] ||= {}
885
+ [resolved_type, resolved_value]
563
886
  end
564
- # Use this magic key so that the hash contains:
565
- # - string keys for nested fields
566
- # - :__type for the object type of a selection
567
- types[:__type] ||= type
568
- nil
569
887
  end
570
888
 
571
- # Mark `path` as having been permanently nulled out.
572
- # No values will be added beyond that path.
573
- def add_dead_path(path)
574
- dead = @dead_paths
575
- path.each do |part|
576
- dead = dead[part] ||= {}
577
- end
578
- dead[:__dead] = true
579
- end
580
-
581
- def dead_path?(path)
582
- res = @dead_paths
583
- path.each do |part|
584
- if res
585
- if res[:__dead]
586
- break
587
- else
588
- res = res[part]
589
- end
590
- end
889
+ def lazy?(object)
890
+ obj_class = object.class
891
+ is_lazy = @lazy_cache[obj_class]
892
+ if is_lazy.nil?
893
+ is_lazy = @lazy_cache[obj_class] = @schema.lazy?(object)
591
894
  end
592
- res && res[:__dead]
895
+ is_lazy
593
896
  end
594
897
  end
595
898
  end