From dbf05bfd2ab79568fe706daa9112037192d4d9dd Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 31 Dec 2015 21:21:56 -0800 Subject: [PATCH] This implementation for Java works, but I hate it. --- Execute.cpp | 138 +++---- Internal.hpp | 79 ++-- Java/Cycript.java | 32 ++ Java/Execute.cpp | 789 ++++++++++++++++++++++++++++++++++++++++ JavaScript.hpp | 56 ++- Makefile.am | 18 +- Makefile.in | 75 ++-- ObjectiveC/Internal.hpp | 18 +- ObjectiveC/Library.mm | 109 +++--- String.hpp | 5 + Utility.hpp | 5 + apple.mk | 5 + libcycript.cy | 50 +++ 13 files changed, 1145 insertions(+), 234 deletions(-) create mode 100644 Java/Cycript.java diff --git a/Execute.cpp b/Execute.cpp index e2d2d80..e64469a 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -94,7 +94,12 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J CYSetProperty(context, object, name, JSObjectMakeFunctionWithCallback(context, name, callback), attributes); } +JSObjectRef CYGetPrototype(JSContextRef context, JSObjectRef object) { + return CYCastJSObject(context, JSObjectGetPrototype(context, object)); +} + void CYSetPrototype(JSContextRef context, JSObjectRef object, JSValueRef value) { + _assert(!JSValueIsUndefined(context, value)); JSObjectSetPrototype(context, object, value); _assert(CYIsStrictEqual(context, JSObjectGetPrototype(context, object), value)); } @@ -120,6 +125,10 @@ JSStringRef CYCopyJSString(CYUTF8String value) { } } +JSStringRef CYCopyJSString(const std::string &value) { + return CYCopyJSString(CYUTF8String(value.c_str(), value.size())); +} + JSStringRef CYCopyJSString(CYUTF16String value) { return JSStringCreateWithCharacters(value.data, value.size); } @@ -130,7 +139,7 @@ JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) { return _jsccall(JSValueToStringCopy, context, value); } -static CYUTF16String CYCastUTF16String(JSStringRef value) { +CYUTF16String CYCastUTF16String(JSStringRef value) { return CYUTF16String(JSStringGetCharactersPtr(value), JSStringGetLength(value)); } @@ -156,7 +165,7 @@ size_t CYGetIndex(CYPool &pool, JSContextRef context, JSStringRef value) { static JSObjectRef (*JSObjectMakeArray$)(JSContextRef, size_t, const JSValueRef[], JSValueRef *); -static JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const JSValueRef values[]) { +JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const JSValueRef values[]) { if (JSObjectMakeArray$ != NULL) return _jsccall(*JSObjectMakeArray$, context, length, values); else { @@ -167,7 +176,6 @@ static JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const } static JSClassRef All_; -static JSClassRef Context_; JSClassRef Functor_; static JSClassRef Global_; @@ -204,10 +212,8 @@ sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate) { return aggregate; } -JSClassRef Type_privateData::Class_; - struct Context : - CYData + CYPrivate { JSGlobalContextRef context_; @@ -218,14 +224,14 @@ struct Context : }; struct CArray : - CYValue_ + CYValue { CYProtect owner_; Type_privateData *type_; size_t length_; CArray(void *value, size_t length, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner), type_(new(*pool_) Type_privateData(type, ffi)), length_(length) @@ -233,41 +239,41 @@ struct CArray : if (owner == NULL) { size_t size(ffi->size * length); void *copy(pool_->malloc(size, ffi->alignment)); - memcpy(copy, GetValue(), size); + memcpy(copy, value_, size); value_ = copy; } } }; struct CString : - CYValue_ + CYValue { CYProtect owner_; CString(char *value, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner) { if (owner == NULL) - value_ = pool_->strdup(GetValue()); + value_ = pool_->strdup(value_); } }; struct Pointer : - CYValue_ + CYValue { CYProtect owner_; Type_privateData *type_; Pointer(void *value, const sig::Type &type, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner), type_(new(*pool_) Type_privateData(type)) { } Pointer(void *value, const char *encoding, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner), type_(new(*pool_) Type_privateData(encoding)) { @@ -275,20 +281,20 @@ struct Pointer : }; struct Struct_privateData : - CYValue_ + CYValue { CYProtect owner_; Type_privateData *type_; Struct_privateData(void *value, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner), type_(new(*pool_) Type_privateData(type, ffi)) { if (owner == NULL) { size_t size(ffi->size); void *copy(pool_->malloc(size, ffi->alignment)); - memcpy(copy, GetValue(), size); + memcpy(copy, value_, size); value_ = copy; } } @@ -386,43 +392,6 @@ void CYArrayPush(JSContextRef context, JSObjectRef array, JSValueRef value) { return CYArrayPush(context, array, 1, &value); } -template -class CYArrayBuilder { - private: - JSContextRef context_; - JSObjectRef &array_; - size_t size_; - JSValueRef values_[Size_]; - - void flush() { - if (array_ == NULL) - array_ = CYObjectMakeArray(context_, size_, values_); - else - CYArrayPush(context_, array_, size_, values_); - } - - public: - CYArrayBuilder(JSContextRef context, JSObjectRef &array) : - context_(context), - array_(array), - size_(0) - { - } - - ~CYArrayBuilder() { - flush(); - } - - void operator ()(JSValueRef value) { - if (size_ == Size_) { - flush(); - size_ = 0; - } - - values_[size_++] = value; - } -}; - static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { FILE *file(stdout); @@ -907,7 +876,7 @@ Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, _assert(status == FFI_OK); internal->pool_->atexit(&CYFreeFunctor, writable); - internal->value_ = executable; + internal->value_ = reinterpret_cast(executable); #else ffi_closure *closure((ffi_closure *) _syscall(mmap( NULL, sizeof(ffi_closure), @@ -921,7 +890,7 @@ Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, _syscall(mprotect(closure, sizeof(*closure), PROT_READ | PROT_EXEC)); internal->pool_->atexit(&CYFreeFunctor, closure); - internal->value_ = closure; + internal->value_ = reinterpret_cast(closure); #endif return internal; @@ -964,7 +933,7 @@ static JSValueRef CString_getProperty(JSContextRef context, JSObjectRef object, if (!CYGetOffset(pool, context, property, offset)) return NULL; - return CYCastJSValue(context, CYJSString(CYUTF8String(&internal->GetValue()[offset], 1))); + return CYCastJSValue(context, CYJSString(CYUTF8String(&internal->value_[offset], 1))); } CYCatch(NULL) } static bool CString_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { @@ -976,7 +945,7 @@ static bool CString_setProperty(JSContextRef context, JSObjectRef object, JSStri return false; const char *data(CYPoolCString(pool, context, value)); - internal->GetValue()[offset] = *data; + internal->value_[offset] = *data; return true; } CYCatch(false) } @@ -1236,7 +1205,7 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CYPool pool; cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYCallFunction(pool, context, 0, NULL, count, arguments, false, internal->variadic_, internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 0, NULL, count, arguments, false, internal->variadic_, internal->signature_, &internal->cif_, internal->value_); } CYCatch(NULL) } static JSValueRef Pointer_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1248,8 +1217,7 @@ static JSValueRef Pointer_callAsFunction(JSContextRef context, JSObjectRef objec } CYCatch(NULL) } JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type) { - Type_privateData *internal(new Type_privateData(type)); - return JSObjectMake(context, Type_privateData::Class_, internal); + return Type_privateData::Make(context, type); } extern "C" bool CYBridgeHash(CYPool &pool, CYUTF8String name, const char *&code, unsigned &flags) { @@ -1605,34 +1573,44 @@ static JSValueRef Functor_callAsFunction_$cya(JSContextRef context, JSObjectRef sig::Function type(internal->variadic_); sig::Copy(pool, type.signature, internal->signature_); - return CYMakePointer(context, internal->value_, type, NULL, NULL); + return CYMakePointer(context, reinterpret_cast(internal->value_), type, NULL, NULL); } CYCatch(NULL) } static JSValueRef Pointer_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { return _this; } CYCatch(NULL) } -static JSValueRef CYValue_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - CYValue *internal(reinterpret_cast(JSObjectGetPrivate(_this))); +static JSValueRef CArray_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + CArray *internal(reinterpret_cast(JSObjectGetPrivate(_this))); return CYCastJSValue(context, reinterpret_cast(internal->value_)); } CYCatch(NULL) } -static JSValueRef CYValue_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - CYValue *internal(reinterpret_cast(JSObjectGetPrivate(_this))); +static JSValueRef Pointer_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + Pointer *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + return CYCastJSValue(context, reinterpret_cast(internal->value_)); +} CYCatch(NULL) } + +static JSValueRef Functor_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + return CYCastJSValue(context, reinterpret_cast(internal->value_)); +} CYCatch(NULL) } + +static JSValueRef Functor_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + uint8_t *value(reinterpret_cast(internal->value_)); std::ostringstream str; Dl_info info; if (internal->value_ == NULL) str << "NULL"; - else if (dladdr(internal->value_, &info) == 0) + else if (dladdr(value, &info) == 0) str << internal->value_; else { str << info.dli_sname; - off_t offset(static_cast(internal->value_) - static_cast(info.dli_saddr)); + off_t offset(value - reinterpret_cast(info.dli_saddr)); if (offset != 0) str << "+0x" << std::hex << offset; } - std::string value(str.str()); - return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size()))); + return CYCastJSValue(context, CYJSString(str.str())); } CYCatch(NULL) } static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1666,7 +1644,7 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { CString *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYCastJSValue(context, strlen(internal->GetValue())); + return CYCastJSValue(context, strlen(internal->value_)); } CYCatch(NULL) } static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1687,7 +1665,7 @@ static JSValueRef Pointer_getProperty_$cyt(JSContextRef context, JSObjectRef obj static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CString *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - const char *string(internal->GetValue()); + const char *string(internal->value_); std::ostringstream str; if (string == NULL) str << "NULL"; @@ -1701,7 +1679,7 @@ static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRe static JSValueRef CString_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CString *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - return CYCastJSValue(context, internal->GetValue()); + return CYCastJSValue(context, internal->value_); } CYCatch(NULL) } static JSValueRef Functor_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1751,7 +1729,7 @@ static JSStaticFunction All_staticFunctions[2] = { static JSStaticFunction CArray_staticFunctions[3] = { {"toPointer", &CArray_callAsFunction_toPointer, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"valueOf", &CArray_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} }; @@ -1777,7 +1755,7 @@ static JSStaticValue CString_staticValues[3] = { static JSStaticFunction Pointer_staticFunctions[4] = { {"toCYON", &Pointer_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toPointer", &Pointer_callAsFunction_toPointer, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"valueOf", &Pointer_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} }; @@ -1798,8 +1776,8 @@ static JSStaticValue Struct_staticValues[2] = { static JSStaticFunction Functor_staticFunctions[4] = { {"$cya", &Functor_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"toCYON", &CYValue_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"toCYON", &Functor_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"valueOf", &Functor_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} }; @@ -1940,7 +1918,7 @@ void CYInitializeDynamic() { definition = kJSClassDefinitionEmpty; definition.className = "Context"; definition.finalize = &CYFinalize; - Context_ = JSClassCreate(&definition); + Context::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "CArray"; @@ -2163,7 +2141,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { JSObjectRef global(CYGetGlobalObject(context)); - JSObjectRef cy(JSObjectMake(context, Context_, new Context(context))); + JSObjectRef cy(Context::Make(context, context)); CYSetProperty(context, global, cy_s, cy, kJSPropertyAttributeDontEnum); /* Cache Globals {{{ */ diff --git a/Internal.hpp b/Internal.hpp index 0d6ae78..242456b 100644 --- a/Internal.hpp +++ b/Internal.hpp @@ -39,11 +39,34 @@ sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate); extern JSClassRef Functor_; -struct Type_privateData : +template +struct CYPrivate : CYData { static JSClassRef Class_; + _finline JSValueRef GetPrototype(JSContextRef context) const { + return NULL; + } + + template + _finline static JSClassRef GetClass(Args_ &&... args) { + return Class_; + } + + template + static JSObjectRef Make(JSContextRef context, Args_ &&... args) { + Internal_ *internal(new Internal_(cy::Forward(args)...)); + JSObjectRef object(JSObjectMake(context, Internal_::GetClass(cy::Forward(args)...), internal)); + if (JSValueRef prototype = internal->GetPrototype(context)) + CYSetPrototype(context, object, prototype); + return object; + } +}; + +struct Type_privateData : + CYPrivate +{ ffi_type *ffi_; sig::Type *type_; @@ -89,16 +112,17 @@ struct Type_privateData : } }; +template struct CYValue : - CYData + CYPrivate { - void *value_; + Value_ value_; CYValue() { } - CYValue(const void *value) : - value_(const_cast(value)) + CYValue(const Value_ &value) : + value_(value) { } @@ -108,39 +132,8 @@ struct CYValue : } }; -template -struct CYValue_ : - CYValue -{ - static JSClassRef Class_; - - using CYValue::CYValue; - - _finline Value_ GetValue() const { - return reinterpret_cast(value_); - } - - _finline JSValueRef GetPrototype(JSContextRef context) const { - return NULL; - } - - template - _finline static JSClassRef GetClass(Args_ &&... args) { - return Class_; - } - - template - static JSObjectRef Make(JSContextRef context, Args_ &&... args) { - Internal_ *internal(new Internal_(cy::Forward(args)...)); - JSObjectRef object(JSObjectMake(context, Internal_::GetClass(cy::Forward(args)...), internal)); - if (JSValueRef prototype = internal->GetPrototype(context)) - CYSetPrototype(context, object, prototype); - return object; - } -}; - -template -JSClassRef CYValue_::Class_; +template +JSClassRef CYPrivate::Class_; struct CYProtect { private: @@ -178,7 +171,7 @@ struct CYProtect { namespace cy { struct Functor : - CYValue + CYValue { private: void set() { @@ -191,7 +184,7 @@ struct Functor : ffi_cif cif_; Functor(void (*value)(), bool variadic, const sig::Signature &signature) : - CYValue(reinterpret_cast(value)), + CYValue(value), variadic_(variadic) { sig::Copy(*pool_, signature_, signature); @@ -199,17 +192,13 @@ struct Functor : } Functor(void (*value)(), const char *encoding) : - CYValue(reinterpret_cast(value)), + CYValue(value), variadic_(false) { sig::Parse(*pool_, &signature_, encoding, &Structor_); set(); } - void (*GetValue() const)() { - return reinterpret_cast(value_); - } - static JSStaticFunction const * const StaticFunctions; static JSStaticValue const * const StaticValues; }; } diff --git a/Java/Cycript.java b/Java/Cycript.java new file mode 100644 index 0000000..76ac7fc --- /dev/null +++ b/Java/Cycript.java @@ -0,0 +1,32 @@ +/* Cycript - Optimizing JavaScript Compiler/Runtime + * Copyright (C) 2009-2015 Jay Freeman (saurik) +*/ + +/* GNU Affero General Public License, Version 3 {{{ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +**/ +/* }}} */ + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +public class Cycript { + +public class OnInvoke implements InvocationHandler { + native public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; +} + +} diff --git a/Java/Execute.cpp b/Java/Execute.cpp index 48c5808..c972562 100644 --- a/Java/Execute.cpp +++ b/Java/Execute.cpp @@ -19,8 +19,797 @@ **/ /* }}} */ +#include +#include +#include + #ifdef __APPLE__ #include #else #include #endif + +#include "cycript.hpp" +#include "Execute.hpp" +#include "Internal.hpp" +#include "JavaScript.hpp" +#include "Pooling.hpp" + +#define _jnicall(expr) ({ \ + jint _value(expr); \ + if (_value != JNI_OK) \ + CYThrow("_jnicall(%s) == %d", #expr, _value); \ +}) + +#define _envcall(jni, expr) ({ \ + __typeof__(jni->expr) _value(jni->expr); \ + if (jthrowable _error = jni->ExceptionOccurred()) { \ + jni->ExceptionClear(); \ + CYThrow("_envcall(%s): %p", #expr, _error); \ + } \ +_value; }) + +#define _envcallv(jni, expr) do { \ + jni->expr; \ + if (jthrowable _error = jni->ExceptionOccurred()) { \ + jni->ExceptionClear(); \ + CYThrow("_envcall(%s): %p", #expr, _error); \ + } \ +} while (false) + +extern "C" { + // Android's jni.h seriously doesn't declare these :/ + jint JNI_CreateJavaVM(JavaVM **, void **, void *); + jint JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *); +} + +JNIEnv *GetJNI() { + static JavaVM *jvm(NULL); + static JNIEnv *jni(NULL); + + if (jni != NULL) + return jni; + jint version(JNI_VERSION_1_4); + + jsize capacity(16); + JavaVM *jvms[capacity]; + jsize size; + _jnicall(JNI_GetCreatedJavaVMs(jvms, capacity, &size)); + + if (size != 0) { + jvm = jvms[0]; + _jnicall(jvm->GetEnv(reinterpret_cast(&jni), version)); + } else { + JavaVMInitArgs args; + memset(&args, 0, sizeof(args)); + args.version = version; + _jnicall(JNI_CreateJavaVM(&jvm, reinterpret_cast(&jni), &args)); + } + + return jni; +} + +class CYJavaUTF8String : + public CYUTF8String +{ + private: + JNIEnv *jni_; + jstring value_; + + public: + CYJavaUTF8String(JNIEnv *jni, jstring value) : + jni_(jni), + value_(value) + { + size = jni_->GetStringUTFLength(value_); + data = jni_->GetStringUTFChars(value_, NULL); + } + + ~CYJavaUTF8String() { + if (value_ != NULL) + jni_->ReleaseStringUTFChars(value_, data); + } + + CYJavaUTF8String(const CYJavaUTF8String &) = delete; + + CYJavaUTF8String(CYJavaUTF8String &&rhs) : + jni_(rhs.jni_), + value_(rhs.value_) + { + rhs.value_ = NULL; + } +}; + +CYJavaUTF8String CYCastUTF8String(JNIEnv *jni, jstring value) { + return CYJavaUTF8String(jni, value); +} + +JSStringRef CYCopyJSString(JNIEnv *jni, jstring value) { + return CYCopyJSString(CYCastUTF8String(jni, value)); +} + +template +struct CYJavaGlobal { + JNIEnv *jni_; + Value_ value_; + + CYJavaGlobal() : + jni_(NULL), + value_(NULL) + { + } + + CYJavaGlobal(JNIEnv *jni, Value_ value) : + jni_(jni), + value_(static_cast(_envcall(jni_, NewGlobalRef(value)))) + { + } + + CYJavaGlobal(const CYJavaGlobal &value) : + CYJavaGlobal(value.jni_, value.value_) + { + } + + CYJavaGlobal(CYJavaGlobal &&value) : + jni_(value.jni_), + value_(value.value_) + { + value.value_ = NULL; + } + + ~CYJavaGlobal() { + if (value_ != NULL) + _envcallv(jni_, DeleteGlobalRef(value_)); + } + + operator bool() const { + return value_ != NULL; + } + + operator JNIEnv *() const { + return jni_; + } + + operator Value_() const { + return value_; + } +}; + +template +struct CYJavaValue : + CYPrivate +{ + CYJavaGlobal value_; + + CYJavaValue(JNIEnv *jni, Value_ value) : + value_(jni, value) + { + } + + CYJavaValue(const CYJavaValue &) = delete; +}; + +#define CYJavaForEachPrimitive \ + CYJavaForEachPrimitive_(Z, Boolean, Boolean) \ + CYJavaForEachPrimitive_(B, Byte, Byte) \ + CYJavaForEachPrimitive_(C, Char, Character) \ + CYJavaForEachPrimitive_(S, Short, Short) \ + CYJavaForEachPrimitive_(I, Int, Integer) \ + CYJavaForEachPrimitive_(J, Long, Long) \ + CYJavaForEachPrimitive_(F, Float, Float) \ + CYJavaForEachPrimitive_(D, Double, Double) + +enum CYJavaPrimitive : char { + CYJavaPrimitiveObject, + CYJavaPrimitiveVoid, +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + CYJavaPrimitive ## Type, +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ +}; + +template +static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, Type_ value) { + return CYCastJSValue(context, value); +} + +static _finline JSValueRef CYJavaCastJSValue(JSContextRef context, jboolean value) { + return CYCastJSValue(context, static_cast(value)); +} + +static std::map Primitives_; + +static CYJavaPrimitive CYJavaGetPrimitive(JNIEnv *jni, jobject type, jmethodID Class$get$$Name) { + CYJavaUTF8String name(jni, static_cast(_envcall(jni, CallObjectMethod(type, Class$get$$Name)))); + auto primitive(Primitives_.find(name)); + return primitive != Primitives_.end() ? primitive->second : CYJavaPrimitiveObject; +} + +typedef std::vector CYJavaShorty; + +static CYJavaShorty CYJavaGetShorty(JNIEnv *jni, jobjectArray types, jmethodID Class$get$$Name) { + size_t count(_envcall(jni, GetArrayLength(types))); + CYJavaShorty shorty(count); + for (size_t index(0); index != count; ++index) + shorty[index] = CYJavaGetPrimitive(jni, _envcall(jni, GetObjectArrayElement(types, index)), Class$get$$Name); + return shorty; +} + +struct CYJavaField { + jfieldID field_; + CYJavaPrimitive primitive_; +}; + +typedef std::map CYJavaFieldMap; + +struct CYJavaSignature { + CYJavaGlobal method; + CYJavaPrimitive primitive; + CYJavaShorty shorty; + + CYJavaSignature(JNIEnv *jni, jobject method, CYJavaPrimitive primitive, const CYJavaShorty &shorty) : + method(jni, method), + primitive(primitive), + shorty(shorty) + { + } + + CYJavaSignature(unsigned count) : + shorty(count) + { + } + + bool operator <(const CYJavaSignature &rhs) const { + return shorty.size() < rhs.shorty.size(); + } +}; + +typedef std::multiset CYJavaOverload; + +struct CYJavaMethod : + CYPrivate +{ + JNIEnv *jni_; + CYJavaOverload overload_; + + // XXX: figure out move constructors on Apple's crappy toolchain + CYJavaMethod(JNIEnv *jni, const CYJavaOverload &overload) : + jni_(jni), + overload_(overload) + { + } +}; + +struct CYJavaClass : + CYJavaValue +{ + CYJavaFieldMap static_; + CYJavaFieldMap instance_; + CYJavaOverload overload_; + + CYJavaClass(JNIEnv *jni, jclass value) : + CYJavaValue(jni, value) + { + } +}; + +struct CYJavaObject : + CYJavaValue +{ + CYJavaObject(JNIEnv *jni, jobject value) : + CYJavaValue(jni, value) + { + } + + JSValueRef GetPrototype(JSContextRef context) const; +}; + +struct CYJavaPackage : + CYPrivate +{ + typedef std::vector Path; + Path package_; + + _finline CYJavaPackage(const Path &package) : + package_(package) + { + } +}; + +static JSObjectRef CYGetJavaClass(JSContextRef context, JNIEnv *jni, jclass _class); + +JSValueRef CYJavaObject::GetPrototype(JSContextRef context) const { + JNIEnv *jni(value_); + return CYGetProperty(context, CYGetJavaClass(context, jni, _envcall(jni, GetObjectClass(value_))), prototype_s); +} + +static JSValueRef CYCastJSValue(JSContextRef context, JNIEnv *jni, jobject value) { + if (value == NULL) + return CYJSNull(context); + + return CYJavaObject::Make(context, jni, value); +} + +static jstring CYCastJavaString(JNIEnv *jni, CYUTF16String value) { + return _envcall(jni, NewString(value.data, value.size)); +} + +static jstring CYCastJavaString(JNIEnv *jni, JSStringRef value) { + return CYCastJavaString(jni, CYCastUTF16String(value)); +} + +#define CYCastJava$(T, Type, jtype, Cast) \ +_disused static jobject CYCastJava ## Type(JNIEnv *jni, JSContextRef context, JSValueRef value) { \ + jclass Type$(_envcall(jni, FindClass("java/lang/" #Type))); \ + jmethodID Type$init$(_envcall(jni, GetMethodID(Type$, "", "(" #T ")V"))); \ + return _envcall(jni, NewObject(Type$, Type$init$, static_cast(Cast(context, value)))); \ +} + +CYCastJava$(Z, Boolean, jboolean, CYCastBool) +CYCastJava$(B, Byte, jbyte, CYCastDouble) +CYCastJava$(C, Character, jchar, CYCastDouble) +CYCastJava$(S, Short, jshort, CYCastDouble) +CYCastJava$(I, Integer, jint, CYCastDouble) +CYCastJava$(J, Long, jlong, CYCastDouble) +CYCastJava$(F, Float, jfloat, CYCastDouble) +CYCastJava$(D, Double, jdouble, CYCastDouble) + +static jobject CYCastJavaObject(JNIEnv *jni, JSContextRef context, JSObjectRef value) { + JSObjectRef object(CYCastJSObject(context, value)); + if (JSValueIsObjectOfClass(context, value, CYJavaObject::Class_)) { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + return internal->value_; + } + + _assert(false); +} + +static jobject CYCastJavaObject(JNIEnv *jni, JSContextRef context, JSValueRef value) { + switch (JSValueGetType(context, value)) { + case kJSTypeNull: + return NULL; + case kJSTypeBoolean: + return CYCastJavaBoolean(jni, context, value); + case kJSTypeNumber: + return CYCastJavaDouble(jni, context, value); + case kJSTypeString: + return CYCastJavaString(jni, CYJSString(context, value)); + case kJSTypeObject: + return CYCastJavaObject(jni, context, CYCastJSObject(context, value)); + + case kJSTypeUndefined: + default: + _assert(false); + } +} + +CYJavaClass *CYGetJavaTable(JSContextRef context, JNIEnv *jni, jobject object) { + // XXX: this implementation is absolutely unacceptable :/ + return reinterpret_cast(JSObjectGetPrivate(CYGetJavaClass(context, jni, _envcall(jni, GetObjectClass(object))))); +} + +static JSObjectRef CYGetJavaClass(JSContextRef context, JNIEnv *jni, jclass value) { + JSObjectRef global(CYGetGlobalObject(context)); + JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s))); + + jclass Class$(_envcall(jni, FindClass("java/lang/Class"))); + jmethodID Class$getCanonicalName(_envcall(jni, GetMethodID(Class$, "getCanonicalName", "()Ljava/lang/String;"))); + + CYJSString name(jni, static_cast(_envcall(jni, CallObjectMethod(value, Class$getCanonicalName)))); + JSValueRef cached(CYGetProperty(context, cy, name)); + if (!JSValueIsUndefined(context, cached)) + return CYCastJSObject(context, cached); + + jmethodID Class$getDeclaredConstructors(_envcall(jni, GetMethodID(Class$, "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;"))); + jmethodID Class$getDeclaredFields(_envcall(jni, GetMethodID(Class$, "getDeclaredFields", "()[Ljava/lang/reflect/Field;"))); + jmethodID Class$getDeclaredMethods(_envcall(jni, GetMethodID(Class$, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"))); + + jclass Constructor$(_envcall(jni, FindClass("java/lang/reflect/Constructor"))); + //jmethodID Constructor$getModifiers(_envcall(jni, GetMethodID(Constructor$, "getModifiers", "()I"))); + jmethodID Constructor$getParameterTypes(_envcall(jni, GetMethodID(Constructor$, "getParameterTypes", "()[Ljava/lang/Class;"))); + + jclass Field$(_envcall(jni, FindClass("java/lang/reflect/Field"))); + jmethodID Field$getModifiers(_envcall(jni, GetMethodID(Field$, "getModifiers", "()I"))); + jmethodID Field$getName(_envcall(jni, GetMethodID(Field$, "getName", "()Ljava/lang/String;"))); + jmethodID Field$getType(_envcall(jni, GetMethodID(Field$, "getType", "()Ljava/lang/Class;"))); + + jclass Method$(_envcall(jni, FindClass("java/lang/reflect/Method"))); + jmethodID Method$getModifiers(_envcall(jni, GetMethodID(Method$, "getModifiers", "()I"))); + jmethodID Method$getName(_envcall(jni, GetMethodID(Method$, "getName", "()Ljava/lang/String;"))); + jmethodID Method$getParameterTypes(_envcall(jni, GetMethodID(Method$, "getParameterTypes", "()[Ljava/lang/Class;"))); + jmethodID Method$getReturnType(_envcall(jni, GetMethodID(Method$, "getReturnType", "()Ljava/lang/Class;"))); + + jclass Modifier$(_envcall(jni, FindClass("java/lang/reflect/Modifier"))); + jmethodID Modifier$isStatic(_envcall(jni, GetStaticMethodID(Modifier$, "isStatic", "(I)Z"))); + + CYJavaClass *table(new CYJavaClass(jni, value)); + + for (jclass prototype(value); prototype != NULL; prototype = _envcall(jni, GetSuperclass(prototype))) { + jobjectArray fields(static_cast(_envcall(jni, CallObjectMethod(prototype, Class$getDeclaredFields)))); + + for (jsize i(0), e(_envcall(jni, GetArrayLength(fields))); i != e; ++i) { + jobject field(_envcall(jni, GetObjectArrayElement(fields, e - i - 1))); + jint modifiers(_envcall(jni, CallIntMethod(field, Field$getModifiers))); + bool instance(!_envcall(jni, CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers))); + auto &map(instance ? table->instance_ : table->static_); + CYJavaUTF8String name(jni, static_cast(_envcall(jni, CallObjectMethod(field, Field$getName)))); + jfieldID id(_envcall(jni, FromReflectedField(field))); + jobject type(_envcall(jni, CallObjectMethod(field, Field$getType))); + map.insert(std::make_pair(std::string(name), CYJavaField{id, CYJavaGetPrimitive(jni, type, Class$getCanonicalName)})); + } + } + + JSObjectRef constructor(JSObjectMake(context, CYJavaClass::Class_, table)); + JSObjectRef indirect(JSObjectMake(context, NULL, NULL)); + CYSetPrototype(context, constructor, indirect); + + JSObjectRef prototype(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, constructor, prototype_s, prototype, kJSPropertyAttributeDontEnum); + + jobjectArray constructors(static_cast(_envcall(jni, CallObjectMethod(value, Class$getDeclaredConstructors)))); + + for (jsize i(0), e(_envcall(jni, GetArrayLength(constructors))); i != e; ++i) { + jobject constructor(_envcall(jni, GetObjectArrayElement(constructors, i))); + jobjectArray parameters(static_cast(_envcall(jni, CallObjectMethod(constructor, Constructor$getParameterTypes)))); + CYJavaShorty shorty(CYJavaGetShorty(jni, parameters, Class$getCanonicalName)); + table->overload_.insert(CYJavaSignature(jni, constructor, CYJavaPrimitiveObject, shorty)); + } + + jobjectArray methods(static_cast(_envcall(jni, CallObjectMethod(value, Class$getDeclaredMethods)))); + + std::map, CYJavaOverload> entries; + + for (jsize i(0), e(_envcall(jni, GetArrayLength(methods))); i != e; ++i) { + jobject method(_envcall(jni, GetObjectArrayElement(methods, i))); + jint modifiers(_envcall(jni, CallIntMethod(method, Method$getModifiers))); + bool instance(!_envcall(jni, CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers))); + CYJavaUTF8String name(jni, static_cast(_envcall(jni, CallObjectMethod(method, Method$getName)))); + jobjectArray parameters(static_cast(_envcall(jni, CallObjectMethod(method, Method$getParameterTypes)))); + CYJavaShorty shorty(CYJavaGetShorty(jni, parameters, Class$getCanonicalName)); + jobject type(_envcall(jni, CallObjectMethod(method, Method$getReturnType))); + auto primitive(CYJavaGetPrimitive(jni, type, Class$getCanonicalName)); + entries[std::make_pair(instance, std::string(name))].insert(CYJavaSignature(jni, method, primitive, shorty)); + } + + for (const auto &entry : entries) { + bool instance(entry.first.first); + CYJSString name(entry.first.second); + auto &overload(entry.second); + auto target(instance ? prototype : indirect); + JSValueRef wrapper(CYJavaMethod::Make(context, jni, overload)); + CYSetProperty(context, target, name, wrapper, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete); + } + + // XXX: for some reason kJSPropertyAttributeDontEnum doesn't work if there's already a property with the same name + // by not linking the prototypes until after we set the properties, we hide the parent property from this issue :( + + if (jclass super = _envcall(jni, GetSuperclass(value))) { + JSObjectRef parent(CYGetJavaClass(context, jni, super)); + CYSetPrototype(context, indirect, CYGetPrototype(context, parent)); + CYSetPrototype(context, prototype, CYGetProperty(context, parent, prototype_s)); + } + + CYSetProperty(context, cy, name, constructor); + return constructor; +} + +static jobjectArray CYCastJavaArguments(JNIEnv *jni, const CYJavaShorty &shorty, JSContextRef context, const JSValueRef arguments[], jclass Object$) { + jobjectArray array(_envcall(jni, NewObjectArray(shorty.size(), Object$, NULL))); + for (size_t index(0); index != shorty.size(); ++index) { + jobject argument; + switch (shorty[index]) { + case CYJavaPrimitiveObject: + argument = CYCastJavaObject(jni, context, arguments[index]); + break; +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + case CYJavaPrimitive ## Type: \ + argument = CYCastJava ## Type(jni, context, arguments[index]); \ + break; +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + default: + _assert(false); + } + _envcallv(jni, SetObjectArrayElement(array, index, argument)); + } + + return array; +} + +static JSValueRef JavaMethod_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + CYJavaMethod *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->jni_); + + jclass Object$(_envcall(jni, FindClass("java/lang/Object"))); + + jclass Method$(_envcall(jni, FindClass("java/lang/reflect/Method"))); + jmethodID Method$invoke(_envcall(jni, GetMethodID(Method$, "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"))); + + jobject self(CYCastJavaObject(jni, context, _this)); + + CYJavaSignature bound(count); + for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) { + jobjectArray array(CYCastJavaArguments(jni, overload->shorty, context, arguments, Object$)); + jobject object(_envcall(jni, CallObjectMethod(overload->method, Method$invoke, self, array))); + return CYCastJSValue(context, jni, object); + } + + CYThrow("invalid method call"); +} CYCatch(NULL) } + +static JSObjectRef JavaClass_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(table->value_); + + jclass Object$(_envcall(jni, FindClass("java/lang/Object"))); + + jclass Constructor$(_envcall(jni, FindClass("java/lang/reflect/Constructor"))); + jmethodID Constructor$newInstance(_envcall(jni, GetMethodID(Constructor$, "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;"))); + + CYJavaSignature bound(count); + for (auto overload(table->overload_.lower_bound(bound)), e(table->overload_.upper_bound(bound)); overload != e; ++overload) { + jobjectArray array(CYCastJavaArguments(jni, overload->shorty, context, arguments, Object$)); + jobject object(_envcall(jni, CallObjectMethod(overload->method, Constructor$newInstance, array))); + return CYCastJSObject(context, CYCastJSValue(context, jni, object)); + } + + CYThrow("invalid constructor call"); +} CYCatch(NULL) } + +static bool JavaClass_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->static_.find(name)); + if (field == table->static_.end()) + return false; + return true; +} + +static JSValueRef JavaClass_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(table->value_); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->static_.find(name)); + if (field == table->static_.end()) + return NULL; + + switch (field->second.primitive_) { + case CYJavaPrimitiveObject: + return CYCastJSValue(context, jni, _envcall(jni, GetStaticObjectField(table->value_, field->second.field_))); +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + case CYJavaPrimitive ## Type: \ + return CYJavaCastJSValue(context, _envcall(jni, GetStatic ## Typ ## Field(table->value_, field->second.field_))); +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + default: _assert(false); + } +} CYCatch(NULL) } + +static bool JavaClass_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(table->value_); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->static_.find(name)); + if (field == table->static_.end()) + return false; + + switch (field->second.primitive_) { + case CYJavaPrimitiveObject: + _envcallv(jni, SetStaticObjectField(table->value_, field->second.field_, CYCastJavaObject(jni, context, value))); +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + case CYJavaPrimitive ## Type: \ + _envcallv(jni, SetStatic ## Typ ## Field(table->value_, field->second.field_, CYCastDouble(context, value))); \ + break; +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + default: _assert(false); + } + + return true; +} CYCatch(false) } + +static void JavaClass_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + for (const auto &field : table->static_) + JSPropertyNameAccumulatorAddName(names, CYJSString(field.first)); +} + +static JSValueRef JavaClass_getProperty_class(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYJavaClass *table(reinterpret_cast(JSObjectGetPrivate(object))); + return CYCastJSValue(context, table->value_, table->value_); +} CYCatch(NULL) } + +static bool JavaObject_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->value_); + CYJavaClass *table(CYGetJavaTable(context, jni, internal->value_)); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->instance_.find(name)); + if (field == table->instance_.end()) + return false; + return true; +} + +static JSValueRef JavaObject_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->value_); + CYJavaClass *table(CYGetJavaTable(context, jni, internal->value_)); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->instance_.find(name)); + if (field == table->instance_.end()) + return NULL; + + switch (field->second.primitive_) { + case CYJavaPrimitiveObject: + return CYCastJSValue(context, jni, _envcall(jni, GetObjectField(internal->value_, field->second.field_))); +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + case CYJavaPrimitive ## Type: \ + return CYJavaCastJSValue(context, _envcall(jni, Get ## Typ ## Field(internal->value_, field->second.field_))); +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + default: _assert(false); + } +} CYCatch(NULL) } + +static bool JavaObject_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->value_); + CYJavaClass *table(CYGetJavaTable(context, jni, internal->value_)); + CYPool pool; + auto name(CYPoolUTF8String(pool, context, property)); + auto field(table->instance_.find(name)); + if (field == table->instance_.end()) + return false; + + switch (field->second.primitive_) { + case CYJavaPrimitiveObject: + _envcallv(jni, SetObjectField(table->value_, field->second.field_, CYCastJavaObject(jni, context, value))); +#define CYJavaForEachPrimitive_(T, Typ, Type) \ + case CYJavaPrimitive ## Type: \ + _envcallv(jni, Set ## Typ ## Field(table->value_, field->second.field_, CYCastDouble(context, value))); \ + break; +CYJavaForEachPrimitive +#undef CYJavaForEachPrimitive_ + default: _assert(false); + } + + return true; +} CYCatch(false) } + +static void JavaObject_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->value_); + CYJavaClass *table(CYGetJavaTable(context, jni, internal->value_)); + for (const auto &field : table->instance_) + JSPropertyNameAccumulatorAddName(names, CYJSString(field.first)); +} + +static JSValueRef JavaObject_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYJavaObject *internal(reinterpret_cast(JSObjectGetPrivate(object))); + JNIEnv *jni(internal->value_); + return CYGetJavaClass(context, jni, _envcall(jni, GetObjectClass(internal->value_))); +} CYCatch(NULL) } + +static bool CYJavaPackage_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { + return true; +} + +static JSValueRef CYJavaPackage_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYJavaPackage *internal(reinterpret_cast(JSObjectGetPrivate(object))); + CYJavaPackage::Path package(internal->package_); + + CYPool pool; + const char *next(CYPoolCString(pool, context, property)); + + std::ostringstream name; + for (auto &package : internal->package_) + name << package << '/'; + name << next; + + JNIEnv *jni(GetJNI()); + if (jclass _class = jni->FindClass(name.str().c_str())) + return CYGetJavaClass(context, jni, _class); + jni->ExceptionClear(); + + package.push_back(next); + return CYJavaPackage::Make(context, package); +} CYCatch(NULL) } + +static JSStaticValue JavaClass_staticValues[2] = { + {"class", &JavaClass_getProperty_class, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, NULL, 0} +}; + +static JSStaticValue JavaObject_staticValues[2] = { + {"constructor", &JavaObject_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, NULL, 0} +}; + +static JSStaticFunction JavaPackage_staticFunctions[1] = { + {NULL, NULL, 0} +}; + +void CYJava_Initialize() { + Primitives_.insert(std::make_pair("void", CYJavaPrimitiveVoid)); + Primitives_.insert(std::make_pair("boolean", CYJavaPrimitiveBoolean)); + Primitives_.insert(std::make_pair("byte", CYJavaPrimitiveByte)); + Primitives_.insert(std::make_pair("char", CYJavaPrimitiveCharacter)); + Primitives_.insert(std::make_pair("short", CYJavaPrimitiveShort)); + Primitives_.insert(std::make_pair("int", CYJavaPrimitiveInteger)); + Primitives_.insert(std::make_pair("long", CYJavaPrimitiveLong)); + Primitives_.insert(std::make_pair("float", CYJavaPrimitiveFloat)); + Primitives_.insert(std::make_pair("double", CYJavaPrimitiveDouble)); + + JSClassDefinition definition; + + definition = kJSClassDefinitionEmpty; + definition.className = "JavaClass"; + definition.staticValues = JavaClass_staticValues; + definition.hasProperty = &JavaClass_hasProperty; + definition.getProperty = &JavaClass_getProperty; + definition.setProperty = &JavaClass_setProperty; + definition.getPropertyNames = &JavaClass_getPropertyNames; + definition.callAsConstructor = &JavaClass_callAsConstructor; + definition.finalize = &CYFinalize; + CYJavaClass::Class_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "JavaMethod"; + definition.callAsFunction = &JavaMethod_callAsFunction; + definition.finalize = &CYFinalize; + CYJavaMethod::Class_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.attributes = kJSClassAttributeNoAutomaticPrototype; + definition.className = "JavaObject"; + definition.staticValues = JavaObject_staticValues; + definition.hasProperty = &JavaObject_hasProperty; + definition.getProperty = &JavaObject_getProperty; + definition.setProperty = &JavaObject_setProperty; + definition.getPropertyNames = &JavaObject_getPropertyNames; + definition.finalize = &CYFinalize; + CYJavaObject::Class_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "JavaPackage"; + definition.staticFunctions = JavaPackage_staticFunctions; + definition.hasProperty = &CYJavaPackage_hasProperty; + definition.getProperty = &CYJavaPackage_getProperty; + definition.finalize = &CYFinalize; + CYJavaPackage::Class_ = JSClassCreate(&definition); +} + +void CYJava_SetupContext(JSContextRef context) { + JSObjectRef global(CYGetGlobalObject(context)); + //JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s))); + JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript")))); + JSObjectRef all(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("all")))); + //JSObjectRef alls(CYCastJSObject(context, CYGetProperty(context, cycript, CYJSString("alls")))); + + JSObjectRef Java(JSObjectMake(context, NULL, NULL)); + CYSetProperty(context, cycript, CYJSString("Java"), Java); + + JSObjectRef Packages(CYJavaPackage::Make(context, CYJavaPackage::Path())); + CYSetProperty(context, all, CYJSString("Packages"), Packages); + + for (auto name : (const char *[]) {"java", "javax", "android", "com", "net", "org"}) { + CYJSString js(name); + CYSetProperty(context, all, js, CYGetProperty(context, Packages, js)); + } +} + +static CYHook CYJavaHook = { + NULL, + NULL, + NULL, + &CYJava_Initialize, + &CYJava_SetupContext, + NULL, +}; + +CYRegisterHook CYJava(&CYJavaHook); diff --git a/JavaScript.hpp b/JavaScript.hpp index a162d9a..7a4d8a4 100644 --- a/JavaScript.hpp +++ b/JavaScript.hpp @@ -23,6 +23,7 @@ #define CYCRIPT_JAVASCRIPT_HPP #include +#include #include #include @@ -72,6 +73,7 @@ double CYCastDouble(JSContextRef context, JSValueRef value); bool CYIsEqual(JSContextRef context, JSValueRef lhs, JSValueRef rhs); bool CYIsStrictEqual(JSContextRef context, JSValueRef lhs, JSValueRef rhs); +CYUTF16String CYCastUTF16String(JSStringRef value); CYUTF8String CYPoolUTF8String(CYPool &pool, JSContextRef context, JSStringRef value); const char *CYPoolCString(CYPool &pool, JSContextRef context, JSStringRef value); @@ -83,6 +85,7 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSVal void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes = kJSPropertyAttributeNone); void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes = kJSPropertyAttributeNone); +JSObjectRef CYGetPrototype(JSContextRef context, JSObjectRef object); void CYSetPrototype(JSContextRef context, JSObjectRef object, JSValueRef prototype); JSValueRef CYGetCachedValue(JSContextRef context, JSStringRef name); @@ -90,12 +93,15 @@ JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name); JSValueRef CYCastJSValue(JSContextRef context, bool value); JSValueRef CYCastJSValue(JSContextRef context, double value); -JSValueRef CYCastJSValue(JSContextRef context, int value); + +JSValueRef CYCastJSValue(JSContextRef context, signed short int value); +JSValueRef CYCastJSValue(JSContextRef context, unsigned short int value); +JSValueRef CYCastJSValue(JSContextRef context, signed int value); JSValueRef CYCastJSValue(JSContextRef context, unsigned int value); -JSValueRef CYCastJSValue(JSContextRef context, long int value); -JSValueRef CYCastJSValue(JSContextRef context, long unsigned int value); -JSValueRef CYCastJSValue(JSContextRef context, long long int value); -JSValueRef CYCastJSValue(JSContextRef context, long long unsigned int value); +JSValueRef CYCastJSValue(JSContextRef context, signed long int value); +JSValueRef CYCastJSValue(JSContextRef context, unsigned long int value); +JSValueRef CYCastJSValue(JSContextRef context, signed long long int value); +JSValueRef CYCastJSValue(JSContextRef context, unsigned long long int value); JSValueRef CYCastJSValue(JSContextRef context, JSStringRef value); JSValueRef CYCastJSValue(JSContextRef context, const char *value); @@ -142,6 +148,8 @@ JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type); void CYFinalize(JSObjectRef object); +JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const JSValueRef values[]); + size_t CYArrayLength(JSContextRef context, JSObjectRef array); JSValueRef CYArrayGet(JSContextRef context, JSObjectRef array, size_t index); @@ -153,6 +161,7 @@ const char *CYPoolCString(CYPool &pool, JSContextRef context, JSValueRef value); JSStringRef CYCopyJSString(const char *value); JSStringRef CYCopyJSString(JSStringRef value); JSStringRef CYCopyJSString(CYUTF8String value); +JSStringRef CYCopyJSString(const std::string &value); JSStringRef CYCopyJSString(CYUTF16String value); JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value); @@ -206,6 +215,43 @@ class CYJSString { } }; +template +class CYArrayBuilder { + private: + JSContextRef context_; + JSObjectRef &array_; + size_t size_; + JSValueRef values_[Size_]; + + void flush() { + if (array_ == NULL) + array_ = CYObjectMakeArray(context_, size_, values_); + else + CYArrayPush(context_, array_, size_, values_); + } + + public: + CYArrayBuilder(JSContextRef context, JSObjectRef &array) : + context_(context), + array_(array), + size_(0) + { + } + + ~CYArrayBuilder() { + flush(); + } + + void operator ()(JSValueRef value) { + if (size_ == Size_) { + flush(); + size_ = 0; + } + + values_[size_++] = value; + } +}; + #ifdef __APPLE__ #define _weak __attribute__((__weak_import__)); #else diff --git a/Makefile.am b/Makefile.am index 82536eb..64ed082 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,6 +37,9 @@ AM_OBJCXXFLAGS += -fobjc-exceptions CY_LDFLAGS = -no-undefined -avoid-version -export-dynamic +datdir = $(libdir) +dat_DATA = + lib_LTLIBRARIES = lib_LTLIBRARIES += libcycript.la @@ -59,13 +62,11 @@ if CY_EXECUTE libcycript_la_SOURCES += sig/ffi_type.cpp sig/parse.cpp sig/copy.cpp libcycript_la_SOURCES += Execute.cpp JavaScriptCore.cpp libcycript_la_LIBADD += $(LTJAVASCRIPTCORE) +dat_DATA += libcycript.db AM_CPPFLAGS += -DCY_EXECUTE filters += C -datdir = $(libdir) -dat_DATA = libcycript.db - CLEANFILES += libcycript.db libcycript.db: Bridge.def libcycript.sh $(srcdir)/libcycript.sh $(CY_SYSTEM) $@ $< @@ -97,6 +98,17 @@ if CY_JAVA filters += Java libcycript_la_SOURCES += Java/Execute.cpp libcycript_la_LIBADD += $(LTJAVA) +dat_DATA += libcycript.jar + +CLEANFILES += Class +Class/Cycript.class: Java/Cycript.java + rm -rf Class; mkdir Class; javac -g -Xlint:unchecked -source 1.5 -target 1.5 -d Class -sourcepath $(srcdir)/Java $< +Class/classes.dex: Class/Cycript.class + cd Class; dx --dex --output=../$@ *.class + +CLEANFILES += libcycript.jar +libcycript.jar: Class/classes.dex Class/Cycript.class + cd Class; jar cf ../$@ * endif if CY_RUBY diff --git a/Makefile.in b/Makefile.in index e66ec1d..90e3543 100644 --- a/Makefile.in +++ b/Makefile.in @@ -114,24 +114,27 @@ host_triplet = @host@ @CY_EXECUTE_TRUE@am__append_2 = sig/ffi_type.cpp sig/parse.cpp \ @CY_EXECUTE_TRUE@ sig/copy.cpp Execute.cpp JavaScriptCore.cpp @CY_EXECUTE_TRUE@am__append_3 = $(LTJAVASCRIPTCORE) -@CY_EXECUTE_TRUE@am__append_4 = -DCY_EXECUTE -@CY_EXECUTE_TRUE@am__append_5 = C -@CY_EXECUTE_TRUE@am__append_6 = libcycript.db -@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@am__append_7 = Analyze Bridge.def -@CY_EXECUTE_TRUE@@CY_PRELINK_FALSE@am__append_8 = Bridge.def -@CY_EXECUTE_TRUE@am__append_9 = Bridge.gperf Bridge.hpp -@CY_JAVA_TRUE@am__append_10 = Java -@CY_JAVA_TRUE@am__append_11 = Java/Execute.cpp -@CY_JAVA_TRUE@am__append_12 = $(LTJAVA) -@CY_RUBY_TRUE@am__append_13 = Ruby Python -@CY_RUBY_TRUE@am__append_14 = Ruby/Execute.cpp Python/Execute.cpp -@CY_RUBY_TRUE@am__append_15 = $(LTRUBY) $(LTPYTHON) -@CY_OBJECTIVEC_TRUE@am__append_16 = ObjectiveC -@CY_OBJECTIVEC_TRUE@am__append_17 = ObjectiveC/Output.cpp ObjectiveC/Replace.cpp ObjectiveC/Library.mm -@CY_OBJECTIVEC_TRUE@am__append_18 = $(LTOBJECTIVEC) -@CY_ATTACH_TRUE@am__append_19 = Handler.cpp -@CY_ATTACH_TRUE@@CY_CONSOLE_TRUE@am__append_20 = Inject.cpp -@CY_ATTACH_TRUE@@CY_CONSOLE_TRUE@am__append_21 = -DCY_ATTACH +@CY_EXECUTE_TRUE@am__append_4 = libcycript.db +@CY_EXECUTE_TRUE@am__append_5 = -DCY_EXECUTE +@CY_EXECUTE_TRUE@am__append_6 = C +@CY_EXECUTE_TRUE@am__append_7 = libcycript.db +@CY_EXECUTE_TRUE@@CY_PRELINK_TRUE@am__append_8 = Analyze Bridge.def +@CY_EXECUTE_TRUE@@CY_PRELINK_FALSE@am__append_9 = Bridge.def +@CY_EXECUTE_TRUE@am__append_10 = Bridge.gperf Bridge.hpp +@CY_JAVA_TRUE@am__append_11 = Java +@CY_JAVA_TRUE@am__append_12 = Java/Execute.cpp +@CY_JAVA_TRUE@am__append_13 = $(LTJAVA) +@CY_JAVA_TRUE@am__append_14 = libcycript.jar +@CY_JAVA_TRUE@am__append_15 = Class libcycript.jar +@CY_RUBY_TRUE@am__append_16 = Ruby Python +@CY_RUBY_TRUE@am__append_17 = Ruby/Execute.cpp Python/Execute.cpp +@CY_RUBY_TRUE@am__append_18 = $(LTRUBY) $(LTPYTHON) +@CY_OBJECTIVEC_TRUE@am__append_19 = ObjectiveC +@CY_OBJECTIVEC_TRUE@am__append_20 = ObjectiveC/Output.cpp ObjectiveC/Replace.cpp ObjectiveC/Library.mm +@CY_OBJECTIVEC_TRUE@am__append_21 = $(LTOBJECTIVEC) +@CY_ATTACH_TRUE@am__append_22 = Handler.cpp +@CY_ATTACH_TRUE@@CY_CONSOLE_TRUE@am__append_23 = Inject.cpp +@CY_ATTACH_TRUE@@CY_CONSOLE_TRUE@am__append_24 = -DCY_ATTACH subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ @@ -573,36 +576,36 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects -CLEANFILES = $(am__append_6) $(am__append_7) $(am__append_8) \ - $(am__append_9) Parser.ypp Scanner.lpp Scanner.cpp \ - Scanner.output lex.backup Parser.cpp Parser.hpp stack.hh \ - Parser.output +CLEANFILES = $(am__append_7) $(am__append_8) $(am__append_9) \ + $(am__append_10) $(am__append_15) Parser.ypp Scanner.lpp \ + Scanner.cpp Scanner.output lex.backup Parser.cpp Parser.hpp \ + stack.hh Parser.output SUBDIRS = ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -DYYDEBUG=1 -DCY_SYSTEM="\"$(CY_SYSTEM)\"" -include \ - config.h -include $(srcdir)/unconfig.h $(am__append_4) \ - $(am__append_21) + config.h -include $(srcdir)/unconfig.h $(am__append_5) \ + $(am__append_24) AM_CFLAGS = -fvisibility=hidden AM_CXXFLAGS = -fvisibility=hidden AM_OBJCXXFLAGS = -fvisibility=hidden -fobjc-exceptions AM_LDFLAGS = -fvisibility=hidden CY_LDFLAGS = -no-undefined -avoid-version -export-dynamic +datdir = $(libdir) +dat_DATA = $(am__append_4) $(am__append_14) lib_LTLIBRARIES = libcycript.la libcycript_la_LDFLAGS = $(CY_LDFLAGS) libcycript_la_LIBADD = $(LTLIBUV) $(LTLIBFFI) $(LTLIBSQLITE3) \ - $(LTLIBGCC) -ldl $(am__append_3) $(am__append_12) \ - $(am__append_15) $(am__append_18) + $(LTLIBGCC) -ldl $(am__append_3) $(am__append_13) \ + $(am__append_18) $(am__append_21) libcycript_la_SOURCES = ConvertUTF.c Decode.cpp Driver.cpp Error.cpp \ Highlight.cpp Library.cpp Network.cpp Output.cpp Replace.cpp \ Syntax.cpp Parser.cpp Scanner.cpp $(am__append_1) \ - $(am__append_2) $(am__append_11) $(am__append_14) \ - $(am__append_17) $(am__append_19) -filters = $(am__append_5) $(am__append_10) $(am__append_13) \ - $(am__append_16) -@CY_CONSOLE_TRUE@cycript_SOURCES = Console.cpp $(am__append_20) + $(am__append_2) $(am__append_12) $(am__append_17) \ + $(am__append_20) $(am__append_22) +filters = $(am__append_6) $(am__append_11) $(am__append_16) \ + $(am__append_19) +@CY_CONSOLE_TRUE@cycript_SOURCES = Console.cpp $(am__append_23) @CY_CONSOLE_TRUE@cycript_LDADD = libcycript.la $(LTLIBREADLINE) $(LTLIBTERMCAP) $(LTLIBGCC) $(PTHREAD_CFLAGS) -ldl -@CY_EXECUTE_TRUE@datdir = $(libdir) -@CY_EXECUTE_TRUE@dat_DATA = libcycript.db all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -1400,6 +1403,12 @@ uninstall-am: uninstall-binPROGRAMS uninstall-datDATA \ @CY_EXECUTE_TRUE@ $(srcdir)/Bridge.sh <$< >$@ @CY_EXECUTE_TRUE@Bridge.hpp: Bridge.gperf @CY_EXECUTE_TRUE@ $(GPERF) $< >$@ +@CY_JAVA_TRUE@Class/Cycript.class: Java/Cycript.java +@CY_JAVA_TRUE@ rm -rf Class; mkdir Class; javac -g -Xlint:unchecked -source 1.5 -target 1.5 -d Class -sourcepath $(srcdir)/Java $< +@CY_JAVA_TRUE@Class/classes.dex: Class/Cycript.class +@CY_JAVA_TRUE@ cd Class; dx --dex --output=../$@ *.class +@CY_JAVA_TRUE@libcycript.jar: Class/classes.dex Class/Cycript.class +@CY_JAVA_TRUE@ cd Class; jar cf ../$@ * Parser.ypp: Parser.ypp.in $(srcdir)/Filter.sh $< >$@ $(filters) Scanner.lpp: Scanner.lpp.in UnicodeIDStart.l UnicodeIDContinue.l diff --git a/ObjectiveC/Internal.hpp b/ObjectiveC/Internal.hpp index 4946148..a19b076 100644 --- a/ObjectiveC/Internal.hpp +++ b/ObjectiveC/Internal.hpp @@ -27,16 +27,16 @@ #include "../Internal.hpp" struct Selector_privateData : - CYValue_ + CYValue { _finline Selector_privateData(SEL value) : - CYValue_(value) + CYValue(value) { } }; struct Instance : - CYValue_ + CYValue { enum Flags { None = 0, @@ -60,22 +60,22 @@ struct Instance : namespace cy { struct Super : - CYValue_ + CYValue { Class class_; _finline Super(id value, Class _class) : - CYValue_(value), + CYValue(value), class_(_class) { } }; } struct Messages : - CYValue_ + CYValue { _finline Messages(Class value) : - CYValue_(value) + CYValue(value) { } @@ -83,12 +83,12 @@ struct Messages : }; struct Internal : - CYValue_ + CYValue { CYProtect owner_; _finline Internal(id value, JSContextRef context, JSObjectRef owner) : - CYValue_(value), + CYValue(value), owner_(context, owner) { } diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 49dede4..11a1305 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -296,7 +296,6 @@ JSValueRef CYGetClassPrototype(JSContextRef context, Class self, bool meta) { if (!JSValueIsUndefined(context, value)) return value; - JSClassRef _class(NULL); JSValueRef prototype; #ifdef __APPLE__ @@ -318,7 +317,7 @@ JSValueRef CYGetClassPrototype(JSContextRef context, Class self, bool meta) { else prototype = CYGetClassPrototype(context, class_getSuperclass(self), meta); - JSObjectRef object(JSObjectMake(context, _class, NULL)); + JSObjectRef object(JSObjectMake(context, NULL, NULL)); CYSetPrototype(context, object, prototype); CYSetProperty(context, cy, name, object); @@ -330,7 +329,7 @@ _finline JSValueRef CYGetClassPrototype(JSContextRef context, Class self) { } JSValueRef Messages::GetPrototype(JSContextRef context) const { - if (Class super = class_getSuperclass(GetValue())) + if (Class super = class_getSuperclass(value_)) return Messages::Make(context, super); return NULL; } @@ -343,7 +342,7 @@ bool CYIsKindOfClass(id object, Class _class) { } JSValueRef Instance::GetPrototype(JSContextRef context) const { - return CYGetClassPrototype(context, object_getClass(GetValue())); + return CYGetClassPrototype(context, object_getClass(value_)); } JSClassRef Instance::GetClass(id object, Flags flags) { @@ -351,16 +350,16 @@ JSClassRef Instance::GetClass(id object, Flags flags) { } Instance::Instance(id value, Flags flags) : - CYValue_(value), + CYValue(value), flags_(flags) { if ((flags & Instance::Permanent) == 0) - value_ = [GetValue() retain]; + value_ = [value_ retain]; } Instance::~Instance() { if ((flags_ & Permanent) == 0) - [GetValue() release]; + [value_ release]; } struct Message_privateData : @@ -644,7 +643,7 @@ NSBlock *CYMakeBlock(JSContextRef context, JSObjectRef function, sig::Signature memset(&descriptor->d_, 0, sizeof(descriptor->d_)); descriptor->internal_ = CYMakeFunctor_(context, function, signature, &BlockAdapter_); - literal->invoke = reinterpret_cast(descriptor->internal_->GetValue()); + literal->invoke = reinterpret_cast(descriptor->internal_->value_); literal->isa = __NSMallocBlock__; literal->flags = BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL; @@ -662,7 +661,7 @@ NSBlock *CYMakeBlock(JSContextRef context, JSObjectRef function, sig::Signature NSObject *CYCastNSObject(CYPool *pool, JSContextRef context, JSObjectRef object) { if (CYJSValueIsNSObject(context, object)) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return internal->GetValue(); + return internal->value_; } bool array(CYJSValueIsInstanceOfCachedConstructor(context, object, Array_s)); @@ -1501,10 +1500,10 @@ static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef val JSObjectRef object(CYCastJSObject(context, value)); if (JSValueIsObjectOfClass(context, object, FunctionInstance_)) - return reinterpret_cast(JSObjectGetPrivate(object))->GetValue(); + return reinterpret_cast(JSObjectGetPrivate(object))->value_; if (JSValueIsObjectOfClass(context, object, Instance::Class_)) { - _assert(reinterpret_cast(JSObjectGetPrivate(object))->GetValue() == nil); + _assert(reinterpret_cast(JSObjectGetPrivate(object))->value_ == nil); return nil; } @@ -1618,12 +1617,12 @@ static IMP CYMakeMessage(JSContextRef context, JSValueRef value, const char *enc sig::Parse(pool, &signature, encoding, &Structor_); Closure_privateData *internal(CYMakeFunctor_(context, function, signature, &MessageAdapter_)); // XXX: see notes in Library.cpp about needing to leak - return reinterpret_cast(internal->GetValue()); + return reinterpret_cast(internal->value_); } static bool Messages_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Class _class(internal->GetValue()); + Class _class(internal->value_); CYPool pool; const char *name(CYPoolCString(pool, context, property)); @@ -1637,7 +1636,7 @@ static bool Messages_hasProperty(JSContextRef context, JSObjectRef object, JSStr static JSValueRef Messages_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Class _class(internal->GetValue()); + Class _class(internal->value_); CYPool pool; const char *name(CYPoolCString(pool, context, property)); @@ -1651,7 +1650,7 @@ static JSValueRef Messages_getProperty(JSContextRef context, JSObjectRef object, static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Class _class(internal->GetValue()); + Class _class(internal->value_); CYPool pool; const char *name(CYPoolCString(pool, context, property)); @@ -1663,7 +1662,7 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr if (JSValueIsObjectOfClass(context, value, Message_privateData::Class_)) { Message_privateData *message(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); type = sig::Unparse(pool, &message->signature_); - imp = reinterpret_cast(message->GetValue()); + imp = reinterpret_cast(message->value_); } else if (objc_method *method = class_getInstanceMethod(_class, sel)) { type = method_getTypeEncoding(method); imp = CYMakeMessage(context, value, type); @@ -1689,7 +1688,7 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr static void Messages_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); - Class _class(internal->GetValue()); + Class _class(internal->value_); unsigned int size; objc_method **data(class_copyMethodList(_class, &size)); @@ -1707,7 +1706,7 @@ static bool CYHasImplicitProperties(Class _class) { static bool Instance_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (JSStringIsEqualToUTF8CString(property, "$cyi")) return true; @@ -1743,7 +1742,7 @@ static bool Instance_hasProperty(JSContextRef context, JSObjectRef object, JSStr static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (JSStringIsEqualToUTF8CString(property, "$cyi")) return Internal::Make(context, self, context, object); @@ -1779,7 +1778,7 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); CYPool pool; @@ -1837,7 +1836,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); CYPoolTry { NSString *name(CYCastNSString(NULL, context, property)); @@ -1859,7 +1858,7 @@ static void Instance_getPropertyNames_message(JSPropertyNameAccumulatorRef names static void Instance_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); CYPool pool; Class _class(object_getClass(self)); @@ -1890,7 +1889,7 @@ static void Instance_getPropertyNames(JSContextRef context, JSObjectRef object, static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - JSObjectRef value(CYMakeInstance(context, [internal->GetValue() alloc], Instance::Uninitialized)); + JSObjectRef value(CYMakeInstance(context, [internal->value_ alloc], Instance::Uninitialized)); return value; } CYCatch(NULL) } @@ -1925,7 +1924,7 @@ static bool CYBlockSignature(CYPool &pool, NSBlock *self, sig::Signature &signat static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (const char *encoding = CYBlockEncoding(self)) { CYPool pool; @@ -1956,14 +1955,14 @@ static JSValueRef FunctionInstance_callAsFunction(JSContextRef context, JSObject static bool Instance_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef instance, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) constructor))); - Class _class(internal->GetValue()); + Class _class(internal->value_); if (!CYIsClass(_class)) return false; if (CYJSValueIsNSObject(context, instance)) { Instance *linternal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) instance))); // XXX: this isn't always safe - return [linternal->GetValue() isKindOfClass:_class]; + return [linternal->value_ isKindOfClass:_class]; } return false; @@ -1983,7 +1982,7 @@ static bool Internal_hasProperty(JSContextRef context, JSObjectRef object, JSStr Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; - id self(internal->GetValue()); + id self(internal->value_); const char *name(CYPoolCString(pool, context, property)); if (object_getInstanceVariable(self, name, NULL) != NULL) @@ -2014,7 +2013,7 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object, Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; - id self(internal->GetValue()); + id self(internal->value_); const char *name(CYPoolCString(pool, context, property)); if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) { @@ -2050,7 +2049,7 @@ static bool Internal_setProperty(JSContextRef context, JSObjectRef object, JSStr Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; - id self(internal->GetValue()); + id self(internal->value_); const char *name(CYPoolCString(pool, context, property)); if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) { @@ -2091,7 +2090,7 @@ static void Internal_getPropertyNames(JSContextRef context, JSObjectRef object, Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; - id self(internal->GetValue()); + id self(internal->value_); Class _class(object_getClass(self)); Internal_getPropertyNames_(_class, names); @@ -2420,12 +2419,12 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje if (JSValueIsObjectOfClass(context, arguments[0], cy::Super::Class_)) { cy::Super *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) arguments[0]))); - self = internal->GetValue(); + self = internal->value_; _class = internal->class_;; uninitialized = false; } else if (CYJSValueIsNSObject(context, arguments[0])) { Instance *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) arguments[0]))); - self = internal->GetValue(); + self = internal->value_; _class = nil; uninitialized = internal->IsUninitialized(); if (uninitialized) @@ -2467,7 +2466,7 @@ static JSValueRef Message_callAsFunction(JSContextRef context, JSObjectRef objec setup[0] = &self; setup[1] = &internal->sel_; - return CYCallFunction(pool, context, 2, setup, count, arguments, false, true, internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 2, setup, count, arguments, false, true, internal->signature_, &internal->cif_, internal->value_); } CYCatch(NULL) } static JSObjectRef Super_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2493,18 +2492,13 @@ static JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t return CYMakeInstance(context, CYCastPointer(context, arguments[0])); } CYCatch(NULL) } -static JSValueRef CYValue_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { - CYValue *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYCastJSValue(context, reinterpret_cast(internal->value_)); -} CYCatch(NULL) } - static JSValueRef Selector_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { return CYMakeType(context, sig::Selector()); } CYCatch(NULL) } static JSValueRef Instance_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (CYIsClass(self)) return CYMakeType(context, sig::Meta()); return CYMakeType(context, sig::Object(class_getName(object_getClass(self)))); @@ -2514,19 +2508,19 @@ static JSValueRef FunctionInstance_getProperty_$cyt(JSContextRef context, JSObje Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); CYPool pool; sig::Block type; - if (!CYBlockSignature(pool, internal->GetValue(), type.signature)) + if (!CYBlockSignature(pool, internal->value_, type.signature)) return CYJSNull(context); return CYMakeType(context, type); } CYCatch(NULL) } static JSValueRef Instance_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYMakeInstance(context, object_getClass(internal->GetValue()), Instance::Permanent); + return CYMakeInstance(context, object_getClass(internal->value_), Instance::Permanent); } CYCatch(NULL) } static JSValueRef Instance_getProperty_prototype(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (!CYIsClass(self)) return CYJSUndefined(context); return CYGetClassPrototype(context, self); @@ -2534,7 +2528,7 @@ static JSValueRef Instance_getProperty_prototype(JSContextRef context, JSObjectR static JSValueRef Instance_getProperty_messages(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - id self(internal->GetValue()); + id self(internal->value_); if (!CYIsClass(self)) return CYJSUndefined(context); return Messages::Make(context, (Class) self); @@ -2547,7 +2541,7 @@ static JSValueRef Instance_callAsFunction_toCYON(JSContextRef context, JSObjectR return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - return CYCastJSValue(context, CYJSString(context, CYCastNSCYON(internal->GetValue(), false, objects))); + return CYCastJSValue(context, CYJSString(context, CYCastNSCYON(internal->value_, false, objects))); } CYCatch(NULL) } static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2555,7 +2549,7 @@ static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectR return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - id value(internal->GetValue()); + id value(internal->value_); CYPoolTry { NSString *key; @@ -2578,7 +2572,7 @@ static JSValueRef Instance_callAsFunction_valueOf(JSContextRef context, JSObject return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - id value(internal->GetValue()); + id value(internal->value_); _assert(value != nil); if (![value respondsToSelector:@selector(cy$valueOfInContext:)]) @@ -2596,7 +2590,7 @@ static JSValueRef Instance_callAsFunction_toPointer(JSContextRef context, JSObje Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); // XXX: but... but... THIS ISN'T A POINTER! :( - return CYCastJSValue(context, reinterpret_cast(internal->GetValue())); + return CYCastJSValue(context, reinterpret_cast(internal->value_)); } CYCatch(NULL) return /*XXX*/ NULL; } static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2604,7 +2598,7 @@ static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjec return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - id value(internal->GetValue()); + id value(internal->value_); CYPoolTry { // XXX: this seems like a stupid implementation; what if it crashes? why not use the CYONifier backend? @@ -2617,7 +2611,7 @@ static JSValueRef Class_callAsFunction_pointerTo(JSContextRef context, JSObjectR return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - id value(internal->GetValue()); + id value(internal->value_); if (!CYIsClass(value)) CYThrow("non-Class object cannot be used as Type"); @@ -2628,7 +2622,7 @@ static JSValueRef Class_callAsFunction_pointerTo(JSContextRef context, JSObjectR static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - return CYCastJSValue(context, sel_getName(internal->GetValue())); + return CYCastJSValue(context, sel_getName(internal->value_)); } CYCatch(NULL) } static JSValueRef Selector_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @@ -2637,7 +2631,7 @@ static JSValueRef Selector_callAsFunction_toJSON(JSContextRef context, JSObjectR static JSValueRef Selector_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - const char *name(sel_getName(internal->GetValue())); + const char *name(sel_getName(internal->value_)); CYPoolTry { NSString *string([NSString stringWithFormat:@"@selector(%s)", name]); @@ -2651,7 +2645,7 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef CYPool pool; Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - SEL sel(internal->GetValue()); + SEL sel(internal->value_); Class _class(_require(CYCastClass(pool, context, arguments[0]))); objc_method *method(_require(class_getInstanceMethod(_class, sel))); @@ -2662,29 +2656,26 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef return CYMakeType(context, type); } CYCatch(NULL) } -static JSStaticValue Selector_staticValues[3] = { +static JSStaticValue Selector_staticValues[2] = { {"$cyt", &Selector_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; -static JSStaticValue Instance_staticValues[6] = { +static JSStaticValue Instance_staticValues[5] = { {"$cyt", &Instance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, // XXX: this is sadly duplicated in FunctionInstance_staticValues {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"prototype", &Instance_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; -static JSStaticValue FunctionInstance_staticValues[6] = { +static JSStaticValue FunctionInstance_staticValues[5] = { {"$cyt", &FunctionInstance_getProperty_$cyt, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, // XXX: this is sadly a duplicate of Instance_staticValues {"constructor", &Instance_getProperty_constructor, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"messages", &Instance_getProperty_messages, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"prototype", &Instance_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, - {"value", &CYValue_getProperty_value, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} }; @@ -2897,11 +2888,11 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { CYSetProperty(context, ObjectiveC, CYJSString("images"), JSObjectMake(context, ObjectiveC_Images_, NULL)); #endif - JSObjectRef Instance(JSObjectMakeConstructor(context, Instance::Class_, &Instance_new)); JSObjectRef Message(JSObjectMakeConstructor(context, Message_privateData::Class_, NULL)); JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_privateData::Class_, &Selector_new)); JSObjectRef Super(JSObjectMakeConstructor(context, cy::Super::Class_, &Super_new)); + JSObjectRef Instance(JSObjectMakeConstructor(context, Instance::Class_, &Instance_new)); JSObjectRef Instance_prototype(CYCastJSObject(context, CYGetProperty(context, Instance, prototype_s))); CYSetProperty(context, cy, CYJSString("Instance_prototype"), Instance_prototype); diff --git a/String.hpp b/String.hpp index e0e292e..57814a4 100644 --- a/String.hpp +++ b/String.hpp @@ -23,6 +23,7 @@ #define CYCRIPT_STRING_HPP #include +#include #include "Pooling.hpp" @@ -52,6 +53,10 @@ struct CYUTF8String { size_t length(strlen(data)); return length == size && memcmp(value, data, length) == 0; } + + operator std::string() const { + return std::string(data, size); + } }; static inline std::ostream &operator <<(std::ostream &lhs, const CYUTF8String &rhs) { diff --git a/Utility.hpp b/Utility.hpp index c2aa4e3..9111eba 100644 --- a/Utility.hpp +++ b/Utility.hpp @@ -44,6 +44,11 @@ inline T &&Forward(typename cy::remove_reference::type &&t) noexcept { return static_cast(t); } +template +inline typename cy::remove_reference::type &&Move(T &&t) { + return static_cast::type &&>(t); +} + } #endif/*CYCRIPT_UTILITY_HPP*/ diff --git a/apple.mk b/apple.mk index 1ad1ccf..d20ab22 100644 --- a/apple.mk +++ b/apple.mk @@ -39,6 +39,7 @@ cycript += Cycript.lib/libcycript-sys.dylib cycript += Cycript.lib/libcycript-sim.dylib cycript += Cycript.lib/libcycript.cy cycript += Cycript.lib/libcycript.db +cycript += Cycript.lib/libcycript.jar framework := framework += Cycript @@ -209,6 +210,10 @@ Cycript.lib/libcycript.db: $(db) ./libcycript.sh 0 $@ ./libcycript.py $@ $^ +Cycript.lib/libcycript.jar: build.osx-x86_64/libcycript.jar + @mkdir -p $(dir $@) + cp -af $< $@ + Cycript.lib/cycript0.9: @mkdir -p $(dir $@) ln -s ../modules $@ diff --git a/libcycript.cy b/libcycript.cy index 4014fd6..88fe069 100644 --- a/libcycript.cy +++ b/libcycript.cy @@ -83,6 +83,56 @@ $cy_set(RegExp.prototype, { }, }); +if ("Java" in Cycript) { + $cy_set(java.lang.Boolean.prototype, { + toCYON: function() { + return `new java.lang.Boolean(${this.value})`; + }, + }); + + $cy_set(java.lang.Byte.prototype, { + toCYON: function() { + return `new java.lang.Byte(${this.value})`; + }, + }); + + $cy_set(java.lang.Character.prototype, { + toCYON: function() { + return `new java.lang.Character(${this.value})`; + }, + }); + + $cy_set(java.lang.Short.prototype, { + toCYON: function() { + return `new java.lang.Short(${this.value})`; + }, + }); + + $cy_set(java.lang.Integer.prototype, { + toCYON: function() { + return `new java.lang.Integer(${this.value})`; + }, + }); + + $cy_set(java.lang.Long.prototype, { + toCYON: function() { + return `new java.lang.Long(${this.value})`; + }, + }); + + $cy_set(java.lang.Float.prototype, { + toCYON: function() { + return `new java.lang.Float(${this.value})`; + }, + }); + + $cy_set(java.lang.Double.prototype, { + toCYON: function() { + return `new java.lang.Double(${this.value})`; + }, + }); +} + let IsFile = function(path) { // XXX: this doesn't work on symlinks, but I don't want to fix stat :/ return access(path, F_OK) == 0 && access(path + '/', F_OK) == -1; -- 2.45.2