graphql 2.3.4 → 2.3.6
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.
- checksums.yaml +4 -4
 - data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
 - data/lib/graphql/analysis/analyzer.rb +89 -0
 - data/lib/graphql/analysis/field_usage.rb +82 -0
 - data/lib/graphql/analysis/max_query_complexity.rb +20 -0
 - data/lib/graphql/analysis/max_query_depth.rb +20 -0
 - data/lib/graphql/analysis/query_complexity.rb +183 -0
 - data/lib/graphql/analysis/{ast/query_depth.rb → query_depth.rb} +23 -25
 - data/lib/graphql/analysis/visitor.rb +282 -0
 - data/lib/graphql/analysis.rb +92 -1
 - data/lib/graphql/dataloader/async_dataloader.rb +2 -0
 - data/lib/graphql/dataloader/null_dataloader.rb +1 -1
 - data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +7 -4
 - data/lib/graphql/execution/interpreter/runtime.rb +40 -59
 - data/lib/graphql/execution/interpreter.rb +2 -2
 - data/lib/graphql/language/nodes.rb +17 -22
 - data/lib/graphql/language/parser.rb +54 -13
 - data/lib/graphql/query/validation_pipeline.rb +2 -2
 - data/lib/graphql/query.rb +1 -1
 - data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
 - data/lib/graphql/schema/addition.rb +21 -11
 - data/lib/graphql/schema/argument.rb +19 -5
 - data/lib/graphql/schema/directive.rb +2 -0
 - data/lib/graphql/schema/field.rb +8 -0
 - data/lib/graphql/schema/has_single_input_argument.rb +1 -0
 - data/lib/graphql/schema/input_object.rb +1 -0
 - data/lib/graphql/schema/introspection_system.rb +2 -2
 - data/lib/graphql/schema/late_bound_type.rb +4 -0
 - data/lib/graphql/schema/list.rb +2 -2
 - data/lib/graphql/schema/member/has_arguments.rb +2 -35
 - data/lib/graphql/schema/member/has_directives.rb +1 -1
 - data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
 - data/lib/graphql/schema/member/type_system_helpers.rb +1 -2
 - data/lib/graphql/schema/resolver.rb +1 -0
 - data/lib/graphql/schema/warden.rb +2 -3
 - data/lib/graphql/schema.rb +20 -20
 - data/lib/graphql/static_validation/rules/fields_will_merge.rb +1 -1
 - data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -1
 - data/lib/graphql/subscriptions/broadcast_analyzer.rb +1 -1
 - data/lib/graphql/subscriptions.rb +1 -1
 - data/lib/graphql/type_kinds.rb +1 -1
 - data/lib/graphql/version.rb +1 -1
 - data/lib/graphql.rb +0 -8
 - metadata +10 -11
 - data/lib/graphql/analysis/ast/analyzer.rb +0 -91
 - data/lib/graphql/analysis/ast/field_usage.rb +0 -84
 - data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
 - data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
 - data/lib/graphql/analysis/ast/query_complexity.rb +0 -185
 - data/lib/graphql/analysis/ast/visitor.rb +0 -284
 - data/lib/graphql/analysis/ast.rb +0 -94
 
| 
         @@ -65,16 +65,6 @@ module GraphQL 
     | 
|
| 
       65 
65 
     | 
    
         
             
                      "#<#{self.class.name} response=#{@response.inspect}>"
         
     | 
| 
       66 
66 
     | 
    
         
             
                    end
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                    def tap_or_each(obj_or_array)
         
     | 
| 
       69 
     | 
    
         
            -
                      if obj_or_array.is_a?(Array)
         
     | 
| 
       70 
     | 
    
         
            -
                        obj_or_array.each do |item|
         
     | 
| 
       71 
     | 
    
         
            -
                          yield(item, true)
         
     | 
| 
       72 
     | 
    
         
            -
                        end
         
     | 
| 
       73 
     | 
    
         
            -
                      else
         
     | 
| 
       74 
     | 
    
         
            -
                        yield(obj_or_array, false)
         
     | 
| 
       75 
     | 
    
         
            -
                      end
         
     | 
| 
       76 
     | 
    
         
            -
                    end
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
68 
     | 
    
         
             
                    # This _begins_ the execution. Some deferred work
         
     | 
| 
       79 
69 
     | 
    
         
             
                    # might be stored up in lazies.
         
     | 
| 
       80 
70 
     | 
    
         
             
                    # @return [void]
         
     | 
| 
         @@ -84,7 +74,8 @@ module GraphQL 
     | 
|
| 
       84 
74 
     | 
    
         
             
                      root_type = schema.root_type_for_operation(root_op_type)
         
     | 
| 
       85 
75 
     | 
    
         
             
                      runtime_object = root_type.wrap(query.root_value, context)
         
     | 
| 
       86 
76 
     | 
    
         
             
                      runtime_object = schema.sync_lazy(runtime_object)
         
     | 
| 
       87 
     | 
    
         
            -
                       
     | 
| 
      
 77 
     | 
    
         
            +
                      is_eager = root_op_type == "mutation"
         
     | 
| 
      
 78 
     | 
    
         
            +
                      @response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false, root_operation.selections, is_eager)
         
     | 
| 
       88 
79 
     | 
    
         
             
                      st = get_current_runtime_state
         
     | 
| 
       89 
80 
     | 
    
         
             
                      st.current_result = @response
         
     | 
| 
       90 
81 
     | 
    
         | 
| 
         @@ -93,17 +84,9 @@ module GraphQL 
     | 
|
| 
       93 
84 
     | 
    
         
             
                        @response = nil
         
     | 
| 
       94 
85 
     | 
    
         
             
                      else
         
     | 
| 
       95 
86 
     | 
    
         
             
                        call_method_on_directives(:resolve, runtime_object, root_operation.directives) do # execute query level directives
         
     | 
| 
       96 
     | 
    
         
            -
                           
     | 
| 
       97 
     | 
    
         
            -
                          # This is kind of a hack -- `gathered_selections` is an Array if any of the selections
         
     | 
| 
       98 
     | 
    
         
            -
                          # require isolation during execution (because of runtime directives). In that case,
         
     | 
| 
       99 
     | 
    
         
            -
                          # make a new, isolated result hash for writing the result into. (That isolated response
         
     | 
| 
       100 
     | 
    
         
            -
                          # is eventually merged back into the main response)
         
     | 
| 
       101 
     | 
    
         
            -
                          #
         
     | 
| 
       102 
     | 
    
         
            -
                          # Otherwise, `gathered_selections` is a hash of selections which can be
         
     | 
| 
       103 
     | 
    
         
            -
                          # directly evaluated and the results can be written right into the main response hash.
         
     | 
| 
       104 
     | 
    
         
            -
                          tap_or_each(gathered_selections) do |selections, is_selection_array|
         
     | 
| 
      
 87 
     | 
    
         
            +
                          each_gathered_selections(@response) do |selections, is_selection_array|
         
     | 
| 
       105 
88 
     | 
    
         
             
                            if is_selection_array
         
     | 
| 
       106 
     | 
    
         
            -
                              selection_response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false)
         
     | 
| 
      
 89 
     | 
    
         
            +
                              selection_response = GraphQLResultHash.new(nil, root_type, runtime_object, nil, false, selections, is_eager)
         
     | 
| 
       107 
90 
     | 
    
         
             
                              final_response = @response
         
     | 
| 
       108 
91 
     | 
    
         
             
                            else
         
     | 
| 
       109 
92 
     | 
    
         
             
                              selection_response = @response
         
     | 
| 
         @@ -112,12 +95,10 @@ module GraphQL 
     | 
|
| 
       112 
95 
     | 
    
         | 
| 
       113 
