Skip to content

Commit

Permalink
Merge pull request #2250 from herwinw/marshal_dump_object_links
Browse files Browse the repository at this point in the history
  • Loading branch information
seven1m authored Oct 5, 2024
2 parents 45947f7 + 929367b commit eae28fc
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 15 deletions.
7 changes: 2 additions & 5 deletions spec/core/marshal/dump_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,7 @@ def _dump(level)
end
end

# NATFIXME: This results in an infinite loop
xit "dumps a recursive Array" do
it "dumps a recursive Array" do
a = []
a << a
Marshal.dump(a).should == "\x04\b[\x06@\x00"
Expand Down Expand Up @@ -896,9 +895,7 @@ def finalizer.noop(_)

it "dumps subsequent appearances of an object as a link" do
o = Object.new
NATFIXME 'dumps subsequent appearances of an object as a link', exception: SpecFailedException do
Marshal.dump([o, o]).should == "\004\b[\ao:\vObject\000@\006"
end
Marshal.dump([o, o]).should == "\004\b[\ao:\vObject\000@\006"
end

MarshalSpec::DATA_19.each do |description, (object, marshal, attributes)|
Expand Down
22 changes: 12 additions & 10 deletions spec/core/marshal/shared/load.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,16 @@
end

ruby_bug "#18141", ""..."3.1" do
# NATFIXME: Causes an infinite loop/stack overflow
xit "calls the proc for recursively visited data" do
it "calls the proc for recursively visited data" do
a = [1]
a << a
ret = []
Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg })
ret[0].should == 1.inspect
ret[1].should == a.inspect
ret.size.should == 2
NATFIXME 'Support proc argument', exception: ArgumentError, message: 'wrong number of arguments (given 2, expected 1)' do
Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg })
ret[0].should == 1.inspect
ret[1].should == a.inspect
ret.size.should == 2
end
end

it "loads an Array with proc" do
Expand Down Expand Up @@ -350,12 +351,13 @@
end

describe "when called with nil for the proc argument" do
# NATFIXME: Causes an infinite loop/stack overflow
xit "behaves as if no proc argument was passed" do
it "behaves as if no proc argument was passed" do
a = [1]
a << a
b = Marshal.send(@method, Marshal.dump(a), nil)
b.should == a
NATFIXME 'Support proc argument', exception: ArgumentError, message: 'wrong number of arguments (given 2, expected 1)' do
b = Marshal.send(@method, Marshal.dump(a), nil)
b.should == a
end
end
end

Expand Down
15 changes: 15 additions & 0 deletions src/marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Writer
def initialize(output)
@output = output
@symbol_lookup = {}
@object_lookup = {}
end

def write_byte(value)
Expand Down Expand Up @@ -194,6 +195,11 @@ def write_float(value)
end
end

def write_object_link(value)
write_char('@')
write_integer_bytes(@object_lookup.fetch(value.object_id))
end

def write_array(values)
write_char('[')
write_integer_bytes(values.size)
Expand Down Expand Up @@ -264,6 +270,15 @@ def write_object(value)
end

def write(value)
if value.respond_to?(:object_id) && @object_lookup.key?(value.object_id)
write_object_link(value)
return @output
end

if !value.nil? && !value.is_a?(TrueClass) && !value.is_a?(FalseClass) && !value.is_a?(Integer) && !value.is_a?(Float) && !value.is_a?(Symbol)
@object_lookup[value.object_id] = @object_lookup.size
end

if value.nil?
write_nil
elsif value.is_a?(TrueClass)
Expand Down

0 comments on commit eae28fc

Please sign in to comment.