From 115d995665c43203aa54e4e8ebe9491d0732ab87 Mon Sep 17 00:00:00 2001 From: Josh Wise Date: Tue, 24 Mar 2026 15:20:03 -0700 Subject: [PATCH] Register the results of custom domain type parsers Using a custom domain type parser and attempting to read YAML with those types represented more than once results in all instances except the first being returned as Hashes rather than as the expected type. Register the results from custom domain type parsers so that subsequent objects are found as the already-parsed object. Fixes #786 --- lib/psych/visitors/to_ruby.rb | 1 + test/psych/test_psych.rb | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index 475444e5..61bc46e2 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -45,6 +45,7 @@ def accept target if @domain_types.key? key value, block = @domain_types[key] result = block.call value, result + register(target, result) end end diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb index 4455c471..2080e971 100644 --- a/test/psych/test_psych.rb +++ b/test/psych/test_psych.rb @@ -212,6 +212,28 @@ def test_domain_types assert_equal({ 'hello' => 'world' }, got) end + def test_domain_types_with_aliases + my_test_class = Struct.new(:prop1, :prop2) + + Psych.add_domain_type('test/custom_yaml', 'my_test_object') do |type, value| + my_test_class.new(prop1: value['prop1'], prop2: value['prop2']) + end + + yaml = <<-eoyml +--- +object1: &1 !test/custom_yaml:my_test_object + prop1: 13 + prop2: 1989 +object2: *1 +object3: *1 +eoyml + + data = Psych.load(yaml, aliases: true) + assert_equal(my_test_class.new(prop1: 13, prop2: 1989), data['object1']) + assert_equal(my_test_class.new(prop1: 13, prop2: 1989), data['object2']) + assert_equal(my_test_class.new(prop1: 13, prop2: 1989), data['object3']) + end + def test_load_freeze data = Psych.load("--- {foo: ['a']}", freeze: true) assert_predicate data, :frozen?