96 
     | 
    
         
             
                            @dataloader.append_job {
         
     | 
| 
       114 
97 
     | 
    
         
             
                              evaluate_selections(
         
     | 
| 
       115 
     | 
    
         
            -
                                root_op_type == "mutation",
         
     | 
| 
       116 
98 
     | 
    
         
             
                                selections,
         
     | 
| 
       117 
99 
     | 
    
         
             
                                selection_response,
         
     | 
| 
       118 
100 
     | 
    
         
             
                                final_response,
         
     | 
| 
       119 
101 
     | 
    
         
             
                                nil,
         
     | 
| 
       120 
     | 
    
         
            -
                                nil,
         
     | 
| 
       121 
102 
     | 
    
         
             
                              )
         
     | 
| 
       122 
103 
     | 
    
         
             
                            }
         
     | 
| 
       123 
104 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -126,6 +107,17 @@ module GraphQL 
     | 
|
| 
       126 
107 
     | 
    
         
             
                      nil
         
     | 
| 
       127 
108 
     | 
    
         
             
                    end
         
     | 
| 
       128 
109 
     | 
    
         | 
| 
      
 110 
     | 
    
         
            +
                    def each_gathered_selections(response_hash)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      gathered_selections = gather_selections(response_hash.graphql_application_value, response_hash.graphql_result_type, response_hash.graphql_selections)
         
     | 
| 
      
 112 
     | 
    
         
            +
                      if gathered_selections.is_a?(Array)
         
     | 
| 
      
 113 
     | 
    
         
            +
                        gathered_selections.each do |item|
         
     | 
| 
      
 114 
     | 
    
         
            +
                          yield(item, true)
         
     | 
| 
      
 115 
     | 
    
         
            +
                        end
         
     | 
| 
      
 116 
     | 
    
         
            +
                      else
         
     | 
| 
      
 117 
     | 
    
         
            +
                        yield(gathered_selections, false)
         
     | 
| 
      
 118 
     | 
    
         
            +
                      end
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
       129 
121 
     | 
    
         
             
                    def gather_selections(owner_object, owner_type, selections, selections_to_run = nil, selections_by_name = {})
         
     | 
| 
       130 
122 
     | 
    
         
             
                      selections.each do |node|
         
     | 
| 
       131 
123 
     | 
    
         
             
                        # Skip gathering this if the directive says so
         
     | 
| 
         @@ -138,7 +130,7 @@ module GraphQL 
     | 
|
| 
       138 
130 
     | 
    
         
             
                          selections = selections_by_name[response_key]
         
     | 
| 
       139 
131 
     | 
    
         
             
                          # if there was already a selection of this field,
         
     | 
| 
       140 
132 
     | 
    
         
             
                          # use an array to hold all selections,
         
     | 
| 
       141 
     | 
    
         
            -
                          #  
     | 
| 
      
 133 
     | 
    
         
            +
                          # otherwise, use the single node to represent the selection
         
     | 
| 
       142 
134 
     | 
    
         
             
                          if selections
         
     | 
| 
       143 
135 
     | 
    
         
             
                            # This field was already selected at least once,
         
     | 
| 
       144 
136 
     | 
    
         
             
                            # add this node to the list of selections
         
     | 
| 
         @@ -203,7 +195,7 @@ module GraphQL 
     | 
|
| 
       203 
195 
     | 
    
         
             
                    NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
         
     | 
| 
       204 
196 
     | 
    
         | 
| 
       205 
197 
     | 
    
         
             
                    # @return [void]
         
     | 
