@@ -22,7 +22,11 @@ def initialize
2222 end
2323
2424 module GraphQLResult
25- def initialize ( result_name , parent_result , is_non_null_in_parent )
25+ # FIXME: storing `represented_value` here holds onto a lot of objects, keeping them from GCing and increasing peak memory.
26+ # ... but the value is only needed for lists with skippable items.
27+ # Maybe we can set to `nil` unless we know this object is a skippable list item
28+ # (i.e. a direct child of a list with `skip_items_on_raise: true`)
29+ def initialize ( result_name , parent_result , is_non_null_in_parent , represented_value )
2630 @graphql_parent = parent_result
2731 if parent_result && parent_result . graphql_dead
2832 @graphql_dead = true
@@ -31,6 +35,7 @@ def initialize(result_name, parent_result, is_non_null_in_parent)
3135 @graphql_is_non_null_in_parent = is_non_null_in_parent
3236 # Jump through some hoops to avoid creating this duplicate storage if at all possible.
3337 @graphql_metadata = nil
38+ @represented_value = represented_value
3439 end
3540
3641 def path
@@ -43,7 +48,7 @@ def build_path(path_array)
4348 end
4449
4550 attr_accessor :graphql_dead
46- attr_reader :graphql_parent , :graphql_result_name , :graphql_is_non_null_in_parent
51+ attr_reader :graphql_parent , :graphql_result_name , :graphql_is_non_null_in_parent , :represented_value
4752
4853 # True when this result is a List that was marked `skip_items_on_raise: true`.
4954 # Descendants of this result will have `can_be_skipped?` be true.
@@ -63,7 +68,7 @@ def can_be_skipped?
6368 end
6469
6570 class GraphQLResultHash
66- def initialize ( _result_name , _parent_result , _is_non_null_in_parent )
71+ def initialize ( _result_name , _parent_result , _is_non_null_in_parent , _represented_value )
6772 super
6873 @graphql_result_data = { }
6974 end
@@ -151,7 +156,7 @@ def merge_into(into_result)
151156 class GraphQLResultArray
152157 include GraphQLResult
153158
154- def initialize ( _result_name , _parent_result , _is_non_null_in_parent )
159+ def initialize ( _result_name , _parent_result , _is_non_null_in_parent , _represented_value )
155160 super
156161 @graphql_result_data = [ ]
157162 end
@@ -211,7 +216,7 @@ def initialize(query:, lazies_at_depth:)
211216 @lazies_at_depth = lazies_at_depth
212217 @schema = query . schema
213218 @context = query . context
214- @response = GraphQLResultHash . new ( nil , nil , false )
219+ @response = GraphQLResultHash . new ( nil , nil , false , query . root_value )
215220 # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
216221 @runtime_directive_names = [ ]
217222 noop_resolve_owner = GraphQL ::Schema ::Directive . singleton_class
@@ -278,7 +283,7 @@ def run_eager
278283 # directly evaluated and the results can be written right into the main response hash.
279284 tap_or_each ( gathered_selections ) do |selections , is_selection_array |
280285 if is_selection_array
281- selection_response = GraphQLResultHash . new ( nil , nil , false )
286+ selection_response = GraphQLResultHash . new ( nil , nil , false , query . root_value )
282287 final_response = @response
283288 else
284289 selection_response = @response
@@ -835,7 +840,7 @@ def continue_field(value, owner_type, field, current_type, ast_node, next_select
835840 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 ) do |inner_object |
836841 continue_value = continue_value ( inner_object , owner_type , field , is_non_null , ast_node , result_name , selection_result )
837842 if HALT != continue_value
838- response_hash = GraphQLResultHash . new ( result_name , selection_result , is_non_null )
843+ response_hash = GraphQLResultHash . new ( result_name , selection_result , is_non_null , continue_value )
839844 set_result ( selection_result , result_name , response_hash , true , is_non_null )
840845 gathered_selections = gather_selections ( continue_value , current_type , next_selections )
841846 # There are two possibilities for `gathered_selections`:
@@ -848,7 +853,7 @@ def continue_field(value, owner_type, field, current_type, ast_node, next_select
848853 # (Technically, it's possible that one of those entries _doesn't_ require isolation.)
849854 tap_or_each ( gathered_selections ) do |selections , is_selection_array |
850855 if is_selection_array
851- this_result = GraphQLResultHash . new ( result_name , selection_result , is_non_null )
856+ this_result = GraphQLResultHash . new ( result_name , selection_result , is_non_null , continue_value )
852857 final_result = response_hash
853858 else
854859 this_result = response_hash
@@ -885,7 +890,7 @@ def continue_field(value, owner_type, field, current_type, ast_node, next_select
885890 # This is true for objects, unions, and interfaces
886891 use_dataloader_job = !inner_type . unwrap . kind . input?
887892 inner_type_non_null = inner_type . non_null?
888- response_list = GraphQLResultArray . new ( result_name , selection_result , is_non_null )
893+ response_list = GraphQLResultArray . new ( result_name , selection_result , is_non_null , value )
889894 response_list . graphql_skip_list_items_that_raise = current_type . skip_nodes_on_raise?
890895 set_result ( selection_result , result_name , response_list , true , is_non_null )
891896 idx = nil
0 commit comments