graphql 1.11.6 → 1.13.19
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/core.rb +3 -8
 - data/lib/generators/graphql/enum_generator.rb +4 -10
 - data/lib/generators/graphql/field_extractor.rb +31 -0
 - data/lib/generators/graphql/input_generator.rb +50 -0
 - data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
 - data/lib/generators/graphql/install_generator.rb +17 -7
 - data/lib/generators/graphql/interface_generator.rb +7 -7
 - data/lib/generators/graphql/loader_generator.rb +1 -0
 - data/lib/generators/graphql/mutation_create_generator.rb +22 -0
 - data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
 - data/lib/generators/graphql/mutation_generator.rb +6 -30
 - data/lib/generators/graphql/mutation_update_generator.rb +22 -0
 - data/lib/generators/graphql/object_generator.rb +12 -38
 - data/lib/generators/graphql/orm_mutations_base.rb +40 -0
 - data/lib/generators/graphql/relay.rb +63 -0
 - data/lib/generators/graphql/relay_generator.rb +21 -0
 - data/lib/generators/graphql/scalar_generator.rb +4 -2
 - data/lib/generators/graphql/templates/base_connection.erb +8 -0
 - data/lib/generators/graphql/templates/base_edge.erb +8 -0
 - data/lib/generators/graphql/templates/enum.erb +5 -1
 - data/lib/generators/graphql/templates/graphql_controller.erb +2 -2
 - data/lib/generators/graphql/templates/input.erb +9 -0
 - data/lib/generators/graphql/templates/interface.erb +4 -2
 - data/lib/generators/graphql/templates/mutation.erb +1 -1
 - data/lib/generators/graphql/templates/mutation_create.erb +20 -0
 - data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
 - data/lib/generators/graphql/templates/mutation_update.erb +21 -0
 - data/lib/generators/graphql/templates/node_type.erb +9 -0
 - data/lib/generators/graphql/templates/object.erb +5 -3
 - data/lib/generators/graphql/templates/query_type.erb +1 -3
 - data/lib/generators/graphql/templates/scalar.erb +3 -1
 - data/lib/generators/graphql/templates/schema.erb +19 -34
 - data/lib/generators/graphql/templates/union.erb +4 -2
 - data/lib/generators/graphql/type_generator.rb +47 -10
 - data/lib/generators/graphql/union_generator.rb +5 -5
 - data/lib/graphql/analysis/analyze_query.rb +7 -0
 - data/lib/graphql/analysis/ast/field_usage.rb +28 -1
 - data/lib/graphql/analysis/ast/query_complexity.rb +10 -14
 - data/lib/graphql/analysis/ast/visitor.rb +14 -5
 - data/lib/graphql/analysis/ast.rb +11 -2
 - data/lib/graphql/argument.rb +1 -1
 - data/lib/graphql/backtrace/inspect_result.rb +0 -1
 - data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
 - data/lib/graphql/backtrace/table.rb +34 -3
 - data/lib/graphql/backtrace/traced_error.rb +0 -1
 - data/lib/graphql/backtrace/tracer.rb +40 -10
 - data/lib/graphql/backtrace.rb +28 -19
 - data/lib/graphql/backwards_compatibility.rb +2 -1
 - data/lib/graphql/base_type.rb +6 -4
 - data/lib/graphql/boolean_type.rb +1 -1
 - data/lib/graphql/compatibility/execution_specification.rb +1 -0
 - data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
 - data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
 - data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
 - data/lib/graphql/dataloader/null_dataloader.rb +22 -0
 - data/lib/graphql/dataloader/request.rb +19 -0
 - data/lib/graphql/dataloader/request_all.rb +19 -0
 - data/lib/graphql/dataloader/source.rb +155 -0
 - data/lib/graphql/dataloader.rb +308 -0
 - data/lib/graphql/date_encoding_error.rb +16 -0
 - data/lib/graphql/define/assign_global_id_field.rb +1 -1
 - data/lib/graphql/define/instance_definable.rb +48 -3
 - data/lib/graphql/define/type_definer.rb +5 -5
 - data/lib/graphql/deprecated_dsl.rb +18 -5
 - data/lib/graphql/deprecation.rb +9 -0
 - data/lib/graphql/directive/deprecated_directive.rb +1 -1
 - data/lib/graphql/directive/include_directive.rb +1 -1
 - data/lib/graphql/directive/skip_directive.rb +1 -1
 - data/lib/graphql/directive.rb +1 -5
 - data/lib/graphql/enum_type.rb +9 -3
 - data/lib/graphql/execution/errors.rb +110 -7
 - data/lib/graphql/execution/execute.rb +8 -1
 - data/lib/graphql/execution/interpreter/arguments.rb +57 -5
 - data/lib/graphql/execution/interpreter/arguments_cache.rb +49 -15
 - data/lib/graphql/execution/interpreter/handles_raw_value.rb +0 -7
 - data/lib/graphql/execution/interpreter/resolve.rb +37 -25
 - data/lib/graphql/execution/interpreter/runtime.rb +670 -294
 - data/lib/graphql/execution/interpreter.rb +16 -16
 - data/lib/graphql/execution/lazy.rb +5 -1
 - data/lib/graphql/execution/lookahead.rb +2 -2
 - data/lib/graphql/execution/multiplex.rb +39 -23
 - data/lib/graphql/field.rb +1 -1
 - data/lib/graphql/float_type.rb +1 -1
 - data/lib/graphql/function.rb +4 -0
 - data/lib/graphql/id_type.rb +1 -1
 - data/lib/graphql/input_object_type.rb +3 -1
 - data/lib/graphql/int_type.rb +1 -1
 - data/lib/graphql/integer_decoding_error.rb +17 -0
 - data/lib/graphql/integer_encoding_error.rb +18 -2
 - data/lib/graphql/interface_type.rb +4 -2
 - data/lib/graphql/internal_representation/document.rb +2 -2
 - data/lib/graphql/internal_representation/rewrite.rb +1 -1
 - data/lib/graphql/introspection/directive_location_enum.rb +2 -2
 - data/lib/graphql/introspection/directive_type.rb +11 -5
 - data/lib/graphql/introspection/entry_points.rb +2 -2
 - data/lib/graphql/introspection/enum_value_type.rb +2 -2
 - data/lib/graphql/introspection/field_type.rb +3 -3
 - data/lib/graphql/introspection/input_value_type.rb +10 -4
 - data/lib/graphql/introspection/schema_type.rb +10 -5
 - data/lib/graphql/introspection/type_type.rb +18 -12
 - data/lib/graphql/introspection.rb +5 -2
 - data/lib/graphql/invalid_null_error.rb +1 -1
 - data/lib/graphql/language/block_string.rb +2 -6
 - data/lib/graphql/language/cache.rb +37 -0
 - data/lib/graphql/language/document_from_schema_definition.rb +60 -26
 - data/lib/graphql/language/lexer.rb +50 -28
 - data/lib/graphql/language/lexer.rl +2 -4
 - data/lib/graphql/language/nodes.rb +14 -4
 - data/lib/graphql/language/parser.rb +856 -825
 - data/lib/graphql/language/parser.y +28 -11
 - data/lib/graphql/language/printer.rb +10 -1
 - data/lib/graphql/language/sanitized_printer.rb +5 -5
 - data/lib/graphql/language/token.rb +0 -4
 - data/lib/graphql/language.rb +1 -0
 - data/lib/graphql/name_validator.rb +0 -4
 - data/lib/graphql/object_type.rb +4 -4
 - data/lib/graphql/pagination/active_record_relation_connection.rb +47 -3
 - data/lib/graphql/pagination/connection.rb +19 -1
 - data/lib/graphql/pagination/connections.rb +45 -30
 - data/lib/graphql/pagination/relation_connection.rb +69 -28
 - data/lib/graphql/parse_error.rb +0 -1
 - data/lib/graphql/query/arguments.rb +2 -2
 - data/lib/graphql/query/arguments_cache.rb +1 -2
 - data/lib/graphql/query/context.rb +22 -4
 - data/lib/graphql/query/executor.rb +0 -1
 - data/lib/graphql/query/input_validation_result.rb +9 -0
 - data/lib/graphql/query/literal_input.rb +1 -1
 - data/lib/graphql/query/null_context.rb +21 -9
 - data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
 - data/lib/graphql/query/serial_execution.rb +1 -0
 - data/lib/graphql/query/validation_pipeline.rb +3 -4
 - data/lib/graphql/query/variable_validation_error.rb +3 -3
 - data/lib/graphql/query/variables.rb +35 -4
 - data/lib/graphql/query.rb +20 -8
 - data/lib/graphql/railtie.rb +9 -1
 - data/lib/graphql/rake_task.rb +3 -0
 - data/lib/graphql/relay/array_connection.rb +2 -2
 - data/lib/graphql/relay/base_connection.rb +7 -0
 - data/lib/graphql/relay/connection_instrumentation.rb +4 -4
 - data/lib/graphql/relay/connection_type.rb +16 -3
 - data/lib/graphql/relay/edges_instrumentation.rb +0 -1
 - data/lib/graphql/relay/global_id_resolve.rb +1 -2
 - data/lib/graphql/relay/mutation.rb +2 -1
 - data/lib/graphql/relay/node.rb +3 -0
 - data/lib/graphql/relay/page_info.rb +1 -1
 - data/lib/graphql/relay/range_add.rb +14 -5
 - data/lib/graphql/relay/type_extensions.rb +2 -0
 - data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
 - data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
 - data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
 - data/lib/graphql/rubocop.rb +4 -0
 - data/lib/graphql/scalar_type.rb +3 -1
 - data/lib/graphql/schema/addition.rb +247 -0
 - data/lib/graphql/schema/argument.rb +177 -21
 - data/lib/graphql/schema/build_from_definition.rb +150 -55
 - data/lib/graphql/schema/default_type_error.rb +2 -0
 - data/lib/graphql/schema/directive/feature.rb +1 -1
 - data/lib/graphql/schema/directive/flagged.rb +57 -0
 - data/lib/graphql/schema/directive/include.rb +1 -1
 - data/lib/graphql/schema/directive/skip.rb +1 -1
 - data/lib/graphql/schema/directive/transform.rb +14 -2
 - data/lib/graphql/schema/directive.rb +103 -4
 - data/lib/graphql/schema/enum.rb +72 -11
 - data/lib/graphql/schema/enum_value.rb +18 -6
 - data/lib/graphql/schema/field/connection_extension.rb +4 -2
 - data/lib/graphql/schema/field/scope_extension.rb +1 -1
 - data/lib/graphql/schema/field.rb +332 -111
 - data/lib/graphql/schema/field_extension.rb +89 -2
 - data/lib/graphql/schema/find_inherited_value.rb +4 -1
 - data/lib/graphql/schema/finder.rb +5 -5
 - data/lib/graphql/schema/input_object.rb +79 -55
 - data/lib/graphql/schema/interface.rb +12 -20
 - data/lib/graphql/schema/introspection_system.rb +1 -1
 - data/lib/graphql/schema/list.rb +21 -4
 - data/lib/graphql/schema/loader.rb +11 -0
 - data/lib/graphql/schema/member/accepts_definition.rb +15 -3
 - data/lib/graphql/schema/member/base_dsl_methods.rb +5 -16
 - data/lib/graphql/schema/member/build_type.rb +4 -7
 - data/lib/graphql/schema/member/cached_graphql_definition.rb +29 -2
 - data/lib/graphql/schema/member/has_arguments.rb +166 -74
 - data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
 - data/lib/graphql/schema/member/has_directives.rb +98 -0
 - data/lib/graphql/schema/member/has_fields.rb +77 -22
 - data/lib/graphql/schema/member/has_interfaces.rb +100 -0
 - data/lib/graphql/schema/member/has_validators.rb +31 -0
 - data/lib/graphql/schema/member/instrumentation.rb +0 -1
 - data/lib/graphql/schema/member/type_system_helpers.rb +1 -1
 - data/lib/graphql/schema/member/validates_input.rb +2 -2
 - data/lib/graphql/schema/member.rb +5 -0
 - data/lib/graphql/schema/middleware_chain.rb +1 -1
 - data/lib/graphql/schema/non_null.rb +9 -3
 - data/lib/graphql/schema/object.rb +40 -80
 - data/lib/graphql/schema/printer.rb +16 -20
 - data/lib/graphql/schema/relay_classic_mutation.rb +38 -4
 - data/lib/graphql/schema/resolver/has_payload_type.rb +29 -2
 - data/lib/graphql/schema/resolver.rb +110 -64
 - data/lib/graphql/schema/scalar.rb +18 -2
 - data/lib/graphql/schema/subscription.rb +55 -9
 - data/lib/graphql/schema/timeout_middleware.rb +3 -1
 - data/lib/graphql/schema/traversal.rb +1 -1
 - data/lib/graphql/schema/type_expression.rb +1 -1
 - data/lib/graphql/schema/type_membership.rb +18 -4
 - data/lib/graphql/schema/union.rb +8 -1
 - data/lib/graphql/schema/validation.rb +4 -2
 - data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
 - data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
 - data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
 - data/lib/graphql/schema/validator/format_validator.rb +48 -0
 - data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
 - data/lib/graphql/schema/validator/length_validator.rb +59 -0
 - data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
 - data/lib/graphql/schema/validator/required_validator.rb +82 -0
 - data/lib/graphql/schema/validator.rb +171 -0
 - data/lib/graphql/schema/warden.rb +126 -53
 - data/lib/graphql/schema.rb +262 -281
 - data/lib/graphql/static_validation/all_rules.rb +2 -0
 - data/lib/graphql/static_validation/base_visitor.rb +9 -6
 - data/lib/graphql/static_validation/definition_dependencies.rb +0 -1
 - data/lib/graphql/static_validation/error.rb +3 -1
 - data/lib/graphql/static_validation/literal_validator.rb +1 -1
 - data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +4 -2
 - data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +6 -2
 - data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
 - data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
 - data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
 - data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +1 -1
 - data/lib/graphql/static_validation/rules/fields_will_merge.rb +90 -47
 - data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
 - data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
 - data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
 - data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
 - data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
 - data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
 - data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -2
 - data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
 - data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
 - data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +14 -8
 - data/lib/graphql/static_validation/validation_context.rb +12 -2
 - data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
 - data/lib/graphql/static_validation/validator.rb +41 -10
 - data/lib/graphql/static_validation.rb +1 -0
 - data/lib/graphql/string_encoding_error.rb +13 -3
 - data/lib/graphql/string_type.rb +1 -1
 - data/lib/graphql/subscriptions/action_cable_subscriptions.rb +39 -8
 - data/lib/graphql/subscriptions/broadcast_analyzer.rb +0 -3
 - data/lib/graphql/subscriptions/event.rb +68 -32
 - data/lib/graphql/subscriptions/instrumentation.rb +0 -1
 - data/lib/graphql/subscriptions/serialize.rb +34 -5
 - data/lib/graphql/subscriptions/subscription_root.rb +1 -1
 - data/lib/graphql/subscriptions.rb +34 -39
 - data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -21
 - data/lib/graphql/tracing/appoptics_tracing.rb +3 -1
 - data/lib/graphql/tracing/appsignal_tracing.rb +15 -0
 - data/lib/graphql/tracing/data_dog_tracing.rb +24 -2
 - data/lib/graphql/tracing/notifications_tracing.rb +59 -0
 - data/lib/graphql/tracing/platform_tracing.rb +24 -12
 - data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
 - data/lib/graphql/tracing/skylight_tracing.rb +1 -1
 - data/lib/graphql/tracing.rb +2 -2
 - data/lib/graphql/types/big_int.rb +5 -1
 - data/lib/graphql/types/int.rb +10 -3
 - data/lib/graphql/types/iso_8601_date.rb +13 -5
 - data/lib/graphql/types/iso_8601_date_time.rb +8 -1
 - data/lib/graphql/types/relay/base_connection.rb +6 -91
 - data/lib/graphql/types/relay/base_edge.rb +2 -34
 - data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
 - data/lib/graphql/types/relay/default_relay.rb +31 -0
 - data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
 - data/lib/graphql/types/relay/has_node_field.rb +41 -0
 - data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
 - data/lib/graphql/types/relay/node.rb +2 -4
 - data/lib/graphql/types/relay/node_behaviors.rb +15 -0
 - data/lib/graphql/types/relay/node_field.rb +3 -22
 - data/lib/graphql/types/relay/nodes_field.rb +16 -18
 - data/lib/graphql/types/relay/page_info.rb +2 -14
 - data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
 - data/lib/graphql/types/relay.rb +11 -3
 - data/lib/graphql/types/string.rb +8 -2
 - data/lib/graphql/unauthorized_error.rb +1 -1
 - data/lib/graphql/union_type.rb +3 -1
 - data/lib/graphql/upgrader/member.rb +1 -0
 - data/lib/graphql/upgrader/schema.rb +1 -0
 - data/lib/graphql/version.rb +1 -1
 - data/lib/graphql.rb +68 -37
 - data/readme.md +3 -6
 - metadata +83 -113
 - data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
 - data/lib/graphql/types/relay/base_field.rb +0 -22
 - data/lib/graphql/types/relay/base_interface.rb +0 -29
 - data/lib/graphql/types/relay/base_object.rb +0 -26
 - /data/lib/generators/graphql/{templates → install/templates}/base_mutation.erb +0 -0
 - /data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +0 -0
 
| 
         @@ -18,17 +18,83 @@ module GraphQL 
     | 
|
| 
       18 
18 
     | 
    
         
             
                #
         
     | 
| 
       19 
19 
     | 
    
         
             
                class Errors
         
     | 
| 
       20 
20 
     | 
    
         
             
                  def self.use(schema)
         
     | 
| 
       21 
     | 
    
         
            -
                     
     | 
| 
      
 21 
     | 
    
         
            +
                    definition_line = caller(2, 1).first
         
     | 
| 
      
 22 
     | 
    
         
            +
                    GraphQL::Deprecation.warn("GraphQL::Execution::Errors is now installed by default, remove `use GraphQL::Execution::Errors` from #{definition_line}")
         
     | 
| 
       22 
23 
     | 
    
         
             
                  end
         
     | 
| 
       23 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
                  NEW_HANDLER_HASH = ->(h, k) {
         
     | 
| 
      
 26 
     | 
    
         
            +
                    h[k] = {
         
     | 
| 
      
 27 
     | 
    
         
            +
                      class: k,
         
     | 
| 
      
 28 
     | 
    
         
            +
                      handler: nil,
         
     | 
| 
      
 29 
     | 
    
         
            +
                      subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
         
     | 
| 
      
 30 
     | 
    
         
            +
                     }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       24 
33 
     | 
    
         
             
                  def initialize(schema)
         
     | 
| 
       25 
34 
     | 
    
         
             
                    @schema = schema
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @handlers = {
         
     | 
| 
      
 36 
     | 
    
         
            +
                      class: nil,
         
     | 
| 
      
 37 
     | 
    
         
            +
                      handler: nil,
         
     | 
| 
      
 38 
     | 
    
         
            +
                      subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
         
     | 
| 
      
 39 
     | 
    
         
            +
                    }
         
     | 
| 
       26 
40 
     | 
    
         
             
                  end
         
     | 
| 
       27 
41 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # @api private
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def each_rescue
         
     | 
| 
      
 44 
     | 
    
         
            +
                    handlers = @handlers.values
         
     | 
| 
      
 45 
     | 
    
         
            +
                    while (handler = handlers.shift) do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      yield(handler[:class], handler[:handler])
         
     | 
| 
      
 47 
     | 
    
         
            +
                      handlers.concat(handler[:subclass_handlers].values)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # Register this handler, updating the
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # internal handler index to maintain least-to-most specific.
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # @param error_class [Class<Exception>]
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @param error_handler [Proc]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  # @return [void]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def rescue_from(error_class, error_handler)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    subclasses_handlers = {}
         
     | 
| 
      
 59 
     | 
    
         
            +
                    this_level_subclasses = []
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # During this traversal, do two things:
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # - Identify any already-registered subclasses of this error class
         
     | 
| 
      
 62 
     | 
    
         
            +
                    #   and gather them up to be inserted _under_ this class
         
     | 
| 
      
 63 
     | 
    
         
            +
                    # - Find the point in the index where this handler should be inserted
         
     | 
| 
      
 64 
     | 
    
         
            +
                    #   (That is, _under_ any superclasses, or at top-level, if there are no superclasses registered)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    handlers = @handlers[:subclass_handlers]
         
     | 
| 
      
 66 
     | 
    
         
            +
                    while (handlers) do
         
     | 
| 
      
 67 
     | 
    
         
            +
                      this_level_subclasses.clear
         
     | 
| 
      
 68 
     | 
    
         
            +
                      # First, identify already-loaded handlers that belong
         
     | 
| 
      
 69 
     | 
    
         
            +
                      # _under_ this one. (That is, they're handlers
         
     | 
| 
      
 70 
     | 
    
         
            +
                      # for subclasses of `error_class`.)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      handlers.each do |err_class, handler|
         
     | 
| 
      
 72 
     | 
    
         
            +
                        if err_class < error_class
         
     | 
| 
      
 73 
     | 
    
         
            +
                          subclasses_handlers[err_class] = handler
         
     | 
| 
      
 74 
     | 
    
         
            +
                          this_level_subclasses << err_class
         
     | 
| 
      
 75 
     | 
    
         
            +
                        end
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
                      # Any handlers that we'll be moving, delete them from this point in the index
         
     | 
| 
      
 78 
     | 
    
         
            +
                      this_level_subclasses.each do |err_class|
         
     | 
| 
      
 79 
     | 
    
         
            +
                        handlers.delete(err_class)
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                      # See if any keys in this hash are superclasses of this new class:
         
     | 
| 
      
 83 
     | 
    
         
            +
                      next_index_point = handlers.find { |err_class, handler| error_class < err_class }
         
     | 
| 
      
 84 
     | 
    
         
            +
                      if next_index_point
         
     | 
| 
      
 85 
     | 
    
         
            +
                        handlers = next_index_point[1][:subclass_handlers]
         
     | 
| 
      
 86 
     | 
    
         
            +
                      else
         
     | 
| 
      
 87 
     | 
    
         
            +
                        # this new handler doesn't belong to any sub-handlers,
         
     | 
| 
      
 88 
     | 
    
         
            +
                        # so insert it in the current set of `handlers`
         
     | 
| 
      
 89 
     | 
    
         
            +
                        break
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
       31 
91 
     | 
    
         
             
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                    # Having found the point at which to insert this handler,
         
     | 
| 
      
 93 
     | 
    
         
            +
                    # register it and merge any subclass handlers back in at this point.
         
     | 
| 
      
 94 
     | 
    
         
            +
                    this_class_handlers = handlers[error_class]
         
     | 
| 
      
 95 
     | 
    
         
            +
                    this_class_handlers[:handler] = error_handler
         
     | 
| 
      
 96 
     | 
    
         
            +
                    this_class_handlers[:subclass_handlers].merge!(subclasses_handlers)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    nil
         
     | 
| 
       32 
98 
     | 
    
         
             
                  end
         
     | 
| 
       33 
99 
     | 
    
         | 
| 
       34 
100 
     | 
    
         
             
                  # Call the given block with the schema's configured error handlers.
         
     | 
| 
         @@ -40,21 +106,58 @@ module GraphQL 
     | 
|
| 
       40 
106 
     | 
    
         
             
                  def with_error_handling(ctx)
         
     | 
| 
       41 
107 
     | 
    
         
             
                    yield
         
     | 
| 
       42 
108 
     | 
    
         
             
                  rescue StandardError => err
         
     | 
| 
       43 
     | 
    
         
            -
                     
     | 
| 
       44 
     | 
    
         
            -
                    _err_class, handler = rescues.find { |err_class, handler| err.is_a?(err_class) }
         
     | 
| 
      
 109 
     | 
    
         
            +
                    handler = find_handler_for(err.class)
         
     | 
| 
       45 
110 
     | 
    
         
             
                    if handler
         
     | 
| 
       46 
111 
     | 
    
         
             
                      runtime_info = ctx.namespace(:interpreter) || {}
         
     | 
| 
       47 
112 
     | 
    
         
             
                      obj = runtime_info[:current_object]
         
     | 
| 
       48 
113 
     | 
    
         
             
                      args = runtime_info[:current_arguments]
         
     | 
| 
      
 114 
     | 
    
         
            +
                      args = args && args.keyword_arguments
         
     | 
| 
       49 
115 
     | 
    
         
             
                      field = runtime_info[:current_field]
         
     | 
| 
       50 
116 
     | 
    
         
             
                      if obj.is_a?(GraphQL::Schema::Object)
         
     | 
| 
       51 
117 
     | 
    
         
             
                        obj = obj.object
         
     | 
| 
       52 
118 
     | 
    
         
             
                      end
         
     | 
| 
       53 
     | 
    
         
            -
                      handler.call(err, obj, args, ctx, field)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      handler[:handler].call(err, obj, args, ctx, field)
         
     | 
| 
       54 
120 
     | 
    
         
             
                    else
         
     | 
| 
       55 
121 
     | 
    
         
             
                      raise err
         
     | 
| 
       56 
122 
     | 
    
         
             
                    end
         
     | 
| 
       57 
123 
     | 
    
         
             
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  # @return [Proc, nil] The handler for `error_class`, if one was registered on this schema or inherited
         
     | 
| 
      
 126 
     | 
    
         
            +
                  def find_handler_for(error_class)
         
     | 
| 
      
 127 
     | 
    
         
            +
                    handlers = @handlers[:subclass_handlers]
         
     | 
| 
      
 128 
     | 
    
         
            +
                    handler = nil
         
     | 
| 
      
 129 
     | 
    
         
            +
                    while (handlers) do
         
     | 
| 
      
 130 
     | 
    
         
            +
                      _err_class, next_handler = handlers.find { |err_class, handler| error_class <= err_class }
         
     | 
| 
      
 131 
     | 
    
         
            +
                      if next_handler
         
     | 
| 
      
 132 
     | 
    
         
            +
                        handlers = next_handler[:subclass_handlers]
         
     | 
| 
      
 133 
     | 
    
         
            +
                        handler = next_handler
         
     | 
| 
      
 134 
     | 
    
         
            +
                      else
         
     | 
| 
      
 135 
     | 
    
         
            +
                        # Don't reassign `handler` --
         
     | 
| 
      
 136 
     | 
    
         
            +
                        # let the previous assignment carry over outside this block.
         
     | 
| 
      
 137 
     | 
    
         
            +
                        break
         
     | 
| 
      
 138 
     | 
    
         
            +
                      end
         
     | 
| 
      
 139 
     | 
    
         
            +
                    end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                    # check for a handler from a parent class:
         
     | 
| 
      
 142 
     | 
    
         
            +
                    if @schema.superclass.respond_to?(:error_handler) && (parent_errors = @schema.superclass.error_handler)
         
     | 
| 
      
 143 
     | 
    
         
            +
                      parent_handler = parent_errors.find_handler_for(error_class)
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    # If the inherited handler is more specific than the one defined here,
         
     | 
| 
      
 147 
     | 
    
         
            +
                    # use it.
         
     | 
| 
      
 148 
     | 
    
         
            +
                    # If it's a tie (or there is no parent handler), use the one defined here.
         
     | 
| 
      
 149 
     | 
    
         
            +
                    # If there's an inherited one, but not one defined here, use the inherited one.
         
     | 
| 
      
 150 
     | 
    
         
            +
                    # Otherwise, there's no handler for this error, return `nil`.
         
     | 
| 
      
 151 
     | 
    
         
            +
                    if parent_handler && handler && parent_handler[:class] < handler[:class]
         
     | 
| 
      
 152 
     | 
    
         
            +
                      parent_handler
         
     | 
| 
      
 153 
     | 
    
         
            +
                    elsif handler
         
     | 
| 
      
 154 
     | 
    
         
            +
                      handler
         
     | 
| 
      
 155 
     | 
    
         
            +
                    elsif parent_handler
         
     | 
| 
      
 156 
     | 
    
         
            +
                      parent_handler
         
     | 
| 
      
 157 
     | 
    
         
            +
                    else
         
     | 
| 
      
 158 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 159 
     | 
    
         
            +
                    end
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
       58 
161 
     | 
    
         
             
                end
         
     | 
| 
       59 
162 
     | 
    
         
             
              end
         
     | 
| 
       60 
163 
     | 
    
         
             
            end
         
     | 
| 
         @@ -6,7 +6,7 @@ module GraphQL 
     | 
|
| 
       6 
6 
     | 
    
         
             
                class Execute
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                  # @api private
         
     | 
| 
       9 
     | 
    
         
            -
                  class Skip; end
         
     | 
| 
      
 9 
     | 
    
         
            +
                  class Skip < GraphQL::Error; end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                  # Just a singleton for implementing {Query::Context#skip}
         
     | 
| 
       12 
12 
     | 
    
         
             
                  # @api private
         
     | 
| 
         @@ -18,7 +18,14 @@ module GraphQL 
     | 
|
| 
       18 
18 
     | 
    
         
             
                  # @api private
         
     | 
| 
       19 
19 
     | 
    
         
             
                  PROPAGATE_NULL = PropagateNull.new
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                  def self.use(schema_class)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    schema_class.query_execution_strategy(self)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    schema_class.mutation_execution_strategy(self)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    schema_class.subscription_execution_strategy(self)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       21 
27 
     | 
    
         
             
                  def execute(ast_operation, root_type, query)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    GraphQL::Deprecation.warn "#{self.class} will be removed in GraphQL-Ruby 2.0, please upgrade to the Interpreter: https://graphql-ruby.org/queries/interpreter.html"
         
     | 
| 
       22 
29 
     | 
    
         
             
                    result = resolve_root_selection(query)
         
     | 
| 
       23 
30 
     | 
    
         
             
                    lazy_resolve_root_selection(result, **{query: query})
         
     | 
| 
       24 
31 
     | 
    
         
             
                    GraphQL::Execution::Flatten.call(query.context)
         
     | 
| 
         @@ -5,6 +5,9 @@ module GraphQL 
     | 
|
| 
       5 
5 
     | 
    
         
             
                class Interpreter
         
     | 
| 
       6 
6 
     | 
    
         
             
                  # A wrapper for argument hashes in GraphQL queries.
         
     | 
| 
       7 
7 
     | 
    
         
             
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # This object is immutable so that the runtime code can be sure that
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # modifications don't leak from one use to another
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
       8 
11 
     | 
    
         
             
                  # @see GraphQL::Query#arguments_for to get access to these objects.
         
     | 
| 
       9 
12 
     | 
    
         
             
                  class Arguments
         
     | 
| 
       10 
13 
     | 
    
         
             
                    extend Forwardable
         
     | 
| 
         @@ -16,20 +19,69 @@ module GraphQL 
     | 
|
| 
       16 
19 
     | 
    
         
             
                    # @return [Hash<Symbol, Object>]
         
     | 
| 
       17 
20 
     | 
    
         
             
                    attr_reader :keyword_arguments
         
     | 
| 
       18 
21 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                     
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 22 
     | 
    
         
            +
                    # @param argument_values [nil, Hash{Symbol => ArgumentValue}]
         
     | 
| 
      
 23 
     | 
    
         
            +
                    # @param keyword_arguments [nil, Hash{Symbol => Object}]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    def initialize(keyword_arguments: nil, argument_values:)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      @empty = argument_values.nil? || argument_values.empty?
         
     | 
| 
      
 26 
     | 
    
         
            +
                      # This is only present when `extras` have been merged in:
         
     | 
| 
      
 27 
     | 
    
         
            +
                      if keyword_arguments
         
     | 
| 
      
 28 
     | 
    
         
            +
                        # This is a little crazy. We expect the `:argument_details` extra to _include extras_,
         
     | 
| 
      
 29 
     | 
    
         
            +
                        # but the object isn't created until _after_ extras are put together.
         
     | 
| 
      
 30 
     | 
    
         
            +
                        # So, we have to use a special flag here to say, "at the last minute, add yourself to the keyword args."
         
     | 
| 
      
 31 
     | 
    
         
            +
                        #
         
     | 
| 
      
 32 
     | 
    
         
            +
                        # Otherwise:
         
     | 
| 
      
 33 
     | 
    
         
            +
                        # - We can't access the final Arguments instance _while_ we're preparing extras
         
     | 
| 
      
 34 
     | 
    
         
            +
                        # - After we _can_ access it, it's frozen, so we can't add anything.
         
     | 
| 
      
 35 
     | 
    
         
            +
                        #
         
     | 
| 
      
 36 
     | 
    
         
            +
                        # So, this flag gives us a chance to sneak it in before freezing, _and_ while we have access
         
     | 
| 
      
 37 
     | 
    
         
            +
                        # to the new Arguments instance itself.
         
     | 
| 
      
 38 
     | 
    
         
            +
                        if keyword_arguments[:argument_details] == :__arguments_add_self
         
     | 
| 
      
 39 
     | 
    
         
            +
                          keyword_arguments[:argument_details] = self
         
     | 
| 
      
 40 
     | 
    
         
            +
                        end
         
     | 
| 
      
 41 
     | 
    
         
            +
                        @keyword_arguments = keyword_arguments.freeze
         
     | 
| 
      
 42 
     | 
    
         
            +
                      elsif !@empty
         
     | 
| 
      
 43 
     | 
    
         
            +
                        @keyword_arguments = {}
         
     | 
| 
      
 44 
     | 
    
         
            +
                        argument_values.each do |name, arg_val|
         
     | 
| 
      
 45 
     | 
    
         
            +
                          @keyword_arguments[name] = arg_val.value
         
     | 
| 
      
 46 
     | 
    
         
            +
                        end
         
     | 
| 
      
 47 
     | 
    
         
            +
                        @keyword_arguments.freeze
         
     | 
| 
      
 48 
     | 
    
         
            +
                      else
         
     | 
| 
      
 49 
     | 
    
         
            +
                        @keyword_arguments = NO_ARGS
         
     | 
| 
      
 50 
     | 
    
         
            +
                      end
         
     | 
| 
      
 51 
     | 
    
         
            +
                      @argument_values = argument_values ? argument_values.freeze : NO_ARGS
         
     | 
| 
      
 52 
     | 
    
         
            +
                      freeze
         
     | 
| 
       22 
53 
     | 
    
         
             
                    end
         
     | 
| 
       23 
54 
     | 
    
         | 
| 
       24 
55 
     | 
    
         
             
                    # @return [Hash{Symbol => ArgumentValue}]
         
     | 
| 
       25 
56 
     | 
    
         
             
                    attr_reader :argument_values
         
     | 
| 
       26 
57 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                     
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                    def empty?
         
     | 
| 
      
 59 
     | 
    
         
            +
                      @empty
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    def_delegators :keyword_arguments, :key?, :[], :fetch, :keys, :each, :values, :size, :to_h
         
     | 
| 
      
 63 
     | 
    
         
            +
                    def_delegators :argument_values, :each_value
         
     | 
| 
       29 
64 
     | 
    
         | 
| 
       30 
65 
     | 
    
         
             
                    def inspect
         
     | 
| 
       31 
66 
     | 
    
         
             
                      "#<#{self.class} @keyword_arguments=#{keyword_arguments.inspect}>"
         
     | 
| 
       32 
67 
     | 
    
         
             
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    # Create a new arguments instance which includes these extras.
         
     | 
| 
      
 70 
     | 
    
         
            +
                    #
         
     | 
| 
      
 71 
     | 
    
         
            +
                    # This is called by the runtime to implement field `extras: [...]`
         
     | 
| 
      
 72 
     | 
    
         
            +
                    #
         
     | 
| 
      
 73 
     | 
    
         
            +
                    # @param extra_args [Hash<Symbol => Object>]
         
     | 
| 
      
 74 
     | 
    
         
            +
                    # @return [Interpreter::Arguments]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    # @api private
         
     | 
| 
      
 76 
     | 
    
         
            +
                    def merge_extras(extra_args)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      self.class.new(
         
     | 
| 
      
 78 
     | 
    
         
            +
                        argument_values: argument_values,
         
     | 
| 
      
 79 
     | 
    
         
            +
                        keyword_arguments: keyword_arguments.merge(extra_args)
         
     | 
| 
      
 80 
     | 
    
         
            +
                      )
         
     | 
| 
      
 81 
     | 
    
         
            +
                    end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                    NO_ARGS = {}.freeze
         
     | 
| 
      
 84 
     | 
    
         
            +
                    EMPTY = self.new(argument_values: nil, keyword_arguments: NO_ARGS).freeze
         
     | 
| 
       33 
85 
     | 
    
         
             
                  end
         
     | 
| 
       34 
86 
     | 
    
         
             
                end
         
     | 
| 
       35 
87 
     | 
    
         
             
              end
         
     | 
| 
         @@ -6,17 +6,21 @@ module GraphQL 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  class ArgumentsCache
         
     | 
| 
       7 
7 
     | 
    
         
             
                    def initialize(query)
         
     | 
| 
       8 
8 
     | 
    
         
             
                      @query = query
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @dataloader = query.context.dataloader
         
     | 
| 
       9 
10 
     | 
    
         
             
                      @storage = Hash.new do |h, ast_node|
         
     | 
| 
       10 
11 
     | 
    
         
             
                        h[ast_node] = Hash.new do |h2, arg_owner|
         
     | 
| 
       11 
12 
     | 
    
         
             
                          h2[arg_owner] = Hash.new do |h3, parent_object|
         
     | 
| 
       12 
     | 
    
         
            -
                             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
      
 13 
     | 
    
         
            +
                            dataload_for(ast_node, arg_owner, parent_object) do |kwarg_arguments|
         
     | 
| 
      
 14 
     | 
    
         
            +
                              h3[parent_object] = @query.schema.after_lazy(kwarg_arguments) do |resolved_args|
         
     | 
| 
      
 15 
     | 
    
         
            +
                                h3[parent_object] = resolved_args
         
     | 
| 
      
 16 
     | 
    
         
            +
                              end
         
     | 
| 
      
 17 
     | 
    
         
            +
                            end
         
     | 
| 
       16 
18 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                            h3 
     | 
| 
       18 
     | 
    
         
            -
                              #  
     | 
| 
       19 
     | 
    
         
            -
                              h3[parent_object] =  
     | 
| 
      
 19 
     | 
    
         
            +
                            if !h3.key?(parent_object)
         
     | 
| 
      
 20 
     | 
    
         
            +
                              # TODO should i bother putting anything here?
         
     | 
| 
      
 21 
     | 
    
         
            +
                              h3[parent_object] = NO_ARGUMENTS
         
     | 
| 
      
 22 
     | 
    
         
            +
                            else
         
     | 
| 
      
 23 
     | 
    
         
            +
                              h3[parent_object]
         
     | 
| 
       20 
24 
     | 
    
         
             
                            end
         
     | 
| 
       21 
25 
     | 
    
         
             
                          end
         
     | 
| 
       22 
26 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -24,36 +28,66 @@ module GraphQL 
     | 
|
| 
       24 
28 
     | 
    
         
             
                    end
         
     | 
| 
       25 
29 
     | 
    
         | 
| 
       26 
30 
     | 
    
         
             
                    def fetch(ast_node, argument_owner, parent_object)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      # If any jobs were enqueued, run them now,
         
     | 
| 
      
 32 
     | 
    
         
            +
                      # since this might have been called outside of execution.
         
     | 
| 
      
 33 
     | 
    
         
            +
                      # (The jobs are responsible for updating `result` in-place.)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      if !@storage.key?(ast_node) || !@storage[ast_node].key?(argument_owner)
         
     | 
| 
      
 35 
     | 
    
         
            +
                        @dataloader.run_isolated do
         
     | 
| 
      
 36 
     | 
    
         
            +
                          @storage[ast_node][argument_owner][parent_object]
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
      
 39 
     | 
    
         
            +
                      # Ack, the _hash_ is updated, but the key is eventually
         
     | 
| 
      
 40 
     | 
    
         
            +
                      # overridden with an immutable arguments instance.
         
     | 
| 
      
 41 
     | 
    
         
            +
                      # The first call queues up the job,
         
     | 
| 
      
 42 
     | 
    
         
            +
                      # then this call fetches the result.
         
     | 
| 
      
 43 
     | 
    
         
            +
                      # TODO this should be better, find a solution
         
     | 
| 
      
 44 
     | 
    
         
            +
                      # that works with merging the runtime.rb code
         
     | 
| 
       27 
45 
     | 
    
         
             
                      @storage[ast_node][argument_owner][parent_object]
         
     | 
| 
       28 
46 
     | 
    
         
             
                    end
         
     | 
| 
       29 
47 
     | 
    
         | 
| 
      
 48 
     | 
    
         
            +
                    # @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
         
     | 
| 
      
 49 
     | 
    
         
            +
                    def dataload_for(ast_node, argument_owner, parent_object, &block)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      # First, normalize all AST or Ruby values to a plain Ruby hash
         
     | 
| 
      
 51 
     | 
    
         
            +
                      args_hash = self.class.prepare_args_hash(@query, ast_node)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      argument_owner.coerce_arguments(parent_object, args_hash, @query.context, &block)
         
     | 
| 
      
 53 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
       30 
56 
     | 
    
         
             
                    private
         
     | 
| 
       31 
57 
     | 
    
         | 
| 
      
 58 
     | 
    
         
            +
                    NO_ARGUMENTS = {}.freeze
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       32 
60 
     | 
    
         
             
                    NO_VALUE_GIVEN = Object.new
         
     | 
| 
       33 
61 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                    def prepare_args_hash(ast_arg_or_hash_or_value)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
         
     | 
| 
       35 
63 
     | 
    
         
             
                      case ast_arg_or_hash_or_value
         
     | 
| 
       36 
64 
     | 
    
         
             
                      when Hash
         
     | 
| 
      
 65 
     | 
    
         
            +
                        if ast_arg_or_hash_or_value.empty?
         
     | 
| 
      
 66 
     | 
    
         
            +
                          return NO_ARGUMENTS
         
     | 
| 
      
 67 
     | 
    
         
            +
                        end
         
     | 
| 
       37 
68 
     | 
    
         
             
                        args_hash = {}
         
     | 
| 
       38 
69 
     | 
    
         
             
                        ast_arg_or_hash_or_value.each do |k, v|
         
     | 
| 
       39 
     | 
    
         
            -
                          args_hash[k] = prepare_args_hash(v)
         
     | 
| 
      
 70 
     | 
    
         
            +
                          args_hash[k] = prepare_args_hash(query, v)
         
     | 
| 
       40 
71 
     | 
    
         
             
                        end
         
     | 
| 
       41 
72 
     | 
    
         
             
                        args_hash
         
     | 
| 
       42 
73 
     | 
    
         
             
                      when Array
         
     | 
| 
       43 
     | 
    
         
            -
                        ast_arg_or_hash_or_value.map { |v| prepare_args_hash(v) }
         
     | 
| 
      
 74 
     | 
    
         
            +
                        ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
         
     | 
| 
       44 
75 
     | 
    
         
             
                      when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
         
     | 
| 
      
 76 
     | 
    
         
            +
                        if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
         
     | 
| 
      
 77 
     | 
    
         
            +
                          return NO_ARGUMENTS
         
     | 
| 
      
 78 
     | 
    
         
            +
                        end
         
     | 
| 
       45 
79 
     | 
    
         
             
                        args_hash = {}
         
     | 
| 
       46 
     | 
    
         
            -
                        ast_arg_or_hash_or_value.arguments.each do |arg|
         
     | 
| 
       47 
     | 
    
         
            -
                          v = prepare_args_hash(arg.value)
         
     | 
| 
      
 80 
     | 
    
         
            +
                        ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
         
     | 
| 
      
 81 
     | 
    
         
            +
                          v = prepare_args_hash(query, arg.value)
         
     | 
| 
       48 
82 
     | 
    
         
             
                          if v != NO_VALUE_GIVEN
         
     | 
| 
       49 
83 
     | 
    
         
             
                            args_hash[arg.name] = v
         
     | 
| 
       50 
84 
     | 
    
         
             
                          end
         
     | 
| 
       51 
85 
     | 
    
         
             
                        end
         
     | 
| 
       52 
86 
     | 
    
         
             
                        args_hash
         
     | 
| 
       53 
87 
     | 
    
         
             
                      when GraphQL::Language::Nodes::VariableIdentifier
         
     | 
| 
       54 
     | 
    
         
            -
                        if  
     | 
| 
       55 
     | 
    
         
            -
                          variable_value =  
     | 
| 
       56 
     | 
    
         
            -
                          prepare_args_hash(variable_value)
         
     | 
| 
      
 88 
     | 
    
         
            +
                        if query.variables.key?(ast_arg_or_hash_or_value.name)
         
     | 
| 
      
 89 
     | 
    
         
            +
                          variable_value = query.variables[ast_arg_or_hash_or_value.name]
         
     | 
| 
      
 90 
     | 
    
         
            +
                          prepare_args_hash(query, variable_value)
         
     | 
| 
       57 
91 
     | 
    
         
             
                        else
         
     | 
| 
       58 
92 
     | 
    
         
             
                          NO_VALUE_GIVEN
         
     | 
| 
       59 
93 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -6,10 +6,9 @@ module GraphQL 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  module Resolve
         
     | 
| 
       7 
7 
     | 
    
         
             
                    # Continue field results in `results` until there's nothing else to continue.
         
     | 
| 
       8 
8 
     | 
    
         
             
                    # @return [void]
         
     | 
| 
       9 
     | 
    
         
            -
                    def self.resolve_all(results)
         
     | 
| 
       10 
     | 
    
         
            -
                       
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                      end
         
     | 
| 
      
 9 
     | 
    
         
            +
                    def self.resolve_all(results, dataloader)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      dataloader.append_job { resolve(results, dataloader) }
         
     | 
| 
      
 11 
     | 
    
         
            +
                      nil
         
     | 
| 
       13 
12 
     | 
    
         
             
                    end
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
14 
     | 
    
         
             
                    # After getting `results` back from an interpreter evaluation,
         
     | 
| 
         @@ -24,33 +23,46 @@ module GraphQL 
     | 
|
| 
       24 
23 
     | 
    
         
             
                    # return {Lazy} instances if there's more work to be done,
         
     | 
| 
       25 
24 
     | 
    
         
             
                    # or return {Hash}/{Array} if the query should be continued.
         
     | 
| 
       26 
25 
     | 
    
         
             
                    #
         
     | 
| 
       27 
     | 
    
         
            -
                    # @ 
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 27 
     | 
    
         
            +
                    def self.resolve(results, dataloader)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      # There might be pending jobs here that _will_ write lazies
         
     | 
| 
      
 29 
     | 
    
         
            +
                      # into the result hash. We should run them out, so we
         
     | 
| 
      
 30 
     | 
    
         
            +
                      # can be sure that all lazies will be present in the result hashes.
         
     | 
| 
      
 31 
     | 
    
         
            +
                      # A better implementation would somehow interleave (or unify)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      # these approaches.
         
     | 
| 
      
 33 
     | 
    
         
            +
                      dataloader.run
         
     | 
| 
       30 
34 
     | 
    
         
             
                      next_results = []
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                      # Work through the queue until it's empty
         
     | 
| 
       33 
     | 
    
         
            -
                      while results.size > 0
         
     | 
| 
      
 35 
     | 
    
         
            +
                      while results.any?
         
     | 
| 
       34 
36 
     | 
    
         
             
                        result_value = results.shift
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                           
     | 
| 
       38 
     | 
    
         
            -
                         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                          # Since this field returned another lazy,
         
     | 
| 
       42 
     | 
    
         
            -
                          # add it to the same queue
         
     | 
| 
       43 
     | 
    
         
            -
                          results << result_value
         
     | 
| 
       44 
     | 
    
         
            -
                        elsif result_value.is_a?(Hash)
         
     | 
| 
       45 
     | 
    
         
            -
                          # This is part of the next level, add it
         
     | 
| 
       46 
     | 
    
         
            -
                          next_results.concat(result_value.values)
         
     | 
| 
      
 37 
     | 
    
         
            +
                        if result_value.is_a?(Runtime::GraphQLResultHash) || result_value.is_a?(Hash)
         
     | 
| 
      
 38 
     | 
    
         
            +
                          results.concat(result_value.values)
         
     | 
| 
      
 39 
     | 
    
         
            +
                          next
         
     | 
| 
      
 40 
     | 
    
         
            +
                        elsif result_value.is_a?(Runtime::GraphQLResultArray)
         
     | 
| 
      
 41 
     | 
    
         
            +
                          results.concat(result_value.values)
         
     | 
| 
      
 42 
     | 
    
         
            +
                          next
         
     | 
| 
       47 
43 
     | 
    
         
             
                        elsif result_value.is_a?(Array)
         
     | 
| 
       48 
     | 
    
         
            -
                           
     | 
| 
       49 
     | 
    
         
            -
                           
     | 
| 
      
 44 
     | 
    
         
            +
                          results.concat(result_value)
         
     | 
| 
      
 45 
     | 
    
         
            +
                          next
         
     | 
| 
      
 46 
     | 
    
         
            +
                        elsif result_value.is_a?(Lazy)
         
     | 
| 
      
 47 
     | 
    
         
            +
                          loaded_value = result_value.value
         
     | 
| 
      
 48 
     | 
    
         
            +
                          if loaded_value.is_a?(Lazy)
         
     | 
| 
      
 49 
     | 
    
         
            +
                            # Since this field returned another lazy,
         
     | 
| 
      
 50 
     | 
    
         
            +
                            # add it to the same queue
         
     | 
| 
      
 51 
     | 
    
         
            +
                            results << loaded_value
         
     | 
| 
      
 52 
     | 
    
         
            +
                          elsif loaded_value.is_a?(Runtime::GraphQLResultHash) || loaded_value.is_a?(Runtime::GraphQLResultArray) ||
         
     | 
| 
      
 53 
     | 
    
         
            +
                              loaded_value.is_a?(Hash) || loaded_value.is_a?(Array)
         
     | 
| 
      
 54 
     | 
    
         
            +
                            # Add these values in wholesale --
         
     | 
| 
      
 55 
     | 
    
         
            +
                            # they might be modified by later work in the dataloader.
         
     | 
| 
      
 56 
     | 
    
         
            +
                            next_results << loaded_value
         
     | 
| 
      
 57 
     | 
    
         
            +
                          end
         
     | 
| 
       50 
58 
     | 
    
         
             
                        end
         
     | 
| 
       51 
59 
     | 
    
         
             
                      end
         
     | 
| 
       52 
60 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                      next_results
         
     | 
| 
      
 61 
     | 
    
         
            +
                      if next_results.any?
         
     | 
| 
      
 62 
     | 
    
         
            +
                        dataloader.append_job { resolve(next_results, dataloader) }
         
     | 
| 
      
 63 
     | 
    
         
            +
                      end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      nil
         
     | 
| 
       54 
66 
     | 
    
         
             
                    end
         
     | 
| 
       55 
67 
     | 
    
         
             
                  end
         
     | 
| 
       56 
68 
     | 
    
         
             
                end
         
     |