| 
       206 
     | 
    
         
            -
                    def evaluate_selections( 
     | 
| 
      
 198 
     | 
    
         
            +
                    def evaluate_selections(gathered_selections, selections_result, target_result, runtime_state) # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       207 
199 
     | 
    
         
             
                      runtime_state ||= get_current_runtime_state
         
     | 
| 
       208 
200 
     | 
    
         
             
                      runtime_state.current_result_name = nil
         
     | 
| 
       209 
201 
     | 
    
         
             
                      runtime_state.current_result = selections_result
         
     | 
| 
         @@ -218,7 +210,7 @@ module GraphQL 
     | 
|
| 
       218 
210 
     | 
    
         
             
                        gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
         
     | 
| 
       219 
211 
     | 
    
         
             
                          @dataloader.append_job {
         
     | 
| 
       220 
212 
     | 
    
         
             
                            evaluate_selection(
         
     | 
| 
       221 
     | 
    
         
            -
                              result_name, field_ast_nodes_or_ast_node,  
     | 
| 
      
 213 
     | 
    
         
            +
                              result_name, field_ast_nodes_or_ast_node, selections_result
         
     | 
| 
       222 
214 
     | 
    
         
             
                            )
         
     | 
| 
       223 
215 
     | 
    
         
             
                            finished_jobs += 1
         
     | 
| 
       224 
216 
     | 
    
         
             
                            if target_result && finished_jobs == enqueued_jobs
         
     | 
| 
         @@ -228,7 +220,7 @@ module GraphQL 
     | 
|
| 
       228 
220 
     | 
    
         
             
                          # Field resolution may pause the fiber,
         
     | 
| 
       229 
221 
     | 
    
         
             
                          # so it wouldn't get to the `Resolve` call that happens below.
         
     | 
| 
       230 
222 
     | 
    
         
             
                          # So instead trigger a run from this outer context.
         
     | 
| 
       231 
     | 
    
         
            -
                          if  
     | 
| 
      
 223 
     | 
    
         
            +
                          if selections_result.graphql_is_eager
         
     | 
| 
       232 
224 
     | 
    
         
             
                            @dataloader.clear_cache
         
     | 
| 
       233 
225 
     | 
    
         
             
                            @dataloader.run
         
     | 
| 
       234 
226 
     | 
    
         
             
                            @dataloader.clear_cache
         
     | 
| 
         @@ -239,7 +231,7 @@ module GraphQL 
     | 
|
| 
       239 
231 
     | 
    
         
             
                    end
         
     | 
| 
       240 
232 
     | 
    
         | 
| 
       241 
233 
     | 
    
         
             
                    # @return [void]
         
     | 
| 
       242 
     | 
    
         
            -
                    def evaluate_selection(result_name, field_ast_nodes_or_ast_node,  
     | 
| 
      
 234 
     | 
    
         
            +
                    def evaluate_selection(result_name, field_ast_nodes_or_ast_node, selections_result) # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       243 
235 
     | 
    
         
             
                      return if selections_result.graphql_dead
         
     | 
| 
       244 
236 
     | 
    
         
             
                      # As a performance optimization, the hash key will be a `Node` if
         
     | 
| 
       245 
237 
     | 
    
         
             
                      # there's only one selection of the field. But if there are multiple
         
     | 
| 
         @@ -266,28 +258,27 @@ module GraphQL 
     | 
|
| 
       266 
258 
     | 
    
         
             
                        owner_object = field_defn.owner.wrap(owner_object, context)
         
     | 
| 
       267 
259 
     | 
    
         
             
                      end
         
     | 
| 
       268 
260 
     | 
    
         | 
| 
       269 
     | 
    
         
            -
                      return_type = field_defn.type
         
     | 
| 
       270 
261 
     | 
    
         
             
                      if !field_defn.any_arguments?
         
     | 
| 
       271 
262 
     | 
    
         
             
                        resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
         
     | 
| 
       272 
263 
     | 
    
         
             
                        if field_defn.extras.size == 0
         
     | 
| 
       273 
264 
     | 
    
         
             
                          evaluate_selection_with_resolved_keyword_args(
         
     | 
| 
       274 
     | 
    
         
            -
                            NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,  
     | 
| 
      
 265 
     | 
    
         
            +
                            NO_ARGS, resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state
         
     | 
| 
       275 
266 
     | 
    
         
             
                          )
         
     | 
| 
       276 
267 
     | 
    
         
             
                        else
         
     | 
| 
       277 
     | 
    
         
            -
                          evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,  
     | 
| 
      
 268 
     | 
    
         
            +
                          evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state)
         
     | 
| 
       278 
269 
     | 
    
         
             
                        end
         
     | 
| 
       279 
270 
     | 
    
         
             
                      else
         
     | 
| 
       280 
271 
     | 
    
         
             
                        @query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
         
     | 
| 
       281 
272 
     | 
    
         
             
                          runtime_state = get_current_runtime_state # This might be in a different fiber
         
     | 
| 
       282 
     | 
    
         
            -
                          evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object,  
     | 
| 
      
 273 
     | 
    
         
            +
                          evaluate_selection_with_args(resolved_arguments, field_defn, ast_node, field_ast_nodes, owner_object, result_name, selections_result, runtime_state)
         
     | 
| 
       283 
274 
     | 
    
         
             
                        end
         
     | 
| 
       284 
275 
     | 
    
         
             
                      end
         
     | 
| 
       285 
276 
     | 
    
         
             
                    end
         
     | 
| 
       286 
277 
     | 
    
         | 
| 
       287 
     | 
    
         
            -
                    def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, object,  
     | 
| 
      
 278 
     | 
    
         
            +
                    def evaluate_selection_with_args(arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state)  # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       288 
279 
     | 
    
         
             
                      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|
         
     | 
| 
       289 
     | 
    
         
            -
                        return_type_non_null = return_type.non_null?
         
     | 
| 
       290 
280 
     | 
    
         
             
                        if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
         
     | 
| 
      
 281 
     | 
    
         
            +
                          return_type_non_null = field_defn.type.non_null?
         
     | 
| 
       291 
282 
     | 
    
         
             
                          continue_value(resolved_arguments, field_defn, return_type_non_null, ast_node, result_name, selection_result)
         
     | 
| 
       292 
283 
     | 
    
         
             
                          next
         
     | 
| 
       293 
284 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -326,7 +317,8 @@ module GraphQL 
     | 
|
| 
       326 
317 
     | 
    
         
             
                              # to the keyword args hash _before_ freezing everything.
         
     | 
| 
       327 
318 
     | 
    
         
             
                              extra_args[:argument_details] = :__arguments_add_self
         
     | 
| 
       328 
319 
     | 
    
         
             
                            when :parent
         
     | 
| 
       329 
     | 
    
         
            -
                               
     | 
| 
      
 320 
     | 
    
         
            +
                              parent_result = selection_result.graphql_parent
         
     | 
| 
      
 321 
     | 
    
         
            +
                              extra_args[:parent] = parent_result&.graphql_application_value&.object
         
     | 
| 
       330 
322 
     | 
    
         
             
                            else
         
     | 
| 
       331 
323 
     | 
    
         
             
                              extra_args[extra] = field_defn.fetch_extra(extra, context)
         
     | 
| 
       332 
324 
     | 
    
         
             
                            end
         
     | 
| 
         @@ -337,11 +329,11 @@ module GraphQL 
     | 
|
| 
       337 
329 
     | 
    
         
             
                          resolved_arguments.keyword_arguments
         
     | 
| 
       338 
330 
     | 
    
         
             
                        end
         
     | 
| 
       339 
331 
     | 
    
         | 
| 
       340 
     | 
    
         
            -
                        evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object,  
     | 
| 
      
 332 
     | 
    
         
            +
                        evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state)
         
     | 
| 
       341 
333 
     | 
    
         
             
                      end
         
     | 
| 
       342 
334 
     | 
    
         
             
                    end
         
     | 
| 
       343 
335 
     | 
    
         | 
| 
       344 
     | 
    
         
            -
                    def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object,  
     | 
| 
      
 336 
     | 
    
         
            +
                    def evaluate_selection_with_resolved_keyword_args(kwarg_arguments, resolved_arguments, field_defn, ast_node, field_ast_nodes, object, result_name, selection_result, runtime_state)  # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       345 
337 
     | 
    
         
             
                      runtime_state.current_field = field_defn
         
     | 
| 
       346 
338 
     | 
    
         
             
                      runtime_state.current_arguments = resolved_arguments
         
     | 
| 
       347 
339 
     | 
    
         
             
                      runtime_state.current_result_name = result_name
         
     | 
| 
         @@ -384,7 +376,8 @@ module GraphQL 
     | 
|
| 
       384 
376 
     | 
    
         
             
                        end
         
     | 
| 
       385 
377 
     | 
    
         
             
                        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|
         
     | 
| 
       386 
378 
     | 
    
         
             
                          owner_type = selection_result.graphql_result_type
         
     | 
| 
       387 
     | 
    
         
            -
                           
     | 
| 
      
 379 
     | 
    
         
            +
                          return_type = field_defn.type
         
     | 
| 
      
 380 
     | 
    
         
            +
                          continue_value = continue_value(inner_result, field_defn, return_type.non_null?, ast_node, result_name, selection_result)
         
     | 
| 
       388 
381 
     | 
    
         
             
                          if HALT != continue_value
         
     | 
| 
       389 
382 
     | 
    
         
             
                            was_scoped = runtime_state.was_authorized_by_scope_items
         
     | 
| 
       390 
383 
     | 
    
         
             
                            runtime_state.was_authorized_by_scope_items = nil
         
     | 
| 
         @@ -395,7 +388,7 @@ module GraphQL 
     | 
|
| 
       395 
388 
     | 
    
         
             
                      # If this field is a root mutation field, immediately resolve
         
     | 
| 
       396 
389 
     | 
    
         
             
                      # all of its child fields before moving on to the next root mutation field.
         
     | 
| 
       397 
390 
     | 
    
         
             
                      # (Subselections of this mutation will still be resolved level-by-level.)
         
     | 
| 
       398 
     | 
    
         
            -
                      if  
     | 
| 
      
 391 
     | 
    
         
            +
                      if selection_result.graphql_is_eager
         
     | 
| 
       399 
392 
     | 
    
         
             
                        Interpreter::Resolve.resolve_all([field_result], @dataloader)
         
     | 
| 
       400 
393 
     | 
    
         
             
                      end
         
     | 
| 
       401 
394 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -607,21 +600,11 @@ module GraphQL 
     | 
|
| 
       607 
600 
     | 
    
         
             
                        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|
         
     | 
| 
       608 
601 
     | 
    
         
             
                          continue_value = continue_value(inner_object, field, is_non_null, ast_node, result_name, selection_result)
         
     | 
| 
       609 
602 
     | 
    
         
             
                          if HALT != continue_value
         
     | 
| 
       610 
     | 
    
         
            -
                            response_hash = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
         
     | 
| 
      
 603 
     | 
    
         
            +
                            response_hash = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null, next_selections, false)
         
     | 
| 
       611 
604 
     | 
    
         
             
                            set_result(selection_result, result_name, response_hash, true, is_non_null)
         
     | 
| 
       612 
     | 
    
         
            -
             
     | 
| 
       613 
     | 
    
         
            -
                            gathered_selections = gather_selections(continue_value, current_type, next_selections)
         
     | 
| 
       614 
     | 
    
         
            -
                            # There are two possibilities for `gathered_selections`:
         
     | 
| 
       615 
     | 
    
         
            -
                            # 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
         
     | 
| 
       616 
     | 
    
         
            -
                            #    This case is handled below, and the result can be written right into the main `response_hash` above.
         
     | 
| 
       617 
     | 
    
         
            -
                            #    In this case, `gathered_selections` is a hash of selections.
         
     | 
| 
       618 
     | 
    
         
            -
                            # 2. Some selections of this object have runtime directives that may or may not modify execution.
         
     | 
| 
       619 
     | 
    
         
            -
                            #    That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
         
     | 
| 
       620 
     | 
    
         
            -
                            #    eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
         
     | 
| 
       621 
     | 
    
         
            -
                            #    (Technically, it's possible that one of those entries _doesn't_ require isolation.)
         
     | 
| 
       622 
     | 
    
         
            -
                            tap_or_each(gathered_selections) do |selections, is_selection_array|
         
     | 
| 
      
 605 
     | 
    
         
            +
                            each_gathered_selections(response_hash) do |selections, is_selection_array|
         
     | 
| 
       623 
606 
     | 
    
         
             
                              if is_selection_array
         
     | 
| 
       624 
     | 
    
         
            -
                                this_result = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null)
         
     | 
| 
      
 607 
     | 
    
         
            +
                                this_result = GraphQLResultHash.new(result_name, current_type, continue_value, selection_result, is_non_null, selections, false)
         
     | 
| 
       625 
608 
     | 
    
         
             
                                final_result = response_hash
         
     | 
| 
       626 
609 
     | 
    
         
             
                              else
         
     | 
| 
       627 
610 
     | 
    
         
             
                                this_result = response_hash
         
     | 
| 
         @@ -629,11 +612,9 @@ module GraphQL 
     | 
|
| 
       629 
612 
     | 
    
         
             
                              end
         
     | 
| 
       630 
613 
     | 
    
         | 
| 
       631 
614 
     | 
    
         
             
                              evaluate_selections(
         
     | 
| 
       632 
     | 
    
         
            -
                                false,
         
     | 
| 
       633 
615 
     | 
    
         
             
                                selections,
         
     | 
| 
       634 
616 
     | 
    
         
             
                                this_result,
         
     | 
| 
       635 
617 
     | 
    
         
             
                                final_result,
         
     | 
| 
       636 
     | 
    
         
            -
                                owner_object.object,
         
     | 
| 
       637 
618 
     | 
    
         
             
                                runtime_state,
         
     | 
| 
       638 
619 
     | 
    
         
             
                              )
         
     | 
| 
       639 
620 
     | 
    
         
             
                            end
         
     | 
| 
         @@ -644,7 +625,7 @@ module GraphQL 
     | 
|
| 
       644 
625 
     | 
    
         
             
                        # This is true for objects, unions, and interfaces
         
     | 
| 
       645 
626 
     | 
    
         
             
                        use_dataloader_job = !inner_type.unwrap.kind.input?
         
     | 
| 
       646 
627 
     | 
    
         
             
                        inner_type_non_null = inner_type.non_null?
         
     | 
| 
       647 
     | 
    
         
            -
                        response_list = GraphQLResultArray.new(result_name, current_type,  
     | 
| 
      
 628 
     | 
    
         
            +
                        response_list = GraphQLResultArray.new(result_name, current_type, owner_object, selection_result, is_non_null, next_selections, false)
         
     | 
| 
       648 
629 
     | 
    
         
             
                        set_result(selection_result, result_name, response_list, true, is_non_null)
         
     | 
| 
       649 
630 
     | 
    
         
             
                        idx = nil
         
     | 
| 
       650 
631 
     | 
    
         
             
                        list_value = begin
         
     | 
| 
         @@ -654,10 +635,10 @@ module GraphQL 
     | 
|
| 
       654 
635 
     | 
    
         
             
                            idx += 1
         
     | 
| 
       655 
636 
     | 
    
         
             
                            if use_dataloader_job
         
     | 
| 
       656 
637 
     | 
    
         
             
                              @dataloader.append_job do
         
     | 
| 
       657 
     | 
    
         
            -
                                resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,  
     | 
| 
      
 638 
     | 
    
         
            +
                                resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state)
         
     | 
| 
       658 
639 
     | 
    
         
             
                              end
         
     | 
| 
       659 
640 
     | 
    
         
             
                            else
         
     | 
| 
       660 
     | 
    
         
            -
                              resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,  
     | 
| 
      
 641 
     | 
    
         
            +
                              resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state)
         
     | 
| 
       661 
642 
     | 
    
         
             
                            end
         
     | 
| 
       662 
643 
     | 
    
         
             
                          end
         
     | 
| 
       663 
644 
     | 
    
         | 
| 
         @@ -688,7 +669,7 @@ module GraphQL 
     | 
|
| 
       688 
669 
     | 
    
         
             
                      end
         
     | 
| 
       689 
670 
     | 
    
         
             
                    end
         
     | 
| 
       690 
671 
     | 
    
         | 
| 
       691 
     | 
    
         
            -
                    def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list,  
     | 
| 
      
 672 
     | 
    
         
            +
                    def resolve_list_item(inner_value, inner_type, inner_type_non_null, ast_node, field, owner_object, arguments, this_idx, response_list, owner_type, was_scoped, runtime_state) # rubocop:disable Metrics/ParameterLists
         
     | 
| 
       692 
673 
     | 
    
         
             
                      runtime_state.current_result_name = this_idx
         
     | 
| 
       693 
674 
     | 
    
         
             
                      runtime_state.current_result = response_list
         
     | 
| 
       694 
675 
     | 
    
         
             
                      call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
         
     | 
| 
         @@ -696,7 +677,7 @@ module GraphQL 
     | 
|
| 
       696 
677 
     | 
    
         
             
                        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|
         
     | 
| 
       697 
678 
     | 
    
         
             
                          continue_value = continue_value(inner_inner_value, field, inner_type_non_null, ast_node, this_idx, response_list)
         
     | 
| 
       698 
679 
     | 
    
         
             
                          if HALT != continue_value
         
     | 
