X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/04450da07de267133734cde8dbf426422e253524..5a36c6cf6ef94d7f7c6b55c8acf05e81ea0c64b3:/Tweak.mm diff --git a/Tweak.mm b/Tweak.mm index 2be2afc..0efe892 100644 --- a/Tweak.mm +++ b/Tweak.mm @@ -134,6 +134,14 @@ class _H { #define _pooled _H _pool([[NSAutoreleasePool alloc] init], true); +void *operator new(size_t size, apr_pool_t *pool) { + return apr_palloc(pool, size); +} + +void *operator new [](size_t size, apr_pool_t *pool) { + return apr_palloc(pool, size); +} + static JSContextRef Context_; static JSClassRef ffi_; @@ -154,6 +162,10 @@ struct Client { CFSocketRef socket_; }; +JSObjectRef CYMakeObject(JSContextRef context, id object) { + return JSObjectMake(context, joc_, [object retain]); +} + @interface NSMethodSignature (Cyrver) - (NSString *) _typeString; @end @@ -170,7 +182,7 @@ struct Client { } - (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return JSObjectMake(context, joc_, [self retain]); + return CYMakeObject(context, self); } @end @@ -264,7 +276,7 @@ struct Client { @end -@interface CY$JSObject : NSDictionary { +@interface CYJSObject : NSDictionary { JSObjectRef object_; JSContextRef context_; } @@ -279,7 +291,7 @@ struct Client { @end -@interface CY$JSArray : NSArray { +@interface CYJSArray : NSArray { JSObjectRef object_; JSContextRef context_; } @@ -295,17 +307,23 @@ JSContextRef JSGetContext() { return Context_; } +#define CYCatch \ + @catch (id error) { \ + CYThrow(context, error, exception); \ + return NULL; \ + } + void CYThrow(JSContextRef context, JSValueRef value); -id JSObjectToNSObject(JSContextRef context, JSObjectRef object) { +id CYCastNSObject(JSContextRef context, JSObjectRef object) { if (JSValueIsObjectOfClass(context, object, joc_)) return reinterpret_cast(JSObjectGetPrivate(object)); JSValueRef exception(NULL); bool array(JSValueIsInstanceOfConstructor(context, object, Array_, &exception)); CYThrow(context, exception); if (array) - return [[[CY$JSArray alloc] initWithJSObject:object inContext:context] autorelease]; - return [[[CY$JSObject alloc] initWithJSObject:object inContext:context] autorelease]; + return [[[CYJSArray alloc] initWithJSObject:object inContext:context] autorelease]; + return [[[CYJSObject alloc] initWithJSObject:object inContext:context] autorelease]; } CFStringRef CYCopyCFString(JSStringRef value) { @@ -321,44 +339,33 @@ CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) { return object; } +CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { + JSValueRef exception(NULL); + double number(JSValueToNumber(context, value, &exception)); + CYThrow(context, exception); + return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); +} + NSString *CYCastNSString(JSStringRef value) { return [reinterpret_cast(CYCopyCFString(value)) autorelease]; } CFTypeRef CYCopyCFType(JSContextRef context, JSValueRef value) { - JSType type(JSValueGetType(context, value)); - - switch (type) { + switch (JSValueGetType(context, value)) { case kJSTypeUndefined: return CFRetain([WebUndefined undefined]); - break; - case kJSTypeNull: return nil; - break; - case kJSTypeBoolean: return CFRetain(JSValueToBoolean(context, value) ? kCFBooleanTrue : kCFBooleanFalse); - break; - - case kJSTypeNumber: { - JSValueRef exception(NULL); - double number(JSValueToNumber(context, value, &exception)); - CYThrow(context, exception); - return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); - } break; - + case kJSTypeNumber: + return CYCopyCFNumber(context, value); case kJSTypeString: return CYCopyCFString(context, value); - break; - case kJSTypeObject: - return CFRetain((CFTypeRef) JSObjectToNSObject(context, (JSObjectRef) value)); - break; - + return CFRetain((CFTypeRef) CYCastNSObject(context, (JSObjectRef) value)); default: _assert(false); - break; } } @@ -421,7 +428,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { *exception = CYCastJSValue(context, error); } -@implementation CY$JSObject +@implementation CYJSObject - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { if ((self = [super init]) != nil) { @@ -466,7 +473,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { @end -@implementation CY$JSArray +@implementation CYJSArray - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { if ((self = [super init]) != nil) { @@ -578,13 +585,22 @@ static JSValueRef joc_getProperty(JSContextRef context, JSObjectRef object, JSSt typedef id jocData; +static JSObjectRef joc_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled + @try { + id data(reinterpret_cast(JSObjectGetPrivate(object))); + return CYMakeObject(context, [[data alloc] autorelease]); + } CYCatch +} + struct ptrData { + apr_pool_t *pool_; void *value_; + sig::Type type_; }; static void ptr_finalize(JSObjectRef object) { ptrData *data(reinterpret_cast(JSObjectGetPrivate(object))); - free(data); + apr_pool_destroy(data->pool_); } static void joc_finalize(JSObjectRef object) { @@ -592,10 +608,10 @@ static void joc_finalize(JSObjectRef object) { [data release]; } -static JSValueRef obc_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef *exception) { +static JSValueRef obc_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef *exception) { _pooled NSString *name([(NSString *) JSStringCopyCFString(kCFAllocatorDefault, propertyName) autorelease]); if (Class _class = NSClassFromString(name)) - return JSObjectMake(context, joc_, [_class retain]); + return CYMakeObject(context, _class); return NULL; } @@ -615,26 +631,49 @@ struct ffiData { char *CYPoolCString(apr_pool_t *pool, JSStringRef value) { size_t size(JSStringGetMaximumUTF8CStringSize(value)); - char *string(reinterpret_cast(apr_palloc(pool, size))); + char *string(new(pool) char[size]); JSStringGetUTF8CString(value, string, size); JSStringRelease(value); return string; } +// XXX: this macro is dangerous +#define CYCastCString(context, value) ({ \ + JSValueRef exception(NULL); \ + JSStringRef string(JSValueToStringCopy(context, value, &exception)); \ + CYThrow(context, exception); \ + size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ + char *utf8(reinterpret_cast(alloca(size))); \ + JSStringGetUTF8CString(string, utf8, size); \ + JSStringRelease(string); \ + utf8; \ +}) + SEL CYCastSEL(JSContextRef context, JSValueRef value) { if (JSValueIsNull(context, value)) return NULL; else if (JSValueIsObjectOfClass(context, value, sel_)) return reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value)); - else { - JSValueRef exception(NULL); - JSStringRef string(JSValueToStringCopy(context, value, &exception)); - CYThrow(context, exception); - size_t size(JSStringGetMaximumUTF8CStringSize(string)); - char utf8[size]; - JSStringGetUTF8CString(string, utf8, size); - JSStringRelease(string); - return sel_registerName(utf8); + else + return sel_registerName(CYCastCString(context, value)); +} + +void *CYCastPointer(JSContextRef context, JSValueRef value) { + switch (JSValueGetType(context, value)) { + case kJSTypeNull: + return NULL; + case kJSTypeString: + return dlsym(RTLD_DEFAULT, CYCastCString(context, value)); + case kJSTypeObject: + if (JSValueIsObjectOfClass(context, value, ptr_)) { + ptrData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); + return data->value_; + } + default: + JSValueRef exception(NULL); + double number(JSValueToNumber(context, value, &exception)); + CYThrow(context, exception); + return reinterpret_cast(static_cast(number)); } } @@ -674,27 +713,16 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *da *reinterpret_cast(data) = CYCastSEL(context, value); break; - case sig::pointer_P: { - void *&pointer(*reinterpret_cast(data)); - if (JSValueIsNull(context, value)) - pointer = NULL; - else if (JSValueIsObjectOfClass(context, value, ptr_)) { - ptrData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); - pointer = data->value_; - } else { - JSValueRef exception(NULL); - double number(JSValueToNumber(context, value, &exception)); - CYThrow(context, exception); - pointer = reinterpret_cast(static_cast(number)); - } - } break; + case sig::pointer_P: + *reinterpret_cast(data) = CYCastPointer(context, value); + break; case sig::string_P: { JSValueRef exception(NULL); JSStringRef string(JSValueToStringCopy(context, value, &exception)); CYThrow(context, exception); size_t size(JSStringGetMaximumUTF8CStringSize(string)); - char *utf8(reinterpret_cast(apr_palloc(pool, size))); + char *utf8(new(pool) char[size]); JSStringGetUTF8CString(string, utf8, size); JSStringRelease(string); *reinterpret_cast(data) = utf8; @@ -750,7 +778,10 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { case sig::pointer_P: { if (void *pointer = *reinterpret_cast(data)) { - ptrData *data(reinterpret_cast(malloc(sizeof(ptrData)))); + apr_pool_t *pool; + apr_pool_create(&pool, NULL); + ptrData *data(new(pool) ptrData()); + data->pool_ = pool; data->value_ = pointer; value = JSObjectMake(context, ptr_, data); } else value = JSValueMakeNull(context); @@ -794,7 +825,7 @@ class CYPool { } }; -static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { +static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { _pooled @try { if (count != signature->count - 1) [NSException raise:NSInvalidArgumentException format:@"incorrect number of arguments to ffi function"]; @@ -804,7 +835,7 @@ static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSVal for (unsigned index(0); index != count; ++index) { sig::Element *element(&signature->elements[index + 1]); - values[index] = apr_palloc(pool, cif->arg_types[index]->size); + values[index] = new(pool) uint8_t[cif->arg_types[index]->size]; CYPoolFFI(pool, context, element->type, values[index], arguments[index]); } @@ -812,10 +843,7 @@ static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSVal ffi_call(cif, function, value, values); return CYFromFFI(context, signature->elements[0].type, value); - } @catch (id error) { - CYThrow(context, error, exception); - return NULL; - } + } CYCatch } bool stret(ffi_type *ffi_type) { @@ -842,10 +870,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje [NSException raise:NSInvalidArgumentException format:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self]; type = [[method _typeString] UTF8String]; - } @catch (id error) { - CYThrow(context, error, exception); - return NULL; - } + } CYCatch CYPool pool; @@ -853,7 +878,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje sig::Parse(pool, &signature, type); ffi_cif cif; - sig::sig_ffi_cif(pool, &sig::sig_objc_ffi_type, &signature, &cif); + sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); void (*function)() = stret(cif.rtype) ? reinterpret_cast(&objc_msgSend_stret) : reinterpret_cast(&objc_msgSend); return CYCallFunction(context, count, arguments, exception, &signature, &cif, function); @@ -869,21 +894,30 @@ static void ffi_finalize(JSObjectRef object) { apr_pool_destroy(data->pool_); } -void CYSetFunction(JSContextRef context, JSObjectRef object, const char *name, void (*function)(), const char *type) { +JSObjectRef CYMakeFunction(JSContextRef context, void (*function)(), const char *type) { apr_pool_t *pool; apr_pool_create(&pool, NULL); - ffiData *data(reinterpret_cast(apr_palloc(pool, sizeof(ffiData)))); + ffiData *data(new(pool) ffiData()); data->pool_ = pool; data->function_ = function; data->type_ = apr_pstrdup(pool, type); sig::Parse(pool, &data->signature_, type); - sig::sig_ffi_cif(pool, &sig::sig_objc_ffi_type, &data->signature_, &data->cif_); + sig::sig_ffi_cif(pool, &sig::ObjectiveC, &data->signature_, &data->cif_); - JSObjectRef value(JSObjectMake(context, ffi_, data)); - CYSetProperty(context, object, name, value); + return JSObjectMake(context, ffi_, data); +} + +JSObjectRef ffi(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + @try { + if (count != 2) + [NSException raise:NSInvalidArgumentException format:@"incorrect number of arguments to ffi constructor"]; + void (*function)() = reinterpret_cast(CYCastPointer(context, arguments[0])); + const char *type(CYCastCString(context, arguments[1])); + return CYMakeFunction(context, function, type); + } CYCatch } JSValueRef ptr_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef *exception) { @@ -945,6 +979,7 @@ MSInitialize { _pooled definition = kJSClassDefinitionEmpty; definition.className = "joc"; definition.getProperty = &joc_getProperty; + definition.callAsConstructor = &joc_callAsConstructor; definition.finalize = &joc_finalize; joc_ = JSClassCreate(&definition); @@ -953,8 +988,11 @@ MSInitialize { _pooled JSObjectRef global(JSContextGetGlobalObject(context)); + CYSetProperty(context, global, "ffi", JSObjectMakeConstructor(context, ffi_, &ffi)); + CYSetProperty(context, global, "obc", JSObjectMake(context, obc, NULL)); + #define CYSetFunction_(name, type) \ - CYSetFunction(context, global, #name, reinterpret_cast(&name), type) + CYSetProperty(context, global, #name, CYMakeFunction(context, reinterpret_cast(&name), type)) CYSetFunction_(class_addIvar, "B#*LC*"); CYSetFunction_(class_addMethod, "B#:^?*");