Skip to content

Commit bf533a8

Browse files
swalkinshawclaude
andcommitted
Inline setting_errors and cache context accessors in FieldsWillMerge
Inline the setting_errors block to eliminate closure allocation per on_field/on_operation_definition call. Cache context.max_errors, context.fragments, and context.query.types as instance variables to reduce method dispatch overhead in hot paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fe31aa2 commit bf533a8

1 file changed

Lines changed: 16 additions & 17 deletions

File tree

lib/graphql/static_validation/rules/fields_will_merge.rb

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,21 @@ def initialize(*)
3737
@visited_fragments = {}
3838
@compared_fragments = {}
3939
@conflict_count = 0
40+
@max_errors = context.max_errors
41+
@fragments = context.fragments
4042
end
4143

4244
def on_operation_definition(node, _parent)
43-
setting_errors { conflicts_within_selection_set(node, type_definition) }
45+
@conflicts = nil
46+
conflicts_within_selection_set(node, type_definition)
47+
@conflicts&.each_value { |error_type| error_type.each_value { |error| add_error(error) } }
4448
super
4549
end
4650

4751
def on_field(node, _parent)
48-
setting_errors { conflicts_within_selection_set(node, type_definition) }
52+
@conflicts = nil
53+
conflicts_within_selection_set(node, type_definition)
54+
@conflicts&.each_value { |error_type| error_type.each_value { |error| add_error(error) } }
4955
super
5056
end
5157

@@ -59,13 +65,6 @@ def conflicts
5965
end
6066
end
6167

62-
def setting_errors
63-
@conflicts = nil
64-
yield
65-
# don't initialize these if they weren't initialized in the block:
66-
@conflicts&.each_value { |error_type| error_type.each_value { |error| add_error(error) } }
67-
end
68-
6968
def conflicts_within_selection_set(node, parent_type)
7069
return if parent_type.nil?
7170

@@ -123,13 +122,13 @@ def find_conflicts_between_fragments(fragment_spread1, fragment_spread2, mutuall
123122
@compared_fragments[cache_key] = true
124123
end
125124

126-
fragment1 = context.fragments[fragment_name1]
127-
fragment2 = context.fragments[fragment_name2]
125+
fragment1 = @fragments[fragment_name1]
126+
fragment2 = @fragments[fragment_name2]
128127

129128
return if fragment1.nil? || fragment2.nil?
130129

131-
fragment_type1 = context.query.types.type(fragment1.type.name)
132-
fragment_type2 = context.query.types.type(fragment2.type.name)
130+
fragment_type1 = @types.type(fragment1.type.name)
131+
fragment_type2 = @types.type(fragment2.type.name)
133132

134133
return if fragment_type1.nil? || fragment_type2.nil?
135134

@@ -178,7 +177,7 @@ def find_conflicts_between_fields_and_fragment(fragment_spread, fields, mutually
178177
return if @visited_fragments.key?(fragment_name)
179178
@visited_fragments[fragment_name] = true
180179

181-
fragment = context.fragments[fragment_name]
180+
fragment = @fragments[fragment_name]
182181
return if fragment.nil?
183182

184183
fragment_type = @types.type(fragment.type.name)
@@ -222,7 +221,7 @@ def find_conflicts_within(response_keys)
222221
end
223222

224223
def find_conflict(response_key, field1, field2, mutually_exclusive: false)
225-
return if @conflict_count >= context.max_errors
224+
return if @conflict_count >= @max_errors
226225
return if field1.definition.nil? || field2.definition.nil?
227226

228227
node1 = field1.node
@@ -493,8 +492,8 @@ def mutually_exclusive?(parents1, parents2)
493492
false
494493
else
495494
# Check if these two scopes have _any_ types in common.
496-
possible_right_types = context.types.possible_types(type1)
497-
possible_left_types = context.types.possible_types(type2)
495+
possible_right_types = @types.possible_types(type1)
496+
possible_left_types = @types.possible_types(type2)
498497
(possible_right_types & possible_left_types).empty?
499498
end
500499
end

0 commit comments

Comments
 (0)