| 
       699 
     | 
    
         
            -
                            continue_field(continue_value, owner_type, field, inner_type, ast_node,  
     | 
| 
      
 680 
     | 
    
         
            +
                            continue_field(continue_value, owner_type, field, inner_type, ast_node, response_list.graphql_selections, false, owner_object, arguments, this_idx, response_list, was_scoped, runtime_state)
         
     | 
| 
       700 
681 
     | 
    
         
             
                          end
         
     | 
| 
       701 
682 
     | 
    
         
             
                        end
         
     | 
| 
       702 
683 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -20,7 +20,7 @@ module GraphQL 
     | 
|
| 
       20 
20 
     | 
    
         
             
                    # @param queries [Array<GraphQL::Query, Hash>]
         
     | 
| 
       21 
21 
     | 
    
         
             
                    # @param context [Hash]
         
     | 
| 
       22 
22 
     | 
    
         
             
                    # @param max_complexity [Integer, nil]
         
     | 
| 
       23 
     | 
    
         
            -
                    # @return [Array< 
     | 
| 
      
 23 
     | 
    
         
            +
                    # @return [Array<GraphQL::Query::Result>] One result per query
         
     | 
| 
       24 
24 
     | 
    
         
             
                    def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
         
     | 
| 
       25 
25 
     | 
    
         
             
                      queries = query_options.map do |opts|
         
     | 
| 
       26 
26 
     | 
    
         
             
                        case opts
         
     | 
| 
         @@ -40,7 +40,7 @@ module GraphQL 
     | 
|
| 
       40 
40 
     | 
    
         
             
                        lazies_at_depth = Hash.new { |h, k| h[k] = [] }
         
     | 
| 
       41 
41 
     | 
    
         
             
                        multiplex_analyzers = schema.multiplex_analyzers
         
     | 
| 
       42 
42 
     | 
    
         
             
                        if multiplex.max_complexity
         
     | 
| 
       43 
     | 
    
         
            -
                          multiplex_analyzers += [GraphQL::Analysis:: 
     | 
| 
      
 43 
     | 
    
         
            +
                          multiplex_analyzers += [GraphQL::Analysis::MaxQueryComplexity]
         
     | 
| 
       44 
44 
     | 
    
         
             
                        end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                        schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
         
     | 
| 
         @@ -274,6 +274,8 @@ module GraphQL 
     | 
|
| 
       274 
274 
     | 
    
         
             
                      ]
         
     | 
| 
       275 
275 
     | 
    
         | 
| 
       276 
276 
     | 
    
         
             
                      def generate_initialize
         
     | 
| 
      
 277 
     | 
    
         
            +
                        return if method_defined?(:marshal_load, false) # checking for `:initialize` doesn't work right
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
       277 
279 
     | 
    
         
             
                        scalar_method_names = @scalar_methods
         
     | 
| 
       278 
280 
     | 
    
         
             
                        # TODO: These probably should be scalar methods, but `types` returns an array
         
     | 
| 
       279 
281 
     | 
    
         
             
                        [:types, :description].each do |extra_method|
         
     | 
| 
         @@ -392,16 +394,6 @@ module GraphQL 
     | 
|
| 
       392 
394 
     | 
    
         | 
| 
       393 
395 
     | 
    
         
             
                  # A single selection in a GraphQL query.
         
     | 
| 
       394 
396 
     | 
    
         
             
                  class Field < AbstractNode
         
     | 
| 
       395 
     | 
    
         
            -
                    scalar_methods :name, :alias
         
     | 
| 
       396 
     | 
    
         
            -
                    children_methods({
         
     | 
| 
       397 
     | 
    
         
            -
                      arguments: GraphQL::Language::Nodes::Argument,
         
     | 
| 
       398 
     | 
    
         
            -
                      selections: GraphQL::Language::Nodes::Field,
         
     | 
| 
       399 
     | 
    
         
            -
                      directives: GraphQL::Language::Nodes::Directive,
         
     | 
| 
       400 
     | 
    
         
            -
                    })
         
     | 
| 
       401 
     | 
    
         
            -
             
     | 
| 
       402 
     | 
    
         
            -
                    # @!attribute selections
         
     | 
| 
       403 
     | 
    
         
            -
                    #   @return [Array<Nodes::Field>] Selections on this object (or empty array if this is a scalar field)
         
     | 
| 
       404 
     | 
    
         
            -
             
     | 
| 
       405 
397 
     | 
    
         
             
                    def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
         
     | 
| 
       406 
398 
     | 
    
         
             
                      @name = name
         
     | 
| 
       407 
399 
     | 
    
         
             
                      @arguments = arguments || NONE
         
     | 
| 
         @@ -428,24 +420,19 @@ module GraphQL 
     | 
|
| 
       428 
420 
     | 
    
         
             
                      @line, @col, @filename, @name, @arguments, @directives, @selections, @alias = values
         
     | 
| 
       429 
421 
     | 
    
         
             
                    end
         
     | 
| 
       430 
422 
     | 
    
         | 
| 
       431 
     | 
    
         
            -
                     
     | 
| 
       432 
     | 
    
         
            -
                    self.children_method_name = :selections
         
     | 
| 
       433 
     | 
    
         
            -
                  end
         
     | 
| 
       434 
     | 
    
         
            -
             
     | 
| 
       435 
     | 
    
         
            -
                  # A reusable fragment, defined at document-level.
         
     | 
| 
       436 
     | 
    
         
            -
                  class FragmentDefinition < AbstractNode
         
     | 
| 
       437 
     | 
    
         
            -
                    scalar_methods :name, :type
         
     | 
| 
      
 423 
     | 
    
         
            +
                    scalar_methods :name, :alias
         
     | 
| 
       438 
424 
     | 
    
         
             
                    children_methods({
         
     | 
| 
      
 425 
     | 
    
         
            +
                      arguments: GraphQL::Language::Nodes::Argument,
         
     | 
| 
       439 
426 
     | 
    
         
             
                      selections: GraphQL::Language::Nodes::Field,
         
     | 
| 
       440 
427 
     | 
    
         
             
                      directives: GraphQL::Language::Nodes::Directive,
         
     | 
| 
       441 
428 
     | 
    
         
             
                    })
         
     | 
| 
       442 
429 
     | 
    
         | 
| 
       443 
     | 
    
         
            -
                     
     | 
| 
       444 
     | 
    
         
            -
                     
     | 
| 
       445 
     | 
    
         
            -
             
     | 
| 
      
 430 
     | 
    
         
            +
                    # Override this because default is `:fields`
         
     | 
| 
      
 431 
     | 
    
         
            +
                    self.children_method_name = :selections
         
     | 
| 
      
 432 
     | 
    
         
            +
                  end
         
     | 
| 
       446 
433 
     | 
    
         | 
| 
       447 
     | 
    
         
            -
             
     | 
| 
       448 
     | 
    
         
            -
             
     | 
| 
      
 434 
     | 
    
         
            +
                  # A reusable fragment, defined at document-level.
         
     | 
| 
      
 435 
     | 
    
         
            +
                  class FragmentDefinition < AbstractNode
         
     | 
| 
       449 
436 
     | 
    
         
             
                    def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source: nil, line: nil, col: nil)
         
     | 
| 
       450 
437 
     | 
    
         
             
                      @name = name
         
     | 
| 
       451 
438 
     | 
    
         
             
                      @type = type
         
     | 
| 
         @@ -469,6 +456,14 @@ module GraphQL 
     | 
|
| 
       469 
456 
     | 
    
         
             
                    def marshal_load(values)
         
     | 
| 
       470 
457 
     | 
    
         
             
                      @line, @col, @filename, @name, @type, @directives, @selections = values
         
     | 
| 
       471 
458 
     | 
    
         
             
                    end
         
     | 
| 
      
 459 
     | 
    
         
            +
             
     | 
| 
      
 460 
     | 
    
         
            +
                    scalar_methods :name, :type
         
     | 
| 
      
 461 
     | 
    
         
            +
                    children_methods({
         
     | 
| 
      
 462 
     | 
    
         
            +
                      selections: GraphQL::Language::Nodes::Field,
         
     | 
| 
      
 463 
     | 
    
         
            +
                      directives: GraphQL::Language::Nodes::Directive,
         
     | 
| 
      
 464 
     | 
    
         
            +
                    })
         
     | 
| 
      
 465 
     | 
    
         
            +
             
     | 
| 
      
 466 
     | 
    
         
            +
                    self.children_method_name = :definitions
         
     | 
| 
       472 
467 
     | 
    
         
             
                  end
         
     | 
| 
       473 
468 
     | 
    
         | 
| 
       474 
469 
     | 
    
         
             
                  # Application of a named fragment in a selection
         
     | 
| 
         @@ -379,7 +379,12 @@ module GraphQL 
     | 
|
| 
       379 
379 
     | 
    
         
             
                        v_loc = pos
         
     | 
| 
       380 
380 
     | 
    
         
             
                        description = if at?(:STRING); string_value; end
         
     | 
| 
       381 
381 
     | 
    
         
             
                        defn_loc = pos
         
     | 
| 
       382 
     | 
    
         
            -
                         
     | 
| 
      
 382 
     | 
    
         
            +
                        # Any identifier, but not true, false, or null
         
     | 
| 
      
 383 
     | 
    
         
            +
                        enum_value = if at?(:TRUE) || at?(:FALSE) || at?(:NULL)
         
     | 
| 
      
 384 
     | 
    
         
            +
                          expect_token(:IDENTIFIER)
         
     | 
| 
      
 385 
     | 
    
         
            +
                        else
         
     | 
| 
      
 386 
     | 
    
         
            +
                          parse_name
         
     | 
| 
      
 387 
     | 
    
         
            +
                        end
         
     | 
| 
       383 
388 
     | 
    
         
             
                        v_directives = parse_directives
         
     | 
| 
       384 
389 
     | 
    
         
             
                        list << EnumValueDefinition.new(pos: v_loc, definition_pos: defn_loc, description: description, name: enum_value, directives: v_directives, filename: @filename, source: self)
         
     | 
| 
       385 
390 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -615,9 +620,6 @@ module GraphQL 
     | 
|
| 
       615 
620 
     | 
    
         
             
                    when :ON
         
     | 
| 
       616 
621 
     | 
    
         
             
                      advance_token
         
     | 
| 
       617 
622 
     | 
    
         
             
                      "on"
         
     | 
| 
       618 
     | 
    
         
            -
                    when :DIRECTIVE
         
     | 
| 
       619 
     | 
    
         
            -
                      advance_token
         
     | 
| 
       620 
     | 
    
         
            -
                      "directive"
         
     | 
| 
       621 
623 
     | 
    
         
             
                    when :EXTEND
         
     | 
| 
       622 
624 
     | 
    
         
             
                      advance_token
         
     | 
