3

Let me first start with admitting that I am a noob in JavaScript. So the question might not be very sound at the basics and might lack enough information to help me.

Background

My organisation has an internal Eclipse based IDE for JavaScript. All we have to do is write scripts in JavaScript and directly execute them. My guess is it uses Rhino since I have seen it in the stack trace of some exceptions.

My code runs across 3 ".js" files.

Script-1: Declare global variables and instantiate them as Java objects

importClass(java.util.HashMap);
var hmTCResult = new HashMap();

Script-2: Perform some actions using the global variables from Script-1

Script-2.prototype.run = function() {
hmTCResult.put("Result", "Fail");
};

changeStatus = function(strStatus){
hmTCResult.put("Result", strStatus);
};

Script-3: Call function in Script-2 which uses the global variables

changeStatus("Pass") 

Problem Definition

When from Script-3 I call the function in Script-2 it doesn't seem pick the instance variables and my function fails i.e. I get an exception "hmTCResult not set to the instance of an object." Please note that the the same variable hmTCResult works well in Script 1.

I have done some reading of the Scope and the Context in JavaScript but haven't been able to break through it, since I don't see it explicitly in the IDE.

I will be happy to provide more information if needed.

4

3 回答 3

1

这很好用,只需调整您的范围并设置原型搜索:

Context cx = Context.enter();
try {
    // Cache and reuse:
    ScriptableObject sealedSharedScope = cx.initStandardObjects(null,
            true);
    // Force the LiveConnect stuff to be loaded.
    String loadMe = "RegExp; getClass; java; Packages; JavaAdapter;";
    cx.evaluateString(sealedSharedScope, loadMe, "preLoadLazyLoad", 0,
            null);

    cx.evaluateString(sealedSharedScope, "varInRoot = 'blah';",
            "setVarInRoot", 0, null);

    // here you can put more cx.evaluateString calls to set up your
    // environment (eg. hmTCResult)

    // now connect a throw-away new scope into the hierarchy, with local
    // vars:
    Scriptable scope = cx.newObject(sealedSharedScope);
    // ensure that definitions in the root scope are found
    scope.setPrototype(sealedSharedScope);
    // ensure that new global variables are created in this scope (don't
    // use
    // var for them!)
    scope.setParentScope(null);

    cx.evaluateString(scope, "localVar = varInRoot;", "mySource", 0,
            null);
    assertEquals("blah", scope.get("localVar", scope).toString());
    // new var not in root:
    assertEquals(ScriptableObject.NOT_FOUND,
            sealedSharedScope.get("localVar", scope));
} finally {
    Context.exit();
}

注意 scope.get 不会搜索原型链——必须自己做!

范围独立于 Context 并且在 Context.exit() 中存在。

于 2012-11-27T17:59:58.563 回答
0

要在 Java 中评估 js 脚本,可以执行以下操作

ScriptEngine engine = new ScriptEngineManager().getEngineByMimeType( "text/javascript" );
Bindings bindings = engine.getBindings( ScriptContext.GLOBAL_SCOPE );
bindings.put( "varname", ... );
bindings.put( ... );
engine.put( ScriptEngine.FILENAME, script.toString());
engine.eval( new FileReader( script ));

如果在同一个引擎/绑定中加载了 3 个脚本,则可以,但如果新分配了引擎以执行 script3,则上下文已被清除。

这篇文章并不是真正的答案,但太长了,无法发表评论。

于 2012-10-22T21:41:42.690 回答
0

My guess, without more information, and assuming your modified transcripts are absolutely correct, is that your scripts are being run in separate scopes, all with the global scope as a parent.

As such, my guess is that the reason changeStatus works in the third script is because there is no var declaration for it. Thus, absent other configuration, this will be defined as a variable in the top-level, or global, scope, that is shared across the three scripts.

My guess is that the reason hmTCResult does not work is that it is declared with the keyword var, indicating a local variable. If all scripts were running in the top-level scope, this would define a variable on the global object. But if each script runs in its own scope, this would define a variable only in the scope of script 1. You wouldn't see the problem in the scope of script 2, because no one is executing the code in script 2 until script 3 executes.

于 2012-11-21T22:18:33.233 回答