v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) { v8::HandleScope scope; if(obj == NULL) { return v8::Null(); } jclass objClazz = env->GetObjectClass(obj); jvalueType resultType = javaGetType(env, objClazz); //printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str()); switch(resultType) { case TYPE_ARRAY: { v8::Handle<v8::Value> result = javaArrayToV8(java, env, (jobjectArray)obj); return scope.Close(result); } case TYPE_VOID: return v8::Undefined(); case TYPE_BOOLEAN: { jclass booleanClazz = env->FindClass("java/lang/Boolean"); jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z"); bool result = env->CallBooleanMethod(obj, boolean_booleanValue); return scope.Close(v8::Boolean::New(result)); } case TYPE_BYTE: { jclass byteClazz = env->FindClass("java/lang/Byte"); jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B"); jbyte result = env->CallByteMethod(obj, byte_byteValue); return scope.Close(v8::Number::New(result)); } case TYPE_LONG: { jclass longClazz = env->FindClass("java/lang/Long"); jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J"); jlong result = env->CallLongMethod(obj, long_longValue); return scope.Close(v8::Number::New(result)); } case TYPE_INT: { jclass integerClazz = env->FindClass("java/lang/Integer"); jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I"); jint result = env->CallIntMethod(obj, integer_intValue); return scope.Close(v8::Integer::New(result)); } case TYPE_DOUBLE: { jclass doubleClazz = env->FindClass("java/lang/Double"); jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D"); jdouble result = env->CallDoubleMethod(obj, double_doubleValue); return scope.Close(v8::Number::New(result)); } case TYPE_STRING: return scope.Close(v8::String::New(javaObjectToString(env, obj).c_str())); case TYPE_OBJECT: return scope.Close(JavaObject::New(java, obj)); default: printf("unhandled type: 0x%03x\n", resultType); return scope.Close(JavaObject::New(java, obj)); } return v8::Undefined(); }
v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) { v8::HandleScope scope; if(obj == NULL) { return v8::Null(); } jclass objClazz = env->GetObjectClass(obj); jvalueType resultType = javaGetType(env, objClazz); //printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str()); switch(resultType) { case TYPE_ARRAY: { v8::Handle<v8::Value> result = javaArrayToV8(java, env, (jobjectArray)obj); return scope.Close(result); } case TYPE_VOID: return v8::Undefined(); case TYPE_BOOLEAN: { jclass booleanClazz = env->FindClass("java/lang/Boolean"); jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z"); bool result = env->CallBooleanMethod(obj, boolean_booleanValue); return scope.Close(v8::Boolean::New(result)); } case TYPE_BYTE: { jclass byteClazz = env->FindClass("java/lang/Byte"); jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B"); jbyte result = env->CallByteMethod(obj, byte_byteValue); return scope.Close(v8::Number::New(result)); } case TYPE_LONG: { jclass longClazz = env->FindClass("java/lang/Long"); jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J"); jlong result = env->CallLongMethod(obj, long_longValue); std::string strValue = javaObjectToString(env, obj); v8::Local<v8::Value> v8Result = v8::NumberObject::New(result); v8::NumberObject* v8ResultNumberObject = v8::NumberObject::Cast(*v8Result); v8ResultNumberObject->Set(v8::String::New("longValue"), v8::String::New(strValue.c_str())); v8ResultNumberObject->SetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_LONG), v8::Boolean::New(true)); return scope.Close(v8Result); } case TYPE_INT: { jclass integerClazz = env->FindClass("java/lang/Integer"); jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I"); jint result = env->CallIntMethod(obj, integer_intValue); return scope.Close(v8::Integer::New(result)); } case TYPE_SHORT: { jclass shortClazz = env->FindClass("java/lang/Short"); jmethodID short_shortValue = env->GetMethodID(shortClazz, "shortValue", "()S"); jshort result = env->CallShortMethod(obj, short_shortValue); return scope.Close(v8::Integer::New(result)); } case TYPE_DOUBLE: { jclass doubleClazz = env->FindClass("java/lang/Double"); jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D"); jdouble result = env->CallDoubleMethod(obj, double_doubleValue); return scope.Close(v8::Number::New(result)); } case TYPE_FLOAT: { jclass floatClazz = env->FindClass("java/lang/Float"); jmethodID float_floatValue = env->GetMethodID(floatClazz, "floatValue", "()F"); jfloat result = env->CallFloatMethod(obj, float_floatValue); return scope.Close(v8::Number::New(result)); } case TYPE_STRING: return scope.Close(v8::String::New(javaObjectToString(env, obj).c_str())); case TYPE_OBJECT: return scope.Close(JavaObject::New(java, obj)); default: printf("javaToV8: unhandled type: 0x%03x\n", resultType); return scope.Close(JavaObject::New(java, obj)); } return v8::Undefined(); }
void EIO_AfterCallJs(uv_work_t* req, int status) { #else void EIO_AfterCallJs(uv_work_t* req) { #endif DynamicProxyData* dynamicProxyData = static_cast<DynamicProxyData*>(req->data); if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } dynamicProxyData->result = NULL; JNIEnv* env; int ret = dynamicProxyData->java->getJvm()->GetEnv((void**)&env, JNI_BEST_VERSION); if (ret != JNI_OK) { dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; dynamicProxyData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string<int>(ret); dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } Nan::HandleScope scope; v8::Array* v8Args; v8::Function* fn; v8::Handle<v8::Value>* argv; int argc; int i; v8::Local<v8::Value> v8Result; jobject javaResult; v8::Local<v8::Object> dynamicProxyDataFunctions = Nan::New(dynamicProxyData->functions); v8::Local<v8::Value> fnObj = dynamicProxyDataFunctions->Get(Nan::New<v8::String>(dynamicProxyData->methodName.c_str()).ToLocalChecked()); if(fnObj->IsUndefined() || fnObj->IsNull()) { dynamicProxyData->throwableClass = "java/lang/NoSuchMethodError"; dynamicProxyData->throwableMessage = "Could not find js function " + dynamicProxyData->methodName; dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } if(!fnObj->IsFunction()) { dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; dynamicProxyData->throwableMessage = dynamicProxyData->methodName + " is not a function"; dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } fn = v8::Function::Cast(*fnObj); if(dynamicProxyData->args) { v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, dynamicProxyData->args)); argc = v8Args->Length(); } else { argc = 0; } argv = new v8::Handle<v8::Value>[argc]; for(i=0; i<argc; i++) { argv[i] = v8Args->Get(i); } Nan::TryCatch tryCatch; tryCatch.SetCaptureMessage(true); v8Result = fn->Call(dynamicProxyDataFunctions, argc, argv); delete[] argv; if (tryCatch.HasCaught()) { dynamicProxyData->throwableClass = "node/NodeJsException"; v8::String::Utf8Value message(tryCatch.Message()->Get()); dynamicProxyData->throwableMessage = std::string(*message); tryCatch.Reset(); dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } javaResult = v8ToJava(env, v8Result); if(javaResult == NULL) { dynamicProxyData->result = NULL; } else { dynamicProxyData->result = env->NewGlobalRef(javaResult); } dynamicProxyData->done = true; }