@@ -1124,7 +1124,7 @@ static inline long increase_depth(struct generate_json_data *data)
11241124 JSON_Generator_State * state = data -> state ;
11251125 long depth = ++ state -> depth ;
11261126 if (RB_UNLIKELY (depth > state -> max_nesting && state -> max_nesting )) {
1127- rb_raise (eNestingError , "nesting of %ld is too deep" , -- state -> depth );
1127+ rb_raise (eNestingError , "nesting of %ld is too deep. Did you try to serialize objects with circular references? " , -- state -> depth );
11281128 }
11291129 return depth ;
11301130}
@@ -1491,10 +1491,39 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
14911491 rb_check_arity (argc , 1 , 2 );
14921492 VALUE obj = argv [0 ];
14931493 VALUE io = argc > 1 ? argv [1 ] : Qnil ;
1494- VALUE result = cState_partial_generate (self , obj , generate_json , io );
1494+ return cState_partial_generate (self , obj , generate_json , io );
1495+ }
1496+
1497+ static VALUE cState_generate_new (int argc , VALUE * argv , VALUE self )
1498+ {
1499+ rb_check_arity (argc , 1 , 2 );
1500+ VALUE obj = argv [0 ];
1501+ VALUE io = argc > 1 ? argv [1 ] : Qnil ;
1502+
14951503 GET_STATE (self );
1496- (void )state ;
1497- return result ;
1504+
1505+ JSON_Generator_State new_state ;
1506+ MEMCPY (& new_state , state , JSON_Generator_State , 1 );
1507+
1508+ // FIXME: depth shouldn't be part of JSON_Generator_State, as that prevents it from being used concurrently.
1509+ new_state .depth = 0 ;
1510+
1511+ char stack_buffer [FBUFFER_STACK_SIZE ];
1512+ FBuffer buffer = {
1513+ .io = RTEST (io ) ? io : Qfalse ,
1514+ };
1515+ fbuffer_stack_init (& buffer , state -> buffer_initial_length , stack_buffer , FBUFFER_STACK_SIZE );
1516+
1517+ struct generate_json_data data = {
1518+ .buffer = & buffer ,
1519+ .vstate = Qfalse ,
1520+ .state = & new_state ,
1521+ .obj = obj ,
1522+ .func = generate_json
1523+ };
1524+ rb_rescue (generate_json_try , (VALUE )& data , generate_json_rescue , (VALUE )& data );
1525+
1526+ return fbuffer_finalize (& buffer );
14981527}
14991528
15001529static VALUE cState_initialize (int argc , VALUE * argv , VALUE self )
@@ -2072,7 +2101,7 @@ void Init_generator(void)
20722101 rb_define_method (cState , "buffer_initial_length" , cState_buffer_initial_length , 0 );
20732102 rb_define_method (cState , "buffer_initial_length=" , cState_buffer_initial_length_set , 1 );
20742103 rb_define_method (cState , "generate" , cState_generate , -1 );
2075- rb_define_alias (cState , "generate_new" , "generate" ); // :nodoc:
2104+ rb_define_method (cState , "generate_new" , cState_generate_new , -1 ); // :nodoc:
20762105
20772106 rb_define_private_method (cState , "allow_duplicate_key?" , cState_allow_duplicate_key_p , 0 );
20782107
0 commit comments