graphql 1.13.17 → 2.0.20

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