Search code examples
javascriptmultithreadingscalajava-8nashorn

Multi-threaded Nashorn: o.constructor === o.constructor gives false


I'm experimenting with multi-threaded scripts loading and evaluation in Nashorn and get kind of shocking behavior:

// having some object o loaded in another thread
print(o.constructor === o.constructor); // false
print(o.constructor === Object); // false as well
print(o.foo === o.foo); // true - OK

How can this be possible within single script engine? o above is just an object created using object literal notation (in another thread). Printing o.constructor gives usual function Object() { [native code] };.

At the same time:

print({}.constructor === {}.constructor); // true

Any ideas?

Update

It turned out this was unrelated to multi-threading at all. See my answer below for details.


Solution

  • It turned out this does not relate to multi-threading at all. Here is a simple Scala program which reproduces the problem:

    object Test extends App {
      val engine = new ScriptEngineManager().getEngineByName("nashorn")
      var o = engine.eval("({ foo: 'bar' })")
      var result = engine.eval("(o.constructor === o.constructor)", new SimpleBindings() {
        put("o", o)
      })
      print(result) // false
    }
    

    I was using bindings parameter incorrectly. Instead, I should take existing bindings and update 'em in-place. I'm still not convinced this should result in o.constructor === o.constructor to be false, but at least it works now. Corrected version:

    object Test extends App {
      val engine = new ScriptEngineManager().getEngineByName("nashorn")
      var o = engine.eval("({ foo: 'bar' })")
    
      val bindings =  engine.getBindings(ScriptContext.ENGINE_SCOPE)
      bindings.put("o", o)
    
      var result = engine.eval("(o.constructor === o.constructor)", bindings)
      print(result) // true
    }