summaryrefslogtreecommitdiff
path: root/akono/src
diff options
context:
space:
mode:
Diffstat (limited to 'akono/src')
-rw-r--r--akono/src/main/cpp/akono-jni.cpp253
-rw-r--r--akono/src/main/java/akono/AkonoJni.kt58
2 files changed, 27 insertions, 284 deletions
diff --git a/akono/src/main/cpp/akono-jni.cpp b/akono/src/main/cpp/akono-jni.cpp
index 0480eea5..1d0f7512 100644
--- a/akono/src/main/cpp/akono-jni.cpp
+++ b/akono/src/main/cpp/akono-jni.cpp
@@ -1,9 +1,11 @@
-#include <string.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <cstring>
#include <jni.h>
#include <libplatform/libplatform.h>
#include <v8.h>
-#define NODE_WANT_INTERNALS 1
+#define NODE_WANT_INTERNALS 1 // NOLINT(cppcoreguidelines-macro-usage)
#include <node.h>
@@ -11,10 +13,9 @@
#include <unistd.h>
#include <android/log.h>
#include <node_main_instance.h>
+#include <node_binding.h>
#include <node_native_module_env.h>
-
-
// Provide stubs so that libnode.so links properly
namespace node {
namespace native_module {
@@ -40,7 +41,7 @@ static const char *tag = "myapp";
static void *thread_func(void *) {
ssize_t rdsz;
- char buf[128];
+ char buf[1024];
while ((rdsz = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if (buf[rdsz - 1] == '\n') --rdsz;
buf[rdsz] = 0; /* add null-terminator */
@@ -83,7 +84,7 @@ private:
JNIEnv *m_env;
public:
JStringValue(JNIEnv *env, jstring s) : m_env(env), m_jstr(s) {
- m_cstr = env->GetStringUTFChars(s, NULL);
+ m_cstr = env->GetStringUTFChars(s, nullptr);
}
~JStringValue() {
@@ -111,82 +112,21 @@ static void InitNode(std::vector<const char *> argv) {
void notifyCb(uv_async_t *async);
static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
-static void loadModuleCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
-static void getDataCallback(const v8::FunctionCallbackInfo<v8::Value> &args);
static const char *main_code = "global.__akono_run = (x) => {"
- " console.log('running code', x);"
+ " 0 && console.log('running code', x);"
" global.eval(x);"
"};"
""
"global.__akono_onMessage = (x) => {"
- " console.log('got __akono_onMessage', x);"
- "};"
- ""
- "mod = require('module');"
- "mod._saved_findPath = mod._findPath;"
- "mod._akonoMods = {};"
- "mod._findPath = (request, paths, isMain) => {"
- " console.log('in _findPath');"
- " const res = mod._saved_findPath(request, paths, isMain);"
- " if (res !== false) return res;"
- " const args = JSON.stringify({ request, paths});"
- " const loadResult = JSON.parse(global.__akono_loadModule(args));"
- " console.log('got loadModule result');"
- " if (!loadResult) return false;"
- " console.log('loadModule path is', loadResult.path);"
- " mod._akonoMods[loadResult.path] = loadResult;"
- " console.log('returning path', loadResult.path);"
- " return loadResult.path;"
- "};"
- ""
- "function stripBOM(content) {"
- " if (content.charCodeAt(0) === 0xFEFF) {"
- " content = content.slice(1);"
- " }"
- " return content;"
- "}"
- ""
- "mod._saved_js_extension = mod._extensions[\".js\"];"
- "mod._extensions[\".js\"] = (module, filename) => {"
- " console.log('handling js extension', [module, filename]);"
- " if (mod._akonoMods.hasOwnProperty(filename)) {"
- " const akmod = mod._akonoMods[filename];"
- " console.log('found mod');"
- " const content = akmod.content;"
- " module._compile(stripBOM(content), filename);"
- " return;"
- " }"
- " console.log('falling back');"
- " return mod._saved_js_extension(module, filename);"
- "};"
- ""
- "mod._saved_json_extension = mod._extensions[\".json\"];"
- "mod._extensions[\".json\"] = (module, filename) => {"
- " console.log('handling json extension', [module, filename]);"
- " if (mod._akonoMods.hasOwnProperty(filename)) {"
- " const akmod = mod._akonoMods[filename];"
- " console.log('found mod');"
- " const content = akmod.content;"
- " try {"
- " module.exports = JSON.parse(stripBOM(content));"
- " return;"
- " } catch (err) {"
- " err.message = filename + ': ' + err.message;"
- " throw err;"
- " }"
- " }"
- " console.log('falling back');"
- " return mod._saved_json_extension(module, filename);"
- "};"
- "";
+ " 0 && console.log('got __akono_onMessage', x);"
+ "};";
class NativeAkonoInstance {
private:
static bool logInitialized;
static bool v8Initialized;
- //static std::unique_ptr<v8::Platform> platform;
static node::MultiIsolatePlatform *platform;
public:
v8::Isolate *isolate;
@@ -245,12 +185,8 @@ public:
// Arguments for the script run by node
std::vector<const char *> nodeExecArgv{};
- mylog("entering global scope");
-
v8::Context::Scope context_scope(globalContext.Get(isolate));
- mylog("creating environment");
-
node::Environment *environment = node::CreateEnvironment(
isolateData,
globalContext.Get(isolate),
@@ -259,12 +195,8 @@ public:
nodeExecArgv.size(),
&nodeExecArgv[0]);
- mylog("loading environment");
-
node::LoadEnvironment(environment);
- mylog("finished loading environment");
-
v8::Local<v8::ObjectTemplate> dataTemplate = v8::ObjectTemplate::New(isolate);
dataTemplate->SetInternalFieldCount(1);
v8::Local<v8::Object> dataObject = dataTemplate->NewInstance(context).ToLocalChecked();
@@ -274,29 +206,12 @@ public:
sendMessageCallback,
dataObject).ToLocalChecked();
- v8::Local<v8::Function> loadModuleFunction = v8::Function::New(context,
- loadModuleCallback,
- dataObject).ToLocalChecked();
-
- v8::Local<v8::Function> getDataFunction = v8::Function::New(context,
- getDataCallback,
- dataObject).ToLocalChecked();
-
v8::Local<v8::Object> global = context->Global();
global->Set(v8::String::NewFromUtf8(isolate, "__akono_sendMessage",
v8::NewStringType::kNormal).ToLocalChecked(),
sendMessageFunction);
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_loadModule",
- v8::NewStringType::kNormal).ToLocalChecked(),
- loadModuleFunction);
-
- // Get data synchronously (!) from the embedder
- global->Set(v8::String::NewFromUtf8(isolate, "__akono_getData",
- v8::NewStringType::kNormal).ToLocalChecked(),
- getDataFunction);
-
}
/**
@@ -305,12 +220,14 @@ 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));
+ v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = globalContext.Get(isolate);
v8::Context::Scope context_scope(context);
this->breakRequested = false;
- while (1) {
+ while (true) {
uv_run(uv_default_loop(), UV_RUN_ONCE);
platform->DrainTasks(isolate);
if (this->breakRequested)
@@ -324,7 +241,7 @@ public:
* Must not be called from a different thread.
*/
void makeCallback(const char *code) {
- mylog("in makeCallback");
+ v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = globalContext.Get(isolate);
@@ -334,7 +251,6 @@ public:
v8::String::NewFromUtf8(isolate, code,
v8::NewStringType::kNormal).ToLocalChecked()
};
- mylog("calling node::MakeCallback");
node::MakeCallback(isolate, global, "__akono_run", 1, argv, {0, 0});
}
@@ -343,8 +259,6 @@ public:
}
jstring evalJs(JNIEnv *env, jstring sourceString) {
- mylog("begin evalJs");
-
JStringValue jsv(env, sourceString);
v8::Isolate::Scope isolate_scope(isolate);
@@ -370,28 +284,19 @@ public:
// Compile the source code.
v8::Local<v8::Script> script;
- mylog("about to compile script");
-
if (!v8::Script::Compile(context, source).ToLocal(&script)) {
return nullptr;
}
- mylog("about to run script");
-
// Run the script to get the result.
v8::Local<v8::Value> result;
if (!script->Run(context).ToLocal(&result)) {
- mylog("running script failed");
return nullptr;
}
- mylog("converting script result value");
-
// Convert the result to an UTF8 string and print it.
v8::String::Utf8Value utf8(isolate, result);
- mylog("about to return value");
-
return env->NewStringUTF(*utf8);
}
}
@@ -404,8 +309,7 @@ node::MultiIsolatePlatform *NativeAkonoInstance::platform = nullptr;
void notifyCb(uv_async_t *async) {
- NativeAkonoInstance *akono = (NativeAkonoInstance *) async->data;
- mylog("async notifyCb called!");
+ auto akono = (NativeAkonoInstance *) async->data;
akono->breakRequested = true;
}
@@ -415,11 +319,9 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args)
v8::HandleScope scope(isolate);
v8::Local<v8::Value> arg = args[0];
v8::String::Utf8Value value(isolate, arg);
- mylog("sendMessageCallback called, yay!");
v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
- mylog("getting instance");
NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
JNIEnv *env = myInstance->currentJniEnv;
@@ -429,7 +331,6 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args)
return;
}
- mylog("finding class");
jclass clazz = env->FindClass("akono/AkonoJni");
if (clazz == nullptr) {
@@ -437,12 +338,9 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args)
return;
}
- mylog("creating strings");
jstring jstr1 = env->NewStringUTF("message");
jstring jstr2 = env->NewStringUTF(*value);
- mylog("getting method");
-
jmethodID meth = env->GetMethodID(clazz, "internalOnNotify", "(Ljava/lang/String;Ljava/lang/String;)V");
if (meth == nullptr) {
@@ -450,122 +348,9 @@ static void sendMessageCallback(const v8::FunctionCallbackInfo<v8::Value> &args)
return;
}
- mylog("calling method");
-
env->CallVoidMethod(myInstance->currentJniThiz, meth, jstr1, jstr2);
}
-
-static void loadModuleCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
- v8::Isolate *isolate = args.GetIsolate();
- v8::HandleScope scope(isolate);
- v8::Local<v8::Value> arg = args[0];
- v8::String::Utf8Value value(isolate, arg);
- mylog("sendMessageCallback called, yay!");
-
- v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
-
- mylog("getting instance");
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
-
- JNIEnv *env = myInstance->currentJniEnv;
-
- if (env == nullptr) {
- mylog("FATAL: JNI env is nullptr");
- return;
- }
-
- mylog("finding class");
- jclass clazz = env->FindClass("akono/AkonoJni");
-
- if (clazz == nullptr) {
- mylog("FATAL: class not found");
- return;
- }
-
- mylog("creating strings");
- jstring jstr1 = env->NewStringUTF(*value);
-
- mylog("getting method");
-
- jmethodID meth = env->GetMethodID(clazz, "internalOnModuleLoad", "(Ljava/lang/String;)Ljava/lang/String;");
-
- if (meth == nullptr) {
- mylog("FATAL: method not found");
- return;
- }
-
- mylog("calling method");
-
- jstring jresult = (jstring) env->CallObjectMethod(myInstance->currentJniThiz, meth, jstr1);
-
- JStringValue resultStringValue(env, jresult);
-
- // Create a string containing the JavaScript source code.
- v8::Local<v8::String> rs =
- v8::String::NewFromUtf8(isolate, *resultStringValue,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-
- args.GetReturnValue().Set(rs);
-}
-
-
-static void getDataCallback(const v8::FunctionCallbackInfo<v8::Value> &args) {
- if (args.Length() < 1) return;
- v8::Isolate *isolate = args.GetIsolate();
- v8::HandleScope scope(isolate);
- v8::Local<v8::Value> arg = args[0];
- v8::String::Utf8Value value(isolate, arg);
- mylog("getDataCallback called");
-
- v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data());
- mylog("getting instance");
- NativeAkonoInstance *myInstance = (NativeAkonoInstance *) data->GetAlignedPointerFromInternalField(0);
-
- JNIEnv *env = myInstance->currentJniEnv;
- if (env == nullptr) {
- mylog("FATAL: JNI env is nullptr");
- return;
- }
-
- mylog("finding class");
- jclass clazz = env->FindClass("akono/AkonoJni");
-
- if (clazz == nullptr) {
- mylog("FATAL: class not found");
- return;
- }
-
- mylog("creating strings");
- jstring jstr1 = env->NewStringUTF(*value);
-
- mylog("getting method");
-
- jmethodID meth = env->GetMethodID(clazz, "internalOnGetData", "(Ljava/lang/String;)Ljava/lang/String;");
-
- if (meth == nullptr) {
- mylog("FATAL: method not found");
- return;
- }
-
- mylog("calling method");
-
- jstring jresult = (jstring) env->CallObjectMethod(myInstance->currentJniThiz, meth, jstr1);
-
- JStringValue resultStringValue(env, jresult);
-
- // Create a string containing the JavaScript source code.
- v8::Local<v8::String> rs =
- v8::String::NewFromUtf8(isolate, *resultStringValue,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-
- args.GetReturnValue().Set(rs);
-}
-
-
extern "C" JNIEXPORT jobject JNICALL
Java_akono_AkonoJni_initNative(JNIEnv *env, jobject thiz) {
NativeAkonoInstance *myInstance = new NativeAkonoInstance();
@@ -608,3 +393,11 @@ Java_akono_AkonoJni_makeCallbackNative(JNIEnv *env, jobject thiz, jstring source
myInstance->currentJniThiz = thiz;
return myInstance->makeCallback(*jsv);
}
+
+void InitializeAkono(v8::Local<v8::Object> target,
+ v8::Local<v8::Value> unused,
+ v8::Local<v8::Context> context,
+ void* priv) {
+}
+
+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 0ba31ee8..6aecb3af 100644
--- a/akono/src/main/java/akono/AkonoJni.kt
+++ b/akono/src/main/java/akono/AkonoJni.kt
@@ -13,10 +13,10 @@ typealias AkonoNativePointer = ByteBuffer
data class ModuleResult(val path: String, val contents: String)
+private val TAG = "AkonoJni"
+
class AkonoJni(vararg nodeArgv: String) {
- private var getDataHandler: GetDataHandler? = null
private var messageHandler: MessageHandler? = null
- private var loadModuleHandler: LoadModuleHandler? = null
private val initializedLatch = CountDownLatch(1)
private val workQueue = LinkedBlockingDeque<() -> Unit>()
@@ -53,49 +53,6 @@ class AkonoJni(vararg nodeArgv: String) {
messageHandler?.handleMessage(payload)
}
- /**
- * Called by node/v8 from its thread.
- */
- @Suppress("unused")
- private fun internalOnModuleLoad(loadInfoStr: String): String {
- try {
- val loadInfo = JSONObject(loadInfoStr)
- val request: String = loadInfo.getString("request")
- Log.i("myapp", "request is $request")
- val paths = ArrayList<String>()
- val pathsJson = loadInfo.getJSONArray("paths")
- for (i in 0 until pathsJson.length()) {
- val path = pathsJson.getString(i)
- if (path.startsWith("/vmodroot/")) {
- paths.add(path)
- }
- }
- paths.add("/vmodroot")
- val handler = loadModuleHandler
- if (handler != null) {
- val modResult = handler.loadModule(request, paths.toTypedArray()) ?: return "null"
- val result = JSONObject()
- result.put("path", modResult.path)
- result.put("content", modResult.contents)
- return result.toString()
- } else {
- Log.w("myapp", "no module load handler registered")
- return "null"
- }
- } catch (e: Exception) {
- Log.e("myapp", "exception during internalOnModuleLoad: $e")
- return "null"
- }
- }
-
- /**
- * Called by node/v8 from its thread.
- */
- @Suppress("unused")
- private fun internalOnGetData(what: String): String? {
- val data = getDataHandler?.handleGetData(what) ?: return null
- return Base64.encodeToString(data, Base64.NO_WRAP)
- }
fun notifyNative() {
initializedLatch.await()
@@ -142,7 +99,7 @@ class AkonoJni(vararg nodeArgv: String) {
*
*/
fun waitStopped(): Unit {
- Log.i("myapp", "waiting for stop")
+ Log.i(TAG, "waiting for stop")
scheduleNodeThread {
stopped = true
}
@@ -160,13 +117,6 @@ class AkonoJni(vararg nodeArgv: String) {
this.messageHandler = handler
}
- fun setLoadModuleHandler(handler: LoadModuleHandler) {
- this.loadModuleHandler = handler
- }
-
- fun setGetDataHandler(handler: GetDataHandler) {
- this.getDataHandler = handler
- }
@Override
protected fun finalize() {
@@ -208,4 +158,4 @@ class AkonoJni(vararg nodeArgv: String) {
interface GetDataHandler {
fun handleGetData(what: String): ByteArray?
}
-} \ No newline at end of file
+}