graphql 2.5.4 → 2.5.11

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/query_complexity.rb +2 -2
  3. data/lib/graphql/dataloader/active_record_association_source.rb +14 -2
  4. data/lib/graphql/dataloader/null_dataloader.rb +7 -0
  5. data/lib/graphql/execution/interpreter/resolve.rb +3 -3
  6. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +11 -1
  7. data/lib/graphql/execution/interpreter/runtime.rb +136 -49
  8. data/lib/graphql/execution/interpreter.rb +1 -1
  9. data/lib/graphql/language/lexer.rb +9 -2
  10. data/lib/graphql/language/nodes.rb +5 -1
  11. data/lib/graphql/language/parser.rb +1 -0
  12. data/lib/graphql/query/context.rb +1 -1
  13. data/lib/graphql/query/partial.rb +179 -0
  14. data/lib/graphql/query.rb +55 -43
  15. data/lib/graphql/schema/addition.rb +3 -1
  16. data/lib/graphql/schema/argument.rb +5 -0
  17. data/lib/graphql/schema/build_from_definition.rb +5 -1
  18. data/lib/graphql/schema/directive.rb +33 -1
  19. data/lib/graphql/schema/field.rb +8 -0
  20. data/lib/graphql/schema/input_object.rb +28 -21
  21. data/lib/graphql/schema/member/has_arguments.rb +2 -2
  22. data/lib/graphql/schema/member/has_interfaces.rb +2 -2
  23. data/lib/graphql/schema/member/type_system_helpers.rb +16 -2
  24. data/lib/graphql/schema/ractor_shareable.rb +79 -0
  25. data/lib/graphql/schema/scalar.rb +1 -6
  26. data/lib/graphql/schema/timeout.rb +19 -2
  27. data/lib/graphql/schema/validator/required_validator.rb +15 -6
  28. data/lib/graphql/schema/visibility/migration.rb +2 -2
  29. data/lib/graphql/schema/visibility/profile.rb +74 -10
  30. data/lib/graphql/schema/visibility.rb +30 -17
  31. data/lib/graphql/schema/warden.rb +13 -5
  32. data/lib/graphql/schema.rb +53 -22
  33. data/lib/graphql/static_validation/all_rules.rb +1 -1
  34. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +6 -2
  35. data/lib/graphql/tracing/notifications_trace.rb +3 -1
  36. data/lib/graphql/tracing/null_trace.rb +1 -1
  37. data/lib/graphql/tracing/perfetto_trace.rb +1 -1
  38. data/lib/graphql/type_kinds.rb +1 -0
  39. data/lib/graphql/version.rb +1 -1
  40. data/lib/graphql.rb +1 -1
  41. metadata +19 -3
@@ -31,10 +31,37 @@ module GraphQL
31
31
  # @return [Symbol, nil]
32
32
  attr_reader :name
33
33
 
34
- def initialize(name: nil, context:, schema:)
34
+ def freeze
35
+ @cached_visible.default_proc = nil
36
+ @cached_visible_fields.default_proc = nil
37
+ @cached_visible_fields.each do |type, fields|
38
+ fields.default_proc = nil
39
+ end
40
+ @cached_visible_arguments.default_proc = nil
41
+ @cached_visible_arguments.each do |type, fields|
42
+ fields.default_proc = nil
43
+ end
44
+ @cached_parent_fields.default_proc = nil
45
+ @cached_parent_fields.each do |type, fields|
46
+ fields.default_proc = nil
47
+ end
48
+ @cached_parent_arguments.default_proc = nil
49
+ @cached_parent_arguments.each do |type, args|
50
+ args.default_proc = nil
51
+ end
52
+ @cached_possible_types.default_proc = nil
53
+ @cached_enum_values.default_proc = nil
54
+ @cached_fields.default_proc = nil
55
+ @cached_arguments.default_proc = nil
56
+ @loadable_possible_types.default_proc = nil
57
+ super
58
+ end
59
+
60
+ def initialize(name: nil, context:, schema:, visibility:)
35
61
  @name = name
36
62
  @context = context
37
63
  @schema = schema
