From 98cc15ed1e9193e17fad6b87cccf8f8b5ade7801 Mon Sep 17 00:00:00 2001 From: Kenta Murata Date: Sun, 20 Dec 2020 12:17:32 +0900 Subject: [PATCH] [json] Stop using prototype objects --- ext/json/generator/generator.c | 7 ++---- ext/json/lib/json/common.rb | 21 ++++++++++------- test/json/json_generator_test.rb | 39 +++----------------------------- 3 files changed, 18 insertions(+), 49 deletions(-) diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 80d1ca7bf3..2e802c8ea4 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -15,8 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, #endif mFloat, mString, mString_Extend, mTrueClass, mFalseClass, mNilClass, eGeneratorError, - eNestingError, - i_SAFE_STATE_PROTOTYPE; + eNestingError; static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only, @@ -1166,8 +1165,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts) } else if (rb_obj_is_kind_of(opts, rb_cHash)) { return rb_funcall(self, i_new, 1, opts); } else { - VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE); - return rb_funcall(prototype, i_dup, 0); + return rb_class_new_instance(0, NULL, cState); } } @@ -1608,5 +1606,4 @@ void Init_generator(void) i_encoding = rb_intern("encoding"); i_encode = rb_intern("encode"); #endif - i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE"); } diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 111d70c332..c34fa61eb7 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -71,22 +71,27 @@ module JSON end self.state = generator::State const_set :State, self.state - const_set :SAFE_STATE_PROTOTYPE, State.new - const_set :FAST_STATE_PROTOTYPE, State.new( + ensure + $VERBOSE = old + end + + def create_fast_state + State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) - const_set :PRETTY_STATE_PROTOTYPE, State.new( + end + + def create_pretty_state + State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) - ensure - $VERBOSE = old end # Returns the JSON generator module that is used by JSON. This is @@ -276,7 +281,7 @@ module JSON if State === opts state, opts = opts, nil else - state = SAFE_STATE_PROTOTYPE.dup + state = State.new end if opts if opts.respond_to? :to_hash @@ -315,7 +320,7 @@ module JSON if State === opts state, opts = opts, nil else - state = FAST_STATE_PROTOTYPE.dup + state = JSON.create_fast_state end if opts if opts.respond_to? :to_hash @@ -370,7 +375,7 @@ module JSON if State === opts state, opts = opts, nil else - state = PRETTY_STATE_PROTOTYPE.dup + state = JSON.create_pretty_state end if opts if opts.respond_to? :to_hash diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 2ecdc97298..5bafc3ead4 100644 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -48,35 +48,6 @@ EOT $VERBOSE = v end - def test_remove_const_segv - stress = GC.stress - const = JSON::SAFE_STATE_PROTOTYPE.dup - - bignum_too_long_to_embed_as_string = 1234567890123456789012345 - expect = bignum_too_long_to_embed_as_string.to_s - GC.stress = true - - 10.times do |i| - tmp = bignum_too_long_to_embed_as_string.to_json - raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect - end - - silence do - JSON.const_set :SAFE_STATE_PROTOTYPE, nil - end - - 10.times do |i| - assert_raise TypeError do - bignum_too_long_to_embed_as_string.to_json - end - end - ensure - GC.stress = stress - silence do - JSON.const_set :SAFE_STATE_PROTOTYPE, const - end - end if JSON.const_defined?("Ext") && RUBY_ENGINE != 'jruby' - def test_generate json = generate(@hash) assert_equal(parse(@json2), parse(json)) @@ -171,7 +142,7 @@ EOT end def test_pretty_state - state = PRETTY_STATE_PROTOTYPE.dup + state = JSON.create_pretty_state assert_equal({ :allow_nan => false, :array_nl => "\n", @@ -188,7 +159,7 @@ EOT end def test_safe_state - state = SAFE_STATE_PROTOTYPE.dup + state = JSON::State.new assert_equal({ :allow_nan => false, :array_nl => "", @@ -205,7 +176,7 @@ EOT end def test_fast_state - state = FAST_STATE_PROTOTYPE.dup + state = JSON.create_fast_state assert_equal({ :allow_nan => false, :array_nl => "", @@ -241,12 +212,8 @@ EOT def test_depth ary = []; ary << ary - assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth assert_raise(JSON::NestingError) { generate(ary) } - assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth - assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) } - assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth s = JSON.state.new assert_equal 0, s.depth assert_raise(JSON::NestingError) { ary.to_json(s) }