graphql 2.6.2 → 2.6.5

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/field_extractor.rb +17 -1
  3. data/lib/graphql/analysis/query_complexity.rb +31 -15
  4. data/lib/graphql/backtrace/table.rb +10 -1
  5. data/lib/graphql/current.rb +7 -1
  6. data/lib/graphql/dataloader/async_dataloader.rb +310 -60
  7. data/lib/graphql/dataloader/source.rb +18 -10
  8. data/lib/graphql/dataloader.rb +1 -1
  9. data/lib/graphql/execution/directive_checks.rb +2 -0
  10. data/lib/graphql/execution/field_resolve_step.rb +84 -18
  11. data/lib/graphql/execution/finalize.rb +10 -9
  12. data/lib/graphql/execution/interpreter/arguments_cache.rb +3 -0
  13. data/lib/graphql/execution/interpreter/runtime.rb +0 -6
  14. data/lib/graphql/execution/load_argument_step.rb +6 -0
  15. data/lib/graphql/execution/prepare_object_step.rb +14 -4
  16. data/lib/graphql/execution/runner.rb +7 -1
  17. data/lib/graphql/execution/selections_step.rb +6 -2
  18. data/lib/graphql/execution_error.rb +4 -0
  19. data/lib/graphql/language.rb +8 -2
  20. data/lib/graphql/schema/argument.rb +1 -1
  21. data/lib/graphql/schema/interface.rb +1 -1
  22. data/lib/graphql/schema/introspection_system.rb +6 -21
  23. data/lib/graphql/schema/printer.rb +1 -1
  24. data/lib/graphql/schema/validator/allow_blank_validator.rb +3 -3
  25. data/lib/graphql/schema/validator/allow_null_validator.rb +3 -3
  26. data/lib/graphql/schema/validator/exclusion_validator.rb +2 -2
  27. data/lib/graphql/schema/validator/format_validator.rb +3 -3
  28. data/lib/graphql/schema/validator/inclusion_validator.rb +2 -2
  29. data/lib/graphql/schema/validator/length_validator.rb +6 -6
  30. data/lib/graphql/schema/validator/numericality_validator.rb +19 -19
  31. data/lib/graphql/schema/validator/required_validator.rb +6 -4
  32. data/lib/graphql/schema/validator.rb +9 -0
  33. data/lib/graphql/schema/visibility/profile.rb +6 -4
  34. data/lib/graphql/schema/visibility.rb +30 -22
  35. data/lib/graphql/schema.rb +1 -1
  36. data/lib/graphql/version.rb +1 -1
  37. metadata +2 -2
@@ -49,12 +49,16 @@ module GraphQL
49
49
  end
50
50
 
51
51
  def value
52
+ return nil if @selections_step.killed
52
53
  query = @selections_step.query
53
- query.current_trace.begin_execute_field(@field_definition, @arguments, @field_results, query)
54
+ set_current_field
55
+ query.current_trace.begin_execute_field(@field_definition, @field_results, @arguments, query)
54
56
  sync(@field_results)
55
- query.current_trace.end_execute_field(@field_definition, @arguments, @field_results, query, @field_results)
57
+ query.current_trace.end_execute_field(@field_definition, @field_results, @arguments, query, @field_results)
56
58
  @runner.add_step(self)
57
59
  true
60
+ ensure
61
+ set_current_field(nil)
58
62
  end
59
63
 
60
64
  def sync(lazy)
@@ -76,6 +80,9 @@ module GraphQL
76
80
  end
77
81
 
78
82
  def call
83
+ return nil if @selections_step.killed
84
+ set_current_field if @field_definition
85
+
79
86
  if @enqueued_authorization
80
87
  enqueue_next_steps
81
88
  elsif @finish_extension_idx
@@ -94,26 +101,68 @@ module GraphQL
94
101
  else
95
102
  raise
96
103
  end
104
+ ensure
105
+ set_current_field(nil)
97
106
  end
98
107
 
99
- def add_graphql_error(err)
108
+ def add_graphql_error(result, key, err, return_type: @field_definition.type)
100
109
  err.path = path
101
110
  if err.ast_node.nil?
102
111
  err.ast_nodes = ast_nodes
103
112
  end
104
- @selections_step.query.context.add_error(err)
113
+ @runner.add_finalizer(@selections_step.query, result, key, err)
114
+ if !err.is_a?(GraphQL::Execution::Skip)
115
+ field_type = return_type
116
+ should_propagate_null = field_type.non_null?
117
+ while (should_propagate_null == false && field_type.kind.wraps?)
118
+ field_type = field_type.of_type
119
+ should_propagate_null = field_type.non_null?
120
+ end
121
+ if should_propagate_null
122
+ propagate_nulls
123
+ end
124
+ end
105
125
  err
106
126
  end
107
127
 
128
+ def propagate_nulls
129
+ propagating_null = true
130
+ highest_nulled_depth = path.size
131
+ highest_list_depth = nil
132
+ current_field_step = self
133
+ while current_field_step
134
+ return_type = current_field_step.field_definition.type
135
+ if propagating_null && return_type.non_null?
136
+ highest_nulled_depth = current_field_step.path.size
137
+ else
138
+ propagating_null = false
139
+ end
140
+
141
+ if return_type.list?
142
+ highest_list_depth = current_field_step.path.size
143
+ end
144
+
145
+ current_field_step = current_field_step.selections_step.field_resolve_step
146
+ end
147
+
148
+ if highest_list_depth.nil? || highest_nulled_depth <= highest_list_depth
149
+ kill_field_step = self
150
+ while kill_field_step && highest_nulled_depth <= kill_field_step.path.size
151
+ kill_field_step.selections_step.killed = true
152
+ kill_field_step = kill_field_step.selections_step.field_resolve_step
153
+ end
154
+ end
155
+ end
156
+
108
157
  def build_errors_result(errors, single_error)
109
158
  first_error = errors.nil? ? single_error : errors.pop
110
- @field_results = error_instance_array(@selections_step.objects.size, first_error)
159
+ @field_results = [first_error]
160
+ @results = [@selections_step.results.first]
111
161
  if errors
112
162
  errors.each do |e|
113
- add_graphql_error(e)
163
+ add_graphql_error(@results.first, key, e)
114
164
  end
115
165
  end
116
- @results ||= @selections_step.results
117
166
  build_results
118
167
  end
119
168
 
@@ -121,6 +170,7 @@ module GraphQL
121
170
  query = @selections_step.query
122
171
  field_name = @ast_node.name
123
172
  @field_definition = query.types.field(@parent_type, field_name) || raise(GraphQL::Error, "No field definition found for #{@parent_type.to_type_signature}.#{ast_node.name} (at #{@ast_node.position})")
173
+ set_current_field
124
174
  @arguments, errors = @runner.input_values[query].argument_values(@field_definition, @ast_node.arguments, self) # rubocop:disable Development/ContextIsPassedCop
125
175
  if errors
126
176
  build_errors_result(errors, nil)
@@ -131,6 +181,8 @@ module GraphQL
131
181
  @field_results.nil? # Make sure the arguments flow didn't already call through
132
182
  execute_field
133
183
  end
184
+ ensure
185
+ set_current_field(nil)
134
186
  end
135
187
 
136
188
  # Used for compatibility in Schema::Subscription
@@ -217,7 +269,7 @@ module GraphQL
217
269
  authorized_results << @results[i]
218
270
  end
219
271
  rescue GraphQL::ExecutionError => exec_err
220
- add_graphql_error(exec_err)
272
+ add_graphql_error(@results[i], key, exec_err)
221
273
  end
222
274
  end
223
275
  i += 1
@@ -235,7 +287,7 @@ module GraphQL
235
287
  @was_scoped = true
236
288
  end
237
289
 
238
- query.current_trace.begin_execute_field(@field_definition, @arguments, authorized_objects, query)
290
+ query.current_trace.begin_execute_field(@field_definition, authorized_objects, @arguments, query)
239
291
 
240
292
  if @runner.uses_runtime_directives
241
293
  if @ast_nodes.nil? || @ast_nodes.size == 1
@@ -310,7 +362,7 @@ module GraphQL
310
362
  @field_results = resolve_batch(authorized_objects, ctx, @arguments)
311
363
  end
312
364
 
313
- query.current_trace.end_execute_field(@field_definition, @arguments, authorized_objects, query, @field_results)
365
+ query.current_trace.end_execute_field(@field_definition, authorized_objects, @arguments, query, @field_results)
314
366
 
315
367
  if any_lazy_results?
316
368
  @runner.dataloader.lazy_at_depth(path.size, self)
@@ -322,12 +374,12 @@ module GraphQL
322
374
  end
323
375
  end
324
376
  rescue GraphQL::ExecutionError => err
325
- add_graphql_error(err)
377
+ build_errors_result(nil, err)
326
378
  rescue StandardError => stderr
327
379
  begin
328
380
  @selections_step.query.handle_or_reraise(stderr, field: @field_definition, arguments: @arguments, object: nil)
329
381
  rescue GraphQL::ExecutionError => err
330
- add_graphql_error(err)
382
+ add_graphql_error(@results[0], key, err)
331
383
  end
332
384
  end
333
385
 
@@ -449,13 +501,13 @@ module GraphQL
449
501
  end
450
502
 
451
503
  def finish_leaf_result(result_h, key, field_result, return_type, ctx)
452
- final_field_result = build_leaf_result(field_result, return_type, ctx, false)
504
+ final_field_result = build_leaf_result(result_h, key, field_result, return_type, ctx, false)
453
505
 
454
506
  @directive_finalizers&.each { |f| @runner.add_finalizer(ctx.query, result_h, key, f) }
455
507
  result_h[@key] = final_field_result
456
508
  end
457
509
 
458
- def build_leaf_result(field_result, return_type, ctx, is_from_array)
510
+ def build_leaf_result(result_h, result_key, field_result, return_type, ctx, is_from_array)
459
511
  if field_result.nil?
460
512
  if return_type.non_null?
461
513
  add_non_null_error(is_from_array)
@@ -464,7 +516,7 @@ module GraphQL
464
516
  end
465
517
  elsif field_result.is_a?(Finalizer)
466
518
  if field_result.is_a?(GraphQL::RuntimeError)
467
- add_graphql_error(field_result)
519
+ add_graphql_error(result_h, result_key, field_result, return_type: return_type)
468
520
  else
469
521
  field_result.path = path
470
522
  @runner.add_finalizer(ctx.query, result_h, key, field_result)
@@ -475,7 +527,11 @@ module GraphQL
475
527
  end
476
528
 
477
529
  inner_type = return_type.of_type
478
- field_result.map { |item| build_leaf_result(item, inner_type, ctx, true) }
530
+ result_a = Array.new(field_result.size)
531
+ field_result.each_with_index do |item, idx|
532
+ result_a[idx] = build_leaf_result(result_a, idx, item, inner_type, ctx, true)
533
+ end
534
+ result_a
479
535
  else
480
536
  return_type.coerce_result(field_result, ctx)
481
537
  end
@@ -517,6 +573,7 @@ module GraphQL
517
573
  query.current_trace.objects(obj_type, next_objects, ctx)
