Calling ARGV.shift from a script run via ScriptEngine

Hi all.

I am experiencing a curious issue.

Some library was calling ARGV.shift, and this failed because the shift
method was missing from whatever object was in ARGV. I isolated it to
a simpler test case:

ScriptEngine engine = new 

ScriptEngineManager().getEngineByExtension(“rb”);
ScriptContext context = engine.getContext();
context.setAttribute(ScriptEngine.ARGV, new String[] { “a”, “b” },
ScriptContext.ENGINE_SCOPE);
Object result = engine.eval(“ARGV.shift + ARGV.shift”, context);
assertEquals(“Expected the sum of the strings”, “ab”, result);

This gives:
org.jruby.embed.EvalFailedException: undefined method `shift’ for
#<#Class:01x156a9424:0x7adafa2c>

If I try using an ArrayList instead, I get the same result.

Is this supposed to work? The library in question is ‘optparse’, part
of the Ruby standard library, so the bug must be either in ‘optparse’
(“ARGV is mutable so you shouldn’t call shift on it”) or in JRuby
(“ARGV should be mutable so shift should work like it would work for
any other array”.) If I naively just start up irb and type in
ARGV.shift, it does successfully return nil.

In all other respects, the object works as expected, so I can just add
a “.to_a” in to make everything work, which will be my workaround for
now.

The behaviour is identical on 1.5.6 and 1.6.0 RC1.

TX

On Mon, Jan 31, 2011 at 10:05 PM, Trejkaz [email protected] wrote:

context.setAttribute(ScriptEngine.ARGV, new String[] { “a”, “b” },
ScriptContext.ENGINE_SCOPE);
Object result = engine.eval(“ARGV.shift + ARGV.shift”, context);
assertEquals(“Expected the sum of the strings”, “ab”, result);

This gives:
org.jruby.embed.EvalFailedException: undefined method `shift’ for
#<#Class:01x156a9424:0x7adafa2c>

If I try using an ArrayList instead, I get the same result.

This comes from the same reason as JRUBY-4949. That’s the JRuby’s Java
proxy. JRuby’s proxy wraps Java’s String[], ArrayList, or other List
type objects so that those can be used in Ruby. While wrapping, some
of Ruby methods are added, but behaviors of those methods are not
identical to Ruby counterparts. For example,

irb(main):005:0> a = java.util.ArrayList.new
=> #Java::JavaUtil::ArrayList:0x1f5726ec
irb(main):006:0> a.shift
NoMethodError: undefined method shift' for #<Java::JavaUtil::ArrayList:0x1f5726ec> from (irb):6:in evaluate’
from org/jruby/RubyKernel.java:1088:in `eval’
(snip)

However, as I commented on JRUBY-4949, ARGV should be always an array
of strings, so, now, it is converted to RubyArray before JRuby’s proxy
works. Next release won’t have this issue.

-Yoko