-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Variable update does not update it's javaType and then it causes TypeError in org.jruby.embed.jsr223.Utils#postEval #1952
Comments
jruby 1.7.13 |
I also hit another bug in ScriptEngine. Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
for (Map.Entry<String, Object> entry : bindings.entrySet()) {
Utils.put(container, receiver, entry.getKey(), entry.getValue(), context);
} |
Can be reproduced like this: manager = Java::javax.script.ScriptEngineManager.new
e = manager.getEngineByName("jruby")
b = Java::javax.script.SimpleBindings.new
e.eval 'a = 123', b
e.eval 'a = "fff"', b
puts b['a'] |
Also hit case when global var gets it's old value back in this lines of public void setJavaObject(Ruby runtime, Object javaObject) {
updateByJavaObject(runtime, javaObject);
// tryEagerInjection(runtime, null); //!!!
} Code that set this global var (which new value was lost) even was not call from inside ScriptEngine. It was called not far before ScriptEngine using. |
Please fix so that JRuby becomes usable as an embedded scripting language. I have a test suite that shows how this bug affects programmers. The test suite also shows equivalent JSR223 code for Nashorn, Groovy, and Jython. |
@mslinn Sometimes bugs just slip through the cracks. We're certainly willing to fix things that are affecting users today. I'm not sure how to run your examples, but it appears the behavior you expect is similar to the PERSISTENT variable mode that @guai uses above. Perhaps we just need to set our JSR223 implementation to use that mode? You may be able to test that change yourself, but in any case could you please open another bug showing how we can run these examples? @guai Regarding the original bug report... On JRuby master this appears to now set The second example, where a global variable apparently retains a previous value, does not reproduce in 9.1.13, the original version reported (edit: oops, original reported version was 1.7.13 and I mixed them up in my mind. The examples given all appear to work in JRuby 9.1.15). If it remains an issue in JRuby 9.1.15 (or upcoming 9.1.16) please file a new issue. |
You can just run the unit tests that I referenced to see the bug |
@mslinn Please open a separate bug for the issues you found and we'll tidy them up! |
@mslinn Setting the property @guai mentioned does indeed appear to make all your expected cases run successfully. So the debate then, which we can have in a separate issue, is whether our behavior is actually incorrect. Ruby typically does not reuse the root scope for a script execution, and variables defined at that level are not visible across scripts. However, this case is more along the lines of what we'd call a "scriptlet" and so defaulting to persistent variables may be valid. I am reluctant to change it without some discussion, since there are likely other JRuby+JSR-223 users out there who may depend on the current behavior. Here's the test that runs successfully on JRuby 9.1.15.0: "JRubyEvaluator" should {
"work" in {
System.setProperty("org.jruby.embed.localvariable.behavior", "persistent")
val jruby = new JRubyEvaluator(useClassloader = false)
jruby.scriptEngineOk shouldBe true
val engineFactories: List[ScriptEngineFactory] = jruby.scriptEngineFactories
engineFactories.size should be > 0
jruby.showEngineFactories(engineFactories)
jruby.scriptEngine should not be null
jruby.scriptEngine.getFactory.getLanguageName shouldBe "ruby"
jruby.isDefined("ten") shouldBe false
jruby.put("ten", 10) shouldBe 10
jruby.get("ten") shouldBe 10
jruby.isDefined("ten") shouldBe true
jruby.put("twenty", 20) shouldBe 20
jruby.get("twenty") shouldBe 20
// Seems to define a new variable, but that variable is not added to bindings.
// The new value is returned fine, however
val Some(twelve) = jruby.eval("twelve = 12")
twelve shouldBe 12
jruby.get("twelve") shouldBe 12 // Not bound, so fails
jruby.eval("twelve = ten + 2") // NameError: undefined local variable or method `ten' for main:Object
// Did you mean? test
// <main> at <script>:1
jruby.get("twelve") shouldBe 12 // Fails, unlike Nashorn and Jython JSR223 implementations
jruby.eval("twelve") shouldBe Some(12) // twelve is not bound
jruby.eval("twelve * 2") shouldBe Some(24)
jruby.get("twelve") shouldBe 12
} |
@headius Yes, setting the environment variable solves the problem. I did that in the constructor for the JRuby evaluator. All my tests pass.
|
👍 Since there's not really a bug per se I'll open an issue to discuss switching the default for JSR223 mode. |
FYI, JRuby 9.2+ will default to "persistent" for the 223 engine. You can set it back to "global" if necessary using the property discussed here, |
This bug I got only when used
ScriptEngine
.I updated global variable inside eval. It held java object. New value is java object too.
I think jruby synchronizes global vars after eval in
org.jruby.embed.jsr223.Utils#postEval
.And here
container.getVarMap().get(key)
causes TypeError because javaType field of this var still holds the first value's class.I found out that update goes through
org.jruby.embed.variable.AbstractVariable#updateRubyObject
and it does not update javaType.So I patched it like this:
The text was updated successfully, but these errors were encountered: