@@ -36,7 +36,8 @@ type Resolvable struct {
3636 astjsonArena arena.Arena
3737 parsers []* astjson.Parser
3838
39- print bool
39+ enableRender bool
40+ enableDeferRender bool
4041 out io.Writer
4142 printErr error
4243 path []fastjsonext.PathElement
@@ -92,7 +93,7 @@ func (r *Resolvable) Reset() {
9293 r .errors = nil
9394 r .valueCompletion = nil
9495 r .depth = 0
95- r .print = false
96+ r .enableRender = false
9697 r .out = nil
9798 r .printErr = nil
9899 r .path = r .path [:0 ]
@@ -169,7 +170,7 @@ func (r *Resolvable) InitSubscription(ctx *Context, initialData []byte, postProc
169170
170171func (r * Resolvable ) ResolveNode (node Node , data * astjson.Value , out io.Writer ) error {
171172 r .out = out
172- r .print = false
173+ r .enableRender = false
173174 r .printErr = nil
174175 r .authorizationError = nil
175176 // don't init errors! It will heavily increase memory usage
@@ -180,7 +181,7 @@ func (r *Resolvable) ResolveNode(node Node, data *astjson.Value, out io.Writer)
180181 return fmt .Errorf ("error resolving node" )
181182 }
182183
183- r .print = true
184+ r .enableRender = true
184185 hasErrors = r .walkNode (node , data )
185186 if hasErrors {
186187 return fmt .Errorf ("error resolving node: %w" , r .printErr )
@@ -190,7 +191,7 @@ func (r *Resolvable) ResolveNode(node Node, data *astjson.Value, out io.Writer)
190191
191192func (r * Resolvable ) Resolve (ctx context.Context , rootData * Object , fetchTree * FetchTreeNode , out io.Writer ) error {
192193 r .out = out
193- r .print = false
194+ r .enableRender = false
194195 r .printErr = nil
195196 r .authorizationError = nil
196197
@@ -257,6 +258,14 @@ func (r *Resolvable) err() bool {
257258 return true
258259}
259260
261+ func (r * Resolvable ) render () bool {
262+ if ! r .deferMode {
263+ return r .enableRender
264+ }
265+
266+ return r .enableRender && r .enableDeferRender
267+ }
268+
260269func (r * Resolvable ) printErrors () {
261270 r .printBytes (quote )
262271 r .printBytes (literalErrors )
@@ -273,9 +282,9 @@ func (r *Resolvable) printData(root *Object) {
273282 r .printBytes (quote )
274283 r .printBytes (colon )
275284 r .printBytes (lBrace )
276- r .print = true
285+ r .enableRender = true
277286 _ = r .walkObject (root , r .data )
278- r .print = false
287+ r .enableRender = false
279288 r .printBytes (rBrace )
280289 r .wroteData = true
281290}
@@ -602,7 +611,7 @@ func (r *Resolvable) walkObject(obj *Object, parent *astjson.Value) bool {
602611 // when we have a typename field present in a json object, we need to check if the type is valid
603612
604613 if _ , ok := obj .PossibleTypes [string (typeName )]; ! ok {
605- if ! r .print {
614+ if ! r .render () {
606615 // during pre-walk we need to add an error when the typename do not match a possible type
607616 if r .options .ApolloCompatibilityValueCompletionInExtensions {
608617 r .addValueCompletion (fmt .Sprintf ("Invalid __typename found for object at %s." , r .pathLastElementDescription (obj .TypeName )), errorcodes .InvalidGraphql )
@@ -627,7 +636,7 @@ func (r *Resolvable) walkObject(obj *Object, parent *astjson.Value) bool {
627636 }
628637 }
629638
630- if r .print && ! isRoot {
639+ if r .render () && ! isRoot {
631640 r .printBytes (lBrace )
632641 }
633642 addComma := false
@@ -647,7 +656,7 @@ func (r *Resolvable) walkObject(obj *Object, parent *astjson.Value) bool {
647656 continue
648657 }
649658 }
650- if ! r .print {
659+ if ! r .render () {
651660 skip := r .authorizeField (value , obj .Fields [i ])
652661 if skip {
653662 if obj .Fields [i ].Value .NodeNullable () {
@@ -671,7 +680,7 @@ func (r *Resolvable) walkObject(obj *Object, parent *astjson.Value) bool {
671680 continue
672681 }
673682 }
674- if r .print {
683+ if r .render () {
675684 if addComma {
676685 r .printBytes (comma )
677686 }
@@ -693,7 +702,7 @@ func (r *Resolvable) walkObject(obj *Object, parent *astjson.Value) bool {
693702 }
694703 addComma = true
695704 }
696- if r .print && ! isRoot {
705+ if r .render () && ! isRoot {
697706 r .printBytes (rBrace )
698707 }
699708 return false
@@ -839,23 +848,23 @@ func (r *Resolvable) walkArray(arr *Array, value *astjson.Value) bool {
839848 r .addError ("Array cannot represent non-array value." , arr .Path )
840849 return r .err ()
841850 }
842- if r .print {
851+ if r .render () {
843852 r .printBytes (lBrack )
844853 }
845854 values := value .GetArray ()
846855
847856 hasPrintedValue := false
848857 for i , arrayValue := range values {
849858 skip := false
850- if r .print && arr .SkipItem != nil {
859+ if r .render () && arr .SkipItem != nil {
851860 skip = arr .SkipItem (r .ctx , arrayValue )
852861 }
853862
854863 if skip {
855864 continue
856865 }
857866
858- if r .print && i != 0 && hasPrintedValue {
867+ if r .render () && i != 0 && hasPrintedValue {
859868 r .printBytes (comma )
860869 }
861870
@@ -876,21 +885,21 @@ func (r *Resolvable) walkArray(arr *Array, value *astjson.Value) bool {
876885 return err
877886 }
878887 }
879- if r .print {
888+ if r .render () {
880889 r .printBytes (rBrack )
881890 }
882891 return false
883892}
884893
885894func (r * Resolvable ) walkNull () bool {
886- if r .print {
895+ if r .render () {
887896 r .printBytes (null )
888897 }
889898 return false
890899}
891900
892901func (r * Resolvable ) walkStaticString (str * StaticString ) bool {
893- if r .print {
902+ if r .render () {
894903 r .printBytes (quote )
895904 r .printBytes ([]byte (str .Value ))
896905 r .printBytes (quote )
@@ -913,7 +922,7 @@ func (r *Resolvable) walkString(s *String, value *astjson.Value) bool {
913922 r .addError (fmt .Sprintf ("String cannot represent non-string value: \" %s\" " , string (r .marshalBuf )), s .Path )
914923 return r .err ()
915924 }
916- if r .print {
925+ if r .render () {
917926 if s .IsTypeName {
918927 content := value .GetStringBytes ()
919928 for i := range r .renameTypeNames {
@@ -959,7 +968,7 @@ func (r *Resolvable) walkBoolean(b *Boolean, value *astjson.Value) bool {
959968 r .addError (fmt .Sprintf ("Bool cannot represent non-boolean value: \" %s\" " , string (r .marshalBuf )), b .Path )
960969 return r .err ()
961970 }
962- if r .print {
971+ if r .render () {
963972 r .renderScalarFieldValue (value , b .Nullable )
964973 }
965974 return false
@@ -980,7 +989,7 @@ func (r *Resolvable) walkInteger(i *Integer, value *astjson.Value) bool {
980989 r .addError (fmt .Sprintf ("Int cannot represent non-integer value: \" %s\" " , string (r .marshalBuf )), i .Path )
981990 return r .err ()
982991 }
983- if r .print {
992+ if r .render () {
984993 r .renderScalarFieldValue (value , i .Nullable )
985994 }
986995 return false
@@ -996,14 +1005,14 @@ func (r *Resolvable) walkFloat(f *Float, value *astjson.Value) bool {
9961005 r .addNonNullableFieldError (f .Path , parent )
9971006 return r .err ()
9981007 }
999- if ! r .print {
1008+ if ! r .render () {
10001009 if value .Type () != astjson .TypeNumber {
10011010 r .marshalBuf = value .MarshalTo (r .marshalBuf [:0 ])
10021011 r .addError (fmt .Sprintf ("Float cannot represent non-float value: \" %s\" " , string (r .marshalBuf )), f .Path )
10031012 return r .err ()
10041013 }
10051014 }
1006- if r .print {
1015+ if r .render () {
10071016 if r .options .ApolloCompatibilityTruncateFloatValues {
10081017 floatValue := value .GetFloat64 ()
10091018 if floatValue == float64 (int64 (floatValue )) {
@@ -1026,7 +1035,7 @@ func (r *Resolvable) walkBigInt(b *BigInt, value *astjson.Value) bool {
10261035 r .addNonNullableFieldError (b .Path , parent )
10271036 return r .err ()
10281037 }
1029- if r .print {
1038+ if r .render () {
10301039 r .renderScalarFieldValue (value , b .Nullable )
10311040 }
10321041 return false
@@ -1042,22 +1051,22 @@ func (r *Resolvable) walkScalar(s *Scalar, value *astjson.Value) bool {
10421051 r .addNonNullableFieldError (s .Path , parent )
10431052 return r .err ()
10441053 }
1045- if r .print {
1054+ if r .render () {
10461055 r .renderScalarFieldValue (value , s .Nullable )
10471056 }
10481057 return false
10491058}
10501059
10511060func (r * Resolvable ) walkEmptyObject (_ * EmptyObject ) bool {
1052- if r .print {
1061+ if r .render () {
10531062 r .printBytes (lBrace )
10541063 r .printBytes (rBrace )
10551064 }
10561065 return false
10571066}
10581067
10591068func (r * Resolvable ) walkEmptyArray (_ * EmptyArray ) bool {
1060- if r .print {
1069+ if r .render () {
10611070 r .printBytes (lBrack )
10621071 r .printBytes (rBrack )
10631072 }
@@ -1080,7 +1089,7 @@ func (r *Resolvable) walkCustom(c *CustomNode, value *astjson.Value) bool {
10801089 r .addError (err .Error (), c .Path )
10811090 return r .err ()
10821091 }
1083- if r .print {
1092+ if r .render () {
10841093 r .renderScalarFieldBytes (resolved , c .Nullable )
10851094 }
10861095 return false
@@ -1165,7 +1174,7 @@ func (r *Resolvable) walkEnum(e *Enum, value *astjson.Value) bool {
11651174 * To avoid appending an error twice, the appending only happens on the first walk
11661175 * and not the second walk (which prints the data).
11671176 */
1168- if ! r .print {
1177+ if ! r .render () {
11691178 if r .options .ApolloCompatibilityValueCompletionInExtensions {
11701179 r .renderInaccessibleEnumValueError (e )
11711180 } else {
@@ -1183,7 +1192,7 @@ func (r *Resolvable) walkEnum(e *Enum, value *astjson.Value) bool {
11831192 * To avoid appending an error/value completion twice, the appending only happens on the first walk
11841193 * and not the second walk (which prints the data).
11851194 */
1186- if ! r .print {
1195+ if ! r .render () {
11871196 r .renderInaccessibleEnumValueError (e )
11881197 }
11891198 // Inaccessible enum values are always converted to null
@@ -1192,7 +1201,7 @@ func (r *Resolvable) walkEnum(e *Enum, value *astjson.Value) bool {
11921201 }
11931202 return r .err ()
11941203 }
1195- if r .print {
1204+ if r .render () {
11961205 r .renderEnumValue (value , e .Nullable )
11971206 }
11981207 return false
0 commit comments