64
+ @visibility = visibility
38
65
  @all_types = {}
39
66
  @all_types_loaded = false
40
67
  @unvisited_types = []
@@ -122,7 +149,7 @@ module GraphQL
122
149
  end
123
150
 
124
151
  def type(type_name)
125
- t = @schema.visibility.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
152
+ t = @visibility.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
126
153
  if t
127
154
  if t.is_a?(Array)
128
155
  vis_t = nil
@@ -250,14 +277,13 @@ module GraphQL
250
277
  end
251
278
 
252
279
  def directives
253
- @all_directives ||= @schema.visibility.all_directives.select { |dir|
254
- @cached_visible[dir] && @schema.visibility.all_references[dir].any? { |ref| ref == true || (@cached_visible[ref] && referenced?(ref)) }
280
+ @all_directives ||= @visibility.all_directives.select { |dir|
281
+ @cached_visible[dir] && @visibility.all_references[dir].any? { |ref| ref == true || (@cached_visible[ref] && referenced?(ref)) }
255
282
  }
256
283
  end
257
284
 
258
285
  def loadable?(t, _ctx)
259
- load_all_types
260
- !@all_types[t.graphql_name] && @cached_visible[t]
286
+ @cached_visible[t] && !referenced?(t)
261
287
  end
262
288
 
263
289
  def loadable_possible_types(t, _ctx)
@@ -277,6 +303,42 @@ module GraphQL
277
303
  @cached_visible[enum_value]
278
304
  end
279
305
 
306
+ def preload
307
+ load_all_types
308
+ @all_types.each do |type_name, type_defn|
309
+ if type_defn.kind.fields?
310
+ fields(type_defn).each do |f|
311
+ field(type_defn, f.graphql_name)
312
+ arguments(f).each do |arg|
313
+ argument(f, arg.graphql_name)
314
+ end
315
+ end
316
+ @schema.introspection_system.dynamic_fields.each do |f|
317
+ field(type_defn, f.graphql_name)
318
+ end
319
+ elsif type_defn.kind.input_object?
320
+ arguments(type_defn).each do |arg|
321
+ argument(type_defn, arg.graphql_name)
322
+ end
323
+ elsif type_defn.kind.enum?
324
+ enum_values(type_defn)
325
+ end
326
+ # Lots more to do here
327
+ end
328
+ @schema.introspection_system.entry_points.each do |f|
329
+ arguments(f).each do |arg|
330
+ argument(f, arg.graphql_name)
331
+ end
332
+ field(@schema.query, f.graphql_name)
333
+ end
334
+ @schema.introspection_system.dynamic_fields.each do |f|
335
+ arguments(f).each do |arg|
336
+ argument(f, arg.graphql_name)
337
+ end
338
+ end
339
+
340
+ end
341
+
280
342
  private
281
343
 
282
344
  def non_duplicate_items(definitions, visibility_cache)
@@ -323,7 +385,7 @@ module GraphQL
323
385
  end
324
386
 
325
387
  def referenced?(type_defn)
326
- @schema.visibility.all_references[type_defn].any? do |ref|
388
+ @visibility.all_references[type_defn].any? do |ref|
327
389
  case ref
328
390
  when GraphQL::Schema::Argument
329
391
  @cached_visible_arguments[ref.owner][ref]
@@ -341,9 +403,11 @@ module GraphQL
341
403
  case type.kind.name
342
404
  when "INTERFACE"
343
405
  pts = []
344
- @schema.visibility.all_interface_type_memberships[type].each do |(itm, impl_type)|
345
- if @cached_visible[itm] && @cached_visible[impl_type] && referenced?(impl_type)
346
- pts << impl_type
406
+ @visibility.all_interface_type_memberships[type].each do |impl_type, type_memberships|
407
+ if impl_type.kind.object? && referenced?(impl_type) && @cached_visible[impl_type]
408
+ if type_memberships.any? { |itm| @cached_visible[itm] }
409
+ pts << impl_type
410
+ end
347
411
  end
348
412
  end
349
413
  pts
@@ -12,15 +12,12 @@ module GraphQL
12
12
  # @param profiles [Hash<Symbol => Hash>] A hash of `name => context` pairs for preloading visibility profiles
13
13
  # @param preload [Boolean] if `true`, load the default schema profile and all named profiles immediately (defaults to `true` for `Rails.env.production?`)
14
14
  # @param migration_errors [Boolean] if `true`, raise an error when `Visibility` and `Warden` return different results
15
- def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails) ? Rails.env.production? : nil), migration_errors: false)
15
+ def self.use(schema, dynamic: false, profiles: EmptyObjects::EMPTY_HASH, preload: (defined?(Rails.env) ? Rails.env.production? : nil), migration_errors: false)
16
16
  profiles&.each { |name, ctx|
17
17
  ctx[:visibility_profile] = name
18
18
  ctx.freeze
19
19
  }
