[前][次][番号順一覧][スレッド一覧]

ruby-changes:61572

From: Jean <ko1@a...>
Date: Fri, 5 Jun 2020 11:50:17 +0900 (JST)
Subject: [ruby-changes:61572] f641d78a6f (master): [ruby/psych] Implement `freeze` option for Pysch.load

https://git.ruby-lang.org/ruby.git/commit/?id=f641d78a6f

From f641d78a6fcf0b96c50077503a763478d0599fe5 Mon Sep 17 00:00:00 2001
From: Jean Boussier <jean.boussier@g...>
Date: Wed, 24 Jul 2019 16:01:20 -0400
Subject: [ruby/psych] Implement `freeze` option for Pysch.load

https://github.com/ruby/psych/commit/7dae24894d

diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 68452e5..a922f90 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -32,16 +32,18 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/to_ruby.rb#L32
 
       def accept target
         result = super
-        return result if @domain_types.empty? || !target.tag
 
-        key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
-        key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
+        unless @domain_types.empty? || !target.tag
+          key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
+          key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
 
-        if @domain_types.key? key
-          value, block = @domain_types[key]
-          return block.call value, result
+          if @domain_types.key? key
+            value, block = @domain_types[key]
+            result = block.call value, result
+          end
         end
 
+        result = deduplicate(result).freeze if @freeze
         result
       end
 
@@ -341,7 +343,7 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/to_ruby.rb#L343
           key = accept(k)
           if @symbolize_names
             key = key.to_sym
-          else
+          elsif !@freeze
             key = deduplicate(key)
           end
           val = accept(v)
@@ -378,6 +380,8 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/to_ruby.rb#L380
       if RUBY_VERSION < '2.7'
         def deduplicate key
           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)
           else
             key
diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb
index eeadc86..8fd9d27 100644
--- a/test/psych/test_psych.rb
+++ b/test/psych/test_psych.rb
@@ -192,6 +192,22 @@ class TestPsych < Psych::TestCase https://github.com/ruby/ruby/blob/trunk/test/psych/test_psych.rb#L192
     assert_equal({ 'hello' => 'world' }, got)
   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
     assert_equal false, Psych.load("")
   end
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]