Skip to content

Commit

Permalink
Add arity-2 respond_to? to GzipReader/Writer and add caching.
Browse files Browse the repository at this point in the history
Fixes #4202.
  • Loading branch information
headius committed Oct 6, 2016
1 parent 56eeca0 commit 825877f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 32 deletions.
17 changes: 1 addition & 16 deletions core/src/main/java/org/jruby/ext/zlib/JZlibRubyGzipReader.java
Expand Up @@ -41,6 +41,7 @@
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
Expand Down Expand Up @@ -154,22 +155,6 @@ public IRubyObject initialize19(ThreadContext context, IRubyObject[] args) {
return obj;
}

// These methods are here to avoid defining a singleton #path on every instance, as in MRI

@JRubyMethod
public IRubyObject path(ThreadContext context) {
return this.realIo.callMethod(context, "path");
}

@JRubyMethod(name = "respond_to?", frame = true)
public IRubyObject respond_to(ThreadContext context, IRubyObject name) {
if (name.asJavaString().equals("path")) {
return this.realIo.callMethod(context, "respond_to?", name);
}

return Helpers.invokeSuper(context, this, name, Block.NULL_BLOCK);
}

/**
* Get position within this stream including that has been read by users
* calling read + what jzlib may have speculatively read in because of
Expand Down
16 changes: 0 additions & 16 deletions core/src/main/java/org/jruby/ext/zlib/JZlibRubyGzipWriter.java
Expand Up @@ -124,22 +124,6 @@ public IRubyObject initialize19(ThreadContext context, IRubyObject[] args, Block
return this;
}

// These methods are here to avoid defining a singleton #path on every instance, as in MRI

@JRubyMethod
public IRubyObject path(ThreadContext context) {
return this.realIo.callMethod(context, "path");
}

@JRubyMethod(name = "respond_to?", frame = true)
public IRubyObject respond_to(ThreadContext context, IRubyObject name) {
if (name.asJavaString().equals("path")) {
return this.realIo.callMethod(context, "respond_to?", name);
}

return Helpers.invokeSuper(context, this, name, Block.NULL_BLOCK);
}

private int processStrategy(int argc, IRubyObject[] args) {
return argc < 3 ? JZlib.Z_DEFAULT_STRATEGY : RubyZlib.FIXNUMARG(args[2], JZlib.Z_DEFAULT_STRATEGY);
}
Expand Down
31 changes: 31 additions & 0 deletions core/src/main/java/org/jruby/ext/zlib/RubyGzipFile.java
Expand Up @@ -38,6 +38,8 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
Expand Down Expand Up @@ -112,6 +114,31 @@ public static RubyGzipFile newInstance(IRubyObject recv, Block block) {

return result;
}

// These methods are here to avoid defining a singleton #path on every instance, as in MRI

@JRubyMethod
public IRubyObject path(ThreadContext context) {
return this.realIo.callMethod(context, "path");
}

@JRubyMethod(name = "respond_to?", frame = true)
public IRubyObject respond_to(ThreadContext context, IRubyObject name) {
if (name.asJavaString().equals("path")) {
return sites(context).reader_respond_to.call(context, this, this.realIo, name);
}

return Helpers.invokeSuper(context, this, name, Block.NULL_BLOCK);
}

@JRubyMethod(name = "respond_to?", frame = true)
public IRubyObject respond_to(ThreadContext context, IRubyObject name, IRubyObject includePrivate) {
if (name.asJavaString().equals("path")) {
return sites(context).reader_respond_to.call(context, this, this.realIo, name, includePrivate);
}

return Helpers.invokeSuper(context, this, name, Block.NULL_BLOCK);
}

public RubyGzipFile(Ruby runtime, RubyClass type) {
super(runtime, type);
Expand Down Expand Up @@ -277,6 +304,10 @@ public void setBOM(boolean bom) {
public boolean getBOM() {
return hasBOM;
}

private static JavaSites.ZlibSites sites(ThreadContext context) {
return context.sites.Zlib;
}

protected boolean closed = false;
protected boolean finished = false;
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/org/jruby/runtime/JavaSites.java
Expand Up @@ -36,6 +36,7 @@ public class JavaSites {
public final BigDecimalSites BigDecimal = new BigDecimalSites();
public final ComplexSites Complex = new ComplexSites();
public final RationalSites Rational = new RationalSites();
public final ZlibSites Zlib = new ZlibSites();

public static class BasicObjectSites {
public final CallSite respond_to = new FunctionalCachingCallSite("respond_to?");
Expand Down Expand Up @@ -363,6 +364,11 @@ public static class RationalSites {
public final CheckedSites to_r_checked = new CheckedSites("to_r");
}

public static class ZlibSites {
public final RespondToCallSite reader_respond_to = new RespondToCallSite();
public final RespondToCallSite writer_respond_to = new RespondToCallSite();
}

public static class CheckedSites {
public final RespondToCallSite respond_to_X;
public final CachingCallSite respond_to_missing = new FunctionalCachingCallSite("respond_to_missing?");
Expand Down
25 changes: 25 additions & 0 deletions spec/regression/GH-4202_gzipreader_respond_to_spec.rb
@@ -0,0 +1,25 @@
require 'tempfile'
require 'zlib'

describe "A GzipWriter instance" do
before do
@tempfile = Tempfile.new("GH-4202")
end

it "supports all respond_to? arities" do
gzw = Zlib::GzipWriter.open(@tempfile.path)
gzw.respond_to?(:path).should == true
gzw.respond_to?(:path, false).should == true
end
end

describe "A GzipReader instance" do
it "supports all respond_to? arities" do
gzw = Zlib::GzipWriter.open(@tempfile.path)
gzw << "content"
gzw.close
gzr = Zlib::GzipReader.open(@tempfile.path)
gzr.respond_to?(:path).should == true
gzr.respond_to?(:path, false).should == true
end
end

0 comments on commit 825877f

Please sign in to comment.