20
20
  schema.visibility = self.new(schema, dynamic: dynamic, preload: preload, profiles: profiles, migration_errors: migration_errors)
21
- if preload
22
- schema.visibility.preload
23
- end
24
21
  end
25
22
 
26
23
  def initialize(schema, dynamic:, preload:, profiles:, migration_errors:)
@@ -43,6 +40,17 @@ module GraphQL
43
40
  @types = nil
44
41
  @all_references = nil
45
42
  @loaded_all = false
43
+ if preload
44
+ self.preload
45
+ end
46
+ end
47
+
48
+ def freeze
49
+ load_all
50
+ @visit = true
51
+ @interface_type_memberships.default_proc = nil
52
+ @all_references.default_proc = nil
53
+ super
46
54
  end
47
55
 
48
56
  def all_directives
@@ -65,6 +73,8 @@ module GraphQL
65
73
  @types[type_name]
66
74
  end
67
75
 
76
+ attr_accessor :types
77
+
68
78
  def preload?
69
79
  @preload
70
80
  end
@@ -86,7 +96,7 @@ module GraphQL
86
96
  ensure_all_loaded(types_to_visit)
87
97
  @profiles.each do |profile_name, example_ctx|
88
98
  prof = profile_for(example_ctx)
89
- prof.all_types # force loading
99
+ prof.preload
90
100
  end
91
101
  end
92
102
 
@@ -153,12 +163,12 @@ module GraphQL
153
163
  visibility_profile = context[:visibility_profile]
154
164
  if @profiles.include?(visibility_profile)
155
165
  profile_ctx = @profiles[visibility_profile]
156
- @cached_profiles[visibility_profile] ||= @schema.visibility_profile_class.new(name: visibility_profile, context: profile_ctx, schema: @schema)
166
+ @cached_profiles[visibility_profile] ||= @schema.visibility_profile_class.new(name: visibility_profile, context: profile_ctx, schema: @schema, visibility: self)
157
167
  elsif @dynamic
158
168
  if context.is_a?(Query::NullContext)
159
169
  top_level_profile
160
170
  else
161
- @schema.visibility_profile_class.new(context: context, schema: @schema)
171
+ @schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
162
172
  end
163
173
  elsif !context.key?(:visibility_profile)
164
174
  raise ArgumentError, "#{@schema} expects a visibility profile, but `visibility_profile:` wasn't passed. Provide a `visibility_profile:` value or add `dynamic: true` to your visibility configuration."
@@ -168,7 +178,7 @@ module GraphQL
168
178
  elsif context.is_a?(Query::NullContext)
169
179
  top_level_profile
170
180
  else
171
- @schema.visibility_profile_class.new(context: context, schema: @schema)
181
+ @schema.visibility_profile_class.new(context: context, schema: @schema, visibility: self)
172
182
  end
173
183
  end
174
184
 
@@ -181,7 +191,7 @@ module GraphQL
181
191
  if refresh
182
192
  @top_level_profile = nil
183
193
  end
184
- @top_level_profile ||= @schema.visibility_profile_class.new(context: Query::NullContext.instance, schema: @schema)
194
+ @top_level_profile ||= @schema.visibility_profile_class.new(context: Query::NullContext.instance, schema: @schema, visibility: self)
185
195
  end
186
196
 
187
197
  private
@@ -202,7 +212,11 @@ module GraphQL
202
212
  def load_all(types: nil)
203
213
  if @visit.nil?
204
214
  # Set up the visit system
205
- @interface_type_memberships = Hash.new { |h, interface_type| h[interface_type] = [] }.compare_by_identity
215
+ @interface_type_memberships = Hash.new { |h, interface_type|
216
+ h[interface_type] = Hash.new { |h2, obj_type|
217
+ h2[obj_type] = []
218
+ }.compare_by_identity
219
+ }.compare_by_identity
206
220
  @directives = []
207
221
  @types = {} # String => Module
208
222
  @all_references = Hash.new { |h, member| h[member] = Set.new.compare_by_identity }.compare_by_identity
@@ -227,7 +241,7 @@ module GraphQL
227
241
  @all_references[itm.abstract_type] << member
228
242
  # `itm.object_type` may not actually be `member` if this implementation
229
243
  # is inherited from a superclass
230
- @interface_type_memberships[itm.abstract_type] << [itm, member]
244
+ @interface_type_memberships[itm.abstract_type][member] << itm
231
245
  end
232
246
  elsif member < GraphQL::Schema::Union
233
247
  @unions_for_references << member
@@ -276,12 +290,11 @@ module GraphQL
276
290
 
277
291
  # TODO: somehow don't iterate over all these,
278
292
  # only the ones that may have been modified
279
- @interface_type_memberships.each do |int_type, type_membership_pairs|
280
- referers = @all_references[int_type].select { |r| r.is_a?(GraphQL::Schema::Field) }
281
- if !referers.empty?
282
- type_membership_pairs.each do |(type_membership, impl_type)|
283
- # Add new items only:
284
- @all_references[impl_type] |= referers
293
+ @interface_type_memberships.each do |int_type, obj_type_memberships|
294
+ referrers = @all_references[int_type].select { |r| r.is_a?(GraphQL::Schema::Field) }
295
+ if !referrers.empty?
296
+ obj_type_memberships.each_key do |impl_type|
297
+ @all_references[impl_type] |= referrers
285
298
  end
286
299
  end
287
300
  end
@@ -107,7 +107,7 @@ module GraphQL
107
107
  def get_field(parent_type, field_name); @schema.get_field(parent_type, field_name); end
108
108
  def reachable_type?(type_name); true; end
109
109
  def loadable?(type, _ctx); true; end
110
- def loadable_possible_types(union_type, _ctx); union_type.possible_types; end
110
+ def loadable_possible_types(abstract_type, _ctx); union_type.possible_types; end
111
111
  def reachable_types; @schema.types.values; end # rubocop:disable Development/ContextIsPassedCop
112
112
  def possible_types(type_defn); @schema.possible_types(type_defn, Query::NullContext.instance, false); end
113
113
  def interfaces(obj_type); obj_type.interfaces; end
@@ -232,14 +232,22 @@ module GraphQL
232
232
 
233
233
  # @return [Boolean] True if this type is used for `loads:` but not in the schema otherwise and not _explicitly_ hidden.
234
234
  def loadable?(type, _ctx)
235
- !reachable_type_set.include?(type) && visible_type?(type)
235
+ visible_type?(type) &&
236
+ !referenced?(type) &&
237
+ (type.respond_to?(:interfaces) ? interfaces(type).all? { |i| loadable?(i, _ctx) } : true)
236
238
  end
237
239
 
238
- def loadable_possible_types(union_type, _ctx)
240
+ # This abstract type was determined to be used for `loads` only.
241
+ # All its possible types are valid possibilities here -- no filtering.
242
+ def loadable_possible_types(abstract_type, _ctx)
239
243
  @loadable_possible_types ||= read_through do |t|
240
- t.possible_types # unfiltered
244
+ if t.is_a?(Class) # union
245
+ t.possible_types
246
+ else
247
+ @schema.possible_types(abstract_type)
248
+ end
241
249
  end
242
- @loadable_possible_types[union_type]
250
+ @loadable_possible_types[abstract_type]
243
251
  end
244
252
 
