[WIP] Switch to GraalJS Engine (#793)

* Switch to GraalJS Engine

* Update Polygot
This commit is contained in:
Mitchell Syer
2024-11-17 15:24:08 -05:00
committed by GitHub
parent 9a7344ccbe
commit 746f9f1a11
3 changed files with 67 additions and 38 deletions

View File

@@ -36,8 +36,8 @@ dependencies {
// AndroidX annotations
compileOnly(libs.android.annotations)
// substitute for duktape-android
implementation(libs.bundles.rhino)
// substitute for duktape-android/quickjs
implementation(libs.bundles.polyglot)
// Kotlin wrapper around Java Preferences, makes certain things easier
implementation(libs.bundles.settings)

View File

@@ -1,69 +1,98 @@
package app.cash.quickjs;
import org.mozilla.javascript.ConsString;
import org.mozilla.javascript.NativeArray;
import org.graalvm.polyglot.*;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.Closeable;
import java.math.BigInteger;
import java.util.Arrays;
public final class QuickJs implements Closeable {
private ScriptEngine engine;
private Context context;
public static QuickJs create() {
return new QuickJs(new ScriptEngineManager());
return new QuickJs();
}
public QuickJs(ScriptEngineManager manager) {
this.engine = manager.getEngineByName("rhino");
public QuickJs() {
this.context = Context
.newBuilder("js")
.allowHostAccess(HostAccess.ALL)
.allowPolyglotAccess(PolyglotAccess.NONE)
.allowHostClassLoading(false)
.build();
context.enter();
}
public Object evaluate(String script, String fileName) {
public Object evaluate(String script, String ignoredFileName) {
return this.evaluate(script);
}
public Object evaluate(String script) {
try {
Object value = engine.eval(script);
Value value = context.eval("js", script);
return translateType(value);
} catch (Exception exception) {
throw new QuickJsException(exception.getMessage(), exception);
}
}
private Object translateType(Object obj) {
if (obj instanceof NativeArray) {
NativeArray array = (NativeArray) obj;
long length = array.getLength();
Object[] objects = new Object[(int) length];
for (int i = 0; i < (int) length; i++) {
objects[i] = translateType(array.get(i));
private Object translateType(Value obj) {
if (obj.isBoolean()) {
return obj.asBoolean();
} else if (obj.hasArrayElements()) {
if (obj.getArraySize() == 0) {
return new int[0];
} else {
Value element = obj.getArrayElement(0);
if (element.isBoolean()) {
return obj.as(boolean[].class);
} else if (element.isNumber()) {
if (element.fitsInInt()) {
return obj.as(int[].class);
} else if (element.fitsInBigInteger()) {
return Arrays.stream(obj.as(BigInteger[].class)).map(BigInteger::longValue).toArray();
} else {
return obj.as(double[].class);
}
return objects;
} else if (element.isHostObject()) {
return obj.as(Object[].class);
} else if (element.isString()) {
return obj.as(String[].class);
}
if (obj instanceof ConsString) {
ConsString consString = (ConsString) obj;
return consString.toString();
}
if (obj instanceof Long) {
Long value = (Long) obj;
return value.intValue();
} else if (obj.isNumber()) {
if (obj.fitsInInt()) {
return obj.asInt();
} else if (obj.fitsInBigInteger()) {
return obj.asBigInteger().longValue();
} else {
return obj.asDouble();
}
} else if (obj.isHostObject()) {
return obj.asHostObject();
} else if (obj.isString()) {
return obj.asString();
}
return obj;
}
public byte[] compile(String sourceCode, String fileName) {
public byte[] compile(String sourceCode, String ignoredFileName) {
return sourceCode.getBytes();
}
public Object execute(byte[] bytecode) {
return this.evaluate(new String(bytecode));
}
public <T> void set(String name, Class<T> ignoredType, T object) {
context.getBindings("js").putMember(name, object);
}
@Override
public void close() {
this.engine = null;
this.context.leave();
this.context.close();
this.context = null;
}
}

View File

@@ -3,11 +3,11 @@ kotlin = "2.0.21"
coroutines = "1.9.0"
serialization = "1.7.3"
okhttp = "5.0.0-alpha.14" # Major version is locked by Tachiyomi extensions
javalin = "6.3.0" # Javalin 5.0.0+ requires Java 11
javalin = "6.3.0"
jackson = "2.18.1" # jackson version locked by javalin, ref: `io.javalin.core.util.OptionalDependency`
exposed = "0.40.1"
dex2jar = "v64" # Stuck until https://github.com/ThexXTURBOXx/dex2jar/issues/27 is fixed
rhino = "1.7.15"
polyglot = "24.1.1"
settings = "1.2.0"
twelvemonkeys = "3.12.0"
graphqlkotlin = "8.2.1"
@@ -116,8 +116,8 @@ bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.79"
android-annotations = "androidx.annotation:annotation:1.9.1"
# Substitute for duktape-android
rhino-runtime = { module = "org.mozilla:rhino-runtime", version.ref = "rhino" } # slimmer version of 'org.mozilla:rhino'
rhino-engine = { module = "org.mozilla:rhino-engine", version.ref = "rhino" } # provides the same interface as 'javax.script' a.k.a Nashorn
polyglot-core = { module = "org.graalvm.polyglot:polyglot", version.ref = "polyglot" }
polyglot-graaljs = { module = "org.graalvm.polyglot:js-community", version.ref = "polyglot" } # provides the same interface as 'javax.script' a.k.a Nashorn
# Settings
settings-core = { module = "com.russhwolf:multiplatform-settings-jvm", version.ref = "settings" }
@@ -219,9 +219,9 @@ systemtray = [
"systemtray-utils",
"systemtray-desktop"
]
rhino = [
"rhino-runtime",
"rhino-engine",
polyglot = [
"polyglot-core",
"polyglot-graaljs",
]
settings = [
"settings-core",