@@ -52,7 +52,7 @@ use actix_web::http::{header, StatusCode};
5252use actix_web:: { HttpResponse , HttpResponseBuilder , ResponseError } ;
5353use anyhow:: { bail, format_err, Context as AnyhowContext } ;
5454use awc:: cookie:: time:: Duration ;
55- use handlebars:: { BlockContext , Context , JsonValue , RenderError , Renderable } ;
55+ use handlebars:: { BlockContext , JsonValue , RenderError , Renderable } ;
5656use serde:: Serialize ;
5757use serde_json:: { json, Value } ;
5858use std:: borrow:: Cow ;
@@ -510,7 +510,8 @@ impl<W: std::io::Write> JsonBodyRenderer<W> {
510510}
511511
512512pub struct CsvBodyRenderer {
513- writer : csv_async:: AsyncWriter < AsyncResponseWriter > ,
513+ // The writer is a large struct, so we store it on the heap
514+ writer : Box < csv_async:: AsyncWriter < AsyncResponseWriter > > ,
514515 columns : Vec < String > ,
515516}
516517
@@ -550,7 +551,7 @@ impl CsvBodyRenderer {
550551 tokio:: io:: AsyncWriteExt :: flush ( & mut async_writer) . await ?;
551552 let writer = builder. create_writer ( async_writer) ;
552553 Ok ( CsvBodyRenderer {
553- writer,
554+ writer : Box :: new ( writer ) ,
554555 columns : vec ! [ ] ,
555556 } )
556557 }
@@ -870,14 +871,20 @@ impl<W: std::io::Write> handlebars::Output for HandlebarWriterOutput<W> {
870871
871872pub struct SplitTemplateRenderer {
872873 split_template : Arc < SplitTemplate > ,
873- local_vars : Option < handlebars:: LocalVars > ,
874- ctx : Context ,
874+ // LocalVars is a large struct, so we store it on the heap
875+ local_vars : Option < Box < handlebars:: LocalVars > > ,
876+ ctx : Box < handlebars:: Context > ,
875877 app_state : Arc < AppState > ,
876878 row_index : usize ,
877879 component_index : usize ,
878- nonce : JsonValue ,
880+ nonce : u64 ,
879881}
880882
883+ const _: ( ) = assert ! (
884+ std:: mem:: size_of:: <SplitTemplateRenderer >( ) <= 64 ,
885+ "SplitTemplateRenderer should be small enough to be allocated on the stack"
886+ ) ;
887+
881888impl SplitTemplateRenderer {
882889 fn new (
883890 split_template : Arc < SplitTemplate > ,
@@ -890,9 +897,9 @@ impl SplitTemplateRenderer {
890897 local_vars : None ,
891898 app_state,
892899 row_index : 0 ,
893- ctx : Context :: null ( ) ,
900+ ctx : Box :: new ( handlebars :: Context :: null ( ) ) ,
894901 component_index,
895- nonce : nonce . into ( ) ,
902+ nonce,
896903 }
897904 }
898905 fn name ( & self ) -> & str {
@@ -920,7 +927,7 @@ impl SplitTemplateRenderer {
920927 . block_mut ( )
921928 . expect ( "context created without block" ) ;
922929 blk. set_local_var ( "component_index" , self . component_index . into ( ) ) ;
923- blk. set_local_var ( "csp_nonce" , self . nonce . clone ( ) ) ;
930+ blk. set_local_var ( "csp_nonce" , self . nonce . into ( ) ) ;
924931
925932 * self . ctx . data_mut ( ) = data;
926933 let mut output = HandlebarWriterOutput ( writer) ;
@@ -930,9 +937,11 @@ impl SplitTemplateRenderer {
930937 & mut render_context,
931938 & mut output,
932939 ) ?;
933- self . local_vars = render_context
934- . block_mut ( )
935- . map ( |blk| std:: mem:: take ( blk. local_variables_mut ( ) ) ) ;
940+ let blk = render_context. block_mut ( ) ;
941+ if let Some ( blk) = blk {
942+ let local_vars = std:: mem:: take ( blk. local_variables_mut ( ) ) ;
943+ self . local_vars = Some ( Box :: new ( local_vars) ) ;
944+ }
936945 self . row_index = 0 ;
937946 Ok ( ( ) )
938947 }
@@ -948,12 +957,12 @@ impl SplitTemplateRenderer {
948957 let blk = render_context
949958 . block_mut ( )
950959 . expect ( "context created without block" ) ;
951- * blk. local_variables_mut ( ) = local_vars;
960+ * blk. local_variables_mut ( ) = * local_vars;
952961 let mut blk = BlockContext :: new ( ) ;
953962 blk. set_base_value ( data) ;
954963 blk. set_local_var ( "component_index" , self . component_index . into ( ) ) ;
955964 blk. set_local_var ( "row_index" , self . row_index . into ( ) ) ;
956- blk. set_local_var ( "csp_nonce" , self . nonce . clone ( ) ) ;
965+ blk. set_local_var ( "csp_nonce" , self . nonce . into ( ) ) ;
957966 render_context. push_block ( blk) ;
958967 let mut output = HandlebarWriterOutput ( writer) ;
959968 self . split_template . list_content . render (
@@ -963,9 +972,11 @@ impl SplitTemplateRenderer {
963972 & mut output,
964973 ) ?;
965974 render_context. pop_block ( ) ;
966- self . local_vars = render_context
967- . block_mut ( )
968- . map ( |blk| std:: mem:: take ( blk. local_variables_mut ( ) ) ) ;
975+ let blk = render_context. block_mut ( ) ;
976+ if let Some ( blk) = blk {
977+ let local_vars = std:: mem:: take ( blk. local_variables_mut ( ) ) ;
978+ self . local_vars = Some ( Box :: new ( local_vars) ) ;
979+ }
969980 self . row_index += 1 ;
970981 }
971982 Ok ( ( ) )
@@ -983,12 +994,12 @@ impl SplitTemplateRenderer {
983994 let mut render_context = handlebars:: RenderContext :: new ( None ) ;
984995 local_vars. put ( "row_index" , self . row_index . into ( ) ) ;
985996 local_vars. put ( "component_index" , self . component_index . into ( ) ) ;
986- local_vars. put ( "csp_nonce" , self . nonce . clone ( ) ) ;
997+ local_vars. put ( "csp_nonce" , self . nonce . into ( ) ) ;
987998 log:: trace!( "Rendering the after_list template with the following local variables: {local_vars:?}" ) ;
988999 * render_context
9891000 . block_mut ( )
9901001 . expect ( "ctx created without block" )
991- . local_variables_mut ( ) = local_vars;
1002+ . local_variables_mut ( ) = * local_vars;
9921003 let mut output = HandlebarWriterOutput ( writer) ;
9931004 self . split_template . after_list . render (
9941005 & self . app_state . all_templates . handlebars ,
0 commit comments