lib/graphql/execution/lookahead.rb in graphql-1.10.4 vs lib/graphql/execution/lookahead.rb in graphql-1.10.5
- old
+ new
@@ -49,11 +49,19 @@
# @return [GraphQL::Schema::Object, GraphQL::Schema::Union, GraphQL::Schema::Interface]
attr_reader :owner_type
# @return [Hash<Symbol, Object>]
def arguments
- @arguments ||= @field && ArgumentHelpers.arguments(@query, @field, ast_nodes.first)
+ if defined?(@arguments)
+ @arguments
+ else
+ @arguments = if @field
+ @query.arguments_for(@ast_nodes.first, @field)
+ else
+ nil
+ end
+ end
end
# True if this node has a selection on `field_name`.
# If `field_name` is a String, it is treated as a GraphQL-style (camelized)
# field name and used verbatim. If `field_name` is a Symbol, it is
@@ -79,11 +87,11 @@
# It returns a null object (check with {#selected?})
# @return [GraphQL::Execution::Lookahead]
def selection(field_name, selected_type: @selected_type, arguments: nil)
next_field_name = normalize_name(field_name)
- next_field_defn = FieldHelpers.get_field(@query.schema, selected_type, next_field_name)
+ next_field_defn = get_class_based_field(selected_type, next_field_name)
if next_field_defn
next_nodes = []
@ast_nodes.each do |ast_node|
ast_node.selections.each do |selection|
find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
@@ -125,11 +133,11 @@
subselections = []
subselections_by_type.each do |type, ast_nodes_by_response_key|
ast_nodes_by_response_key.each do |response_key, ast_nodes|
- field_defn = FieldHelpers.get_field(@query.schema, type, ast_nodes.first.name)
+ field_defn = get_class_based_field(type, ast_nodes.first.name)
lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
subselections.push(lookahead)
end
end
@@ -201,16 +209,23 @@
else
keyword
end
end
+ # Wrap get_field and ensure that it returns a GraphQL::Schema::Field.
+ # Remove this when legacy execution is removed.
+ def get_class_based_field(type, name)
+ f = @query.get_field(type, name)
+ f && f.type_class
+ end
+
def skipped_by_directive?(ast_selection)
ast_selection.directives.each do |directive|
dir_defn = @query.schema.directives.fetch(directive.name)
directive_class = dir_defn.type_class
if directive_class
- dir_args = GraphQL::Execution::Lookahead::ArgumentHelpers.arguments(@query, dir_defn, directive)
+ dir_args = @query.arguments_for(directive, dir_defn)
return true unless directive_class.static_include?(dir_args, @query.context)
end
end
false
end
@@ -225,11 +240,11 @@
if selections_on_type.key?(response_key)
selections_on_type[response_key] << ast_selection
elsif arguments.nil? || arguments.empty?
selections_on_type[response_key] = [ast_selection]
else
- field_defn = FieldHelpers.get_field(@query.schema, selected_type, ast_selection.name)
+ field_defn = get_class_based_field(selected_type, ast_selection.name)
if arguments_match?(arguments, field_defn, ast_selection)
selections_on_type[response_key] = [ast_selection]
end
end
when GraphQL::Language::Nodes::InlineFragment
@@ -276,116 +291,14 @@
raise "Unexpected selection comparison on #{node.class.name} (#{node})"
end
end
def arguments_match?(arguments, field_defn, field_node)
- query_kwargs = ArgumentHelpers.arguments(@query, field_defn, field_node)
+ query_kwargs = @query.arguments_for(field_node, field_defn)
arguments.all? do |arg_name, arg_value|
arg_name = normalize_keyword(arg_name)
# Make sure the constraint is present with a matching value
query_kwargs.key?(arg_name) && query_kwargs[arg_name] == arg_value
- end
- end
-
- # TODO Dedup with interpreter
- module ArgumentHelpers
- module_function
-
- def arguments(query, arg_owner, ast_node)
- kwarg_arguments = {}
- arg_defns = arg_owner.arguments
- ast_node.arguments.each do |arg|
- arg_defn = arg_defns[arg.name] || raise("Invariant: missing argument definition for #{arg.name.inspect} in #{arg_defns.keys} from #{arg_owner}")
- # Need to distinguish between client-provided `nil`
- # and nothing-at-all
- is_present, value = arg_to_value(query, arg_defn.type, arg.value)
- if is_present
- kwarg_arguments[arg_defn.keyword] = value
- end
- end
- arg_defns.each do |name, arg_defn|
- if arg_defn.default_value? && !kwarg_arguments.key?(arg_defn.keyword)
- kwarg_arguments[arg_defn.keyword] = arg_defn.default_value
- end
- end
- kwarg_arguments
- end
-
- # Get a Ruby-ready value from a client query.
- # @param graphql_object [Object] The owner of the field whose argument this is
- # @param arg_type [Class, GraphQL::Schema::NonNull, GraphQL::Schema::List]
- # @param ast_value [GraphQL::Language::Nodes::VariableIdentifier, String, Integer, Float, Boolean]
- # @return [Array(is_present, value)]
- def arg_to_value(query, arg_type, ast_value)
- if ast_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
- # If it's not here, it will get added later
- if query.variables.key?(ast_value.name)
- return true, query.variables[ast_value.name]
- else
- return false, nil
- end
- elsif ast_value.is_a?(GraphQL::Language::Nodes::NullValue)
- return true, nil
- elsif arg_type.is_a?(GraphQL::Schema::NonNull)
- arg_to_value(query, arg_type.of_type, ast_value)
- elsif arg_type.is_a?(GraphQL::Schema::List)
- # Treat a single value like a list
- arg_value = Array(ast_value)
- list = []
- arg_value.map do |inner_v|
- _present, value = arg_to_value(query, arg_type.of_type, inner_v)
- list << value
- end
- return true, list
- elsif arg_type.is_a?(Class) && arg_type < GraphQL::Schema::InputObject
- # For these, `prepare` is applied during `#initialize`.
- # Pass `nil` so it will be skipped in `#arguments`.
- # What a mess.
- args = arguments(query, nil, arg_type, ast_value)
- # We're not tracking defaults_used, but for our purposes
- # we compare the value to the default value.
- return true, arg_type.new(ruby_kwargs: args, context: query.context, defaults_used: nil)
- else
- flat_value = flatten_ast_value(query, ast_value)
- return true, arg_type.coerce_input(flat_value, query.context)
- end
- end
-
- def flatten_ast_value(query, v)
- case v
- when GraphQL::Language::Nodes::Enum
- v.name
- when GraphQL::Language::Nodes::InputObject
- h = {}
- v.arguments.each do |arg|
- h[arg.name] = flatten_ast_value(query, arg.value)
- end
- h
- when Array
- v.map { |v2| flatten_ast_value(query, v2) }
- when GraphQL::Language::Nodes::VariableIdentifier
- flatten_ast_value(query.variables[v.name])
- else
- v
- end
- end
- end
-
- # TODO dedup with interpreter
- module FieldHelpers
- module_function
-
- def get_field(schema, owner_type, field_name)
- field_defn = owner_type.get_field(field_name)
- field_defn ||= if owner_type == schema.query.type_class && (entry_point_field = schema.introspection_system.entry_point(name: field_name))
- entry_point_field.type_class
- elsif (dynamic_field = schema.introspection_system.dynamic_field(name: field_name))
- dynamic_field.type_class
- else
- nil
- end
-
- field_defn
end
end
end
end
end