是否可以在 Rhino 中多次恢复延续?
Is it possible to resume a continuation in Rhino multiple times?
我希望能够捕获一个延续并多次恢复它,这样每个这样的调用都将独立于其他调用。
例如,在下面的代码中,我希望在 run
方法中对 context.resumeContinuation
的 2 次调用产生输出:1 1
,而不是当前的1 2
.
的输出
据我了解,产生结果输出的原因是我总是使用相同的 scope
对象,该对象在传递给第二个之前由第一个延续进行修改。所以看来我应该用原始 scope
的 copy 恢复每个延续,但是类型 Scriptable
没有clone
方法(或任何等效方法),并使用 serialization/deserialization 复制它也无济于事。
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;
所以我想出了一个可行的解决方案:
我应该复制 capturedContinuation
对象而不是复制 scope
对象,因此对 resumeContinuation
的 2 次调用将是:
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
This question 提供了 deepCopy
方法的可能实现。
但请注意:Rhino 的 NativeContinuation
类型实例(即上面代码中 capturedContinuation
的动态类型)似乎相当大(序列化时约 15KB 或更大)到字节数组),因此 time/memory 在应用程序中深度复制它们时应考虑消耗影响。
这只是一个猜测,但我认为这可能有效 (Rhino 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);
我希望能够捕获一个延续并多次恢复它,这样每个这样的调用都将独立于其他调用。
例如,在下面的代码中,我希望在 run
方法中对 context.resumeContinuation
的 2 次调用产生输出:1 1
,而不是当前的1 2
.
据我了解,产生结果输出的原因是我总是使用相同的 scope
对象,该对象在传递给第二个之前由第一个延续进行修改。所以看来我应该用原始 scope
的 copy 恢复每个延续,但是类型 Scriptable
没有clone
方法(或任何等效方法),并使用 serialization/deserialization 复制它也无济于事。
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;
所以我想出了一个可行的解决方案:
我应该复制 capturedContinuation
对象而不是复制 scope
对象,因此对 resumeContinuation
的 2 次调用将是:
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
This question 提供了 deepCopy
方法的可能实现。
但请注意:Rhino 的 NativeContinuation
类型实例(即上面代码中 capturedContinuation
的动态类型)似乎相当大(序列化时约 15KB 或更大)到字节数组),因此 time/memory 在应用程序中深度复制它们时应考虑消耗影响。
这只是一个猜测,但我认为这可能有效 (Rhino 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);