使用Rhino解释Java中的JavaScript:暂停/恢复脚本

Jos*_*ion 15 javascript java scripting rhino

我正在使用JDK的javax.script.*包.具体来说,我正在使用JavaScript引擎,根据我的阅读,它似乎基于Mozilla开发的名为Rhino的JavaScript-in-Java解释器.

我希望完成的是基本上让我的JavaScript能够在代码中的某个点"暂停"自己(比如说,在函数调用的中途),并且只有在Java允许它执行时才会自行恢复.

为了说明我的意思,想象一下这个JavaScript代码:

function myJSFunction() {
    print("Hello ");
    mysteriousPauseFunction(); // this is the part I'm wondering about.  basically, the script should break here and resume later at Java's discretion...
    // upon reaching this comment, we know now that Java has told JavaScript that it's okay to resume, so the next line will now be executed...
    print("world");
}
Run Code Online (Sandbox Code Playgroud)

如果"暂停"/"破坏"部分涉及绑定Java函数并将其传递给当前ScriptEngine或其他任何东西,那对我来说很酷.我认为这可能涉及到:从Java中暂停JavaScript.

我做了一些谷歌搜索,发现这里的关键字似乎是"延续".据我所知,Rhino只支持解释模式下的延续(与编译模式相比),我看到它是通过将"context"设置为-2来实现的.由于内置的​​JDK ScriptEngine似乎没有提及有关上下文的任何内容(或者我可能缺少它),这是否意味着我必须直接下载并使用Mozilla的Rhino库?

我需要实现这个目标吗?我已经找到关于Rhino延续的有用教程,但在阅读完之后,我不能100%确定这是否能够完成我上面描述的内容.如果这我正在寻找的,那么我的后续问题是关于所提到的"序列化":这是否意味着当我恢复我的脚本时,所有变量都将被取消,除非我将它们序列化?

更新:看起来这可能与Rhino有关.这是我到目前为止在JavaScript中所拥有的内容; 在代码之后,我将解释它的作用......

var end = new Continuation();

function myJSFunction()
{
    print("Hello ");
    var kont = new Continuation();
    storePause(script, kont); // script is previously bound by Java into the JavaScript.  it is a reference to the script itself.
    end();
    print("world");

}
Run Code Online (Sandbox Code Playgroud)

我的"storePause()"函数是我编写的Java函数,它绑定到JavaScript,但是现在它没有做任何事情.我的下一个目标是充实其代码,以便将延续和脚本信息存储为Java对象,以便Java可以在以后恢复脚本.

现在,它正在做的是在"Hello"打印之后但在打印"world"之前暂停/"打破"脚本,因此这向我证明可以以这种方式暂停脚本.

所以,我现在应该留意的是如何恢复延续.请注意,上面的工作默认使用JDK脚本引擎(此时我不需要担心解释模式与编译模式 - 它似乎默认为解释模式),但它看起来像恢复脚本的过程需要Mozilla的Rhino库.

Jos*_*ion 5

好吧,我花了很多时间挖掘文档,教程和示例,并在这里和Rhino Google Group上发布,但我已经设法编译了一个可行的解决方案.由于似乎没有完整的例子,我将在这里发布我的发现给任何在未来偶然发现的人.

实际上,我的发现可能太长了,不能发布在这里,所以我决定在我的博客上写一个教程:

http://www.joshforde.com/blog/?p=7

希望能帮助别人.据我所知,这是唯一完整的Rhino教程,展示了如何执行以下所有操作:初始化Rhino,从JavaScript(*.js)文件加载脚本,自动绑定特定Java类中的所有函数(例如ScriptFunctions)作为JavaScript中的全局函数,最后调用JavaScript函数并处理该调用的延续.

基本上,问题是我需要首先下载Mozilla Rhino源代码(因为JDK中包含的版本已经过时且不支持continuation),重写我的所有代码以使用官方Rhino包的语法(它是与JDK的ScriptingEngine语法非常不同),编写一个抛出ContinuationPending异常并将其绑定到JavaScript的Java函数,以便JavaScript可以调用它(因为直接从JavaScript抛出ContinuationPending会导致抛出JavaScriptException,而不是抛出ContinuationPending,甚至试图在JavaScriptException上调用getCause()导致null),然后在调用我的JavaScript函数的Java代码中(在我的原始示例中为"myJSFunction"),尝试/ catch块来检查ContinuationPending(这是一个例外) ),然后使用ContinuationPending稍后恢复脚本.

唷.这很艰难,但现在一切都值得.