JRuby 1.1.5 + BSF: local variables no longer persist between calls to eval()

I am embedding JRuby in an environment where I allow for interactive
evaluation of scripts. It’s similar to irb, but implemented in Java so
I am making repeated eval() calls to Ruby from the Java side. Up until
now I have supported assigning a local variable and having it
available in a future eval(). This no longer works in JRuby 1.1.5.

Here is code to demonstrate this issue:


import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;

public class LocalVariableTest {

private BSFManager bsf;

public LocalVariableTest() {
BSFManager.registerScriptingEngine(“ruby”,
“org.jruby.javasupport.bsf.JRubyEngine”, new String[] { “rb” });
bsf = new BSFManager();
}

public void eval(String script) {
try {
bsf.eval(“ruby”, “(java)”, 1, 1, script);
}
catch (BSFException e) {
System.err.println("Failed to evaluate: " + script);
e.printStackTrace();
}
}

public static void main(String args[]) {
LocalVariableTest lvt = new LocalVariableTest();
lvt.eval(“puts JRUBY_VERSION”);
lvt.eval(“x=99”);
lvt.eval(“puts x”);
}
}

JRuby 1.1.4 gives the following output:
1.1.4
99

JRuby 1.1.5 gives this:
1.1.5

:1: undefined local variable or method `x' for main:Object (NameError) ...internal jruby stack elided... from (unknown).(unknown)(:1) Failed to evaluate: puts x Exception: :1: undefined local variable or method `x' for main:Object (NameError) ...internal jruby stack elided... from (unknown).(unknown)(:1) I am pretty sure nothing significant in BSF or JRuby's BSF engine changed, so I'm guessing it's some change to the JRuby runtime and the way contexts/scopes are handled. Can this change be considered a bug? If so I will file it on JIRA. If not, is there some way for me to continue supporting my irb-like features in JRuby 1.1.5 and BSF? It seems the Sun engine now supports this, but I have reasons to continue using BSF. PS - I mentioned this in the other thread "Differences between BSF and JSR 223" but wanted to bring it up as an issue in a dedicated thread. Thanks, Adam --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email

Let me rephrase my question: is it possible to do “incremental
evaluation”
of Ruby code from Java by remembering the exact state of the Ruby
interpreter when the BSF eval() call finishes?

Perhaps there is a way to do this by calling Kernel.binding, storing the
bindings on the Java side, and then somehow including them in the next
eval() call from Java?
I guess I’m asking a rather strange/tricky question, maybe no one can
answer
easily. Obviously I’d like to find a way to make this work in JRuby
1.1.5 w/
BSF since it used to seamlessly work in older versions. But if someone
tells
me that this is not supported and I shouldn’t count on having this
behavior
anymore, I can at least plan accordingly.

-Adam

Hi Adam,

The reason of wrong behaivor of BSF engine is that the implementation
of Ruby.evalScriptlet method has been changed and probably had a bug.
Since I submitted a patch, I hope future releases won’t have this
trouble.

If you want to use JRuby 1.1.5 and BSF engine now, edit evalScriptlet
method in org.jruby.Ruby.java as in below:

//Node node = parseEval(script, “”, newScope, 0);
Node node = parseEval(script, “”,
newScope.getNextCapturedScope(), 0);

and build JRuby. Then your code will work again.

-Yoko

On Fri, Nov 7, 2008 at 5:02 PM, Adam M. [email protected]
wrote:

me that this is not supported and I shouldn’t count on having this behavior


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

On Sat, Nov 8, 2008 at 2:47 PM, Yoko H. [email protected] wrote:

If you want to use JRuby 1.1.5 and BSF engine now, edit evalScriptlet
method in org.jruby.Ruby.java as in below:

//Node node = parseEval(script, “”, newScope, 0);
Node node = parseEval(script, “”, newScope.getNextCapturedScope(),
0);

and build JRuby. Then your code will work again.

Yoko,
Thanks!! Works perfectly.

I figured it might be some small change like this, so I spent a little
time
digging around in the source code. But it’s the first time I’ve look at
JRuby’s source so I got very lost right away.

Really appreciate your help. You seem to always have an answer for my
questions :slight_smile:

Adam