mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/psych] Implement freeze
option for Pysch.load
https://github.com/ruby/psych/commit/7dae24894d
This commit is contained in:
parent
4085c51a51
commit
f641d78a6f
Notes:
git
2020-06-05 11:50:26 +09:00
2 changed files with 27 additions and 7 deletions
|
@ -32,16 +32,18 @@ module Psych
|
||||||
|
|
||||||
def accept target
|
def accept target
|
||||||
result = super
|
result = super
|
||||||
return result if @domain_types.empty? || !target.tag
|
|
||||||
|
|
||||||
key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
|
unless @domain_types.empty? || !target.tag
|
||||||
key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
|
key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
|
||||||
|
key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
|
||||||
|
|
||||||
if @domain_types.key? key
|
if @domain_types.key? key
|
||||||
value, block = @domain_types[key]
|
value, block = @domain_types[key]
|
||||||
return block.call value, result
|
result = block.call value, result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
result = deduplicate(result).freeze if @freeze
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -341,7 +343,7 @@ module Psych
|
||||||
key = accept(k)
|
key = accept(k)
|
||||||
if @symbolize_names
|
if @symbolize_names
|
||||||
key = key.to_sym
|
key = key.to_sym
|
||||||
else
|
elsif !@freeze
|
||||||
key = deduplicate(key)
|
key = deduplicate(key)
|
||||||
end
|
end
|
||||||
val = accept(v)
|
val = accept(v)
|
||||||
|
@ -378,6 +380,8 @@ module Psych
|
||||||
if RUBY_VERSION < '2.7'
|
if RUBY_VERSION < '2.7'
|
||||||
def deduplicate key
|
def deduplicate key
|
||||||
if key.is_a?(String)
|
if key.is_a?(String)
|
||||||
|
# It is important to untaint the string, otherwise it won't
|
||||||
|
# be deduplicated into an fstring, but simply frozen.
|
||||||
-(key.untaint)
|
-(key.untaint)
|
||||||
else
|
else
|
||||||
key
|
key
|
||||||
|
|
|
@ -192,6 +192,22 @@ class TestPsych < Psych::TestCase
|
||||||
assert_equal({ 'hello' => 'world' }, got)
|
assert_equal({ 'hello' => 'world' }, got)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_load_freeze
|
||||||
|
data = Psych.load("--- {foo: ['a']}", freeze: true)
|
||||||
|
assert_predicate data, :frozen?
|
||||||
|
assert_predicate data['foo'], :frozen?
|
||||||
|
assert_predicate data['foo'].first, :frozen?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_load_freeze_deduplication
|
||||||
|
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
|
||||||
|
skip "This Ruby implementation doesn't support string deduplication"
|
||||||
|
end
|
||||||
|
|
||||||
|
data = Psych.load("--- ['a']", freeze: true)
|
||||||
|
assert_same 'a', data.first
|
||||||
|
end
|
||||||
|
|
||||||
def test_load_default_fallback
|
def test_load_default_fallback
|
||||||
assert_equal false, Psych.load("")
|
assert_equal false, Psych.load("")
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue