Skip to content

Commit 386b36f

Browse files
etiennebarriebyroot
authored andcommitted
Test and restore behavior around to_json changing depth
When serializing an Array, and one of the elements of the Array requires calling `to_json`, if the depth is changed, it will be used for the next entries, which wasn't the case before 5abd434, and is not the case with TruffleRuby and JRuby. Additionally, with TruffleRuby and JRuby the state's depth after the `to_json` call is used to close the Array, which isn't the case with CRuby.
1 parent c54de70 commit 386b36f

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

ext/json/ext/generator/generator.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,8 @@ static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *d
12941294
VALUE tmp;
12951295
if (rb_respond_to(obj, i_to_json)) {
12961296
tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
1297+
GET_STATE(data->vstate);
1298+
data->depth = state->depth;
12971299
Check_Type(tmp, T_STRING);
12981300
fbuffer_append_str(buffer, tmp);
12991301
} else {

test/json/json_generator_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,30 @@ def test_allow_nan
321321
end
322322
end
323323

324+
def test_depth_bad_to_json
325+
obj = Object.new
326+
def obj.to_json(state)
327+
state.depth += 1
328+
"{#{state.object_nl}"\
329+
"#{state.indent * state.depth}\"foo\":#{state.space}1#{state.object_nl}"\
330+
"#{state.indent * (state.depth - 1)}}"
331+
end
332+
indent = " " * 2 if RUBY_ENGINE != "ruby"
333+
assert_equal <<~JSON.chomp, JSON.pretty_generate([obj] * 2)
334+
[
335+
{
336+
"foo": 1
337+
},
338+
{
339+
"foo": 1
340+
}
341+
#{indent}]
342+
JSON
343+
state = JSON::State.new(object_nl: "\n", array_nl: "\n", space: " ", indent: " ")
344+
state.generate(obj)
345+
assert_equal 1, state.depth
346+
end
347+
324348
def test_depth
325349
pretty = { object_nl: "\n", array_nl: "\n", space: " ", indent: " " }
326350
state = JSON.state.new(**pretty)

0 commit comments

Comments
 (0)