@@ -10,18 +10,23 @@ class Interpreter
1010 class Runtime
1111
1212 module GraphQLResult
13- def initialize ( result_name , parent_result )
13+ # FIXME: storing `represented_value` here holds onto a lot of objects, keeping them from GCing and increasing peak memory.
14+ # ... but the value is only needed for lists with skippable items.
15+ # Maybe we can set to `nil` unless we know this object is a skippable list item
16+ # (i.e. a direct child of a list with `skip_items_on_raise: true`)
17+ def initialize ( result_name , parent_result , represented_value )
1418 @graphql_parent = parent_result
1519 if parent_result && parent_result . graphql_dead
1620 @graphql_dead = true
1721 end
1822 @graphql_result_name = result_name
1923 # Jump through some hoops to avoid creating this duplicate storage if at all possible.
2024 @graphql_metadata = nil
25+ @represented_value = represented_value
2126 end
2227
2328 attr_accessor :graphql_dead
24- attr_reader :graphql_parent , :graphql_result_name
29+ attr_reader :graphql_parent , :graphql_result_name , :represented_value
2530
2631 # Although these are used by only one of the Result classes,
2732 # it's handy to have the methods implemented on both (even though they just return `nil`)
@@ -48,7 +53,7 @@ def can_be_skipped?
4853 end
4954
5055 class GraphQLResultHash
51- def initialize ( _result_name , _parent_result )
56+ def initialize ( _result_name , _parent_result , _represented_value )
5257 super
5358 @graphql_result_data = { }
5459 end
@@ -109,7 +114,7 @@ def [](k)
109114 class GraphQLResultArray
110115 include GraphQLResult
111116
112- def initialize ( _result_name , _parent_result )
117+ def initialize ( _result_name , _parent_result , _represented_value )
113118 super
114119 @graphql_result_data = [ ]
115120 end
@@ -177,7 +182,7 @@ def initialize(query:)
177182 @multiplex_context = query . multiplex . context
178183 # Start this off empty:
179184 Thread . current [ :__graphql_runtime_info ] = nil
180- @response = GraphQLResultHash . new ( nil , nil )
185+ @response = GraphQLResultHash . new ( nil , nil , query . root_value )
181186 # Identify runtime directives by checking which of this schema's directives have overridden `def self.resolve`
182187 @runtime_directive_names = [ ]
183188 noop_resolve_owner = GraphQL ::Schema ::Directive . singleton_class
@@ -240,7 +245,7 @@ def run_eager
240245 # directly evaluated and the results can be written right into the main response hash.
241246 tap_or_each ( gathered_selections ) do |selections , is_selection_array |
242247 if is_selection_array
243- selection_response = GraphQLResultHash . new ( nil , nil )
248+ selection_response = GraphQLResultHash . new ( nil , nil , query . root_value )
244249 final_response = @response
245250 else
246251 selection_response = @response
@@ -773,7 +778,7 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
773778 after_lazy ( object_proxy , owner : current_type , path : path , ast_node : ast_node , field : field , owner_object : owner_object , arguments : arguments , trace : false , result_name : result_name , result : selection_result ) do |inner_object |
774779 continue_value = continue_value ( path , inner_object , owner_type , field , is_non_null , ast_node , result_name , selection_result )
775780 if HALT != continue_value
776- response_hash = GraphQLResultHash . new ( result_name , selection_result )
781+ response_hash = GraphQLResultHash . new ( result_name , selection_result , continue_value )
777782 set_result ( selection_result , result_name , response_hash )
778783 gathered_selections = gather_selections ( continue_value , current_type , next_selections )
779784 # There are two possibilities for `gathered_selections`:
@@ -786,7 +791,7 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
786791 # (Technically, it's possible that one of those entries _doesn't_ require isolation.)
787792 tap_or_each ( gathered_selections ) do |selections , is_selection_array |
788793 if is_selection_array
789- this_result = GraphQLResultHash . new ( result_name , selection_result )
794+ this_result = GraphQLResultHash . new ( result_name , selection_result , continue_value )
790795 final_result = response_hash
791796 else
792797 this_result = response_hash
@@ -813,7 +818,7 @@ def continue_field(path, value, owner_type, field, current_type, ast_node, next_
813818 inner_type = current_type . of_type
814819 # This is true for objects, unions, and interfaces
815820 use_dataloader_job = !inner_type . unwrap . kind . input?
816- response_list = GraphQLResultArray . new ( result_name , selection_result )
821+ response_list = GraphQLResultArray . new ( result_name , selection_result , value )
817822 response_list . graphql_non_null_list_items = inner_type . non_null?
818823 response_list . graphql_skip_list_items_that_raise = current_type . skip_nodes_on_raise?
819824 set_result ( selection_result , result_name , response_list )
0 commit comments