graphql 2.3.3 → 2.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/graphql/analysis/ast/query_complexity.rb +1 -1
- data/lib/graphql/dataloader/async_dataloader.rb +1 -0
- data/lib/graphql/dataloader/null_dataloader.rb +1 -1
- data/lib/graphql/dataloader.rb +6 -3
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +7 -4
- data/lib/graphql/execution/interpreter/runtime.rb +52 -63
- data/lib/graphql/execution/interpreter.rb +1 -1
- data/lib/graphql/language/nodes.rb +60 -26
- data/lib/graphql/language/parser.rb +56 -15
- data/lib/graphql/query.rb +2 -2
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/schema/addition.rb +21 -11
- 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/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/tracing/prometheus_trace.rb +8 -8
- data/lib/graphql/tracing/sentry_trace.rb +10 -10
- data/lib/graphql/type_kinds.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +0 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5f20ae656aec8f5ad77a6edd73103d2f5a25511ae3c9b515c5b0c58ecc91cac
|
4
|
+
data.tar.gz: 6b51f66b0f2188c292b34c61e367de84cb37a7894e536b5b8105a95ec60b9c64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96bd289b9d880438ed2c7610b3a7008cb793fd4551191fcf084c0f947c3da195e07f07346e0b2c9b88177fdbeed098591508879756d7f5919c53c9576f5548e8
|
7
|
+
data.tar.gz: ce92d82eee23a710b66f3d29bdc29690b2e368f42ddfd60b159708dac0b018024a87bbf6069d8274878e98e0821f223b0cd2fafba41c23afab86dc7faa97328c
|
@@ -9,7 +9,7 @@ module Graphql
|
|
9
9
|
class MutationRootGenerator < Rails::Generators::Base
|
10
10
|
include Core
|
11
11
|
|
12
|
-
desc "Create mutation base type, mutation root
|
12
|
+
desc "Create mutation base type, mutation root type, and adds the latter to the schema"
|
13
13
|
source_root File.expand_path('../templates', __FILE__)
|
14
14
|
|
15
15
|
class_option :schema,
|
@@ -31,4 +31,4 @@ module Graphql
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
@@ -8,7 +8,7 @@ module GraphQL
|
|
8
8
|
# simple internal code while adding the option to add Dataloader.
|
9
9
|
class NullDataloader < Dataloader
|
10
10
|
# These are all no-ops because code was
|
11
|
-
# executed
|
11
|
+
# executed synchronously.
|
12
12
|
def run; end
|
13
13
|
def run_isolated; yield; end
|
14
14
|
def yield
|
data/lib/graphql/dataloader.rb
CHANGED
@@ -88,6 +88,11 @@ module GraphQL
|
|
88
88
|
nil
|
89
89
|
end
|
90
90
|
|
91
|
+
# This method is called when Dataloader is finished using a fiber.
|
92
|
+
# Use it to perform any cleanup, such as releasing database connections (if required manually)
|
93
|
+
def cleanup_fiber
|
94
|
+
end
|
95
|
+
|
91
96
|
# Get a Source instance from this dataloader, for calling `.load(...)` or `.request(...)` on.
|
92
97
|
#
|
93
98
|
# @param source_class [Class<GraphQL::Dataloader::Source]
|
@@ -231,9 +236,7 @@ module GraphQL
|
|
231
236
|
Fiber.new(blocking: !@nonblocking) {
|
232
237
|
set_fiber_variables(fiber_vars)
|
233
238
|
yield
|
234
|
-
|
235
|
-
# if the fiber is allowed to terminate normally, control is passed to the main fiber instead.
|
236
|
-
true
|
239
|
+
cleanup_fiber
|
237
240
|
}
|
238
241
|
end
|
239
242
|
|
@@ -5,7 +5,7 @@ module GraphQL
|
|
5
5
|
class Interpreter
|
6
6
|
class Runtime
|
7
7
|
module GraphQLResult
|
8
|
-
def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent)
|
8
|
+
def initialize(result_name, result_type, application_value, parent_result, is_non_null_in_parent, selections, is_eager)
|
9
9
|
@graphql_parent = parent_result
|
10
10
|
@graphql_application_value = application_value
|
11
11
|
@graphql_result_type = result_type
|
@@ -16,6 +16,8 @@ module GraphQL
|
|
16
16
|
@graphql_is_non_null_in_parent = is_non_null_in_parent
|
17
17
|
# Jump through some hoops to avoid creating this duplicate storage if at all possible.
|
18
18
|
@graphql_metadata = nil
|
19
|
+
@graphql_selections = selections
|
20
|
+
@graphql_is_eager = is_eager
|
19
21
|
end
|
20
22
|
|
21
23
|
def path
|
@@ -28,14 +30,15 @@ module GraphQL
|
|
28
30
|
end
|
29
31
|
|
30
32
|
attr_accessor :graphql_dead
|
31
|
-
attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent,
|
33
|
+
attr_reader :graphql_parent, :graphql_result_name, :graphql_is_non_null_in_parent,
|
34
|
+
:graphql_application_value, :graphql_result_type, :graphql_selections, :graphql_is_eager
|
32
35
|
|
33
36
|
# @return [Hash] Plain-Ruby result data (`@graphql_metadata` contains Result wrapper objects)
|
34
37
|
attr_accessor :graphql_result_data
|
35
38
|
end
|
36
39
|
|
37
40
|
class GraphQLResultHash
|
38
|
-
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
|
41
|
+
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent, _selections, _is_eager)
|
39
42
|
super
|
40
43
|
@graphql_result_data = {}
|
41
44
|
end
|
@@ -123,7 +126,7 @@ module GraphQL
|
|
123
126
|
class GraphQLResultArray
|
124
127
|
include GraphQLResult
|
125
128
|
|
126
|
-
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent)
|
129
|
+
def initialize(_result_name, _result_type, _application_value, _parent_result, _is_non_null_in_parent, _selections, _is_eager)
|
127
130
|
super
|
128
131
|
@graphql_result_data = []
|
129
132
|
end
|
@@ -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,8 +107,18 @@ module GraphQL
|
|
126
107
|
nil
|
127
108
|
end
|
128
109
|
|
129
|
-
def
|
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
|
130
120
|
|
121
|
+
def gather_selections(owner_object, owner_type, selections, selections_to_run = nil, selections_by_name = {})
|
131
122
|
selections.each do |node|
|
132
123
|
# Skip gathering this if the directive says so
|
133
124
|
if !directives_include?(node, owner_object, owner_type)
|
@@ -139,7 +130,7 @@ module GraphQL
|
|
139
130
|
selections = selections_by_name[response_key]
|
140
131
|
# if there was already a selection of this field,
|
141
132
|
# use an array to hold all selections,
|
142
|
-
#
|
133
|
+
# otherwise, use the single node to represent the selection
|
143
134
|
if selections
|
144
135
|
# This field was already selected at least once,
|
145
136
|
# add this node to the list of selections
|
@@ -172,17 +163,26 @@ module GraphQL
|
|
172
163
|
type_defn = schema.get_type(node.type.name, context)
|
173
164
|
|
174
165
|
if query.warden.possible_types(type_defn).include?(owner_type)
|
175
|
-
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
166
|
+
result = gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
167
|
+
if !result.equal?(next_selections)
|
168
|
+
selections_to_run = result
|
169
|
+
end
|
176
170
|
end
|
177
171
|
else
|
178
172
|
# it's an untyped fragment, definitely continue
|
179
|
-
gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
173
|
+
result = gather_selections(owner_object, owner_type, node.selections, selections_to_run, next_selections)
|
174
|
+
if !result.equal?(next_selections)
|
175
|
+
selections_to_run = result
|
176
|
+
end
|
180
177
|
end
|
181
178
|
when GraphQL::Language::Nodes::FragmentSpread
|
182
179
|
fragment_def = query.fragments[node.name]
|
183
180
|
type_defn = query.get_type(fragment_def.type.name)
|
184
181
|
if query.warden.possible_types(type_defn).include?(owner_type)
|
185
|
-
gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
182
|
+
result = gather_selections(owner_object, owner_type, fragment_def.selections, selections_to_run, next_selections)
|
183
|
+
if !result.equal?(next_selections)
|
184
|
+
selections_to_run = result
|
185
|
+
end
|
186
186
|
end
|
187
187
|
else
|
188
188
|
raise "Invariant: unexpected selection class: #{node.class}"
|
@@ -195,7 +195,7 @@ module GraphQL
|
|
195
195
|
NO_ARGS = GraphQL::EmptyObjects::EMPTY_HASH
|
196
196
|
|
197
197
|
# @return [void]
|
198
|
-
def evaluate_selections(
|
198
|
+
def evaluate_selections(gathered_selections, selections_result, target_result, runtime_state) # rubocop:disable Metrics/ParameterLists
|
199
199
|
runtime_state ||= get_current_runtime_state
|
200
200
|
runtime_state.current_result_name = nil
|
201
201
|
runtime_state.current_result = selections_result
|
@@ -210,7 +210,7 @@ module GraphQL
|
|
210
210
|
gathered_selections.each do |result_name, field_ast_nodes_or_ast_node|
|
211
211
|
@dataloader.append_job {
|
212
212
|
evaluate_selection(
|
213
|
-
result_name, field_ast_nodes_or_ast_node,
|
213
|
+
result_name, field_ast_nodes_or_ast_node, selections_result
|
214
214
|
)
|
215
215
|
finished_jobs += 1
|
216
216
|
if target_result && finished_jobs == enqueued_jobs
|
@@ -220,7 +220,7 @@ module GraphQL
|
|
220
220
|
# Field resolution may pause the fiber,
|
221
221
|
# so it wouldn't get to the `Resolve` call that happens below.
|
222
222
|
# So instead trigger a run from this outer context.
|
223
|
-
if
|
223
|
+
if selections_result.graphql_is_eager
|
224
224
|
@dataloader.clear_cache
|
225
225
|
@dataloader.run
|
226
226
|
@dataloader.clear_cache
|
@@ -231,7 +231,7 @@ module GraphQL
|
|
231
231
|
end
|
232
232
|
|
233
233
|
# @return [void]
|
234
|
-
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
|
235
235
|
return if selections_result.graphql_dead
|
236
236
|
# As a performance optimization, the hash key will be a `Node` if
|
237
237
|
# there's only one selection of the field. But if there are multiple
|
@@ -258,28 +258,27 @@ module GraphQL
|
|
258
258
|
owner_object = field_defn.owner.wrap(owner_object, context)
|
259
259
|
end
|
260
260
|
|
261
|
-
return_type = field_defn.type
|
262
261
|
if !field_defn.any_arguments?
|
263
262
|
resolved_arguments = GraphQL::Execution::Interpreter::Arguments::EMPTY
|
264
263
|
if field_defn.extras.size == 0
|
265
264
|
evaluate_selection_with_resolved_keyword_args(
|
266
|
-
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
|
267
266
|
)
|
268
267
|
else
|
269
|
-
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)
|
270
269
|
end
|
271
270
|
else
|
272
271
|
@query.arguments_cache.dataload_for(ast_node, field_defn, owner_object) do |resolved_arguments|
|
273
272
|
runtime_state = get_current_runtime_state # This might be in a different fiber
|
274
|
-
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)
|
275
274
|
end
|
276
275
|
end
|
277
276
|
end
|
278
277
|
|
279
|
-
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
|
280
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|
|
281
|
-
return_type_non_null = return_type.non_null?
|
282
280
|
if resolved_arguments.is_a?(GraphQL::ExecutionError) || resolved_arguments.is_a?(GraphQL::UnauthorizedError)
|
281
|
+
return_type_non_null = field_defn.type.non_null?
|
283
282
|
continue_value(resolved_arguments, field_defn, return_type_non_null, ast_node, result_name, selection_result)
|
284
283
|
next
|
285
284
|
end
|
@@ -318,7 +317,8 @@ module GraphQL
|
|
318
317
|
# to the keyword args hash _before_ freezing everything.
|
319
318
|
extra_args[:argument_details] = :__arguments_add_self
|
320
319
|
when :parent
|
321
|
-
|
320
|
+
parent_result = selection_result.graphql_parent
|
321
|
+
extra_args[:parent] = parent_result&.graphql_application_value&.object
|
322
322
|
else
|
323
323
|
extra_args[extra] = field_defn.fetch_extra(extra, context)
|
324
324
|
end
|
@@ -329,11 +329,11 @@ module GraphQL
|
|
329
329
|
resolved_arguments.keyword_arguments
|
330
330
|
end
|
331
331
|
|
332
|
-
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)
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
336
|
-
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
|
337
337
|
runtime_state.current_field = field_defn
|
338
338
|
runtime_state.current_arguments = resolved_arguments
|
339
339
|
runtime_state.current_result_name = result_name
|
@@ -376,7 +376,8 @@ module GraphQL
|
|
376
376
|
end
|
377
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|
|
378
378
|
owner_type = selection_result.graphql_result_type
|
379
|
-
|
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)
|
380
381
|
if HALT != continue_value
|
381
382
|
was_scoped = runtime_state.was_authorized_by_scope_items
|
382
383
|
runtime_state.was_authorized_by_scope_items = nil
|
@@ -387,7 +388,7 @@ module GraphQL
|
|
387
388
|
# If this field is a root mutation field, immediately resolve
|
388
389
|
# all of its child fields before moving on to the next root mutation field.
|
389
390
|
# (Subselections of this mutation will still be resolved level-by-level.)
|
390
|
-
if
|
391
|
+
if selection_result.graphql_is_eager
|
391
392
|
Interpreter::Resolve.resolve_all([field_result], @dataloader)
|
392
393
|
end
|
393
394
|
end
|
@@ -599,21 +600,11 @@ module GraphQL
|
|
599
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|
|
600
601
|
continue_value = continue_value(inner_object, field, is_non_null, ast_node, result_name, selection_result)
|
601
602
|
if HALT != continue_value
|
602
|
-
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)
|
603
604
|
set_result(selection_result, result_name, response_hash, true, is_non_null)
|
604
|
-
|
605
|
-
gathered_selections = gather_selections(continue_value, current_type, next_selections)
|
606
|
-
# There are two possibilities for `gathered_selections`:
|
607
|
-
# 1. All selections of this object should be evaluated together (there are no runtime directives modifying execution).
|
608
|
-
# This case is handled below, and the result can be written right into the main `response_hash` above.
|
609
|
-
# In this case, `gathered_selections` is a hash of selections.
|
610
|
-
# 2. Some selections of this object have runtime directives that may or may not modify execution.
|
611
|
-
# That part of the selection is evaluated in an isolated way, writing into a sub-response object which is
|
612
|
-
# eventually merged into the final response. In this case, `gathered_selections` is an array of things to run in isolation.
|
613
|
-
# (Technically, it's possible that one of those entries _doesn't_ require isolation.)
|
614
|
-
tap_or_each(gathered_selections) do |selections, is_selection_array|
|
605
|
+
each_gathered_selections(response_hash) do |selections, is_selection_array|
|
615
606
|
if is_selection_array
|
616
|
-
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)
|
617
608
|
final_result = response_hash
|
618
609
|
else
|
619
610
|
this_result = response_hash
|
@@ -621,11 +612,9 @@ module GraphQL
|
|
621
612
|
end
|
622
613
|
|
623
614
|
evaluate_selections(
|
624
|
-
false,
|
625
615
|
selections,
|
626
616
|
this_result,
|
627
617
|
final_result,
|
628
|
-
owner_object.object,
|
629
618
|
runtime_state,
|
630
619
|
)
|
631
620
|
end
|
@@ -636,7 +625,7 @@ module GraphQL
|
|
636
625
|
# This is true for objects, unions, and interfaces
|
637
626
|
use_dataloader_job = !inner_type.unwrap.kind.input?
|
638
627
|
inner_type_non_null = inner_type.non_null?
|
639
|
-
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)
|
640
629
|
set_result(selection_result, result_name, response_list, true, is_non_null)
|
641
630
|
idx = nil
|
642
631
|
list_value = begin
|
@@ -646,10 +635,10 @@ module GraphQL
|
|
646
635
|
idx += 1
|
647
636
|
if use_dataloader_job
|
648
637
|
@dataloader.append_job do
|
649
|
-
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)
|
650
639
|
end
|
651
640
|
else
|
652
|
-
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)
|
653
642
|
end
|
654
643
|
end
|
655
644
|
|
@@ -680,7 +669,7 @@ module GraphQL
|
|
680
669
|
end
|
681
670
|
end
|
682
671
|
|
683
|
-
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
|
684
673
|
runtime_state.current_result_name = this_idx
|
685
674
|
runtime_state.current_result = response_list
|
686
675
|
call_method_on_directives(:resolve_each, owner_object, ast_node.directives) do
|
@@ -688,7 +677,7 @@ module GraphQL
|
|
688
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|
|
689
678
|
continue_value = continue_value(inner_inner_value, field, inner_type_non_null, ast_node, this_idx, response_list)
|
690
679
|
if HALT != continue_value
|
691
|
-
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)
|
692
681
|
end
|
693
682
|
end
|
694
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
|
@@ -20,6 +20,15 @@ module GraphQL
|
|
20
20
|
@definition_line = definition_line
|
21
21
|
super(**_rest)
|
22
22
|
end
|
23
|
+
|
24
|
+
def marshal_dump
|
25
|
+
super << @definition_line
|
26
|
+
end
|
27
|
+
|
28
|
+
def marshal_load(values)
|
29
|
+
@definition_line = values.pop
|
30
|
+
super
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
34
|
attr_reader :filename
|
@@ -265,6 +274,8 @@ module GraphQL
|
|
265
274
|
]
|
266
275
|
|
267
276
|
def generate_initialize
|
277
|
+
return if method_defined?(:marshal_load, false) # checking for `:initialize` doesn't work right
|
278
|
+
|
268
279
|
scalar_method_names = @scalar_methods
|
269
280
|
# TODO: These probably should be scalar methods, but `types` returns an array
|
270
281
|
[:types, :description].each do |extra_method|
|
@@ -273,18 +284,20 @@ module GraphQL
|
|
273
284
|
end
|
274
285
|
end
|
275
286
|
|
276
|
-
|
287
|
+
children_method_names = @children_methods.keys
|
288
|
+
|
289
|
+
all_method_names = scalar_method_names + children_method_names
|
277
290
|
if all_method_names.include?(:alias)
|
278
291
|
# Rather than complicating this special case,
|
279
292
|
# let it be overridden (in field)
|
280
293
|
return
|
281
294
|
else
|
282
295
|
arguments = scalar_method_names.map { |m| "#{m}: nil"} +
|
283
|
-
|
296
|
+
children_method_names.map { |m| "#{m}: NO_CHILDREN" } +
|
284
297
|
DEFAULT_INITIALIZE_OPTIONS
|
285
298
|
|
286
299
|
assignments = scalar_method_names.map { |m| "@#{m} = #{m}"} +
|
287
|
-
|
300
|
+
children_method_names.map { |m| "@#{m} = #{m}.freeze" }
|
288
301
|
|
289
302
|
if name.end_with?("Definition") && name != "FragmentDefinition"
|
290
303
|
arguments << "definition_pos: nil"
|
@@ -292,7 +305,7 @@ module GraphQL
|
|
292
305
|
end
|
293
306
|
|
294
307
|
keywords = scalar_method_names.map { |m| "#{m}: #{m}"} +
|
295
|
-
|
308
|
+
children_method_names.map { |m| "#{m}: #{m}" }
|
296
309
|
|
297
310
|
module_eval <<-RUBY, __FILE__, __LINE__
|
298
311
|
def initialize(#{arguments.join(", ")})
|
@@ -304,9 +317,21 @@ module GraphQL
|
|
304
317
|
#{assignments.join("\n")}
|
305
318
|
end
|
306
319
|
|
307
|
-
def self.from_a(filename, line, col, #{
|
320
|
+
def self.from_a(filename, line, col, #{all_method_names.join(", ")})
|
308
321
|
self.new(filename: filename, line: line, col: col, #{keywords.join(", ")})
|
309
322
|
end
|
323
|
+
|
324
|
+
def marshal_dump
|
325
|
+
[
|
326
|
+
line, col, # use methods here to force them to be calculated
|
327
|
+
@filename,
|
328
|
+
#{all_method_names.map { |n| "@#{n}," }.join}
|
329
|
+
]
|
330
|
+
end
|
331
|
+
|
332
|
+
def marshal_load(values)
|
333
|
+
@line, @col, @filename #{all_method_names.map { |n| ", @#{n}"}.join} = values
|
334
|
+
end
|
310
335
|
RUBY
|
311
336
|
end
|
312
337
|
end
|
@@ -369,16 +394,6 @@ module GraphQL
|
|
369
394
|
|
370
395
|
# A single selection in a GraphQL query.
|
371
396
|
class Field < AbstractNode
|
372
|
-
scalar_methods :name, :alias
|
373
|
-
children_methods({
|
374
|
-
arguments: GraphQL::Language::Nodes::Argument,
|
375
|
-
selections: GraphQL::Language::Nodes::Field,
|
376
|
-
directives: GraphQL::Language::Nodes::Directive,
|
377
|
-
})
|
378
|
-
|
379
|
-
# @!attribute selections
|
380
|
-
# @return [Array<Nodes::Field>] Selections on this object (or empty array if this is a scalar field)
|
381
|
-
|
382
397
|
def initialize(name: nil, arguments: NONE, directives: NONE, selections: NONE, field_alias: nil, line: nil, col: nil, pos: nil, filename: nil, source: nil)
|
383
398
|
@name = name
|
384
399
|
@arguments = arguments || NONE
|
@@ -397,24 +412,27 @@ module GraphQL
|
|
397
412
|
self.new(filename: filename, line: line, col: col, field_alias: field_alias, name: name, arguments: arguments, directives: directives, selections: selections)
|
398
413
|
end
|
399
414
|
|
400
|
-
|
401
|
-
|
402
|
-
|
415
|
+
def marshal_dump
|
416
|
+
[line, col, @filename, @name, @arguments, @directives, @selections, @alias]
|
417
|
+
end
|
403
418
|
|
404
|
-
|
405
|
-
|
406
|
-
|
419
|
+
def marshal_load(values)
|
420
|
+
@line, @col, @filename, @name, @arguments, @directives, @selections, @alias = values
|
421
|
+
end
|
422
|
+
|
423
|
+
scalar_methods :name, :alias
|
407
424
|
children_methods({
|
425
|
+
arguments: GraphQL::Language::Nodes::Argument,
|
408
426
|
selections: GraphQL::Language::Nodes::Field,
|
409
427
|
directives: GraphQL::Language::Nodes::Directive,
|
410
428
|
})
|
411
429
|
|
412
|
-
|
413
|
-
|
414
|
-
|
430
|
+
# Override this because default is `:fields`
|
431
|
+
self.children_method_name = :selections
|
432
|
+
end
|
415
433
|
|
416
|
-
|
417
|
-
|
434
|
+
# A reusable fragment, defined at document-level.
|
435
|
+
class FragmentDefinition < AbstractNode
|
418
436
|
def initialize(name: nil, type: nil, directives: NONE, selections: NONE, filename: nil, pos: nil, source: nil, line: nil, col: nil)
|
419
437
|
@name = name
|
420
438
|
@type = type
|
@@ -430,6 +448,22 @@ module GraphQL
|
|
430
448
|
def self.from_a(filename, line, col, name, type, directives, selections)
|
431
449
|
self.new(filename: filename, line: line, col: col, name: name, type: type, directives: directives, selections: selections)
|
432
450
|
end
|
451
|
+
|
452
|
+
def marshal_dump
|
453
|
+
[line, col, @filename, @name, @type, @directives, @selections]
|
454
|
+
end
|
455
|
+
|
456
|
+
def marshal_load(values)
|
457
|
+
@line, @col, @filename, @name, @type, @directives, @selections = values
|
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
|
433
467
|
end
|
434
468
|
|
435
469
|
# Application of a named fragment in a selection
|