245
253
  # @return [GraphQL::BaseType, nil] The type named `type_name`, if it exists (else `nil`)
@@ -7,6 +7,7 @@ require "graphql/schema/find_inherited_value"
7
7
  require "graphql/schema/finder"
8
8
  require "graphql/schema/introspection_system"
9
9
  require "graphql/schema/late_bound_type"
10
+ require "graphql/schema/ractor_shareable"
10
11
  require "graphql/schema/timeout"
11
12
  require "graphql/schema/type_expression"
12
13
  require "graphql/schema/unique_within_type"
@@ -148,10 +149,12 @@ module GraphQL
148
149
  end
149
150
 
150
151
  # @param new_mode [Symbol] If configured, this will be used when `context: { trace_mode: ... }` isn't set.
151
- def default_trace_mode(new_mode = nil)
152
- if new_mode
152
+ def default_trace_mode(new_mode = NOT_CONFIGURED)
153
+ if !NOT_CONFIGURED.equal?(new_mode)
153
154
  @default_trace_mode = new_mode
154
- elsif defined?(@default_trace_mode)
155
+ elsif defined?(@default_trace_mode) &&
156
+ !@default_trace_mode.nil? # This `nil?` check seems necessary because of
157
+ # Ractors silently initializing @default_trace_mode somehow
155
158
  @default_trace_mode
156
159
  elsif superclass.respond_to?(:default_trace_mode)
157
160
  superclass.default_trace_mode
@@ -365,7 +368,8 @@ module GraphQL
365
368
  # @return [Module, nil] A type, or nil if there's no type called `type_name`
366
369
  def get_type(type_name, context = GraphQL::Query::NullContext.instance, use_visibility_profile = use_visibility_profile?)
367
370
  if use_visibility_profile
368
- return Visibility::Profile.from_context(context, self).type(type_name)
371
+ profile = Visibility::Profile.from_context(context, self)
372
+ return profile.type(type_name)
369
373
  end
370
374
  local_entry = own_types[type_name]
371
375
  type_defn = case local_entry
@@ -697,7 +701,21 @@ module GraphQL
697
701
  GraphQL::Schema::TypeExpression.build_type(context.query.types, ast_node)
698
702
  end
699
703
 
700
- def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext.instance)
704
+ def get_field(type_or_name, field_name, context = GraphQL::Query::NullContext.instance, use_visibility_profile = use_visibility_profile?)
705
+ if use_visibility_profile
706
+ profile = Visibility::Profile.from_context(context, self)
707
+ parent_type = case type_or_name
708
+ when String
709
+ profile.type(type_or_name)
710
+ when Module
711
+ type_or_name
712
+ when LateBoundType
713
+ profile.type(type_or_name.name)
714
+ else
715
+ raise GraphQL::InvariantError, "Unexpected field owner for #{field_name.inspect}: #{type_or_name.inspect} (#{type_or_name.class})"
716
+ end
717
+ return profile.field(parent_type, field_name)
718
+ end
701
719
  parent_type = case type_or_name
702
720
  when LateBoundType
703
721
  get_type(type_or_name.name, context)
@@ -1105,20 +1123,21 @@ module GraphQL
1105
1123
  end
1106
1124
  end
1107
1125
 
1108
- NEW_HANDLER_HASH = ->(h, k) {
1109
- h[k] = {
1110
- class: k,
1111
- handler: nil,
1112
- subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
1113
- }
1114
- }
1115
-
1116
1126
  def error_handlers
1117
- @error_handlers ||= {
1118
- class: nil,
1119
- handler: nil,
1120
- subclass_handlers: Hash.new(&NEW_HANDLER_HASH),
1121
- }
1127
+ @error_handlers ||= begin
1128
+ new_handler_hash = ->(h, k) {
1129
+ h[k] = {
1130
+ class: k,
1131
+ handler: nil,
1132
+ subclass_handlers: Hash.new(&new_handler_hash),
1133
+ }
1134
+ }
1135
+ {
1136
+ class: nil,
1137
+ handler: nil,
1138
+ subclass_handlers: Hash.new(&new_handler_hash),
1139
+ }
1140
+ end
1122
1141
  end
1123
1142
 
1124
1143
  # @api private
@@ -1189,7 +1208,7 @@ module GraphQL
1189
1208
  # @param context [GraphQL::Query::Context] The query context for the currently-executing query
1190
1209
  # @return [Class<GraphQL::Schema::Object] The Object type definition to use for `obj`
1191
1210
  def resolve_type(abstract_type, application_object, context)
1192
- raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(abstract_type, application_object, context) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{abstract_type.name})"
1211
+ raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(abstract_type, application_object, context) must be implemented to use Union types, Interface types, `loads:`, or `run_partials` (tried to resolve: #{abstract_type.name})"
1193
1212
  end
1194
1213
  # rubocop:enable Lint/DuplicateMethods
1195
1214
 
@@ -1695,7 +1714,11 @@ module GraphQL
1695
1714
  # @return [true, false, nil]
1696
1715
  def allow_legacy_invalid_empty_selections_on_union(new_value = NOT_CONFIGURED)
1697
1716
  if NOT_CONFIGURED.equal?(new_value)
1698
- @allow_legacy_invalid_empty_selections_on_union
1717
+ if defined?(@allow_legacy_invalid_empty_selections_on_union)
1718
+ @allow_legacy_invalid_empty_selections_on_union
1719
+ else
1720
+ find_inherited_value(:allow_legacy_invalid_empty_selections_on_union)
1721
+ end
1699
1722
  else
1700
1723
  @allow_legacy_invalid_empty_selections_on_union = new_value
1701
1724
  end
@@ -1726,7 +1749,11 @@ module GraphQL
1726
1749
  # @return [true, false, nil]
1727
1750
  def allow_legacy_invalid_return_type_conflicts(new_value = NOT_CONFIGURED)
1728
1751
  if NOT_CONFIGURED.equal?(new_value)
1729
- @allow_legacy_invalid_return_type_conflicts
1752
+ if defined?(@allow_legacy_invalid_return_type_conflicts)
1753
+ @allow_legacy_invalid_return_type_conflicts
1754
+ else
1755
+ find_inherited_value(:allow_legacy_invalid_return_type_conflicts)
1756
+ end
1730
1757
  else
1731
1758
  @allow_legacy_invalid_return_type_conflicts = new_value
1732
1759
  end
@@ -1774,7 +1801,11 @@ module GraphQL
1774
1801
  # complexity_cost_calculation_mode(:compare)
1775
1802
  def complexity_cost_calculation_mode(new_mode = NOT_CONFIGURED)
1776
1803
  if NOT_CONFIGURED.equal?(new_mode)
1777
- @complexity_cost_calculation_mode
1804
+ if defined?(@complexity_cost_calculation_mode)
1805
+ @complexity_cost_calculation_mode
1806
+ else
1807
+ find_inherited_value(:complexity_cost_calculation_mode)
1808
+ end
1778
1809
  else
1779
1810
  @complexity_cost_calculation_mode = new_mode
1780
1811
  end
@@ -37,6 +37,6 @@ module GraphQL
37
37
  GraphQL::StaticValidation::SubscriptionRootExistsAndSingleSubscriptionSelection,
38
38
  GraphQL::StaticValidation::InputObjectNamesAreUnique,
39
39
  GraphQL::StaticValidation::OneOfInputObjectsAreValid,
40
- ]
40
+ ].freeze
41
41
  end
42
42
  end
@@ -19,13 +19,17 @@ module GraphQL
19
19
  :on_field,
20
20
  ]
21
21
 
22
- DIRECTIVE_NODE_HOOKS.each do |method_name|
23
- define_method(method_name) do |node, parent|
22
+ VALIDATE_DIRECTIVE_LOCATION_ON_NODE = <<~RUBY
23
+ def %{method_name}(node, parent)
24
24
  if !node.directives.empty?
25
25
  validate_directive_location(node)
26
26
  end
27
27
  super(node, parent)
28
28
  end
