2016-12-11 17 views
0

Я хочу, чтобы иметь возможность фиксировать продолжение и возобновлять его несколько раз, так что каждый такой вызов будет независим от других.Можно ли возобновить продолжение в Rhino несколько раз?

Например, в следующем коде, я хочу, 2 звонки на context.resumeContinuation в методе run привести к выходу: 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; 

ответ

0

Так что я пришел с рабочим раствором:

Вместо того, чтобы копировать scope объект, Я должен был скопировать объект capturedContinuation, поэтому 2 вызова resumeContinuation будет:

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

This question предлагает возможные imeplementations методы deepCopy.

Слово предостережения, хотя: случаи NativeContinuation типа Rhino (который является динамическим типом capturedContinuation в коде выше), как представляется, довольно большой (~ 15KB и когда сериализуется в массив байтов), так что время/следует учитывать последствия потребления памяти при их глубоком копировании в приложении.