ruby-changes:37107
From: tenderlove <ko1@a...>
Date: Fri, 9 Jan 2015 07:01:48 +0900 (JST)
Subject: [ruby-changes:37107] tenderlove:r49188 (trunk): * ext/psych/lib/psych/visitors/to_ruby.rb: revive hashes with ivars
tenderlove 2015-01-09 07:00:54 +0900 (Fri, 09 Jan 2015) New Revision: 49188 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=49188 Log: * ext/psych/lib/psych/visitors/to_ruby.rb: revive hashes with ivars * ext/psych/lib/psych/visitors/yaml_tree.rb: dump hashes with ivars. Fixes github.com/psych/issues/43 * test/psych/test_hash.rb: test for change Modified files: trunk/ChangeLog trunk/ext/psych/lib/psych/visitors/to_ruby.rb trunk/ext/psych/lib/psych/visitors/yaml_tree.rb trunk/test/psych/test_hash.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 49187) +++ ChangeLog (revision 49188) @@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Jan 9 06:58:43 2015 Aaron Patterson <aaron@t...> + + * ext/psych/lib/psych/visitors/to_ruby.rb: revive hashes with ivars + + * ext/psych/lib/psych/visitors/yaml_tree.rb: dump hashes with ivars. + Fixes github.com/psych/issues/43 + + * test/psych/test_hash.rb: test for change + Thu Jan 8 17:05:00 2015 Seiei Higa <hanachin@g...> * vm_method.c (rb_method_entry): if no super class, no original Index: ext/psych/lib/psych/visitors/yaml_tree.rb =================================================================== --- ext/psych/lib/psych/visitors/yaml_tree.rb (revision 49187) +++ ext/psych/lib/psych/visitors/yaml_tree.rb (revision 49188) @@ -367,17 +367,46 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/yaml_tree.rb#L367 end def visit_Hash o - tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" - implicit = !tag + ivars = o.instance_variables - register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) + if ivars.any? + tag = "!ruby/hash-with-ivars" + tag << ":#{o.class}" unless o.class == ::Hash - o.each do |k,v| - accept k - accept v - end + register(o, @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)) + + @emitter.scalar 'elements', nil, nil, true, false, Nodes::Scalar::ANY + + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.each do |k,v| + accept k + accept v + end + @emitter.end_mapping + + @emitter.scalar 'ivars', nil, nil, true, false, Nodes::Scalar::ANY + + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.instance_variables.each do |ivar| + accept ivar + accept o.instance_variable_get ivar + end + @emitter.end_mapping - @emitter.end_mapping + @emitter.end_mapping + else + tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" + implicit = !tag + + register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) + + o.each do |k,v| + accept k + accept v + end + + @emitter.end_mapping + end end def visit_Psych_Set o Index: ext/psych/lib/psych/visitors/to_ruby.rb =================================================================== --- ext/psych/lib/psych/visitors/to_ruby.rb (revision 49187) +++ ext/psych/lib/psych/visitors/to_ruby.rb (revision 49188) @@ -261,6 +261,20 @@ module Psych https://github.com/ruby/ruby/blob/trunk/ext/psych/lib/psych/visitors/to_ruby.rb#L261 end set + when /^!ruby\/hash-with-ivars(?::(.*))?$/ + hash = $1 ? resolve_class($1).new : {} + o.children.each_slice(2) do |key, value| + case key.value + when 'elements' + revive_hash hash, value + when 'ivars' + value.children.each_slice(2) do |k,v| + hash.instance_variable_set accept(k), accept(v) + end + end + end + hash + when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/ revive_hash register(o, resolve_class($1).new), o Index: test/psych/test_hash.rb =================================================================== --- test/psych/test_hash.rb (revision 49187) +++ test/psych/test_hash.rb (revision 49188) @@ -10,6 +10,22 @@ module Psych https://github.com/ruby/ruby/blob/trunk/test/psych/test_hash.rb#L10 @hash = { :a => 'b' } end + def test_hash_with_ivars + @hash.instance_variable_set :@foo, 'bar' + dup = Psych.load Psych.dump @hash + assert_equal 'bar', dup.instance_variable_get(:@foo) + end + + def test_hash_subclass_with_ivars + x = X.new + x[:a] = 'b' + x.instance_variable_set :@foo, 'bar' + dup = Psych.load Psych.dump x + assert_cycle x + assert_equal 'bar', dup.instance_variable_get(:@foo) + assert_equal X, dup.class + end + def test_load_with_class_syck_compatibility hash = Psych.load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n" assert_equal({ user_id: 7, username: 'Lucas'}, hash) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/