@@ -3,21 +3,23 @@ module GraphQL
33 module Execution
44 module Next
55 class Finalize
6- # TODO move more common values and state from arguments to instance variables
6+ # TODO early-return when no more finalizers to run?
77 def initialize ( query , data , runner )
88 @query = query
99 @data = data
1010 @static_type_at = runner . static_type_at
1111 @runner = runner
12+ @current_exec_path = [ ]
13+ @current_result_path = [ ]
1214 @finalizers = runner . finalizers
1315 query . context . errors . each do |err |
1416 @finalizers [ err ] = err
1517 end
1618 end
1719
1820 def run
19- if ( selected_operation = @query . selected_operation )
20- check_object_result ( @data , @query . root_type , selected_operation . selections , [ ] , [ ] )
21+ if ( selected_operation = @query . selected_operation ) && @data
22+ check_object_result ( @data , @query . root_type , selected_operation . selections )
2123 else
2224 @data
2325 end
@@ -37,9 +39,9 @@ def run_finalizers(result_path, finalizer_or_finalizers, result_data, result_key
3739 end
3840 end
3941
40- def check_object_result ( result_h , parent_type , ast_selections , current_exec_path , current_result_path )
42+ def check_object_result ( result_h , parent_type , ast_selections )
4143 if ( f = @finalizers [ result_h ] )
42- run_finalizers ( current_result_path . dup , f , result_h , nil )
44+ run_finalizers ( @ current_result_path. dup , f , result_h , nil )
4345 end
4446
4547 if parent_type . kind . abstract?
@@ -51,8 +53,8 @@ def check_object_result(result_h, parent_type, ast_selections, current_exec_path
5153 when Language ::Nodes ::Field
5254 begin
5355 key = ast_selection . alias || ast_selection . name
54- current_exec_path << key
55- current_result_path << key
56+ @ current_exec_path << key
57+ @ current_result_path << key
5658
5759 result_value = result_h [ key ]
5860 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 } " )
@@ -62,13 +64,13 @@ def check_object_result(result_h, parent_type, ast_selections, current_exec_path
6264 end
6365
6466 new_result_value = if ( finalizer_or_finalizers = @finalizers [ result_value ] )
65- run_finalizers ( current_result_path . dup , finalizer_or_finalizers , result_h , key )
67+ run_finalizers ( @ current_result_path. dup , finalizer_or_finalizers , result_h , key )
6668 result_h . key? ( key ) ? result_h [ key ] : :unassigned
6769 else
6870 if result_type . list?
69- check_list_result ( result_value , result_type . of_type , ast_selection . selections , current_exec_path , current_result_path )
70- elsif !result_type . kind . leaf?
71- check_object_result ( result_value , result_type , ast_selection . selections , current_exec_path , current_result_path )
71+ check_list_result ( result_value , result_type . of_type , ast_selection . selections )
72+ elsif !result_type . kind . leaf? && result_value
73+ check_object_result ( result_value , result_type , ast_selection . selections )
7274 else
7375 new_result_value || result_value
7476 end
@@ -82,30 +84,30 @@ def check_object_result(result_h, parent_type, ast_selections, current_exec_path
8284 result_h [ key ] = new_result_value
8385 end
8486 ensure
85- current_exec_path . pop
86- current_result_path . pop
87+ @ current_exec_path. pop
88+ @ current_result_path. pop
8789 end
8890 when Language ::Nodes ::InlineFragment
8991 static_type_at_result = @static_type_at [ result_h ]
9092 if static_type_at_result && (
9193 ( t = ast_selection . type ) . nil? ||
9294 @runner . type_condition_applies? ( @query . context , static_type_at_result , t . name )
9395 )
94- result_h = check_object_result ( result_h , parent_type , ast_selection . selections , current_exec_path , current_result_path )
96+ result_h = check_object_result ( result_h , parent_type , ast_selection . selections )
9597 end
9698 when Language ::Nodes ::FragmentSpread
9799 fragment_defn = @query . document . definitions . find { |defn | defn . is_a? ( Language ::Nodes ::FragmentDefinition ) && defn . name == ast_selection . name }
98100 static_type_at_result = @static_type_at [ result_h ]
99101 if static_type_at_result && @runner . type_condition_applies? ( @query . context , static_type_at_result , fragment_defn . type . name )
100- result_h = check_object_result ( result_h , parent_type , fragment_defn . selections , current_exec_path , current_result_path )
102+ result_h = check_object_result ( result_h , parent_type , fragment_defn . selections )
101103 end
102104 end
103105 end
104106
105107 result_h
106108 end
107109
108- def check_list_result ( result_arr , inner_type , ast_selections , current_exec_path , current_result_path )
110+ def check_list_result ( result_arr , inner_type , ast_selections )
109111 inner_type_non_null = false
110112 if inner_type . non_null?
111113 inner_type_non_null = true
@@ -119,14 +121,14 @@ def check_list_result(result_arr, inner_type, ast_selections, current_exec_path,
119121 end
120122
121123 result_arr . each_with_index do |result_item , idx |
122- current_result_path << idx
124+ @ current_result_path << idx
123125 new_result = if ( f = @finalizers [ result_item ] )
124- run_finalizers ( current_result_path . dup , f , result_arr , idx )
126+ run_finalizers ( @ current_result_path. dup , f , result_arr , idx )
125127 result_arr [ idx ] # TODO :unassigned?
126128 elsif inner_type . list?
127- check_list_result ( result_item , inner_type . of_type , ast_selections , current_exec_path , current_result_path )
128- elsif !inner_type . kind . leaf? && ! result_item . nil?
129- check_object_result ( result_item , inner_type , ast_selections , current_exec_path , current_result_path )
129+ check_list_result ( result_item , inner_type . of_type , ast_selections )
130+ elsif !inner_type . kind . leaf? && result_item
131+ check_object_result ( result_item , inner_type , ast_selections )
130132 else
131133 result_item
132134 end
@@ -138,7 +140,7 @@ def check_list_result(result_arr, inner_type, ast_selections, current_exec_path,
138140 result_arr [ idx ] = new_result
139141 end
140142 ensure
141- current_result_path . pop
143+ @ current_result_path. pop
142144 end
143145
144146 if new_invalid_null
0 commit comments