29
+ RUBY
30
+ DIRECTIVE_NODE_HOOKS.each do |method_name|
31
+ # Can't use `define_method {...}` here because the proc can't be isolated for use in non-main Ractors
32
+ module_eval(VALIDATE_DIRECTIVE_LOCATION_ON_NODE % { method_name: method_name }) # rubocop:disable Development/NoEvalCop
29
33
  end
30
34
 
31
35
  private
@@ -137,7 +137,9 @@ module GraphQL
137
137
 
138
138
  def dataloader_fiber_resume(source)
139
139
  prev_ev = Fiber[PREVIOUS_EV_KEY]
140
- begin_notifications_event(prev_ev.name, prev_ev.payload)
140
+ if prev_ev
141
+ begin_notifications_event(prev_ev.name, prev_ev.payload)
142
+ end
141
143
  super
142
144
  end
143
145
 
@@ -4,6 +4,6 @@ require "graphql/tracing/trace"
4
4
 
5
5
  module GraphQL
6
6
  module Tracing
7
- NullTrace = Trace.new
7
+ NullTrace = Trace.new.freeze
8
8
  end
9
9
  end
@@ -644,7 +644,7 @@ module GraphQL
644
644
  end
645
645
 
646
646
  if !@new_interned_da_string_values.empty?
647
- str_vals = @new_interned_da_string_values.map { |name, iid| InternedString.new(iid: iid, str: name) }
647
+ str_vals = @new_interned_da_string_values.map { |name, iid| InternedString.new(iid: iid, str: name.b) }
648
648
  @new_interned_da_string_values.clear
649
649
  end
650
650
 
@@ -14,6 +14,7 @@ module GraphQL
14
14
  @leaf = leaf
15
15
  @composite = fields? || abstract?
16
16
  @description = description
17
+ freeze
17
18
  end
18
19
 
19
20
  # Does this TypeKind have multiple possible implementers?
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.5.4"
3
+ VERSION = "2.5.11"
4
4
  end
data/lib/graphql.rb CHANGED
@@ -72,7 +72,7 @@ This is probably a bug in GraphQL-Ruby, please report this error on GitHub: http
72
72
  GraphQL::Language::Lexer.tokenize(graphql_string)
73
73
  end
74
74
 
75
- NOT_CONFIGURED = Object.new
75
+ NOT_CONFIGURED = Object.new.freeze
76
76
  private_constant :NOT_CONFIGURED
77
77
  module EmptyObjects
78
78
  EMPTY_HASH = {}.freeze
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.4
4
+ version: 2.5.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-18 00:00:00.000000000 Z
10
+ date: 2025-07-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -163,6 +163,20 @@ dependencies:
163
163
  - - ">="
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
+ - !ruby/object:Gem::Dependency
167
+ name: ostruct
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
166
180
  - !ruby/object:Gem::Dependency
167
181
  name: rake
168
182
  requirement: !ruby/object:Gem::Requirement
@@ -536,6 +550,7 @@ files:
536
550
  - lib/graphql/query/fingerprint.rb
537
551
  - lib/graphql/query/input_validation_result.rb
538
552
  - lib/graphql/query/null_context.rb
553
+ - lib/graphql/query/partial.rb
539
554
  - lib/graphql/query/result.rb
540
555
  - lib/graphql/query/validation_pipeline.rb
541
556
  - lib/graphql/query/variable_validation_error.rb
@@ -607,6 +622,7 @@ files:
607
622
  - lib/graphql/schema/non_null.rb
608
623
  - lib/graphql/schema/object.rb
609
624
  - lib/graphql/schema/printer.rb
625
+ - lib/graphql/schema/ractor_shareable.rb
610
626
  - lib/graphql/schema/relay_classic_mutation.rb
611
627
  - lib/graphql/schema/resolver.rb
612
628
  - lib/graphql/schema/resolver/has_payload_type.rb
@@ -801,7 +817,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
801
817
  - !ruby/object:Gem::Version
802
818
  version: '0'
803
819
  requirements: []
804
- rubygems_version: 3.6.6
820
+ rubygems_version: 3.6.8
805
821
  specification_version: 4
806
822
  summary: A GraphQL language and runtime for Ruby
807
823
  test_files: []