nodejs-mobile / nodejs-mobile

Full-fledged Node.js on Android and iOS
https://nodejs-mobile.github.io
Other
458 stars 44 forks source link

Can't catch `node::Start` crashes on Android #110

Open jsamol opened 1 month ago

jsamol commented 1 month ago

Version

v18.17.2

Platform

Android 13

Subsystem

No response

What steps will reproduce the bug?

I've been writing a simple feature that will allow me to execute arbitrary JavaScript code with node.js on Android. To achieve this, I've been using the nodejs-mobile-react-native code base as a reference:

// node.cpp

extern "C" JNIEXPORT jint JNICALL
Java_com_example_myapp_startNodeWithArguments(
        JNIEnv *env,
        jobject /* this */,
        jobjectArray arguments,
        jstring modules_path) {

    // ...

    int node_result = node::Start(argc, argv);

    return jint(node_result);
}
// Node.kt

class Node {
    fun startNodeWithScript(script: String) {
        try {
              val result = startNodeWithArguments(arrayOf("node", "--eval", script), /* ... */)
              // check result
          } catch (e: Throwable) {
              e.printStackTrace()
          }
    }
    private external fun startNodeWithArguments(arguments: Array<String>, modulesPath: String): Int
}

Unfortunately, it looks like if the script is erroneous in any way, i.e. contains syntax or uncaught errors, node:Start doesn't return any result and crashes instead in a way that can't be handled and the process on which it was running is killed immediately. Out of desperation, I've already tried catching the error on both the Kotlin and C++ level (try/catch) and checking the JNI environment for caught exceptions (env->ExceptionCheck()), but none seems to work.

How often does it reproduce? Is there a required condition?

No response

What is the expected behavior? Why is that the expected behavior?

Any error that is thrown inside the node.js context and prevents the node::Start from completing should be propagated in a way it can be handled in the end product, so the developer can act on it and avoid having the process crashed.

What do you see instead?

When node:Start is to execute an erroneous code, it crashes with an error that can't be caught and handled and the process on which it was running is killed immediately.

Additional information

No response