518
574
  @runner.add_step(SelectionsStep.new(
519
575
  path: path,
576
+ field_resolve_step: self,
520
577
  parent_type: obj_type,
521
578
  selections: @next_selections,
522
579
  objects: next_objects,
@@ -529,6 +586,7 @@ module GraphQL
529
586
  query.current_trace.objects(@static_type, @all_next_objects, ctx)
530
587
  @runner.add_step(SelectionsStep.new(
531
588
  path: path,
589
+ field_resolve_step: self,
532
590
  parent_type: @static_type,
533
591
  selections: @next_selections,
534
592
  objects: @all_next_objects,
@@ -549,7 +607,15 @@ module GraphQL
549
607
 
550
608
  def add_non_null_error(is_from_array)
551
609
  err = @parent_type::InvalidNullError.new(@parent_type, @field_definition, ast_nodes, is_from_array: is_from_array, path: path)
552
- @runner.schema.type_error(err, @selections_step.query.context)
610
+ nn_result = @runner.schema.type_error(err, @selections_step.query.context)
611
+ if nn_result.nil?
612
+ propagate_nulls
613
+ end
614
+ nn_result
615
+ end
616
+
617
+ def set_current_field(new_value = @field_definition)
618
+ Fiber[:__graphql_current_field] = new_value
553
619
  end
554
620
 
555
621
  private
@@ -563,7 +629,7 @@ module GraphQL
563
629
  end
564
630
  elsif field_result.is_a?(Finalizer)
565
631
  graphql_result[key] = if field_result.is_a?(GraphQL::RuntimeError)
566
- add_graphql_error(field_result)
632
+ add_graphql_error(graphql_result, key, field_result)
567
633
  else
568
634
  field_result.path = path
569
635
  @runner.add_finalizer(@selections_step.query, graphql_result, key, field_result)
@@ -33,14 +33,15 @@ module GraphQL
33
33
 
34
34
  targets.each_with_index do |target, idx|
35
35
  if target.is_a?(Hash)
36
- if target[key].equal?(err)
36
+ value_at_key = target[key]
37
+ if value_at_key.equal?(err)
37
38
  tf = @finalizers[target] ||= {}.compare_by_identity
38
39
  tf[key] = err
39
40
  @finalizers_count += 1
40
- elsif (arr = target[key]).is_a?(Array)
41
- arr.each_with_index do |el, idx|
41
+ elsif value_at_key.is_a?(Array)
42
+ value_at_key.each_with_index do |el, idx|
42
43
  if el.equal?(err)
43
- tf = @finalizers[arr] ||= {}.compare_by_identity
44
+ tf = @finalizers[value_at_key] ||= {}.compare_by_identity
44
45
  tf[idx] = err
45
46
  @finalizers_count += 1
46
47
  end
@@ -117,7 +118,7 @@ module GraphQL
117
118
  @current_exec_path << key
118
119
  @current_result_path << key
119
120
 
120
- field_defn = @query.context.types.field(parent_type, ast_selection.name) || raise("Invariant: No field found for #{static_type.to_type_signature}.#{ast_selection.name}")
121
+ field_defn = @query.context.types.field(parent_type, ast_selection.name) || raise("Invariant: No field found for #{parent_type.to_type_signature}.#{ast_selection.name}")
121
122
  result_type = field_defn.type
122
123
  if (result_type_non_null = result_type.non_null?)
123
124
  result_type = result_type.of_type
@@ -150,16 +151,18 @@ module GraphQL
150
151
  when Language::Nodes::InlineFragment
151
152
  static_type_at_result = @static_type_at[result_h]
152
153
  if static_type_at_result && (
153
- (t = ast_selection.type).nil? ||
154
+ (t = ast_selection.type).nil? ||
154
155
  @runner.type_condition_applies?(@query.context, static_type_at_result, t.name)
155
156
  )
156
157
  result_h = check_object_result(result_h, parent_type, ast_selection.selections)
158
+ return nil if result_h.nil?
157
159
  end
158
160
  when Language::Nodes::FragmentSpread
159
161
  fragment_defn = @query.document.definitions.find { |defn| defn.is_a?(Language::Nodes::FragmentDefinition) && defn.name == ast_selection.name }
160
162
  static_type_at_result = @static_type_at[result_h]
161
163
  if static_type_at_result && @runner.type_condition_applies?(@query.context, static_type_at_result, fragment_defn.type.name)
162
164
  result_h = check_object_result(result_h, parent_type, fragment_defn.selections)
165
+ return nil if result_h.nil?
163
166
  end
164
167
  end
165
168
  end
@@ -168,9 +171,7 @@ module GraphQL
168
171
  end
169
172
 
170
173
  def check_list_result(result_arr, inner_type, ast_selections)
171
- inner_type_non_null = false
172
- if inner_type.non_null?
173
- inner_type_non_null = true
174
+ if (inner_type_non_null = inner_type.non_null?)
174
175
  inner_type = inner_type.of_type
175
176
  end
176
177
 
@@ -30,7 +30,10 @@ module GraphQL
30
30
  @storage[argument_owner][parent_object][ast_node] = resolved_args
31
31
  end
32
32
  end
33
+ end
33
34
 
35
+ def cached_arguments_for(ast_node, argument_owner)
36
+ @storage[argument_owner][nil][ast_node]
34
37
  end
35
38
 
36
39
  # @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
@@ -492,12 +492,6 @@ module GraphQL
492
492
  end
493
493
  end
494
494
  end
495
- # If this field is a root mutation field, immediately resolve
496
- # all of its child fields before moving on to the next root mutation field.
497
- # (Subselections of this mutation will still be resolved level-by-level.)
498
- if selection_result.graphql_is_eager
499
- @dataloader.run
500
- end
501
495
  end
502
496
 
503
497
  def set_result(selection_result, result_name, value, is_child_result, is_non_null)
@@ -14,6 +14,7 @@ module GraphQL
14
14
  end
15
15
 
16
16
  def value
17
+ @field_resolve_step.set_current_field
17
18
  schema = @field_resolve_step.runner.schema
18
19
  @loaded_value = schema.sync_lazy(@loaded_value)
19
20
  assign_value
@@ -34,9 +35,12 @@ module GraphQL
34
35
  @loaded_value = ex_err
35
36
  end
36
37
  assign_value
38
+ ensure
39
+ @field_resolve_step.set_current_field(nil)
37
40
  end
38
41
 
39
42
  def call
43
+ @field_resolve_step.set_current_field
40
44
  context = @field_resolve_step.selections_step.query.context
41
45
  @loaded_value = begin
42
46
  @load_receiver.load_and_authorize_application_object(@argument_definition, @argument_value, context)
@@ -64,6 +68,8 @@ module GraphQL
64
68
  ex_err
65
69
  end
66
70
  assign_value
71
+ ensure
72
+ @field_resolve_step.set_current_field(nil)
67
73
  end
68
74
 
69
75
  private
@@ -19,6 +19,7 @@ module GraphQL
19
19
  end
20
20
 
21
21
  def value
22
+ @field_resolve_step.set_current_field
22
23
  if @authorized_value
23
24
  query = @field_resolve_step.selections_step.query
24
25
  query.current_trace.begin_authorized(@resolved_type, @object, query.context)
@@ -36,9 +37,12 @@ module GraphQL
36
37
  ctx.query.current_trace.end_resolve_type(st, @object, ctx, @resolved_type)
37
38
  end
38
39
  @runner.add_step(self)
40
+ ensure
41
+ @field_resolve_step.set_current_field(nil)
39
42
  end
40
43
 
41
44
  def call
45
+ @field_resolve_step.set_current_field
42
46
  case @next_step
43
47
  when :resolve_type
44
48
  static_type = @field_resolve_step.static_type
@@ -65,6 +69,12 @@ module GraphQL
65
69
  else
66
70
  raise ArgumentError, "This is a bug, unknown step: #{@next_step.inspect}"
67
71
  end
72
+ ensure
73
+ @field_resolve_step.set_current_field(nil)
74
+ end
75
+
76
+ def add_field_error(err)
77
+ @field_resolve_step.add_graphql_error(@graphql_result, @key, err)
68
78
  end
69
79
 
70
80
  def authorize
@@ -90,13 +100,13 @@ module GraphQL
90
100
  create_result
91
101
  end
92
102
  rescue GraphQL::RuntimeError => err
93
- @graphql_result[@key] = @field_resolve_step.add_graphql_error(err)
103
+ @graphql_result[@key] = add_field_error(err)
94
104
  rescue StandardError => err
95
105
  query ||= @field_resolve_step.selections_step.query
96
106
  begin
97
107
  query.handle_or_reraise(err, field: @field_resolve_step.field_definition, arguments: @field_resolve_step.arguments, object: @object) # rubocop:disable Development/ContextIsPassedCop
98
108
  rescue GraphQL::RuntimeError => err
99
- @graphql_result[@key] = @field_resolve_step.add_graphql_error(err)
109
+ @graphql_result[@key] = add_field_error(err)
100
110
  end
101
111
  end
102
112
 
@@ -114,13 +124,13 @@ module GraphQL
114
124
  elsif @is_non_null
115
125
  @graphql_result[@key] = @field_resolve_step.add_non_null_error(@is_from_array)
116
126
  else
117
- @graphql_result[@key] = @field_resolve_step.add_graphql_error(@authorization_error)
127
+ @graphql_result[@key] = add_field_error(@authorization_error)
118
128
  end
119
129
  rescue GraphQL::RuntimeError => err
120
130
  if @is_non_null
121
131
  @graphql_result[@key] = @field_resolve_step.add_non_null_error(@is_from_array)
122
132
  else
123
- @graphql_result[@key] = @field_resolve_step.add_graphql_error(err)
133
+ @graphql_result[@key] = add_field_error(err)
124
134
  end
125
135
  end
126
136
  end
@@ -116,7 +116,7 @@ module GraphQL
116
116
  query.context.add_error(err)
117
117
  end
118
118
 
119
- trace.execute_query_lazy(query: nil, multiplex: @multiplex) do
119
+ trace.execute_query_lazy(query: @multiplex.queries.size == 1 ? @multiplex.queries.first : nil, multiplex: @multiplex) do
120
120
  while (next_isolated_steps = isolated_steps.shift)
121
121
  next_isolated_steps.each do |step|
122
122
  add_step(step)
@@ -298,6 +298,7 @@ module GraphQL
298
298
  if query.query?
299
299
  isolated_steps[0] << SelectionsStep.new(
300
300
  parent_type: root_type,
301
+ field_resolve_step: nil,
301
302
  selections: selected_operation.selections,
302
303
  objects: objects,
303
304
  results: [data],
@@ -317,6 +318,7 @@ module GraphQL
317
318
  isolated_steps << [SelectionsStep.new(
318
319
  clobber: false, # `data` is being shared among several selections steps
319
320
  parent_type: root_type,
321
+ field_resolve_step: field_resolve_step,
320
322
  selections: field_resolve_step.ast_nodes || Array(field_resolve_step.ast_node),
321
323
  objects: objects,
322
324
  results: [data],
@@ -332,6 +334,7 @@ module GraphQL
332
334
  end
333
335
  isolated_steps[0] << SelectionsStep.new(
334
336
  parent_type: root_type,
337
+ field_resolve_step: nil,
335
338
  selections: selected_operation.selections,
336
339
  objects: objects,
337
340
  results: [data],
@@ -355,6 +358,7 @@ module GraphQL
355
358
  results << { "data" => data }
356
359
  isolated_steps[0] << SelectionsStep.new(
357
360
  parent_type: resolved_type,
361
+ field_resolve_step: nil,
358
362
  selections: selected_operation.selections,
359
363
  objects: objects,
360
364
  results: [data],
@@ -372,6 +376,7 @@ module GraphQL
372
376
  results << { "data" => list_result }
373
377
  isolated_steps[0] << SelectionsStep.new(
374
378
  parent_type: inner_type,
379
+ field_resolve_step: nil,
375
380
  selections: selected_operation.selections,
376
381
  objects: root_value,
377
382
  results: list_result,
@@ -420,6 +425,7 @@ module GraphQL
420
425
  selections = partial.ast_nodes
421
426
  dummy_ss = SelectionsStep.new(
422
427
  parent_type: nil,
428
+ field_resolve_step: nil,
423
429
  selections: selections,
424
430
  objects: nil,
425
431
  results: nil,
@@ -2,8 +2,9 @@
2
2
  module GraphQL
3
3
  module Execution
4
4
  class SelectionsStep
5
- def initialize(parent_type:, selections:, objects:, results:, runner:, query:, path:, clobber: true)
5
+ def initialize(parent_type:, field_resolve_step:, selections:, objects:, results:, runner:, query:, path:, clobber: true)
6
6
  @path = path
7
+ @field_resolve_step = field_resolve_step
7
8
  @parent_type = parent_type
8
9
  @selections = selections
9
10
  @runner = runner
@@ -12,10 +13,13 @@ module GraphQL
12
13
  @query = query
13
14
  @graphql_objects = nil
14
15
  @all_selections = nil
16
+ @killed = false
15
17
  @clobber = clobber
16
18
  end
17
19
 
18
- attr_reader :path, :query, :objects, :results
20
+ attr_reader :path, :query, :objects, :results, :field_resolve_step
21
+
22
+ attr_accessor :killed
19
23
 
20
24
  def graphql_objects
21
25
  @graphql_objects ||= @objects.map do |obj|
@@ -26,6 +26,10 @@ module GraphQL
26
26
  end
27
27
 
28
28
  def finalize_graphql_result(query, result_data, key)
29
+ add_this_error = !query.context.errors.any? { |e| e.eql?(self) }
30
+ if add_this_error
31
+ query.context.add_error(self)
32
+ end
29
33
  if ast_node.is_a?(GraphQL::Language::Nodes::Directive)
30
34
  # This is for backwards compatibility ... what does the spec say?
31
35
  result_data.delete(key)
@@ -47,13 +47,19 @@ module GraphQL
47
47
  def self.escape_single_quoted_newlines(query_str)
48
48
  scanner = StringScanner.new(query_str)
49
49
  inside_single_quoted_string = false
50
+ inside_triple_quoted_string = false
50
51
  new_query_str = nil
51
52
  while !scanner.eos?
52
- if scanner.skip(/(?:\\"|[^"\n\r]|""")+/m)
53
+ if scanner.skip('"""')
54
+ inside_triple_quoted_string = !inside_triple_quoted_string
55
+ new_query_str && (new_query_str << scanner.matched)
56
+ elsif scanner.skip(/(?:\\"|[^"\n\r])+/m)
53
57
  new_query_str && (new_query_str << scanner.matched)
54
58
  elsif scanner.skip('"')
55
59
  new_query_str && (new_query_str << '"')
56
- inside_single_quoted_string = !inside_single_quoted_string
60
+ if !inside_triple_quoted_string
61
+ inside_single_quoted_string = !inside_single_quoted_string
62
+ end
57
63
  elsif scanner.skip("\n")
58
64
  if inside_single_quoted_string
59
65
  new_query_str ||= query_str[0, scanner.pos - 1]
@@ -94,7 +94,7 @@ module GraphQL
94
94
  end
95
95
 
96
96
  if required == :nullable
97
- self.owner.validates(required: { argument: arg_name })
97
+ self.owner.validates(required: { argument: @keyword })
98
98
  end
99
99
 
100
100
  if definition_block
@@ -101,7 +101,7 @@ module GraphQL
101
101
  end
102
102
 
103
103
  child_class.ancestors.reverse_each do |ancestor|
104
- if ancestor.const_defined?(:ResolverMethods)
104
+ if ancestor != child_class && ancestor <= GraphQL::Schema::Interface && ancestor.const_defined?(:ResolverMethods, false)
105
105
  child_class.extend(ancestor::ResolverMethods)
106
106
  end
107
107
  end
@@ -105,11 +105,13 @@ module GraphQL
105
105
  end
106
106
 
107
107
  def load_constant(class_name)
108
- const = @custom_namespace.const_get(class_name)
108
+ const = begin
109
+ @custom_namespace.const_get(class_name)
110
+ rescue NameError
111
+ # Dup the built-in so that the cached fields aren't shared
112
+ @built_in_namespace.const_get(class_name)
113
+ end
109
114
  dup_type_class(const)
110
- rescue NameError
111
- # Dup the built-in so that the cached fields aren't shared
112
- dup_type_class(@built_in_namespace.const_get(class_name))
113
115
  end
114
116
 
115
117
  def get_fields_from_class(class_sym:)
@@ -133,23 +135,6 @@ module GraphQL
133
135
  end
134
136
  end
135
137
  end
136
-
137
- class PerFieldProxyResolve
138
- def initialize(object_class:, inner_resolve:)
139
- @object_class = object_class
140
- @inner_resolve = inner_resolve
141
- end
142
-
143
- def call(obj, args, ctx)
144
- query_ctx = ctx.query.context
145
- # Remove the QueryType wrapper
146
- if obj.is_a?(GraphQL::Schema::Object)
147
- obj = obj.object
148
- end
149
- wrapped_object = @object_class.wrap(obj, query_ctx)
150
- @inner_resolve.call(wrapped_object, args, ctx)
151
- end
152
- end
153
138
  end
154
139
  end
155
140
  end
@@ -58,8 +58,8 @@ module GraphQL
58
58
  end
59
59
  end
60
60
  schema = Class.new(GraphQL::Schema) {
61
- use GraphQL::Schema::Visibility
62
61
  query(query_root)
62
+ use GraphQL::Schema::Visibility
63
63
  def self.visible?(member, _ctx)
64
64
  member.graphql_name != "Root"
65
65
  end
@@ -8,7 +8,7 @@ module GraphQL
8
8
  # @example Require a non-empty string for an argument
9
9
  # argument :name, String, required: true, validate: { allow_blank: false }
10
10
  class AllowBlankValidator < Validator
11
- def initialize(allow_blank_positional, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
11
+ def initialize(allow_blank_positional = nil, allow_blank: nil, message: "%{validated} can't be blank", **default_options)
12
12
  @message = message
13
13
  super(**default_options)
14
14
  @allow_blank = allow_blank.nil? ? allow_blank_positional : allow_blank
@@ -16,10 +16,10 @@ module GraphQL
16
16
 
17
17
  def validate(_object, _context, value)
18
18
  if value.respond_to?(:blank?) && value.blank?
19
- if (value.nil? && @allow_null) || @allow_blank
19
+ if (value.nil? && validation_parameter(@allow_null)) || validation_parameter(@allow_blank)
20
20
  # pass
21
21
  else
22
- @message
22
+ validation_parameter(@message)
23
23
  end
24
24
  end
25
25
  end
@@ -9,15 +9,15 @@ module GraphQL
9
9
  # argument :name, String, required: false, validates: { allow_null: false }
10
10
  class AllowNullValidator < Validator
11
11
  MESSAGE = "%{validated} can't be null"
12
- def initialize(allow_null_positional, allow_null: nil, message: MESSAGE, **default_options)
12
+ def initialize(allow_null_positional = nil, allow_null: nil, message: MESSAGE, **default_options)
13
13
  @message = message
14
14
  super(**default_options)
15
15
  @allow_null = allow_null.nil? ? allow_null_positional : allow_null
16
16
  end
17
17
 
18
18
  def validate(_object, _context, value)
19
- if value.nil? && !@allow_null
20
- @message
19
+ if value.nil? && !validation_parameter(@allow_null)
20
+ validation_parameter(@message)
21
21
  end
22
22
  end
23
23
  end
@@ -23,8 +23,8 @@ module GraphQL
23
23
  def validate(_object, _context, value)
24
24
  if permitted_empty_value?(value)
25
25
  # pass
26
- elsif @in_list.include?(value)
27
- @message
26
+ elsif validation_parameter(@in_list).include?(value)
27
+ validation_parameter(@message)
28
28
  end
29
29
  end
30
30
  end