是否有可能多次在Rhino中恢复延续?

时间:2016-12-11 01:06:00

标签: java rhino continuations

我希望能够捕获一个延续并重复几次,这样每次这样的调用都将独立于其他调用。

例如,在以下代码中,我希望context.resumeContinuation方法中run的2次调用导致输出:1 1,而不是当前输出1 2

据我所知,产生结果的原因是我总是使用相同的scope对象,在传递给第二个对象之前,它被第一个继续修改。所以我似乎应该使用原始scope 副本 恢复每个延续,但类型Scriptable没有clone方法(或任何等效的东西),并使用序列化/反序列化复制它也没有帮助。

P.S。我使用的是Rhino版本1.7R5。

Example.java

import org.mozilla.javascript.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    public void run() throws IOException {
        Context context = Context.enter();
        context.setOptimizationLevel(-2);   // Use interpreter mode.
        Scriptable scope = context.initStandardObjects();
        scope.put("javaProxy", scope, Context.javaToJS(this, scope));

        Object capturedContinuation = null;
        try {
            String scriptSource =
                new String(Files.readAllBytes(Paths.get("example.js")));

            String scriptName = "example";
            int startLine = 1;
            Object securityDomain = null;
            Script script =
                context.compileString(scriptSource, scriptName, startLine, securityDomain);
            context.executeScriptWithContinuations(script, scope);
        } catch (ContinuationPending continuationPending) {
            capturedContinuation = continuationPending.getContinuation();
        }

        Object result = "";

        context.resumeContinuation(capturedContinuation, scope, result);
        context.resumeContinuation(capturedContinuation, scope, result);

        Context.exit();
    }

    public void captureContinuation() {
        Context context = Context.enter();
        ContinuationPending continuationPending =
            context.captureContinuation();
        Context.exit();
        throw continuationPending;
    }

    public void print(int i) {
        System.out.print(i + " ");
    }

    public static void main(String[] args) throws IOException {
        new Example().run();
    }
}

example.js

var i = 1;
javaProxy.captureContinuation();
javaProxy.print(i);
i = i + 1;

2 个答案:

答案 0 :(得分:0)

所以我提出了一个有效的解决方案:

我应该复制scope对象,而不是复制capturedContinuation对象,因此对resumeContinuation的2次调用将是:

context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);

This question提供了deepCopy方法的可能补充。

但请注意:Rhino的NativeContinuation类型(上面代码中capturedContinuation的动态类型)的实例似乎非常大(~15KB及以上)当序列化为字节数组时,因此在应用程序中深度复制它们时应考虑时间/内存消耗的影响。

答案 1 :(得分:0)

这只是一个猜测,但我认为这可能有效(犀牛1.7.6):

    NativeContinuation capturedContinuation = ...
    final Object stackFrame = capturedContinuation.getImplementation();

    // Invoke once...
    context.resumeContinuation(capturedContinuation, scope, result);

    // Put stack back where it was
    capturedContinuation.initImplementation(stackFrame);

    // Invoke twice...
    context.resumeContinuation(capturedContinuation, scope, result);