summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-12-10 23:38:24 +0100
committerFlorian Dold <florian.dold@gmail.com>2019-12-10 23:38:24 +0100
commit91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967 (patch)
tree4c5ee6423518ada341dffebc96d94febfa0b9206
parentcb3eb410fbf79cb2bb9ddb969b771259ea9acf6e (diff)
downloadakono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.tar.gz
akono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.tar.bz2
akono-91fbb65ed4e5dc843eb5b1c5d1bcb44a2f256967.zip
module loading
-rw-r--r--.gitmodules2
-rw-r--r--.idea/dictionaries/dold.xml1
-rw-r--r--akono/akono-akono.iml2
-rw-r--r--akono/build.gradle.kts5
-rw-r--r--akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt35
-rw-r--r--akono/src/main/cpp/akono-jni.cpp85
-rw-r--r--akono/src/main/java/akono/AkonoJni.kt20
m---------deps/android-node-v80
8 files changed, 93 insertions, 57 deletions
diff --git a/.gitmodules b/.gitmodules
index c99a6ae7..56f61a59 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
[submodule "deps/android-node-v8"]
path = deps/android-node-v8
url = https://git.taler.net/android-node-v8.git
- branch = androidbuild
+ branch = master
diff --git a/.idea/dictionaries/dold.xml b/.idea/dictionaries/dold.xml
index f383697a..4229f6a5 100644
--- a/.idea/dictionaries/dold.xml
+++ b/.idea/dictionaries/dold.xml
@@ -2,6 +2,7 @@
<dictionary name="dold">
<words>
<w>akono</w>
+ <w>taler</w>
</words>
</dictionary>
</component> \ No newline at end of file
diff --git a/akono/akono-akono.iml b/akono/akono-akono.iml
index 7719671c..80bdb714 100644
--- a/akono/akono-akono.iml
+++ b/akono/akono-akono.iml
@@ -25,7 +25,7 @@
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
- <option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="" />
+ <option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug;file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
diff --git a/akono/build.gradle.kts b/akono/build.gradle.kts
index d5362832..3fb5e31b 100644
--- a/akono/build.gradle.kts
+++ b/akono/build.gradle.kts
@@ -21,7 +21,10 @@ android {
ndk {
// Tells Gradle to build outputs for the following ABIs and package
// them into your APK.
- abiFilters("armeabi-v7a");
+ abiFilters("armeabi-v7a")
+ abiFilters("arm64-v8a")
+ abiFilters("x86")
+ abiFilters("x86_64")
}
externalNativeBuild {
diff --git a/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt b/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt
index beda5119..26fb2012 100644
--- a/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt
+++ b/akono/src/androidTest/java/akono/InstrumentedAkonoTests.kt
@@ -22,24 +22,6 @@ class SyncMessageHandler : AkonoJni.MessageHandler {
}
}
-
-class StaticModuleLoadHandler : AkonoJni.LoadModuleHandler {
- private val modules: MutableMap<String, String> = HashMap()
-
- override fun loadModule(name: String, paths: Array<String>): ModuleResult? {
- val code = modules.get(name) ?: return null
- if (modules.containsKey(name)) {
- return ModuleResult("/vmodroot/$name.js", code)
- }
- return null
- }
-
- fun registerModule(name: String, source: String) {
- modules[name] = source
- }
-}
-
-
// @RunWith is required only if you use a mix of JUnit3 and JUnit4.
@RunWith(AndroidJUnit4::class)
@LargeTest
@@ -47,6 +29,7 @@ public class InstrumentedAkonoTestOne {
@Test
fun myJsTest() {
val ajni: AkonoJni = AkonoJni()
+ ajni.putModuleCode("a", "function foo() {}")
assertEquals("2", ajni.evalSimpleJs("1+1"))
assertEquals("36", ajni.evalSimpleJs("6*6"))
assertEquals("42", ajni.evalSimpleJs("(()=>{let x = 42; return x;})()"))
@@ -64,21 +47,13 @@ public class InstrumentedAkonoTestOne {
assertEquals(sentMessage, receivedMessage)
Log.i("myapp", "test case received message: $receivedMessage")
- val myModHandler = StaticModuleLoadHandler()
-
- ajni.setLoadModuleHandler(myModHandler)
-
- myModHandler.registerModule("a", """
- |console.log('I am module a');
- |exports.foo = () => { global.__akono_sendMessage('hello42'); };
- """.trimMargin())
-
+ ajni.evalNodeCode("require('akono');")
ajni.evalNodeCode("a = require('a');")
- ajni.evalNodeCode("a.foo()")
+ //ajni.evalNodeCode("a.foo()")
- val msg2 = myHandler.waitForMessage()
+ //val msg2 = myHandler.waitForMessage()
- assertEquals("hello42", msg2)
+ //assertEquals("hello42", msg2)
ajni.waitStopped()
}
diff --git a/akono/src/main/cpp/akono-jni.cpp b/akono/src/main/cpp/akono-jni.cpp
index 1d0f7512..0fd05a7e 100644
--- a/akono/src/main/cpp/akono-jni.cpp
+++ b/akono/src/main/cpp/akono-jni.cpp
@@ -1,9 +1,27 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
#include <sys/types.h>
#include <sys/syscall.h>
#include <cstring>
+#include <map>
#include <jni.h>
#include <libplatform/libplatform.h>
#include <v8.h>
+#include <android/asset_manager.h>
#define NODE_WANT_INTERNALS 1 // NOLINT(cppcoreguidelines-macro-usage)
@@ -16,6 +34,9 @@
#include <node_binding.h>
#include <node_native_module_env.h>
+
+void _register_akono();
+
// Provide stubs so that libnode.so links properly
namespace node {
namespace native_module {
@@ -33,10 +54,15 @@ namespace node {
}
}
+/**
+ * Mapping from module name to a string with the module's code.
+ */
+std::map<std::string, char *> modmap;
+
static int pfd[2];
static pthread_t thr;
-static const char *tag = "myapp";
+static const char *tag = "akono-jni.cpp";
static void *thread_func(void *) {
@@ -54,9 +80,7 @@ static void mylog(const char *msg) {
__android_log_write(ANDROID_LOG_DEBUG, tag, msg);
}
-int start_logger(const char *app_name) {
- tag = app_name;
-
+int start_logger() {
/* make stdout line-buffered and stderr unbuffered */
setvbuf(stdout, 0, _IOLBF, 0);
setvbuf(stderr, 0, _IONBF, 0);
@@ -139,12 +163,13 @@ public:
jobject currentJniThiz = nullptr;
NativeAkonoInstance() : globalContext() {
+ _register_akono();
loop = uv_default_loop();
uv_async_init(loop, &async_notify, notifyCb);
async_notify.data = this;
if (!logInitialized) {
- start_logger("myapp");
+ start_logger();
logInitialized = true;
}
@@ -165,7 +190,6 @@ public:
node::ArrayBufferAllocator *allocator = node::CreateArrayBufferAllocator();
this->isolate = node::NewIsolate(allocator, uv_default_loop());
-
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
@@ -208,9 +232,9 @@ public:
v8::Local<v8::Object> global = context->Global();
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_sendMessage",
+ global->Set(context, v8::String::NewFromUtf8(isolate, "__akono_sendMessage",
v8::NewStringType::kNormal).ToLocalChecked(),
- sendMessageFunction);
+ sendMessageFunction).Check();
}
@@ -220,7 +244,7 @@ public:
* @param env JNI env of the thread we're running in.
*/
void runNode() {
- //printf("running node loop, tid=%llu\n", (unsigned long long) syscall(__NR_gettid));
+ //printf("blup running node loop, tid=%llu\n", (unsigned long long) syscall(__NR_gettid));
v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
@@ -260,6 +284,7 @@ public:
jstring evalJs(JNIEnv *env, jstring sourceString) {
JStringValue jsv(env, sourceString);
+ v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
@@ -314,8 +339,9 @@ void notifyCb(uv_async_t *async) {
}
static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
v8::Isolate *isolate = args.GetIsolate();
+ v8::Locker locker(isolate);
+ if (args.Length() < 1) return;
v8::HandleScope scope(isolate);
v8::Local<v8::Value> arg = args[0];
v8::String::Utf8Value value(isolate, arg);
@@ -351,6 +377,34 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args)
env->CallVoidMethod(myInstance->currentJniThiz, meth, jstr1, jstr2);
}
+static void dummy(const v8::FunctionCallbackInfo<v8::Value> &args) {
+
+}
+
+static void getModuleCode(const v8::FunctionCallbackInfo<v8::Value> &args) {
+ if (args.Length() < 1) return;
+ v8::Isolate *isolate = args.GetIsolate();
+ v8::Locker locker(isolate);
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::Value> arg = args[0];
+ v8::String::Utf8Value value(isolate, arg);
+
+ printf("handling request for module %s\n", *value);
+
+ std::string modName(*value);
+
+ char *code = modmap[modName];
+
+ if (!code) {
+ printf("module not found in modmap %s\n", *value);
+ return;
+ }
+ printf("found module in modmap %s\n", *value);
+ args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, code,
+ v8::NewStringType::kNormal).ToLocalChecked());
+
+}
+
extern "C" JNIEXPORT jobject JNICALL
Java_akono_AkonoJni_initNative(JNIEnv *env, jobject thiz) {
NativeAkonoInstance *myInstance = new NativeAkonoInstance();
@@ -372,6 +426,16 @@ Java_akono_AkonoJni_evalJs(JNIEnv *env, jobject thiz, jstring sourceStr, jobject
}
extern "C" JNIEXPORT void JNICALL
+Java_akono_AkonoJni_putModuleCodeNative(JNIEnv *env, jobject thiz, jstring modName, jstring modCode) {
+ mylog("in putModuleCodeNative");
+ JStringValue cModName(env, modName);
+ JStringValue cModCode(env, modCode);
+ std::string cppModName(strdup(*cModName));
+ modmap[cppModName] = strdup(*cModCode);
+ mylog("registered module");
+}
+
+extern "C" JNIEXPORT void JNICALL
Java_akono_AkonoJni_notifyNative(JNIEnv *env, jobject thiz, jobject buf) {
NativeAkonoInstance *myInstance = (NativeAkonoInstance *) env->GetDirectBufferAddress(buf);
uv_async_send(&myInstance->async_notify);
@@ -398,6 +462,7 @@ void InitializeAkono(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
+ NODE_SET_METHOD(target, "getModuleCode", getModuleCode);
}
NODE_MODULE_CONTEXT_AWARE_INTERNAL(akono, InitializeAkono)
diff --git a/akono/src/main/java/akono/AkonoJni.kt b/akono/src/main/java/akono/AkonoJni.kt
index 6aecb3af..e5a10547 100644
--- a/akono/src/main/java/akono/AkonoJni.kt
+++ b/akono/src/main/java/akono/AkonoJni.kt
@@ -11,8 +11,6 @@ import kotlin.concurrent.thread
typealias AkonoNativePointer = ByteBuffer
-data class ModuleResult(val path: String, val contents: String)
-
private val TAG = "AkonoJni"
class AkonoJni(vararg nodeArgv: String) {
@@ -25,6 +23,7 @@ class AkonoJni(vararg nodeArgv: String) {
private external fun runNode(p: AkonoNativePointer)
private external fun makeCallbackNative(source: String, p: AkonoNativePointer)
+ private external fun putModuleCodeNative(key: String, source: String)
private external fun destroyNative(b: AkonoNativePointer)
private external fun initNative(nodeArgv: Array<out String>): AkonoNativePointer
@@ -95,9 +94,6 @@ class AkonoJni(vararg nodeArgv: String) {
evalNodeCode(source)
}
- /**
- *
- */
fun waitStopped(): Unit {
Log.i(TAG, "waiting for stop")
scheduleNodeThread {
@@ -107,6 +103,11 @@ class AkonoJni(vararg nodeArgv: String) {
return
}
+ fun putModuleCode(modName: String, code: String) {
+ Log.v(TAG, "putting module code (kotlin)")
+ putModuleCodeNative(modName, code)
+ }
+
/**
* Register a message handler that is called when the JavaScript code
* running in [runNodeJs] calls __akono_sendMessage
@@ -141,7 +142,6 @@ class AkonoJni(vararg nodeArgv: String) {
}
companion object {
-
init {
System.loadLibrary("akono-jni")
}
@@ -150,12 +150,4 @@ class AkonoJni(vararg nodeArgv: String) {
interface MessageHandler {
fun handleMessage(message: String)
}
-
- interface LoadModuleHandler {
- fun loadModule(name: String, paths: Array<String>): ModuleResult?
- }
-
- interface GetDataHandler {
- fun handleGetData(what: String): ByteArray?
- }
}
diff --git a/deps/android-node-v8 b/deps/android-node-v8
-Subproject 7c040c7d01621f0f704fd88481e8dd455247f04
+Subproject d0e8ef2e22f0f8126760019d104b8858daf7cfa