X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/fc6647448b510836ada0171a58d594e8ae8a842a..5154ab8dbb5374da04cd9f8e2004279700a40881:/Java/Execute.cpp diff --git a/Java/Execute.cpp b/Java/Execute.cpp index 302dd3e..2156045 100644 --- a/Java/Execute.cpp +++ b/Java/Execute.cpp @@ -97,6 +97,15 @@ CYJavaForEachPrimitive #undef CYJavaForEachPrimitive_ }; +template +struct IsJavaPrimitive { static const bool value = false; }; + +#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \ + template <> \ + struct IsJavaPrimitive { static const bool value = true; }; +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + // Java References {{{ template struct CYJavaRef { @@ -109,18 +118,15 @@ struct CYJavaRef { { } - _finline operator bool() const { - return value_ != NULL; + _finline operator Value_() const { + return value_; } - _finline operator JNIEnv *() const { + _finline JNIEnv *jni() const { return jni_; } - _finline operator Value_() const { - return value_; - } - + // XXX: this is only needed to support CYJavaEnv relying on C variadics _finline Value_ get() const { return value_; } @@ -130,6 +136,7 @@ struct CYJavaRef { return {jni_, static_cast(value_)}; } + // XXX: this should be tied into CYJavaFrame Value_ leak() { Value_ value(value_); value_ = NULL; @@ -146,9 +153,14 @@ struct CYJavaDelete : { } - ~CYJavaDelete() { + void clear() { if (this->value_ != NULL) (this->jni_->*Delete_)(this->value_); + this->value_ = NULL; + } + + ~CYJavaDelete() { + clear(); } }; @@ -203,15 +215,24 @@ struct CYJavaLocal : { } - CYJavaLocal(CYJavaLocal &&value) : - CYJavaLocal(value.jni_, value.value_) + template + CYJavaLocal(CYJavaRef &&other) : + CYJavaLocal(other.jni_, other.value_) { - value.value_ = NULL; + other.value_ = NULL; } - CYJavaLocal &operator =(CYJavaLocal &&other) { - std::swap(this->jni_, other.jni_); - std::swap(this->value_, other.value_); + CYJavaLocal(CYJavaLocal &&other) : + CYJavaLocal(static_cast &&>(other)) + { + } + + template + CYJavaLocal &operator =(CYJavaLocal &&other) { + this->clear(); + this->jni_ = other.jni_; + this->value_ = other.value_; + other.value_ = NULL; return *this; } }; @@ -230,7 +251,7 @@ class CYJavaUTF8String : value_(&value) { _assert(value); - JNIEnv *jni(value); + JNIEnv *jni(value.jni()); size = jni->GetStringUTFLength(value); data = jni->GetStringUTFChars(value, NULL); } @@ -242,7 +263,7 @@ class CYJavaUTF8String : ~CYJavaUTF8String() { if (value_ != NULL) { - JNIEnv *jni(*value_); + JNIEnv *jni(value_->jni()); jni->ReleaseStringUTFChars(*value_, data); } } @@ -279,9 +300,7 @@ struct CYJavaError : return CYPoolCString(pool, CYJavaUTF8String(value_.cast())); } - virtual JSValueRef CastJSValue(JSContextRef context, const char *name) const { - return CYCastJSValue(context, value_); - } + virtual JSValueRef CastJSValue(JSContextRef context, const char *name) const; }; // }}} @@ -298,6 +317,10 @@ struct CYJavaFrame { operator ()(NULL); } + operator JNIEnv *() const { + return jni_; + } + jobject operator ()(jobject object) { JNIEnv *jni(jni_); jni_ = NULL; @@ -315,6 +338,12 @@ struct CYJavaEnv { { } + template + CYJavaEnv(const CYJavaRef &value) : + jni(value.jni()) + { + } + operator JNIEnv *() const { return jni; } @@ -375,7 +404,7 @@ CYJavaForEachPrimitive #define CYJavaEnv_(Code) \ template \ - auto Code(Args_ &&... args) const -> decltype(jni->Code(args...)) { \ + auto Code(Args_ &&... args) const -> decltype(jni->Code(cy::Forward(args)...)) { \ return _envcall(jni, Code(cy::Forward(args)...)); \ } @@ -434,6 +463,13 @@ struct CYJavaValue : CYJavaValue(const CYJavaValue &) = delete; }; +static JSValueRef CYCastJSValue(JSContextRef context, const CYJavaRef &value); + +template +static _finline JSValueRef CYCastJSValue(JSContextRef context, const CYJavaRef &value) { + return CYCastJSValue(context, value.template cast()); +} + template static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, Type_ value) { return CYCastJSValue(context, value); @@ -443,6 +479,10 @@ static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, jboolean valu return CYCastJSValue(context, static_cast(value)); } +JSValueRef CYJavaError::CastJSValue(JSContextRef context, const char *name) const { + return CYCastJSValue(context, value_); +} + static std::map Primitives_; static CYJavaPrimitive CYJavaGetPrimitive(JSContextRef context, const CYJavaRef &type, jmethodID Class$get$$Name) { @@ -844,7 +884,9 @@ CYJavaForEachPrimitive } } -static bool CYCastJavaArguments(const CYJavaEnv &jni, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jvalue *array) { +static bool CYCastJavaArguments(const CYJavaFrame &frame, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jvalue *array) { + CYJavaEnv jni(frame); + for (size_t index(0); index != shorty.size(); ++index) { JSValueRef argument(arguments[index]); JSType type(JSValueGetType(context, argument)); @@ -852,6 +894,7 @@ static bool CYCastJavaArguments(const CYJavaEnv &jni, const CYJavaShorty &shorty switch (CYJavaPrimitive primitive = shorty[index]) { case CYJavaPrimitiveObject: + // XXX: figure out a way to tie this in to the CYJavaFrame value.l = CYCastJavaObject(jni, context, argument).leak(); break; @@ -901,9 +944,9 @@ static JSValueRef JavaMethod_callAsFunction(JSContextRef context, JSObjectRef ob CYJavaSignature bound(count); for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); switch (overload->primitive_) { @@ -931,9 +974,9 @@ static JSValueRef JavaStaticMethod_callAsFunction(JSContextRef context, JSObject CYJavaSignature bound(count); for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); switch (overload->primitive_) { @@ -960,18 +1003,16 @@ static JSObjectRef JavaClass_callAsConstructor(JSContextRef context, JSObjectRef jclass _class(table->value_); if (table->interface_ && count == 1) { - JSObjectRef target(CYCastJSObject(context, arguments[0])); auto Cycript$(jni.FindClass("Cycript")); - auto Cycript$Make(jni.GetStaticMethodID(Cycript$, "proxy", "(Ljava/lang/Class;J)Ljava/lang/Object;")); - auto protect(new CYProtect(context, target)); - return CYCastJSObject(context, jni.CallObjectMethod(Cycript$, Cycript$Make, _class, reinterpret_cast(protect))); + auto Cycript$Make(jni.GetStaticMethodID(Cycript$, "proxy", "(Ljava/lang/Class;LCycript$Wrapper;)Ljava/lang/Object;")); + return CYCastJSObject(context, jni.CallObjectMethod(Cycript$, Cycript$Make, _class, CYCastJavaObject(jni, context, CYCastJSObject(context, arguments[0])).get())); } CYJavaSignature bound(count); for (auto overload(table->overload_.lower_bound(bound)), e(table->overload_.upper_bound(bound)); overload != e; ++overload) { - CYJavaFrame(jni, count + 16); + CYJavaFrame frame(jni, count + 16); jvalue array[count]; - if (!CYCastJavaArguments(jni, overload->shorty_, context, arguments, array)) + if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array)) continue; jvalue *values(array); auto object(jni.NewObjectA(_class, overload->method_, values)); @@ -1247,11 +1288,10 @@ static jobject Cycript_handle(JNIEnv *env, jclass api, jlong jprotect, jstring p size_t count(jarguments == NULL ? 0 : jni.GetArrayLength(jarguments)); JSValueRef arguments[count]; - for (size_t index(0); index != count; ++index) { + for (size_t index(0); index != count; ++index) arguments[index] = CYCastJSValue(context, jni.GetObjectArrayElement(jarguments, index)); - } - return CYCastJavaObject(jni, context, CYCallAsFunction(context, CYCastJSObject(context, function), object, count, arguments)); + return CYCastJavaObject(jni, context, CYCallAsFunction(context, CYCastJSObject(context, function), object, count, arguments)).leak(); } CYJavaCatch(NULL) } static JNINativeMethod Cycript_[] = {