Skip to content

org.jruby.ext.pathname.RubyPathname class doesn't properly support instance_variable_set method #1460

@pablito

Description

@pablito

I found this nasty behaviour of Pathname object (rel. 1.7.5 and up)

paoloa@setix-aqua:~$ jruby -S irb
jruby-1.7.10 :001 > require 'pathname'
 => true 
jruby-1.7.10 :002 > p=Pathname.new('test')
 => <Pathname:test> 
jruby-1.7.10 :003 > p.instance_variable_set(:@path, 'foo')
 => "foo" 
jruby-1.7.10 :004 > p.to_path
 => "test" 
jruby-1.7.10 :005 > p.instance_variable_get(:@path)
 => "foo" 

this happens because the java implementation of Pathname (class org.jruby.ext.pathname.RubyPathname) stores the path value used by all its methods into a private field and only synchronizes it with @path instance var at initialization time.

@JRubyClass(name = "Pathname")
public class RubyPathname extends RubyObject {
    private RubyString path;
...

@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject path) {
    ...
    [snipped]
    ...
    // TODO: remove (either direct bridge to field or all native)
    setInstanceVariable("@path", this.path);
    return this;
}


Since @path is never used internally, changing its value has no effect on object behaviour. A byproduct of this is that YAML deserialization always fails.

paoloa@setix-aqua:~$ jruby -S irb
jruby-1.7.10 :001 > require 'yaml'
 => true 
jruby-1.7.10 :002 > require 'pathname'
 => true 
jruby-1.7.10 :003 > p = Pathname.new('test')
 => <Pathname:test> 
jruby-1.7.10 :004 > p.to_yaml
 => "--- !ruby/object:Pathname\npath: test\n" 
jruby-1.7.10 :006 > deserialized = YAML.load(p.to_yaml)
 => <Pathname:null> 
jruby-1.7.10 :008 > deserialized.to_path
 => nil 

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions