<commit_before># frozen_string_literal: true

module GraphQL
  module Execution
    class Interpreter
      # I think it would be even better if we could somehow make
      # `continue_field` not recursive. "Trampolining" it somehow.
      class Runtime
        # @return [GraphQL::Query]
        attr_reader :query

        # @return [Class]
        attr_reader :schema

        # @return [GraphQL::Query::Context]
        attr_reader :context

        def initialize(query:, lazies:, response:)
          @query = query
          @schema = query.schema
          @context = query.context
          @lazies = lazies
          @response = response
          @dead_paths = {}
          @types_at_paths = {}
        end

        def final_value
          @response.final_value
        end

        def inspect
          "#<#{self.class.name} response=#{@response.inspect}>"
        end

        # This _begins_ the execution. Some deferred work
        # might be stored up in {@lazies}.
        # @return [void]
        def run_eager
          root_operation = query.selected_operation
          root_op_type = root_operation.operation_type || "query"
          legacy_root_type = schema.root_type_for_operation(root_op_type)
          root_type = legacy_root_type.metadata[:type_class] || raise("Invariant: type must be class-based: #{legacy_root_type}")
          object_proxy = root_type.authorized_new(query.root_value, context)

          path = []
          evaluate_selections(path, object_proxy, root_type, root_operation.selections, root_operation_type: root_op_type)
        end

        private

        def gather_selections(owner_type, selections, selections_by_name)
          selections.each do |node|
            case node
            when GraphQL::Language::Nodes::Field
              if passes_skip_and_include?(node)
                response_key = node.alias || node.name
                s = selections_by_name[response_key] ||= []
                s << node
              end
            when GraphQL::Language::Nodes::InlineFragment
              if passes_skip_and_include?(node)
                include_fragmment = if node.type
                  type_defn = schema.types[node.type.name]
                  type_defn = type_defn.metadata[:type_class]
                  possible_types = query.warden.possible_types(type_defn).map { |t| t.metadata[:type_class] }
                  possible_types.include?(owner_type)
                else
                  true
                end
                if include_fragmment
                  gather_selections(owner_type, node.selections, selections_by_name)
                end
              end
            when GraphQL::Language::Nodes::FragmentSpread
              if passes_skip_and_include?(node)
                fragment_def = query.fragments[node.name]
                type_defn = schema.types[fragment_def.type.name]
                type_defn = type_defn.metadata[:type_class]
                possible_types = schema.possible_types(type_defn).map { |t| t.metadata[:type_class] }
                if possible_types.include?(owner_type)
                  gather_selections(owner_type, fragment_def.selections, selections_by_name)
                end
              end
            else
              raise "Invariant: unexpected selection class: #{node.class}"
            end
          end
        end

        def evaluate_selections(path, owner_object, owner_type, selections, root_operation_type: nil)
          selections_by_name = {}
          owner_type = resolve_if_late_bound_type(owner_type)
          gather_selections(owner_type, selections, selections_by_name)
          selections_by_name.each do |result_name, fields|
            ast_node = fields.first
            field_name = ast_node.name
            field_defn = owner_type.fields[field_name]
            is_introspection = false
            if field_defn.nil?
              field_defn = if owner_type == schema.query.metadata[:type_class] && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
                is_introspection = true
                entry_point_field.metadata[:type_class]
              elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
                is_introspection = true
                dynamic_field.metadata[:type_class]
              else
                raise "Invariant: no field for #{owner_type}.#{field_name}"
              end
            end

            return_type = resolve_if_late_bound_type(field_defn.type)

            next_path = [*path, result_name].freeze<commit_msg>Remove needless late-bound type check<commit_after># frozen_string_literal: true

module GraphQL
  module Execution
    class Interpreter
      # I think it would be even better if we could somehow make
      # `continue_field` not recursive. "Trampolining" it somehow.
      class Runtime
        # @return [GraphQL::Query]
        attr_reader :query

        # @return [Class]
        attr_reader :schema

        # @return [GraphQL::Query::Context]
        attr_reader :context

        def initialize(query:, lazies:, response:)
          @query = query
          @schema = query.schema
          @context = query.context
          @lazies = lazies
          @response = response
          @dead_paths = {}
          @types_at_paths = {}
        end

        def final_value
          @response.final_value
        end

        def inspect
          "#<#{self.class.name} response=#{@response.inspect}>"
        end

        # This _begins_ the execution. Some deferred work
        # might be stored up in {@lazies}.
        # @return [void]
        def run_eager
          root_operation = query.selected_operation
          root_op_type = root_operation.operation_type || "query"
          legacy_root_type = schema.root_type_for_operation(root_op_type)
          root_type = legacy_root_type.metadata[:type_class] || raise("Invariant: type must be class-based: #{legacy_root_type}")
          object_proxy = root_type.authorized_new(query.root_value, context)

          path = []
          evaluate_selections(path, object_proxy, root_type, root_operation.selections, root_operation_type: root_op_type)
        end

        private

        def gather_selections(owner_type, selections, selections_by_name)
          selections.each do |node|
            case node
            when GraphQL::Language::Nodes::Field
              if passes_skip_and_include?(node)
                response_key = node.alias || node.name
                s = selections_by_name[response_key] ||= []
                s << node
              end
            when GraphQL::Language::Nodes::InlineFragment
              if passes_skip_and_include?(node)
                include_fragmment = if node.type
                  type_defn = schema.types[node.type.name]
                  type_defn = type_defn.metadata[:type_class]
                  possible_types = query.warden.possible_types(type_defn).map { |t| t.metadata[:type_class] }
                  possible_types.include?(owner_type)
                else
                  true
                end
                if include_fragmment
                  gather_selections(owner_type, node.selections, selections_by_name)
                end
              end
            when GraphQL::Language::Nodes::FragmentSpread
              if passes_skip_and_include?(node)
                fragment_def = query.fragments[node.name]
                type_defn = schema.types[fragment_def.type.name]
                type_defn = type_defn.metadata[:type_class]
                possible_types = schema.possible_types(type_defn).map { |t| t.metadata[:type_class] }
                if possible_types.include?(owner_type)
                  gather_selections(owner_type, fragment_def.selections, selections_by_name)
                end
              end
            else
              raise "Invariant: unexpected selection class: #{node.class}"
            end
          end
        end

        def evaluate_selections(path, owner_object, owner_type, selections, root_operation_type: nil)
          selections_by_name = {}
          gather_selections(owner_type, selections, selections_by_name)
          selections_by_name.each do |result_name, fields|
            ast_node = fields.first
            field_name = ast_node.name
            field_defn = owner_type.fields[field_name]
            is_introspection = false
            if field_defn.nil?
              field_defn = if owner_type == schema.query.metadata[:type_class] && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
                is_introspection = true
                entry_point_field.metadata[:type_class]
              elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
                is_introspection = true
                dynamic_field.metadata[:type_class]
              else
                raise "Invariant: no field for #{owner_type}.#{field_name}"
              end
            end

            return_type = resolve_if_late_bound_type(field_defn.type)

            next_path = [*path, result_name].freeze
{'fraction_non_alphanumeric': 0.07712418300653595, 'fraction_numerical': 0.0, 'mean_word_length': 1.9818122767132185, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6429505', 'n_tokens_mistral': 2534, 'n_tokens_neox': 2461, 'n_words': 495}