I have using Rhino to call JS function from few files from few threads (any file from any thread).
For example I have few scripts with various implementations of "findResponse" method. And I want to call "findResponse" from script "1_handler" or "2_handler" relatively to response.
Also I have separate script with data to share to other "findResponse" implementors.
I have created:
1) `Scriptable` "globalScope": Used as common scope. Created one time with:
context = Context.enter();
globalScope = (Scriptable) context.initStandardObjects();
... (ScriptableObject.putProperty(globalScope, ...)
2) `HashMap<String, Scriptable>` "scopesCache". Used to store scriptable-per-file. Each `Scriptable` cached on first call (of function from file, in `cacheScript`):
Scriptable scriptScope = context.newObject(globalScope);
scriptScope.setParentScope(globalScope);
script.exec(context, scriptScope);
scopesCache.put("xxx", scriptScope);
Used as (`callFunctionInGlobalScope`):
Scriptable thisScope = scopesCache.get(...);
Object calledFunction = thisScope.get(funcName, thisScope);
((Function) calledFunction).call(context, globalScope, thisScope, funcArgs);
On last line I catch:
java.lang.IllegalStateException: null
at org.mozilla.javascript.ScriptRuntime.storeScriptable(ScriptRuntime.java:4197) ~[runner.jar:2.7.0-SNAPSHOT]
at org.mozilla.javascript.ScriptRuntime.getPropFunctionAndThisHelper(ScriptRuntime.java:2426) ~[runner.jar:2.7.0-SNAPSHOT]
at org.mozilla.javascript.ScriptRuntime.getPropFunctionAndThis(ScriptRuntime.java:2405) ~[runner.jar:2.7.0-SNAPSHOT]
at xxx ~[na:na]
at xxx ~[na:na]
at xxx callFunctionInGlobalScope(JavaScriptManager.java:170) ~[runner.jar:2.7.0-SNAPSHOT]
As I see it related to [`scratchScriptable` in context](
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/ScriptRuntime.java#L4202)
Repro is not 100%. If try to run it manually not reproduced at all. But on intensive using it reproduced oftenly.
--
[In Issue 195 on GitHub](
https://github.com/mozilla/rhino/issues/195) **eshepelyuk** proposed to catch scripts instead of scopes. I have tried to implement it with changing:
`scopesCache` changed to `HashMap<String, Script>`,
`cacheScript` changed to `scopesCache.put("xxx", script);`
`callFunctionInGlobalScope` changed to:
Scriptable thisScope = context.newObject(globalScope);
thisScope.setParentScope(globalScope);
script.exec(context, thisScope);
Object calledFunction = thisScope.get(funcName, thisScope);
((Function) calledFunction).call(context, globalScope, thisScope, funcArgs);
But in this case I see performance degradation (about 5-10 times), seems like it related to `script.exec` in `callFunctionInGlobalScope`.
Can you have any ideas - how to fix issue or implement first varaiant (cache scopes) thread-safe?