diff --git a/common/src/main/java/dev/latvian/mods/rhino/ArrowFunction.java b/common/src/main/java/dev/latvian/mods/rhino/ArrowFunction.java index 1a8b30ea..81e8ab5e 100644 --- a/common/src/main/java/dev/latvian/mods/rhino/ArrowFunction.java +++ b/common/src/main/java/dev/latvian/mods/rhino/ArrowFunction.java @@ -39,7 +39,7 @@ public ArrowFunction(Context cx, Scriptable scope, Callable targetFunction, Scri @Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Scriptable callThis = boundThis != null ? boundThis : cx.getTopCallOrThrow(); - return targetFunction.call(cx, scope, callThis, args); + return cx.callSync(targetFunction, scope, callThis, args); } @Override diff --git a/common/src/main/java/dev/latvian/mods/rhino/Context.java b/common/src/main/java/dev/latvian/mods/rhino/Context.java index 5915054d..b025043d 100644 --- a/common/src/main/java/dev/latvian/mods/rhino/Context.java +++ b/common/src/main/java/dev/latvian/mods/rhino/Context.java @@ -21,10 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.io.PrintWriter; import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; @@ -57,30 +54,10 @@ @SuppressWarnings("ThrowableNotThrown") public class Context { - public static final String errorReporterProperty = "error reporter"; - public static Context enter() { return new Context(); } - /** - * Call {@link - * Callable#call(Context cx, Scriptable scope, Scriptable thisObj, - * Object[] args)} - * using the Context instance associated with the current thread. - * If no Context is associated with the thread, then - * {@link ContextFactory#makeContext()} will be called to construct - * new Context instance. The instance will be temporary associated - * with the thread during call to {@link ContextAction#run(Context)}. - *
- * It is allowed but not advisable to use null for factory
- * argument in which case the global static singleton ContextFactory
- * instance will be used to create new context instances.
- */
- public static Object call(Context cx, final Callable callable, final Scriptable scope, final Scriptable thisObj, final Object[] args) {
- return callable.call(cx, scope, thisObj, args);
- }
-
/**
* Report a warning using the error reporter for the current thread.
*
@@ -108,17 +85,6 @@ public static void reportWarning(String message, Context cx) {
Context.reportWarning(cx, message, filename, linep[0], null, 0);
}
- public static void reportWarning(Context cx, String message, Throwable t) {
- int[] linep = {0};
- String filename = getSourcePositionFromStack(cx, linep);
- Writer sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- pw.println(message);
- t.printStackTrace(pw);
- pw.flush();
- Context.reportWarning(cx, sw.toString(), filename, linep[0], null, 0);
- }
-
/**
* Report an error using the error reporter for the current thread.
*
@@ -336,6 +302,8 @@ public static String getSourcePositionFromStack(Context cx, int[] linep) {
return null;
}
+ public final Object lock = new Object();
+
// Generate an observer count on compiled code
public boolean generateObserverCount = false;
private Scriptable topCallScope;
@@ -631,95 +599,6 @@ public final Object evaluateReader(Scriptable scope, Reader in, String sourceNam
return null;
}
- /**
- * Execute script that may pause execution by capturing a continuation.
- * Caller must be prepared to catch a ContinuationPending exception
- * and resume execution by calling
- * {@link #resumeContinuation(Object, Scriptable, Object)}.
- *
- * @param script The script to execute. Script must have been compiled
- * with interpreted mode (optimization level -1)
- * @param scope The scope to execute the script against
- * @throws ContinuationPending if the script calls a function that results
- * in a call to {@link #captureContinuation()}
- * @since 1.7 Release 2
- */
- public Object executeScriptWithContinuations(Script script, Scriptable scope) throws ContinuationPending {
- if (!(script instanceof InterpretedFunction) || !((InterpretedFunction) script).isScript()) {
- // Can only be applied to scripts
- throw new IllegalArgumentException("Script argument was not" + " a script or was not created by interpreted mode ");
- }
- return callFunctionWithContinuations((InterpretedFunction) script, scope, ScriptRuntime.EMPTY_OBJECTS);
- }
-
- /**
- * Call function that may pause execution by capturing a continuation.
- * Caller must be prepared to catch a ContinuationPending exception
- * and resume execution by calling
- * {@link #resumeContinuation(Object, Scriptable, Object)}.
- *
- * @param function The function to call. The function must have been
- * compiled with interpreted mode (optimization level -1)
- * @param scope The scope to execute the script against
- * @param args The arguments for the function
- * @throws ContinuationPending if the script calls a function that results
- * in a call to {@link #captureContinuation()}
- * @since 1.7 Release 2
- */
- public Object callFunctionWithContinuations(Callable function, Scriptable scope, Object[] args) throws ContinuationPending {
- if (!(function instanceof InterpretedFunction)) {
- // Can only be applied to scripts
- throw new IllegalArgumentException("Function argument was not" + " created by interpreted mode ");
- }
- if (hasTopCallScope()) {
- throw new IllegalStateException("Cannot have any pending top " + "calls when executing a script with continuations");
- }
- // Annotate so we can check later to ensure no java code in
- // intervening frames
- isContinuationsTopCall = true;
- return ScriptRuntime.doTopCall(this, scope, function, scope, args, isTopLevelStrict);
- }
-
- /**
- * Capture a continuation from the current execution. The execution must
- * have been started via a call to
- * {@link #executeScriptWithContinuations(Script, Scriptable)} or
- * {@link #callFunctionWithContinuations(Callable, Scriptable, Object[])}.
- * This implies that the code calling
- * this method must have been called as a function from the
- * JavaScript script. Also, there cannot be any non-JavaScript code
- * between the JavaScript frames (e.g., a call to eval()). The
- * ContinuationPending exception returned must be thrown.
- *
- * @return A ContinuationPending exception that must be thrown
- * @since 1.7 Release 2
- */
- public ContinuationPending captureContinuation() {
- return new ContinuationPending(Interpreter.captureContinuation(this));
- }
-
- /**
- * Restarts execution of the JavaScript suspended at the call
- * to {@link #captureContinuation()}. Execution of the code will resume
- * with the functionResult as the result of the call that captured the
- * continuation.
- * Execution of the script will either conclude normally and the
- * result returned, another continuation will be captured and
- * thrown, or the script will terminate abnormally and throw an exception.
- *
- * @param continuation The value returned by
- * {@link ContinuationPending#getContinuation()}
- * @param functionResult This value will appear to the code being resumed
- * as the result of the function that captured the continuation
- * @throws ContinuationPending if another continuation is captured before
- * the code terminates
- * @since 1.7 Release 2
- */
- public Object resumeContinuation(Object continuation, Scriptable scope, Object functionResult) throws ContinuationPending {
- Object[] args = {functionResult};
- return Interpreter.restartContinuation((NativeContinuation) continuation, this, scope, args);
- }
-
/**
* Compiles the source in the given reader.
*
@@ -1176,18 +1055,6 @@ public void addToScope(Scriptable scope, String name, Object value) { } } - /** - * Execute top call to script or function. - * When the runtime is about to execute a script or function that will - * create the first stack frame with scriptable code, it calls this method - * to perform the real call. In this way execution of any script - * happens inside this function. - */ - protected Object doTopCall(Callable callable, Scriptable scope, Scriptable thisObj, Object[] args) { - Object result = callable.call(this, scope, thisObj, args); - return result instanceof ConsString ? result.toString() : result; - } - // custom data /** @@ -1359,37 +1226,100 @@ public final void setWrapFactory(WrapFactory wrapFactory) { this.wrapFactory = wrapFactory; } - public synchronized boolean hasTopCallScope() { - return topCallScope != null; + public boolean hasTopCallScope() { + synchronized (lock) { + return topCallScope != null; + } } - public synchronized Scriptable getTopCallScope() { - return topCallScope; + public Scriptable getTopCallScope() { + synchronized (lock) { + return topCallScope; + } } - public synchronized Scriptable getTopCallOrThrow() { - if (topCallScope == null) { - throw new IllegalStateException(); + public Scriptable getTopCallOrThrow() { + synchronized (lock) { + if (topCallScope == null) { + throw new IllegalStateException(); + } + + return topCallScope; } + } - return topCallScope; + public void setTopCall(Scriptable scope) { + synchronized (lock) { + topCallScope = scope; + } } - public synchronized void setTopCall(Scriptable scope) { - topCallScope = scope; + public void storeScriptable(Scriptable value) { + synchronized (lock) { + // The previously stored scratchScriptable should be consumed + if (scratchScriptable != null) { + throw new IllegalStateException(); + } + scratchScriptable = value; + } } - public synchronized void storeScriptable(Scriptable value) { - // The previously stored scratchScriptable should be consumed - if (scratchScriptable != null) { - throw new IllegalStateException(); + public Scriptable lastStoredScriptable() { + synchronized (lock) { + Scriptable result = scratchScriptable; + scratchScriptable = null; + return result; + } + } + + /** + * Call {@link + * Callable#call(Context cx, Scriptable scope, Scriptable thisObj, + * Object[] args)} + * using the Context instance associated with the current thread. + * If no Context is associated with the thread, then makeContext() will be called to construct + * new Context instance. The instance will be temporary associated + * with the thread during call to {@link ContextAction#run(Context)}. + *
+ * It is allowed but not advisable to use null for factory
+ * argument in which case the global static singleton ContextFactory
+ * instance will be used to create new context instances.
+ */
+ public Object callSync(Callable callable, Scriptable scope, Scriptable thisObj, Object[] args) {
+ synchronized (lock) {
+ return callable.call(this, scope, thisObj, args);
}
- scratchScriptable = value;
}
- public synchronized Scriptable lastStoredScriptable() {
- Scriptable result = scratchScriptable;
- scratchScriptable = null;
+ public Object doTopCall(Scriptable scope, Callable callable, Scriptable thisObj, Object[] args, boolean isTopLevelStrict) {
+ if (scope == null) {
+ throw new IllegalArgumentException();
+ }
+ if (hasTopCallScope()) {
+ throw new IllegalStateException();
+ }
+
+ Object result;
+ setTopCall(ScriptableObject.getTopLevelScope(scope));
+ boolean previousTopLevelStrict = this.isTopLevelStrict;
+ this.isTopLevelStrict = isTopLevelStrict;
+ try {
+ result = callSync(callable, scope, thisObj, args);
+
+ if (result instanceof ConsString) {
+ result = result.toString();
+ }
+ } finally {
+ setTopCall(null);
+ // Cleanup cached references
+ this.isTopLevelStrict = previousTopLevelStrict;
+
+ if (currentActivationCall != null) {
+ // Function should always call exitActivationFunction
+ // if it creates activation record
+ throw new IllegalStateException();
+ }
+ }
return result;
}
}
diff --git a/common/src/main/java/dev/latvian/mods/rhino/ContinuationPending.java b/common/src/main/java/dev/latvian/mods/rhino/ContinuationPending.java
deleted file mode 100644
index 54b22ad5..00000000
--- a/common/src/main/java/dev/latvian/mods/rhino/ContinuationPending.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package dev.latvian.mods.rhino;
-
-import java.io.Serial;
-
-/**
- * Exception thrown by
- * {@link Context#executeScriptWithContinuations(Script, Scriptable)}
- * and {@link Context#callFunctionWithContinuations(Callable, Scriptable, Object[])}
- * when execution encounters a continuation captured by
- * {@link Context#captureContinuation()}.
- * Exception will contain the captured state needed to restart the continuation
- * with {@link Context#resumeContinuation(Object, Scriptable, Object)}.
- *
- * @author Norris Boyd
- */
-public class ContinuationPending extends RuntimeException {
- @Serial
- private static final long serialVersionUID = 4956008116771118856L;
- private NativeContinuation continuationState;
- private Object applicationState;
-
- /**
- * Construct a ContinuationPending exception. Internal call only;
- * users of the API should get continuations created on their behalf by
- * calling {@link Context#executeScriptWithContinuations(Script, Scriptable)}
- * and {@link Context#callFunctionWithContinuations(Callable, Scriptable, Object[])}
- * Creating subclasses allowed.
- *
- * @param continuationState Internal Continuation object
- */
- protected ContinuationPending(NativeContinuation continuationState) {
- this.continuationState = continuationState;
- }
-
- /**
- * Get continuation object. The only
- * use for this object is to be passed to
- * {@link Context#resumeContinuation(Object, Scriptable, Object)}.
- *
- * @return continuation object
- */
- public Object getContinuation() {
- return continuationState;
- }
-
- /**
- * Set continuation object. Allows subclasses to modify the internal state.
- *
- * @param continuation object
- */
- public void setContinuation(NativeContinuation continuation) {
- this.continuationState = continuation;
- }
-
- /**
- * @return internal continuation state
- */
- NativeContinuation getContinuationState() {
- return continuationState;
- }
-
- /**
- * @return arbitrary application state
- */
- public Object getApplicationState() {
- return applicationState;
- }
-
- /**
- * Store an arbitrary object that applications can use to associate
- * their state with the continuation.
- *
- * @param applicationState arbitrary application state
- */
- public void setApplicationState(Object applicationState) {
- this.applicationState = applicationState;
- }
-}
diff --git a/common/src/main/java/dev/latvian/mods/rhino/ES6Generator.java b/common/src/main/java/dev/latvian/mods/rhino/ES6Generator.java
index fee11b17..b1ec0fe8 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/ES6Generator.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/ES6Generator.java
@@ -151,7 +151,7 @@ private Scriptable resumeDelegee(Context cx, Scriptable scope, Object value) {
Callable nextFn = ScriptRuntime.getPropFunctionAndThis(cx, scope, delegee, ES6Iterator.NEXT_METHOD);
Scriptable nextThis = cx.lastStoredScriptable();
- Object nr = nextFn.call(cx, scope, nextThis, nextArgs);
+ Object nr = cx.callSync(nextFn, scope, nextThis, nextArgs);
Scriptable nextResult = ScriptableObject.ensureScriptable(nr, cx);
if (ScriptRuntime.isIteratorDone(cx, nextResult)) {
@@ -179,7 +179,7 @@ private Scriptable resumeDelegeeThrow(Context cx, Scriptable scope, Object value
// Delegate to "throw" method. If it's not defined we'll get an error here.
Callable throwFn = ScriptRuntime.getPropFunctionAndThis(cx, scope, delegee, "throw");
Scriptable nextThis = cx.lastStoredScriptable();
- Object throwResult = throwFn.call(cx, scope, nextThis, new Object[]{value});
+ Object throwResult = cx.callSync(throwFn, scope, nextThis, new Object[]{value});
if (ScriptRuntime.isIteratorDone(cx, throwResult)) {
// Iterator is "done".
@@ -385,7 +385,7 @@ private Object callReturnOptionally(Context cx, Scriptable scope, Object value)
if (!(retFnObj instanceof Callable)) {
throw ScriptRuntime.typeError2(cx, "msg.isnt.function", ES6Iterator.RETURN_METHOD, ScriptRuntime.typeof(cx, retFnObj));
}
- return ((Callable) retFnObj).call(cx, scope, ensureScriptable(delegee, cx), retArgs);
+ return cx.callSync((Callable) retFnObj, scope, ensureScriptable(delegee, cx), retArgs);
}
return null;
}
diff --git a/common/src/main/java/dev/latvian/mods/rhino/EqualObjectGraphs.java b/common/src/main/java/dev/latvian/mods/rhino/EqualObjectGraphs.java
index ecde4ead..f58daa83 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/EqualObjectGraphs.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/EqualObjectGraphs.java
@@ -239,9 +239,7 @@ private boolean equalScriptables(Context cx, final Scriptable s1, final Scriptab
}
// Handle special Scriptable implementations
- if (s1 instanceof NativeContinuation s3) {
- return s2 instanceof NativeContinuation s4 && NativeContinuation.equalImplementations(s3, s4);
- } else if (s1 instanceof IdFunctionObject s3) {
+ if (s1 instanceof IdFunctionObject s3) {
return s2 instanceof IdFunctionObject s4 && IdFunctionObject.equalObjectGraphs(cx, s3, s4, this);
} else if (s1 instanceof ArrowFunction s3) {
return s2 instanceof ArrowFunction s4 && ArrowFunction.equalObjectGraphs(cx, s3, s4, this);
diff --git a/common/src/main/java/dev/latvian/mods/rhino/InterfaceAdapter.java b/common/src/main/java/dev/latvian/mods/rhino/InterfaceAdapter.java
index b5e7d179..9d4fe9e0 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/InterfaceAdapter.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/InterfaceAdapter.java
@@ -84,11 +84,7 @@ private InterfaceAdapter(Context cx, Class> cl) {
this.proxyHelper = VMBridge.getInterfaceProxyHelper(cx, new Class[]{cl});
}
- public Object invoke(Context cx, final Object target, final Scriptable topScope, final Object thisObject, final Method method, final Object[] args) {
- return invokeImpl(cx, target, topScope, thisObject, method, args);
- }
-
- Object invokeImpl(Context cx, Object target, Scriptable topScope, Object thisObject, Method method, Object[] args) {
+ public Object invoke(Context cx, Object target, Scriptable topScope, Object thisObject, Method method, Object[] args) {
Callable function;
if (target instanceof Callable) {
function = (Callable) target;
@@ -126,7 +122,7 @@ Object invokeImpl(Context cx, Object target, Scriptable topScope, Object thisObj
}
Scriptable thisObj = wf.wrapAsJavaObject(cx, topScope, thisObject, null);
- Object result = function.call(cx, topScope, thisObj, args);
+ Object result = cx.callSync(function, topScope, thisObj, args);
Class> javaResultType = method.getReturnType();
if (javaResultType == Void.TYPE) {
result = null;
diff --git a/common/src/main/java/dev/latvian/mods/rhino/InterpretedFunction.java b/common/src/main/java/dev/latvian/mods/rhino/InterpretedFunction.java
index b40a4e69..3d3a7c4a 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/InterpretedFunction.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/InterpretedFunction.java
@@ -67,7 +67,7 @@ public String getFunctionName() {
@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
if (!cx.hasTopCallScope()) {
- return ScriptRuntime.doTopCall(cx, scope, this, thisObj, args, idata.isStrict);
+ return cx.doTopCall(scope, this, thisObj, args, idata.isStrict);
}
return Interpreter.interpret(this, cx, scope, thisObj, args);
}
@@ -80,7 +80,7 @@ public Object exec(Context cx, Scriptable scope) {
}
if (!cx.hasTopCallScope()) {
// It will go through "call" path. but they are equivalent
- return ScriptRuntime.doTopCall(cx, scope, this, scope, ScriptRuntime.EMPTY_OBJECTS, idata.isStrict);
+ return cx.doTopCall(scope, this, scope, ScriptRuntime.EMPTY_OBJECTS, idata.isStrict);
}
return Interpreter.interpret(this, cx, scope, scope, ScriptRuntime.EMPTY_OBJECTS);
}
diff --git a/common/src/main/java/dev/latvian/mods/rhino/Interpreter.java b/common/src/main/java/dev/latvian/mods/rhino/Interpreter.java
index 1234e0a1..5522b5cb 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/Interpreter.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/Interpreter.java
@@ -235,7 +235,7 @@ public boolean equals(Object other) {
return equalsInTopScope(otherCallFrame);
}
final Scriptable top = ScriptableObject.getTopLevelScope(scope);
- return (Boolean) ScriptRuntime.doTopCall(localContext, top, (c, scope, thisObj, args) -> equalsInTopScope(otherCallFrame), top, ScriptRuntime.EMPTY_OBJECTS, isStrictTopFrame());
+ return (Boolean) localContext.doTopCall(top, (c, scope, thisObj, args) -> equalsInTopScope(otherCallFrame), top, ScriptRuntime.EMPTY_OBJECTS, isStrictTopFrame());
//} finally {
// Context.exit();
//}
@@ -279,59 +279,6 @@ private boolean fieldsEqual(CallFrame other, EqualObjectGraphs equal, Context cx
}
}
- private static final class ContinuationJump {
- CallFrame capturedFrame;
- CallFrame branchFrame;
- Object result;
- double resultDbl;
-
- ContinuationJump(NativeContinuation c, CallFrame current) {
- this.capturedFrame = (CallFrame) c.getImplementation();
- if (this.capturedFrame == null || current == null) {
- // Continuation and current execution does not share
- // any frames if there is nothing to capture or
- // if there is no currently executed frames
- this.branchFrame = null;
- } else {
- // Search for branch frame where parent frame chains starting
- // from captured and current meet.
- CallFrame chain1 = this.capturedFrame;
- CallFrame chain2 = current;
-
- // First work parents of chain1 or chain2 until the same
- // frame depth.
- int diff = chain1.frameIndex - chain2.frameIndex;
- if (diff != 0) {
- if (diff < 0) {
- // swap to make sure that
- // chain1.frameIndex > chain2.frameIndex and diff > 0
- chain1 = current;
- chain2 = this.capturedFrame;
- diff = -diff;
- }
- do {
- chain1 = chain1.parentFrame;
- } while (--diff != 0);
- if (chain1.frameIndex != chain2.frameIndex) {
- Kit.codeBug();
- }
- }
-
- // Now walk parents in parallel until a shared frame is found
- // or until the root is reached.
- while (chain1 != chain2 && chain1 != null) {
- chain1 = chain1.parentFrame;
- chain2 = chain2.parentFrame;
- }
-
- this.branchFrame = chain1;
- if (this.branchFrame != null && !this.branchFrame.frozen) {
- Kit.codeBug();
- }
- }
- }
- }
-
private static boolean compareIdata(InterpreterData i1, InterpreterData i2) {
return i1 == i2;
}
@@ -444,30 +391,6 @@ public static Object resumeGenerator(Context cx, Scriptable scope, int operation
return result;
}
- public static Object restartContinuation(NativeContinuation c, Context cx, Scriptable scope, Object[] args) {
- if (!cx.hasTopCallScope()) {
- return ScriptRuntime.doTopCall(cx, scope, c, null, args, cx.isTopLevelStrict);
- }
-
- Object arg;
- if (args.length == 0) {
- arg = Undefined.instance;
- } else {
- arg = args[0];
- }
-
- CallFrame capturedFrame = (CallFrame) c.getImplementation();
- if (capturedFrame == null) {
- // No frames to restart
- return arg;
- }
-
- ContinuationJump cjump = new ContinuationJump(c, null);
-
- cjump.result = arg;
- return interpretLoop(cx, null, cjump);
- }
-
private static Object interpretLoop(Context cx, CallFrame frame, Object throwable) {
// throwable holds exception object to rethrow or catch
// It is also used for continuation restart in which case
@@ -510,7 +433,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
// reestablish this call frame
enterFrame(cx, frame, ScriptRuntime.EMPTY_OBJECTS, true);
throwable = null;
- } else if (!(throwable instanceof ContinuationJump)) {
+ } else {
// It should be continuation
Kit.codeBug();
}
@@ -1033,30 +956,7 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
continue StateLoop;
}
- if (fun instanceof NativeContinuation) {
- // Jump to the captured continuation
- ContinuationJump cjump;
- cjump = new ContinuationJump((NativeContinuation) fun, frame);
-
- // continuation result is the first argument if any
- // of continuation call
- if (indexReg == 0) {
- cjump.result = undefined;
- } else {
- cjump.result = stack[stackTop + 2];
- cjump.resultDbl = sDbl[stackTop + 2];
- }
-
- // Start the real unwind job
- throwable = cjump;
- break withoutExceptions;
- }
-
if (fun instanceof IdFunctionObject ifun) {
- if (NativeContinuation.isContinuationConstructor(ifun)) {
- frame.stack[stackTop] = captureContinuation(cx, frame.parentFrame, false);
- continue;
- }
// Bug 405654 -- make best effort to keep Function.apply and
// Function.call within this interpreter loop invocation
if (BaseFunction.isApplyOrCall(ifun)) {
@@ -1113,13 +1013,6 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
throw ScriptRuntime.notFunctionError(cx, lhs);
}
- if (fun instanceof IdFunctionObject ifun) {
- if (NativeContinuation.isContinuationConstructor(ifun)) {
- frame.stack[stackTop] = captureContinuation(cx, frame.parentFrame, false);
- continue;
- }
- }
-
Object[] outArgs = getArgsArray(stack, sDbl, stackTop + 1, indexReg);
stack[stackTop] = fun.construct(cx, frame.scope, outArgs);
continue;
@@ -1500,7 +1393,6 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
final int EX_NO_JS_STATE = 0; // Terminate JS execution
int exState;
- ContinuationJump cjump = null;
if (generatorState != null && generatorState.operation == GeneratorState.GENERATOR_CLOSE && throwable == generatorState.value) {
exState = EX_FINALLY_STATE;
@@ -1511,16 +1403,10 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
exState = EX_CATCH_STATE;
} else if (throwable instanceof EvaluatorException) {
exState = EX_CATCH_STATE;
- } else if (throwable instanceof ContinuationPending) {
- exState = EX_NO_JS_STATE;
} else if (throwable instanceof RuntimeException) {
exState = EX_FINALLY_STATE;
} else if (throwable instanceof Error) {
exState = EX_NO_JS_STATE;
- } else if (throwable instanceof ContinuationJump) {
- // It must be ContinuationJump
- exState = EX_FINALLY_STATE;
- cjump = (ContinuationJump) throwable;
} else {
exState = EX_FINALLY_STATE;
}
@@ -1535,7 +1421,6 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
// Error from instruction counting
// => unconditionally terminate JS
throwable = ex;
- cjump = null;
exState = EX_NO_JS_STATE;
}
}
@@ -1560,30 +1445,8 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
if (frame == null) {
break;
}
- if (cjump != null && cjump.branchFrame == frame) {
- // Continuation branch point was hit,
- // restart the state loop to reenter continuation
- indexReg = -1;
- continue StateLoop;
- }
}
- // No more frames, rethrow the exception or deal with continuation
- if (cjump != null) {
- if (cjump.branchFrame != null) {
- // The above loop should locate the top frame
- Kit.codeBug();
- }
- if (cjump.capturedFrame != null) {
- // Restarting detached continuation
- indexReg = -1;
- continue;
- }
- // Return continuation result to the caller
- interpreterResult = cjump.result;
- interpreterResultDbl = cjump.resultDbl;
- throwable = null;
- }
break;
} // end of StateLoop: for(;;)
@@ -1997,68 +1860,6 @@ private static CallFrame processThrowable(Context cx, Object throwable, CallFram
frame.stack[exLocal] = throwable;
throwable = null;
- } else {
- // Continuation restoration
- ContinuationJump cjump = (ContinuationJump) throwable;
-
- // Clear throwable to indicate that exceptions are OK
- throwable = null;
-
- if (cjump.branchFrame != frame) {
- Kit.codeBug();
- }
-
- // Check that we have at least one frozen frame
- // in the case of detached continuation restoration:
- // unwind code ensure that
- if (cjump.capturedFrame == null) {
- Kit.codeBug();
- }
-
- // Need to rewind branchFrame, capturedFrame
- // and all frames in between
- int rewindCount = cjump.capturedFrame.frameIndex + 1;
- if (cjump.branchFrame != null) {
- rewindCount -= cjump.branchFrame.frameIndex;
- }
-
- int enterCount = 0;
- CallFrame[] enterFrames = null;
-
- CallFrame x = cjump.capturedFrame;
- for (int i = 0; i != rewindCount; ++i) {
- if (!x.frozen) {
- Kit.codeBug();
- }
- if (x.useActivation) {
- if (enterFrames == null) {
- // Allocate enough space to store the rest
- // of rewind frames in case all of them
- // would require to enter
- enterFrames = new CallFrame[rewindCount - i];
- }
- enterFrames[enterCount] = x;
- ++enterCount;
- }
- x = x.parentFrame;
- }
-
- while (enterCount != 0) {
- // execute enter: walk enterFrames in the reverse
- // order since they were stored starting from
- // the capturedFrame, not branchFrame
- --enterCount;
- x = enterFrames[enterCount];
- enterFrame(cx, x, ScriptRuntime.EMPTY_OBJECTS, true);
- }
-
- // Continuation jump is almost done: capturedFrame
- // points to the call to the function that captured
- // continuation, so clone capturedFrame and
- // emulate return that function with the suplied result
- frame = cjump.capturedFrame.cloneFrozen();
- setCallResult(frame, cjump.result, cjump.resultDbl);
- // restart the execution
}
frame.throwable = throwable;
return frame;
@@ -2214,57 +2015,6 @@ private static void setCallResult(CallFrame frame, Object callResult, double cal
frame.savedCallOp = 0;
}
- public static NativeContinuation captureContinuation(Context cx) {
- if (cx.lastInterpreterFrame == null || !(cx.lastInterpreterFrame instanceof CallFrame)) {
- throw new IllegalStateException("Interpreter frames not found");
- }
- return captureContinuation(cx, (CallFrame) cx.lastInterpreterFrame, true);
- }
-
- private static NativeContinuation captureContinuation(Context cx, CallFrame frame, boolean requireContinuationsTopFrame) {
- NativeContinuation c = new NativeContinuation();
- ScriptRuntime.setObjectProtoAndParent(cx, cx.getTopCallOrThrow(), c);
-
- // Make sure that all frames are frozen
- CallFrame x = frame;
- CallFrame outermost = frame;
- while (x != null && !x.frozen) {
- x.frozen = true;
- // Allow to GC unused stack space
- for (int i = x.savedStackTop + 1; i != x.stack.length; ++i) {
- // Allow to GC unused stack space
- x.stack[i] = null;
- x.stackAttributes[i] = ScriptableObject.EMPTY;
- }
- if (x.savedCallOp == Token.CALL) {
- // the call will always overwrite the stack top with the result
- x.stack[x.savedStackTop] = null;
- } else {
- if (x.savedCallOp != Token.NEW) {
- Kit.codeBug();
- }
- // the new operator uses stack top to store the constructed
- // object so it shall not be cleared: see comments in
- // setCallResult
- }
- outermost = x;
- x = x.parentFrame;
- }
-
- if (requireContinuationsTopFrame) {
- while (outermost.parentFrame != null) {
- outermost = outermost.parentFrame;
- }
-
- if (!outermost.isContinuationsTopFrame) {
- throw new IllegalStateException("Cannot capture continuation " + "from JavaScript code not called directly by " + "executeScriptWithContinuations or " + "callFunctionWithContinuations");
- }
- }
-
- c.initImplementation(frame);
- return c;
- }
-
private static int stack_int32(CallFrame frame, int i, Context cx) {
Object x = frame.stack[i];
if (x == UniqueTag.DOUBLE_MARK) {
diff --git a/common/src/main/java/dev/latvian/mods/rhino/JavaMembers.java b/common/src/main/java/dev/latvian/mods/rhino/JavaMembers.java
index c4cd2a8e..062fdd8e 100644
--- a/common/src/main/java/dev/latvian/mods/rhino/JavaMembers.java
+++ b/common/src/main/java/dev/latvian/mods/rhino/JavaMembers.java
@@ -341,7 +341,7 @@ public void put(Scriptable scope, String name, Object javaObject, Object value,
}
} else {
Object[] args = {value};
- bp.setters.call(cx, ScriptableObject.getTopLevelScope(scope), scope, args);
+ cx.callSync(bp.setters, ScriptableObject.getTopLevelScope(scope), scope, args);
}
} else {
if (!(member instanceof Field field)) {
diff --git a/common/src/main/java/dev/latvian/mods/rhino/LazilyLoadedCtor.java b/common/src/main/java/dev/latvian/mods/rhino/LazilyLoadedCtor.java
deleted file mode 100644
index 1767419f..00000000
--- a/common/src/main/java/dev/latvian/mods/rhino/LazilyLoadedCtor.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package dev.latvian.mods.rhino;
-
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * Avoid loading classes unless they are used.
- *
- *
This improves startup time and average memory usage. - */ -public final class LazilyLoadedCtor { - private static final int STATE_BEFORE_INIT = 0; - private static final int STATE_INITIALIZING = 1; - private static final int STATE_WITH_VALUE = 2; - - @SuppressWarnings({"unchecked"}) - private static Class extends Scriptable> cast(Class> cl) { - return (Class extends Scriptable>) cl; - } - - private final ScriptableObject scope; - private final String propertyName; - private final String className; - private final boolean sealed; - private final boolean privileged; - private Object initializedValue; - private int state; - - public LazilyLoadedCtor(ScriptableObject scope, String propertyName, String className, boolean sealed, Context cx) { - this(scope, propertyName, className, sealed, false, cx); - } - - LazilyLoadedCtor(ScriptableObject scope, String propertyName, String className, boolean sealed, boolean privileged, Context cx) { - - this.scope = scope; - this.propertyName = propertyName; - this.className = className; - this.sealed = sealed; - this.privileged = privileged; - this.state = STATE_BEFORE_INIT; - - scope.addLazilyInitializedValue(cx, propertyName, 0, this, ScriptableObject.DONTENUM); - } - - void init(Context cx) { - synchronized (this) { - if (state == STATE_INITIALIZING) { - throw new IllegalStateException("Recursive initialization for " + propertyName); - } - if (state == STATE_BEFORE_INIT) { - state = STATE_INITIALIZING; - // Set value now to have something to set in finally block if - // buildValue throws. - Object value = Scriptable.NOT_FOUND; - try { - value = buildValue(cx); - } finally { - initializedValue = value; - state = STATE_WITH_VALUE; - } - } - } - } - - Object getValue() { - if (state != STATE_WITH_VALUE) { - throw new IllegalStateException(propertyName); - } - return initializedValue; - } - - private Object buildValue(Context cx) { - //if (privileged) { - // return AccessController.doPrivileged((PrivilegedAction