diff --git a/Android/doric/build.gradle b/Android/doric/build.gradle index ab23ab0a..06e6b084 100644 --- a/Android/doric/build.gradle +++ b/Android/doric/build.gradle @@ -47,11 +47,13 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' + api 'com.github.pengfeizhou:jsc4a:0.1.0' + implementation 'com.squareup.okhttp3:okhttp:4.2.1' + implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.0.1' + api 'org.nanohttpd:nanohttpd:2.3.1' + implementation 'com.google.code.gson:gson:2.8.6' + testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - api 'com.github.pengfeizhou:jsc4a:0.1.0' - implementation "com.squareup.okhttp3:okhttp:3.11.0" - implementation 'com.github.penfeizhou.android.animation:glide-plugin:1.0.1' - api 'org.nanohttpd:nanohttpd:2.3.1' } diff --git a/Android/doric/src/main/java/pub/doric/engine/DoricJSEngine.java b/Android/doric/src/main/java/pub/doric/engine/DoricJSEngine.java index acc11349..20acbb84 100644 --- a/Android/doric/src/main/java/pub/doric/engine/DoricJSEngine.java +++ b/Android/doric/src/main/java/pub/doric/engine/DoricJSEngine.java @@ -67,7 +67,8 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time private void initJSExecutor() { - mDoricJSE = new DoricNativeJSExecutor(); +// mDoricJSE = new DoricNativeJSExecutor(); + mDoricJSE = new DoricRemoteJSExecutor(); mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_LOG, new JavaFunction() { @Override public JavaValue exec(JSDecoder[] args) { diff --git a/Android/doric/src/main/java/pub/doric/engine/DoricRemoteJSExecutor.java b/Android/doric/src/main/java/pub/doric/engine/DoricRemoteJSExecutor.java index 9705fefe..65af51be 100644 --- a/Android/doric/src/main/java/pub/doric/engine/DoricRemoteJSExecutor.java +++ b/Android/doric/src/main/java/pub/doric/engine/DoricRemoteJSExecutor.java @@ -20,35 +20,43 @@ import com.github.pengfeizhou.jscore.JSRuntimeException; import com.github.pengfeizhou.jscore.JavaFunction; import com.github.pengfeizhou.jscore.JavaValue; +import pub.doric.engine.remote.RemoteJSExecutor; + public class DoricRemoteJSExecutor implements IDoricJSE { + private final RemoteJSExecutor mRemoteJSExecutor; + + public DoricRemoteJSExecutor() { + this.mRemoteJSExecutor = new RemoteJSExecutor(); + } + @Override public String loadJS(String script, String source) throws JSRuntimeException { - return null; + return mRemoteJSExecutor.loadJS(script, source); } @Override public JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException { - return null; + return mRemoteJSExecutor.evaluateJS(script, source, hashKey); } @Override public void injectGlobalJSFunction(String name, JavaFunction javaFunction) { - + mRemoteJSExecutor.injectGlobalJSFunction(name, javaFunction); } @Override public void injectGlobalJSObject(String name, JavaValue javaValue) { - + mRemoteJSExecutor.injectGlobalJSObject(name, javaValue); } @Override public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException { - return null; + return mRemoteJSExecutor.invokeMethod(objectName, functionName, javaValues, hashKey); } @Override public void teardown() { - + mRemoteJSExecutor.destroy(); } } diff --git a/Android/doric/src/main/java/pub/doric/engine/remote/RemoteJSExecutor.java b/Android/doric/src/main/java/pub/doric/engine/remote/RemoteJSExecutor.java new file mode 100644 index 00000000..c625ff1f --- /dev/null +++ b/Android/doric/src/main/java/pub/doric/engine/remote/RemoteJSExecutor.java @@ -0,0 +1,100 @@ +package pub.doric.engine.remote; + +import com.github.pengfeizhou.jscore.JSDecoder; +import com.github.pengfeizhou.jscore.JavaFunction; +import com.github.pengfeizhou.jscore.JavaValue; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import org.jetbrains.annotations.NotNull; + +import java.io.EOFException; +import java.net.ConnectException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.WebSocket; +import okhttp3.WebSocketListener; + +public class RemoteJSExecutor { + + private final WebSocket webSocket; + private final Gson gson = new Gson(); + + public RemoteJSExecutor() { + OkHttpClient okHttpClient = new OkHttpClient + .Builder() + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build(); + Request request = new Request.Builder().url("ws://192.168.24.166:2080").build(); + + final Thread current = Thread.currentThread(); + webSocket = okHttpClient.newWebSocket(request, new WebSocketListener() { + @Override + public void onOpen(WebSocket webSocket, Response response) { + LockSupport.unpark(current); + } + + @Override + public void onFailure(WebSocket webSocket, Throwable t, Response response) { + if (t instanceof ConnectException) { + // 连接remote异常 + LockSupport.unpark(current); + throw new RuntimeException("remote js executor cannot connect"); + } else if (t instanceof EOFException) { + // 被远端强制断开 + throw new RuntimeException("remote js executor eof"); + } + } + + @Override + public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { + JsonElement je = gson.fromJson(text, JsonElement.class); + System.out.println(je); + + LockSupport.unpark(current); + } + }); + LockSupport.park(current); + } + + public String loadJS(String script, String source) { + JsonObject jo = new JsonObject(); + jo.addProperty("cmd", "loadJS"); + jo.addProperty("script", script); + jo.addProperty("source", source); + webSocket.send(gson.toJson(jo)); + + LockSupport.park(Thread.currentThread()); + return null; + } + + public JSDecoder evaluateJS(String script, String source, boolean hashKey) { + JsonObject jo = new JsonObject(); + jo.addProperty("cmd", "evaluateJS"); + jo.addProperty("script", script); + jo.addProperty("source", source); + jo.addProperty("hashKey", hashKey); + webSocket.send(gson.toJson(jo)); + return null; + } + + public void injectGlobalJSFunction(String name, JavaFunction javaFunction) { + } + + public void injectGlobalJSObject(String name, JavaValue javaValue) { + } + + public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) { + return null; + } + + public void destroy() { + webSocket.close(0, "destroy"); + } +} diff --git a/remote/.gitignore b/remote/.gitignore new file mode 100644 index 00000000..40b878db --- /dev/null +++ b/remote/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/remote/index.js b/remote/index.js new file mode 100644 index 00000000..78d2ee68 --- /dev/null +++ b/remote/index.js @@ -0,0 +1,20 @@ +const WebSocket = require('ws') +const vm = require("vm") + +const wss = new WebSocket.Server({ port: 2080 }) +var sandbox = {} +var context = vm.createContext(sandbox) + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + let messageObject = JSON.parse(message) + switch(messageObject.cmd) { + case "loadJS": + let result = vm.runInContext(messageObject.script, sandbox) + ws.send(JSON.stringify({cmd: 'loadJS', result: String(result)})) + break + case "evaluateJS": + break + } + }) +}) \ No newline at end of file diff --git a/remote/package-lock.json b/remote/package-lock.json new file mode 100644 index 00000000..a0da7af1 --- /dev/null +++ b/remote/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "remote", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + } + } +} diff --git a/remote/package.json b/remote/package.json new file mode 100644 index 00000000..be9c1efa --- /dev/null +++ b/remote/package.json @@ -0,0 +1,10 @@ +{ + "name": "remote", + "version": "0.1.0", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "ws": "^7.2.0" + } +}