| 
       623 
625 
     | 
    
         
             
                      "extend"
         
     | 
| 
         @@ -634,15 +636,6 @@ module GraphQL 
     | 
|
| 
       634 
636 
     | 
    
         
             
                    end
         
     | 
| 
       635 
637 
     | 
    
         
             
                  end
         
     | 
| 
       636 
638 
     | 
    
         | 
| 
       637 
     | 
    
         
            -
                  # Any identifier, but not true, false, or null
         
     | 
| 
       638 
     | 
    
         
            -
                  def parse_enum_name
         
     | 
| 
       639 
     | 
    
         
            -
                    if at?(:TRUE) || at?(:FALSE) || at?(:NULL)
         
     | 
| 
       640 
     | 
    
         
            -
                      expect_token(:IDENTIFIER)
         
     | 
| 
       641 
     | 
    
         
            -
                    else
         
     | 
| 
       642 
     | 
    
         
            -
                      parse_name
         
     | 
| 
       643 
     | 
    
         
            -
                    end
         
     | 
| 
       644 
     | 
    
         
            -
                  end
         
     | 
| 
       645 
     | 
    
         
            -
             
     | 
| 
       646 
639 
     | 
    
         
             
                  def parse_type_name
         
     | 
| 
       647 
640 
     | 
    
         
             
                    TypeName.new(pos: pos, name: parse_name, filename: @filename, source: self)
         
     | 
| 
       648 
641 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -733,6 +726,54 @@ module GraphQL 
     | 
|
| 
       733 
726 
     | 
    
         
             
                      loc = pos
         
     | 
| 
       734 
727 
     | 
    
         
             
                      advance_token
         
     | 
| 
       735 
728 
     | 
    
         
             
                      VariableIdentifier.new(pos: loc, name: parse_name, filename: @filename, source: self)
         
     | 
| 
      
 729 
     | 
    
         
            +
                    when :SCHEMA
         
     | 
| 
      
 730 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 731 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "schema", filename: @filename, source: self)
         
     | 
| 
      
 732 
     | 
    
         
            +
                    when :SCALAR
         
     | 
| 
      
 733 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 734 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "scalar", filename: @filename, source: self)
         
     | 
| 
      
 735 
     | 
    
         
            +
                    when :IMPLEMENTS
         
     | 
| 
      
 736 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 737 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "implements", filename: @filename, source: self)
         
     | 
| 
      
 738 
     | 
    
         
            +
                    when :INTERFACE
         
     | 
| 
      
 739 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 740 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "interface", filename: @filename, source: self)
         
     | 
| 
      
 741 
     | 
    
         
            +
                    when :UNION
         
     | 
| 
      
 742 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 743 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "union", filename: @filename, source: self)
         
     | 
| 
      
 744 
     | 
    
         
            +
                    when :ENUM
         
     | 
| 
      
 745 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 746 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "enum", filename: @filename, source: self)
         
     | 
| 
      
 747 
     | 
    
         
            +
                    when :INPUT
         
     | 
| 
      
 748 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 749 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "input", filename: @filename, source: self)
         
     | 
| 
      
 750 
     | 
    
         
            +
                    when :DIRECTIVE
         
     | 
| 
      
 751 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 752 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "directive", filename: @filename, source: self)
         
     | 
| 
      
 753 
     | 
    
         
            +
                    when :TYPE
         
     | 
| 
      
 754 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 755 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "type", filename: @filename, source: self)
         
     | 
| 
      
 756 
     | 
    
         
            +
                    when :QUERY
         
     | 
| 
      
 757 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 758 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "query", filename: @filename, source: self)
         
     | 
| 
      
 759 
     | 
    
         
            +
                    when :MUTATION
         
     | 
| 
      
 760 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 761 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "mutation", filename: @filename, source: self)
         
     | 
| 
      
 762 
     | 
    
         
            +
                    when :SUBSCRIPTION
         
     | 
| 
      
 763 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 764 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "subscription", filename: @filename, source: self)
         
     | 
| 
      
 765 
     | 
    
         
            +
                    when :FRAGMENT
         
     | 
| 
      
 766 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 767 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "fragment", filename: @filename, source: self)
         
     | 
| 
      
 768 
     | 
    
         
            +
                    when :REPEATABLE
         
     | 
| 
      
 769 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 770 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "repeatable", filename: @filename, source: self)
         
     | 
| 
      
 771 
     | 
    
         
            +
                    when :ON
         
     | 
| 
      
 772 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 773 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "on", filename: @filename, source: self)
         
     | 
| 
      
 774 
     | 
    
         
            +
                    when :EXTEND
         
     | 
| 
      
 775 
     | 
    
         
            +
                      advance_token
         
     | 
| 
      
 776 
     | 
    
         
            +
                      Nodes::Enum.new(pos: pos, name: "extend", filename: @filename, source: self)
         
     | 
| 
       736 
777 
     | 
    
         
             
                    else
         
     | 
| 
       737 
778 
     | 
    
         
             
                      expect_token(:VALUE)
         
     | 
| 
       738 
779 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -100,10 +100,10 @@ module GraphQL 
     | 
|
| 
       100 
100 
     | 
    
         
             
                      # Depending on the analysis engine, we must use different analyzers
         
     | 
| 
       101 
101 
     | 
    
         
             
                      # remove this once everything has switched over to AST analyzers
         
     | 
| 
       102 
102 
     | 
    
         
             
                      if max_depth
         
     | 
| 
       103 
     | 
    
         
            -
                        qa << GraphQL::Analysis:: 
     | 
| 
      
 103 
     | 
    
         
            +
                        qa << GraphQL::Analysis::MaxQueryDepth
         
     | 
| 
       104 
104 
     | 
    
         
             
                      end
         
     | 
| 
       105 
105 
     | 
    
         
             
                      if max_complexity
         
     | 
| 
       106 
     | 
    
         
            -
                        qa << GraphQL::Analysis:: 
     | 
| 
      
 106 
     | 
    
         
            +
                        qa << GraphQL::Analysis::MaxQueryComplexity
         
     | 
| 
       107 
107 
     | 
    
         
             
                      end
         
     | 
| 
       108 
108 
     | 
    
         
             
                      qa
         
     | 
| 
       109 
109 
     | 
    
         
             
                    else
         
     | 
    
        data/lib/graphql/query.rb
    CHANGED
    
    | 
         @@ -222,7 +222,7 @@ module GraphQL 
     | 
|
| 
       222 
222 
     | 
    
         
             
                end
         
     | 
| 
       223 
223 
     | 
    
         | 
| 
       224 
224 
     | 
    
         
             
                # Get the result for this query, executing it once
         
     | 
| 
       225 
     | 
    
         
            -
                # @return [ 
     | 
| 
      
 225 
     | 
    
         
            +
                # @return [GraphQL::Query::Result] A Hash-like GraphQL response, with `"data"` and/or `"errors"` keys
         
     | 
| 
       226 
226 
     | 
    
         
             
                def result
         
     | 
| 
       227 
227 
     | 
    
         
             
                  if !@executed
         
     | 
| 
       228 
228 
     | 
    
         
             
                    Execution::Interpreter.run_all(@schema, [self], context: @context)
         
     | 
| 
         @@ -9,7 +9,7 @@ module GraphQL 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                    # Return the source of `send_node`, but without the keyword argument represented by `pair_node`
         
     | 
| 
       11 
11 
     | 
    
         
             
                    def source_without_keyword_argument(send_node, pair_node)
         
     | 
| 
       12 
     | 
    
         
            -
                      # work back to the  
     | 
| 
      
 12 
     | 
    
         
            +
                      # work back to the preceding comma
         
     | 
| 
       13 
13 
     | 
    
         
             
                      first_pos = pair_node.location.expression.begin_pos
         
     | 
| 
       14 
14 
     | 
    
         
             
                      end_pos = pair_node.location.expression.end_pos
         
     | 
| 
       15 
