@@ -8,6 +8,18 @@ class Interpreter
88 #
99 # @api private
1010 class Runtime
11+ class CurrentState
12+ def initialize
13+ @current_object = nil
14+ @current_field = nil
15+ @current_arguments = nil
16+ @current_result_name = nil
17+ @current_result = nil
18+ end
19+
20+ attr_accessor :current_result , :current_result_name ,
21+ :current_arguments , :current_field , :current_object
22+ end
1123
1224 module GraphQLResult
1325 def initialize ( result_name , parent_result )
@@ -157,15 +169,6 @@ class GraphQLSelectionSet < Hash
157169 # @return [GraphQL::Query::Context]
158170 attr_reader :context
159171
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-
169172 def initialize ( query :, lazies_at_depth :)
170173 @query = query
171174 @dataloader = query . multiplex . dataloader
@@ -218,7 +221,9 @@ def run_eager
218221 root_operation = query . selected_operation
219222 root_op_type = root_operation . operation_type || "query"
220223 root_type = schema . root_type_for_operation ( root_op_type )
221- set_all_interpreter_context ( query . root_value , nil , nil , nil , @response )
224+ st = get_current_runtime_state
225+ st . current_object = query . root_value
226+ st . current_result = @response
222227 object_proxy = authorized_new ( root_type , query . root_value , context )
223228 object_proxy = schema . sync_lazy ( object_proxy )
224229
@@ -245,7 +250,10 @@ def run_eager
245250 end
246251
247252 @dataloader . append_job {
248- set_all_interpreter_context ( query . root_value , nil , nil , nil , selection_response )
253+ st = get_current_runtime_state
254+ st . current_object = query . root_value
255+ st . current_result = selection_response
256+
249257 call_method_on_directives ( :resolve , object_proxy , selections . graphql_directives ) do
250258 evaluate_selections (
251259 object_proxy ,
@@ -364,7 +372,10 @@ def gather_selections(owner_object, owner_type, selections, selections_to_run =
364372
365373 # @return [void]
366374 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 )
375+ st = get_current_runtime_state
376+ st . current_object = owner_object
377+ st . current_result_name = nil
378+ st . current_result = selections_result
368379
369380 finished_jobs = 0
370381 enqueued_jobs = gathered_selections . size
@@ -422,7 +433,11 @@ def evaluate_selection(result_name, field_ast_nodes_or_ast_node, owner_object, o
422433 ( selections_result . graphql_non_null_field_names ||= [ ] ) . push ( result_name )
423434 end
424435 # Set this before calling `run_with_directives`, so that the directive can have the latest path
425- set_all_interpreter_context ( nil , field_defn , nil , result_name , selections_result )
436+ st = get_current_runtime_state
437+ st . current_field = field_defn
438+ st . current_result = selections_result
439+ st . current_result_name = result_name
440+
426441 object = owner_object
427442
428443 if is_introspection
@@ -489,8 +504,12 @@ def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_node
489504 resolved_arguments . keyword_arguments
490505 end
491506
492- set_all_interpreter_context ( nil , nil , resolved_arguments , result_name , selection_result )
493-
507+ st = get_current_runtime_state
508+ st . current_field = field_defn
509+ st . current_object = object
510+ st . current_arguments = resolved_arguments
511+ st . current_result_name = result_name
512+ st . current_result = selection_result
494513 # Optimize for the case that field is selected only once
495514 if field_ast_nodes . nil? || field_ast_nodes . size == 1
496515 next_selections = ast_node . selections
@@ -588,11 +607,10 @@ def set_graphql_dead(selection_result)
588607 end
589608
590609 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 ] )
610+ st = get_current_runtime_state
611+ result = st . current_result
612+ path = result && result . path
613+ if path && ( rn = st . current_result_name )
596614 path = path . dup
597615 path . push ( rn )
598616 end
@@ -769,8 +787,13 @@ def continue_field(value, owner_type, field, current_type, ast_node, next_select
769787 this_result = response_hash
770788 final_result = nil
771789 end
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
790+ # reset this mutable state
791+ # Unset `result_name` here because it's already included in the new response hash
792+ st = get_current_runtime_state
793+ st . current_object = continue_value
794+ st . current_result_name = nil
795+ st . current_result = this_result
796+
774797 call_method_on_directives ( :resolve , continue_value , selections . graphql_directives ) do
775798 evaluate_selections (
776799 continue_value ,
@@ -835,7 +858,9 @@ def continue_field(value, owner_type, field, current_type, ast_node, next_select
835858 end
836859
837860 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 )
861+ st = get_current_runtime_state
862+ st . current_result_name = this_idx
863+ st . current_result = response_list
839864 call_method_on_directives ( :resolve_each , owner_object , ast_node . directives ) do
840865 # This will update `response_list` with the lazy
841866 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 |
@@ -891,21 +916,8 @@ def directives_include?(node, graphql_object, parent_type)
891916 true
892917 end
893918
894- def set_all_interpreter_context ( object , field , arguments , result_name , result )
895- ti = thread_info
896- if object
897- ti [ :current_object ] = object
898- end
899- if field
900- ti [ :current_field ] = field
901- end
902- if arguments
903- ti [ :current_arguments ] = arguments
904- end
905- ti [ :current_result_name ] = result_name
906- if result
907- ti [ :current_result ] = result
908- end
919+ def get_current_runtime_state
920+ Thread . current [ :__graphql_runtime_info ] ||= CurrentState . new
909921 end
910922
911923 # @param obj [Object] Some user-returned value that may want to be batched
@@ -917,7 +929,12 @@ def after_lazy(lazy_obj, owner:, field:, owner_object:, arguments:, ast_node:, r
917929 if lazy? ( lazy_obj )
918930 orig_result = result
919931 lazy = GraphQL ::Execution ::Lazy . new ( field : field ) do
920- set_all_interpreter_context ( owner_object , field , arguments , result_name , orig_result )
932+ st = get_current_runtime_state
933+ st . current_object = owner_object
934+ st . current_field = field
935+ st . current_arguments = arguments
936+ st . current_result_name = result_name
937+ st . current_result = orig_result
921938 # Wrap the execution of _this_ method with tracing,
922939 # but don't wrap the continuation below
923940 inner_obj = begin
@@ -953,7 +970,7 @@ def after_lazy(lazy_obj, owner:, field:, owner_object:, arguments:, ast_node:, r
953970 lazy
954971 end
955972 else
956- set_all_interpreter_context ( owner_object , field , arguments , result_name , result )
973+ # Don't need to reset state here because it _wasn't_ lazy.
957974 yield ( lazy_obj )
958975 end
959976 end
@@ -968,13 +985,7 @@ def arguments(graphql_object, arg_owner, ast_node)
968985 end
969986
970987 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
988+ Thread . current [ :__graphql_runtime_info ] = nil
978989 end
979990
980991 def resolve_type ( type , value )
0 commit comments