Skip to content

Commit 7267dd1

Browse files
authored
Merge pull request #5605 from rmosolgo/exec-next-input-values
Exec-next: improve input handling
2 parents 7b552cd + e22956d commit 7267dd1

10 files changed

Lines changed: 357 additions & 194 deletions

File tree

lib/graphql/execution/field_resolve_step.rb

Lines changed: 2 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -48,173 +48,6 @@ def append_selection(ast_node)
4848
nil
4949
end
5050

51-
def coerce_arguments(argument_owner, ast_arguments_or_hash, run_loads = true)
52-
arg_defns = @selections_step.query.types.arguments(argument_owner)
53-
if arg_defns.empty?
54-
return EmptyObjects::EMPTY_HASH
55-
end
56-
args_hash = {}
57-
58-
if ast_arguments_or_hash.nil? # This can happen with `.trigger`
59-
return args_hash
60-
end
61-
62-
arg_inputs_are_h = ast_arguments_or_hash.is_a?(Hash)
63-
64-
arg_defns.each do |arg_defn|
65-
arg_value = nil
66-
was_found = false
67-
if arg_inputs_are_h
68-
ast_arguments_or_hash.each do |key, value|
69-
if key == arg_defn.keyword || key.to_s == arg_defn.graphql_name
70-
arg_value = value
71-
was_found = true
72-
break
73-
end
74-
end
75-
else
76-
ast_arguments_or_hash.each do |arg_node|
77-
if arg_node.name == arg_defn.graphql_name
78-
arg_value = arg_node.value
79-
was_found = true
80-
break
81-
end
82-
end
83-
end
84-
85-
if arg_value.is_a?(Language::Nodes::VariableIdentifier)
86-
vars = @selections_step.query.variables
87-
arg_value = if vars.key?(arg_value.name)
88-
vars[arg_value.name]
89-
elsif vars.key?(arg_value.name.to_sym)
90-
vars[arg_value.name.to_sym]
91-
else
92-
was_found = false
93-
nil
94-
end
95-
end
96-
97-
if !was_found && arg_defn.default_value?
98-
was_found = true
99-
arg_value = arg_defn.default_value
100-
end
101-
102-
if was_found
103-
coerce_argument_value(args_hash, arg_defn, arg_value, run_loads)
104-
end
105-
end
106-
107-
args_hash
108-
end
109-
110-
def coerce_argument_value(arguments, arg_defn, arg_value, run_loads, target_keyword: run_loads ? arg_defn.keyword : arg_defn.graphql_name, as_type: nil)
111-
arg_t = as_type || arg_defn.type
112-
if arg_t.non_null?
113-
arg_t = arg_t.of_type
114-
end
115-
116-
if arg_value.is_a?(Language::Nodes::VariableIdentifier)
117-
vars = @selections_step.query.variables
118-
arg_value = if vars.key?(arg_value.name)
119-
vars[arg_value.name]
120-
elsif vars.key?(arg_value.name.to_sym)
121-
vars[arg_value.name.to_sym]
122-
else
123-
nil
124-
end
125-
end
126-
127-
if arg_value.is_a?(Language::Nodes::NullValue)
128-
arg_value = nil
129-
elsif arg_value.is_a?(Language::Nodes::Enum)
130-
arg_value = arg_value.name
131-
end
132-
133-
ctx = @selections_step.query.context
134-
arg_value = if arg_t.list?
135-
if arg_value.nil?
136-
arg_value
137-
else
138-
arg_value = Array(arg_value)
139-
inner_t = arg_t.of_type
140-
result = Array.new(arg_value.size)
141-
arg_value.each_with_index { |v, i| coerce_argument_value(result, arg_defn, v, run_loads, target_keyword: i, as_type: inner_t) }
142-
result
143-
end
144-
elsif arg_t.kind.leaf?
145-
begin
146-
arg_t.coerce_input(arg_value, ctx)
147-
rescue GraphQL::UnauthorizedEnumValueError => enum_err
148-
begin
149-
@runner.schema.unauthorized_object(enum_err)
150-
rescue GraphQL::ExecutionError => ex_err
151-
ex_err
152-
end
153-
end
154-
elsif arg_t.kind.input_object?
155-
input_obj_vals = arg_value.is_a?(Language::Nodes::InputObject) ? arg_value.arguments : arg_value # rubocop:disable Development/ContextIsPassedCop
156-
input_obj_args = coerce_arguments(arg_t, input_obj_vals)
157-
arg_t.new(nil, ruby_kwargs: input_obj_args, context: @selections_step.query.context, defaults_used: nil)
158-
else
159-
raise "Unsupported argument value: #{arg_t.to_type_signature} / #{arg_value.class} (#{arg_value.inspect})"
160-
end
161-
162-
if as_type.nil? # only on root arguments, not list elements
163-
arg_value = begin
164-
begin
165-
arg_defn.prepare_value(nil, arg_value, context: ctx)
166-
rescue StandardError => err
167-
@runner.schema.handle_or_reraise(ctx, err)
168-
end
169-
rescue GraphQL::ExecutionError => exec_err
170-
exec_err
171-
end
172-
end
173-
174-
if arg_value.is_a?(GraphQL::RuntimeError)
175-
@arguments = arg_value
176-
elsif run_loads && arg_defn.loads && as_type.nil? && !arg_value.nil?
177-
# This is for legacy compat:
178-
load_receiver = if (r = @field_definition.resolver)
179-
r.new(field: @field_definition, context: @selections_step.query.context, object: nil)
180-
else
181-
@field_definition
182-
end
183-
@pending_steps ||= []
184-
if arg_t.list?
185-
results = Array.new(arg_value.size, nil)
186-
arguments[arg_defn.keyword] = results
187-
arg_value.each_with_index do |inner_v, idx|
188-
loads_step = LoadArgumentStep.new(
189-
field_resolve_step: self,
190-
load_receiver: load_receiver,
191-
argument_value: inner_v,
192-
argument_definition: arg_defn,
193-
arguments: results,
194-
argument_key: idx,
195-
)
196-
@pending_steps.push(loads_step)
197-
@runner.add_step(loads_step)
198-
end
199-
else
200-
loads_step = LoadArgumentStep.new(
201-
field_resolve_step: self,
202-
load_receiver: load_receiver,
203-
argument_value: arg_value,
204-
argument_definition: arg_defn,
205-
arguments: arguments,
206-
argument_key: arg_defn.keyword,
207-
)
208-
@pending_steps.push(loads_step)
209-
@runner.add_step(loads_step)
210-
end
211-
else
212-
arguments[target_keyword] = arg_value
213-
end
214-
nil
215-
end
216-
217-
# Implement that Lazy API
21851
def value
21952
query = @selections_step.query
22053
query.current_trace.begin_execute_field(@field_definition, @arguments, @field_results, query)
@@ -280,7 +113,7 @@ def build_arguments
280113
query = @selections_step.query
281114
field_name = @ast_node.name
282115
@field_definition = query.types.field(@parent_type, field_name) || raise("Invariant: no field found for #{@parent_type.to_type_signature}.#{ast_node.name}")
283-
arguments = coerce_arguments(@field_definition, @ast_node.arguments) # rubocop:disable Development/ContextIsPassedCop
116+
arguments = @runner.input_values[query].argument_values(@field_definition, @ast_node.arguments, self) # rubocop:disable Development/ContextIsPassedCop
284117
@arguments ||= arguments # may have already been set to an error
285118

286119
if (@pending_steps.nil? || @pending_steps.size == 0) &&
@@ -389,7 +222,7 @@ def execute_field
389222
if (dir_defn = @runner.runtime_directives[dir_node.name])
390223
# TODO: `coerce_arguments` modifies self, assuming it's field arguments. Extract to pure function for use
391224
# here and with fragments.
392-
dir_args = coerce_arguments(dir_defn, dir_node.arguments, false) # rubocop:disable Development/ContextIsPassedCop
225+
dir_args = @runner.input_values[query].argument_values(dir_defn, dir_node.arguments, nil) # rubocop:disable Development/ContextIsPassedCop
393226
result = dir_defn.resolve_field(ast_nodes, @parent_type, field_definition, authorized_objects, dir_args, ctx)
394227
if !result.nil?
395228
if result.is_a?(Finalizer)

0 commit comments

Comments
 (0)