15 
     | 
    
         
             
                      node_source = send_node.source_range.source
         
     | 
| 
         @@ -12,7 +12,7 @@ module GraphQL 
     | 
|
| 
       12 
12 
     | 
    
         
             
                    @possible_types = {}
         
     | 
| 
       13 
13 
     | 
    
         
             
                    @types = {}
         
     | 
| 
       14 
14 
     | 
    
         
             
                    @union_memberships = {}
         
     | 
| 
       15 
     | 
    
         
            -
                    @references = Hash.new { |h, k| h[k] =  
     | 
| 
      
 15 
     | 
    
         
            +
                    @references = Hash.new { |h, k| h[k] = Set.new }
         
     | 
| 
       16 
16 
     | 
    
         
             
                    @arguments_with_default_values = []
         
     | 
| 
       17 
17 
     | 
    
         
             
                    add_type_and_traverse(new_types)
         
     | 
| 
       18 
18 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -20,7 +20,7 @@ module GraphQL 
     | 
|
| 
       20 
20 
     | 
    
         
             
                  private
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
                  def references_to(thing, from:)
         
     | 
| 
       23 
     | 
    
         
            -
                    @references[thing] 
     | 
| 
      
 23 
     | 
    
         
            +
                    @references[thing].add(from)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                  def get_type(name)
         
     | 
| 
         @@ -95,7 +95,7 @@ module GraphQL 
     | 
|
| 
       95 
95 
     | 
    
         
             
                        # It's a union with possible_types
         
     | 
| 
       96 
96 
     | 
    
         
             
                        # Replace the item by class name
         
     | 
| 
       97 
97 
     | 
    
         
             
                        owner.assign_type_membership_object_type(type)
         
     | 
| 
       98 
     | 
    
         
            -
                        @possible_types[owner 
     | 
| 
      
 98 
     | 
    
         
            +
                        @possible_types[owner] = owner.possible_types
         
     | 
| 
       99 
99 
     | 
    
         
             
                      elsif type.kind.interface? && (owner.kind.object? || owner.kind.interface?)
         
     | 
| 
       100 
100 
     | 
    
         
             
                        new_interfaces = []
         
     | 
| 
       101 
101 
     | 
    
         
             
                        owner.interfaces.each do |int_t|
         
     | 
| 
         @@ -110,7 +110,7 @@ module GraphQL 
     | 
|
| 
       110 
110 
     | 
    
         
             
                        end
         
     | 
| 
       111 
111 
     | 
    
         
             
                        owner.implements(*new_interfaces)
         
     | 
| 
       112 
112 
     | 
    
         
             
                        new_interfaces.each do |int|
         
     | 
| 
       113 
     | 
    
         
            -
                          pt = @possible_types[int 
     | 
| 
      
 113 
     | 
    
         
            +
                          pt = @possible_types[int] ||= []
         
     | 
| 
       114 
114 
     | 
    
         
             
                          if !pt.include?(owner) && owner.is_a?(Class)
         
     | 
| 
       115 
115 
     | 
    
         
             
                            pt << owner
         
     | 
| 
       116 
116 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -126,6 +126,7 @@ module GraphQL 
     | 
|
| 
       126 
126 
     | 
    
         
             
                      @types[type.graphql_name] = type
         
     | 
| 
       127 
127 
     | 
    
         
             
                    when GraphQL::Schema::Field, GraphQL::Schema::Argument
         
     | 
| 
       128 
128 
     | 
    
         
             
                      orig_type = owner.type
         
     | 
| 
      
 129 
     | 
    
         
            +
                      unwrapped_t = type
         
     | 
| 
       129 
130 
     | 
    
         
             
                      # Apply list/non-null wrapper as needed
         
     | 
| 
       130 
131 
     | 
    
         
             
                      if orig_type.respond_to?(:of_type)
         
     | 
| 
       131 
132 
     | 
    
         
             
                        transforms = []
         
     | 
| 
         @@ -142,6 +143,7 @@ module GraphQL 
     | 
|
| 
       142 
143 
     | 
    
         
             
                        transforms.reverse_each { |t| type = type.public_send(t) }
         
     | 
| 
       143 
144 
     | 
    
         
             
                      end
         
     | 
| 
       144 
145 
     | 
    
         
             
                      owner.type = type
         
     | 
| 
      
 146 
     | 
    
         
            +
                      references_to(unwrapped_t, from: owner)
         
     | 
| 
       145 
147 
     | 
    
         
             
                    else
         
     | 
| 
       146 
148 
     | 
    
         
             
                      raise "Unexpected update: #{owner.inspect} #{type.inspect}"
         
     | 
| 
       147 
149 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -164,7 +166,9 @@ module GraphQL 
     | 
|
| 
       164 
166 
     | 
    
         
             
                      @directives << type
         
     | 
| 
       165 
167 
     | 
    
         
             
                      type.all_argument_definitions.each do |arg|
         
     | 
| 
       166 
168 
     | 
    
         
             
                        arg_type = arg.type.unwrap
         
     | 
| 
       167 
     | 
    
         
            -
                         
     | 
| 
      
 169 
     | 
    
         
            +
                        if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
         
     | 
| 
      
 170 
     | 
    
         
            +
                          references_to(arg_type, from: arg)
         
     | 
| 
      
 171 
     | 
    
         
            +
                        end
         
     | 
| 
       168 
172 
     | 
    
         
             
                        path.push(arg.graphql_name)
         
     | 
| 
       169 
173 
     | 
    
         
             
                        add_type(arg_type, owner: arg, late_types: late_types, path: path)
         
     | 
| 
       170 
174 
     | 
    
         
             
                        path.pop
         
     | 
| 
         @@ -187,14 +191,18 @@ module GraphQL 
     | 
|
| 
       187 
191 
     | 
    
         
             
                        type.all_field_definitions.each do |field|
         
     | 
| 
       188 
192 
     | 
    
         
             
                          name = field.graphql_name
         
     | 
| 
       189 
193 
     | 
    
         
             
                          field_type = field.type.unwrap
         
     | 
| 
       190 
     | 
    
         
            -
                           
     | 
| 
      
 194 
     | 
    
         
            +
                          if !field_type.is_a?(GraphQL::Schema::LateBoundType)
         
     | 
| 
      
 195 
     | 
    
         
            +
                            references_to(field_type, from: field)
         
     | 
| 
      
 196 
     | 
    
         
            +
                          end
         
     | 
| 
       191 
197 
     | 
    
         
             
                          path.push(name)
         
     | 
| 
       192 
198 
     | 
    
         
             
                          add_type(field_type, owner: field, late_types: late_types, path: path)
         
     | 
| 
       193 
199 
     | 
    
         
             
                          add_directives_from(field)
         
     | 
| 
       194 
200 
     | 
    
         
             
                          field.all_argument_definitions.each do |arg|
         
     | 
| 
       195 
201 
     | 
    
         
             
                            add_directives_from(arg)
         
     | 
| 
       196 
202 
     | 
    
         
             
                            arg_type = arg.type.unwrap
         
     | 
| 
       197 
     | 
    
         
            -
                             
     | 
| 
      
 203 
     | 
    
         
            +
                            if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
         
     | 
| 
      
 204 
     | 
    
         
            +
                              references_to(arg_type, from: arg)
         
     | 
| 
      
 205 
     | 
    
         
            +
                            end
         
     | 
| 
       198 
206 
     | 
    
         
             
                            path.push(arg.graphql_name)
         
     | 
| 
       199 
207 
     | 
    
         
             
                            add_type(arg_type, owner: arg, late_types: late_types, path: path)
         
     | 
| 
       200 
208 
     | 
    
         
             
                            path.pop
         
     | 
| 
         @@ -209,7 +217,9 @@ module GraphQL 
     | 
|
| 
       209 
217 
     | 
    
         
             
                        type.all_argument_definitions.each do |arg|
         
     | 
| 
       210 
218 
     | 
    
         
             
                          add_directives_from(arg)
         
     | 
| 
       211 
219 
     | 
    
         
             
                          arg_type = arg.type.unwrap
         
     | 
| 
       212 
     | 
    
         
            -
                           
     | 
| 
      
 220 
     | 
    
         
            +
                          if !arg_type.is_a?(GraphQL::Schema::LateBoundType)
         
     | 
| 
      
 221 
     | 
    
         
            +
                            references_to(arg_type, from: arg)
         
     | 
| 
      
 222 
     | 
    
         
            +
                          end
         
     | 
| 
       213 
223 
     | 
    
         
             
                          path.push(arg.graphql_name)
         
     | 
| 
       214 
224 
     | 
    
         
             
                          add_type(arg_type, owner: arg, late_types: late_types, path: path)
         
     | 
| 
       215 
225 
     | 
    
         
             
                          path.pop
         
     | 
| 
         @@ -219,7 +229,7 @@ module GraphQL 
     | 
|
| 
       219 
229 
     | 
    
         
             
                        end
         
     | 
| 
       220 
230 
     | 
    
         
             
                      end
         
     | 
| 
       221 
231 
     | 
    
         
             
                      if type.kind.union?
         
     | 
| 
       222 
     | 
    
         
            -
                        @possible_types[type 
     | 
| 
      
 232 
     | 
    
         
            +
                        @possible_types[type] = type.all_possible_types
         
     | 
| 
       223 
233 
     | 
    
         
             
                        path.push("possible_types")
         
     | 
| 
       224 
234 
     | 
    
         
             
                        type.all_possible_types.each do |t|
         
     | 
| 
       225 
235 
     | 
    
         
             
                          add_type(t, owner: type, late_types: late_types, path: path)
         
     | 
| 
         @@ -234,7 +244,7 @@ module GraphQL 
     | 
|
| 
       234 
244 
     | 
    
         
             
                        path.pop
         
     | 
| 
       235 
245 
     | 
    
         
             
                      end
         
     | 
| 
       236 
246 
     | 
    
         
             
                      if type.kind.object?
         
     | 
| 
       237 
     | 
    
         
            -
                        possible_types_for_this_name = @possible_types[type 
     | 
| 
      
 247 
     | 
    
         
            +
                        possible_types_for_this_name = @possible_types[type] ||= []
         
     | 
| 
       238 
248 
     | 
    
         
             
                        possible_types_for_this_name << type
         
     | 
| 
       239 
249 
     | 
    
         
             
                      end
         
     | 
| 
       240 
250 
     | 
    
         | 
| 
         @@ -246,7 +256,7 @@ module GraphQL 
     | 
|
| 
       246 
256 
     | 
    
         
             
                            interface_type = interface_type_membership.abstract_type
         
     | 
| 
       247 
257 
     | 
    
         
             
                            # We can get these now; we'll have to get late-bound types later
         
     | 
| 
       248 
258 
     | 
    
         
             
                            if interface_type.is_a?(Module) && type.is_a?(Class)
         
     | 
| 
       249 
     | 
    
         
            -
                              implementers = @possible_types[interface_type 
     | 
| 
      
 259 
     | 
    
         
            +
                              implementers = @possible_types[interface_type] ||= []
         
     | 
| 
       250 
260 
     | 
    
         
             
                              implementers << type
         
     | 
| 
       251 
261 
     | 
    
         
             
                            end
         
     | 
| 
       252 
262 
     | 
    
         
             
                          when String, Schema::LateBoundType
         
     | 
| 
         @@ -312,10 +312,15 @@ module GraphQL 
     | 
|
| 
       312 
312 
     | 
    
         
             
                      context.query.after_lazy(custom_loaded_value) do |custom_value|
         
     | 
| 
       313 
313 
     | 
    
         
             
                        if loads
         
     | 
| 
       314 
314 
     | 
    
         
             
                          if type.list?
         
     | 
| 
       315 
     | 
    
         
            -
                            loaded_values =  
     | 
| 
       316 
     | 
    
         
            -
             
     | 
| 
       317 
     | 
    
         
            -
                               
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
      
 315 
     | 
    
         
            +
                            loaded_values = []
         
     | 
| 
      
 316 
     | 
    
         
            +
                            context.dataloader.run_isolated do
         
     | 
| 
      
 317 
     | 
    
         
            +
                              custom_value.each_with_index.map { |custom_val, idx|
         
     | 
| 
      
 318 
     | 
    
         
            +
                                id = coerced_value[idx]
         
     | 
| 
      
 319 
     | 
    
         
            +
                                context.dataloader.append_job do
         
     | 
| 
      
 320 
     | 
    
         
            +
                                  loaded_values[idx] = load_method_owner.authorize_application_object(self, id, context, custom_val)
         
     | 
| 
      
 321 
     | 
    
         
            +
                                end
         
     | 
| 
      
 322 
     | 
    
         
            +
                              }
         
     | 
| 
      
 323 
     | 
    
         
            +
                            end
         
     | 
| 
       319 
324 
     | 
    
         
             
                            context.schema.after_any_lazies(loaded_values, &:itself)
         
     | 
| 
       320 
325 
     | 
    
         
             
                          else
         
     | 
| 
       321 
326 
     | 
    
         
             
                            load_method_owner.authorize_application_object(self, coerced_value, context, custom_loaded_value)
         
     | 
| 
         @@ -326,7 +331,16 @@ module GraphQL 
     | 
|
| 
       326 
331 
     | 
    
         
             
                      end
         
     | 
| 
       327 
332 
     | 
    
         
             
                    elsif loads
         
     | 
| 
       328 
333 
     | 
    
         
             
                      if type.list?
         
     | 
| 
       329 
     | 
    
         
            -
                        loaded_values =  
     | 
| 
      
 334 
     | 
    
         
            +
                        loaded_values = []
         
     | 
| 
      
 335 
     | 
    
         
            +
                        # We want to run these list items all together,
         
     | 
| 
      
 336 
     | 
    
         
            +
                        # but we also need to wait for the result so we can return it :S
         
     | 
| 
      
 337 
     | 
    
         
            +
                        context.dataloader.run_isolated do
         
     | 
| 
      
 338 
     | 
    
         
            +
                          coerced_value.each_with_index { |val, idx|
         
     | 
| 
      
 339 
     | 
    
         
            +
                            context.dataloader.append_job do
         
     | 
| 
      
 340 
     | 
    
         
            +
                              loaded_values[idx] = load_method_owner.load_and_authorize_application_object(self, val, context)
         
     | 
| 
      
 341 
     | 
    
         
            +
                            end
         
     | 
| 
      
 342 
     | 
    
         
            +
                          }
         
     | 
| 
      
 343 
     | 
    
         
            +
                        end
         
     | 
| 
       330 
344 
     | 
    
         
             
                        context.schema.after_any_lazies(loaded_values, &:itself)
         
     | 
| 
       331 
345 
     | 
    
         
             
                      else
         
     | 
| 
       332 
346 
     | 
    
         
             
                        load_method_owner.load_and_authorize_application_object(self, coerced_value, context)
         
     | 
| 
         @@ -188,6 +188,8 @@ module GraphQL 
     | 
|
| 
       188 
188 
     | 
    
         
             
                        assert_has_location(SCALAR)
         
     | 
| 
       189 
189 
     | 
    
         
             
                      elsif @owner < GraphQL::Schema
         
     | 
| 
       190 
190 
     | 
    
         
             
                        assert_has_location(SCHEMA)
         
     | 
| 
      
 191 
     | 
    
         
            +
                      elsif @owner < GraphQL::Schema::Resolver
         
     | 
| 
      
 192 
     | 
    
         
            +
                        assert_has_location(FIELD_DEFINITION)
         
     | 
| 
       191 
193 
     | 
    
         
             
                      else
         
     | 
| 
       192 
194 
     | 
    
         
             
                        raise "Unexpected directive owner class: #{@owner}"
         
     | 
| 
       193 
195 
     | 
    
         
             
                      end
         
     |