1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[json] Stop using prototype objects

This commit is contained in:
Kenta Murata 2020-12-20 12:17:32 +09:00
parent d84dd66da0
commit 98cc15ed1e
No known key found for this signature in database
GPG key ID: CEFE8AFB6081B062
3 changed files with 18 additions and 49 deletions

View file

@ -15,8 +15,7 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
#endif #endif
mFloat, mString, mString_Extend, mFloat, mString, mString_Extend,
mTrueClass, mFalseClass, mNilClass, eGeneratorError, mTrueClass, mFalseClass, mNilClass, eGeneratorError,
eNestingError, eNestingError;
i_SAFE_STATE_PROTOTYPE;
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, 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, 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)) { } else if (rb_obj_is_kind_of(opts, rb_cHash)) {
return rb_funcall(self, i_new, 1, opts); return rb_funcall(self, i_new, 1, opts);
} else { } else {
VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE); return rb_class_new_instance(0, NULL, cState);
return rb_funcall(prototype, i_dup, 0);
} }
} }
@ -1608,5 +1606,4 @@ void Init_generator(void)
i_encoding = rb_intern("encoding"); i_encoding = rb_intern("encoding");
i_encode = rb_intern("encode"); i_encode = rb_intern("encode");
#endif #endif
i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
} }

View file

@ -71,22 +71,27 @@ module JSON
end end
self.state = generator::State self.state = generator::State
const_set :State, self.state const_set :State, self.state
const_set :SAFE_STATE_PROTOTYPE, State.new ensure
const_set :FAST_STATE_PROTOTYPE, State.new( $VERBOSE = old
end
def create_fast_state
State.new(
:indent => '', :indent => '',
:space => '', :space => '',
:object_nl => "", :object_nl => "",
:array_nl => "", :array_nl => "",
:max_nesting => false :max_nesting => false
) )
const_set :PRETTY_STATE_PROTOTYPE, State.new( end
def create_pretty_state
State.new(
:indent => ' ', :indent => ' ',
:space => ' ', :space => ' ',
:object_nl => "\n", :object_nl => "\n",
:array_nl => "\n" :array_nl => "\n"
) )
ensure
$VERBOSE = old
end end
# Returns the JSON generator module that is used by JSON. This is # Returns the JSON generator module that is used by JSON. This is
@ -276,7 +281,7 @@ module JSON
if State === opts if State === opts
state, opts = opts, nil state, opts = opts, nil
else else
state = SAFE_STATE_PROTOTYPE.dup state = State.new
end end
if opts if opts
if opts.respond_to? :to_hash if opts.respond_to? :to_hash
@ -315,7 +320,7 @@ module JSON
if State === opts if State === opts
state, opts = opts, nil state, opts = opts, nil
else else
state = FAST_STATE_PROTOTYPE.dup state = JSON.create_fast_state
end end
if opts if opts
if opts.respond_to? :to_hash if opts.respond_to? :to_hash
@ -370,7 +375,7 @@ module JSON
if State === opts if State === opts
state, opts = opts, nil state, opts = opts, nil
else else
state = PRETTY_STATE_PROTOTYPE.dup state = JSON.create_pretty_state
end end
if opts if opts
if opts.respond_to? :to_hash if opts.respond_to? :to_hash

View file

@ -48,35 +48,6 @@ EOT
$VERBOSE = v $VERBOSE = v
end 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 def test_generate
json = generate(@hash) json = generate(@hash)
assert_equal(parse(@json2), parse(json)) assert_equal(parse(@json2), parse(json))
@ -171,7 +142,7 @@ EOT
end end
def test_pretty_state def test_pretty_state
state = PRETTY_STATE_PROTOTYPE.dup state = JSON.create_pretty_state
assert_equal({ assert_equal({
:allow_nan => false, :allow_nan => false,
:array_nl => "\n", :array_nl => "\n",
@ -188,7 +159,7 @@ EOT
end end
def test_safe_state def test_safe_state
state = SAFE_STATE_PROTOTYPE.dup state = JSON::State.new
assert_equal({ assert_equal({
:allow_nan => false, :allow_nan => false,
:array_nl => "", :array_nl => "",
@ -205,7 +176,7 @@ EOT
end end
def test_fast_state def test_fast_state
state = FAST_STATE_PROTOTYPE.dup state = JSON.create_fast_state
assert_equal({ assert_equal({
:allow_nan => false, :allow_nan => false,
:array_nl => "", :array_nl => "",
@ -241,12 +212,8 @@ EOT
def test_depth def test_depth
ary = []; ary << ary ary = []; ary << ary
assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
assert_raise(JSON::NestingError) { generate(ary) } 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_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
s = JSON.state.new s = JSON.state.new
assert_equal 0, s.depth assert_equal 0, s.depth
assert_raise(JSON::NestingError) { ary.to_json(s) } assert_raise(JSON::NestingError) { ary.to_json(s) }