X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/707bcb93a9381c936f6793366049a9ae4cab450a..262e358cce35d2730086f4b01942eb2f1145c104:/Tweak.mm?ds=inline diff --git a/Tweak.mm b/Tweak.mm index 43d6f2c..2a8bf97 100644 --- a/Tweak.mm +++ b/Tweak.mm @@ -70,11 +70,9 @@ #undef _assert #undef _trace -/* XXX: bad _assert */ #define _assert(test) do { \ - if ((test)) break; \ - CFLog(kCFLogLevelNotice, CFSTR("_assert(%s):%u"), #test, __LINE__); \ - throw; \ + if (!(test)) \ + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"_assert(%s):%s(%u):%s", #test, __FILE__, __LINE__, __FUNCTION__] userInfo:nil]; \ } while (false) #define _trace() do { \ @@ -187,24 +185,24 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { return JSObjectMake(context, Instance_, [object retain]); } -@interface NSMethodSignature (Cyrver) +@interface NSMethodSignature (Cycript) - (NSString *) _typeString; @end -@interface NSObject (Cyrver) +@interface NSObject (Cycript) - (NSString *) cy$toJSON; - (JSValueRef) cy$JSValueInContext:(JSContextRef)context; @end -@interface NSString (Cyrver) +@interface NSString (Cycript) - (void *) cy$symbol; @end -@interface NSNumber (Cyrver) +@interface NSNumber (Cycript) - (void *) cy$symbol; @end -@implementation NSObject (Cyrver) +@implementation NSObject (Cycript) - (NSString *) cy$toJSON { return [self description]; @@ -216,7 +214,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -@implementation WebUndefined (Cyrver) +@implementation WebUndefined (Cycript) - (NSString *) cy$toJSON { return @"undefined"; @@ -228,7 +226,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -@implementation NSArray (Cyrver) +@implementation NSArray (Cycript) - (NSString *) cy$toJSON { NSMutableString *json([[[NSMutableString alloc] init] autorelease]); @@ -249,7 +247,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -@implementation NSDictionary (Cyrver) +@implementation NSDictionary (Cycript) - (NSString *) cy$toJSON { NSMutableString *json([[[NSMutableString alloc] init] autorelease]); @@ -274,7 +272,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -@implementation NSNumber (Cyrver) +@implementation NSNumber (Cycript) - (NSString *) cy$toJSON { return [self class] != NSCFBoolean_ ? [self stringValue] : [self boolValue] ? @"true" : @"false"; @@ -290,7 +288,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -@implementation NSString (Cyrver) +@implementation NSString (Cycript) - (NSString *) cy$toJSON { CFMutableStringRef json(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) self)); @@ -415,10 +413,15 @@ CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) { return CYCopyCFString(CYString(context, value)); } -CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { +double CYCastDouble(JSContextRef context, JSValueRef value) { JSValueRef exception(NULL); double number(JSValueToNumber(context, value, &exception)); CYThrow(context, exception); + return number; +} + +CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { + double number(CYCastDouble(context, value)); return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); } @@ -427,7 +430,7 @@ NSString *CYCastNSString(JSStringRef value) { } CFTypeRef CYCopyCFType(JSContextRef context, JSValueRef value) { - switch (JSValueGetType(context, value)) { + switch (JSType type = JSValueGetType(context, value)) { case kJSTypeUndefined: return CFRetain([WebUndefined undefined]); case kJSTypeNull: @@ -441,7 +444,7 @@ CFTypeRef CYCopyCFType(JSContextRef context, JSValueRef value) { case kJSTypeObject: return CFRetain((CFTypeRef) CYCastNSObject(context, (JSObjectRef) value)); default: - _assert(false); + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"JSValueGetType() == 0x%x", type] userInfo:nil]; } } @@ -510,7 +513,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { - (void) removeObjectForKey:(id)key { JSValueRef exception(NULL); - // XXX: this returns a bool + // XXX: this returns a bool... throw exception, or ignore? JSObjectDeleteProperty(context_, object_, CYString(key), &exception); CYThrow(context_, exception); } @@ -530,9 +533,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { JSValueRef exception(NULL); JSValueRef value(JSObjectGetProperty(context_, object_, length_, &exception)); CYThrow(context_, exception); - double number(JSValueToNumber(context_, value, &exception)); - CYThrow(context_, exception); - return number; + return CYCastDouble(context_, value); } - (id) objectAtIndex:(NSUInteger)index { @@ -623,8 +624,12 @@ static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef ad } } -static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef *exception) { - return NULL; +static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled + @try { + NSString *name(CYCastNSString(property)); + NSLog(@"%@", name); + return NULL; + } CYCatch } typedef id jocData; @@ -712,7 +717,7 @@ char *CYPoolCString(apr_pool_t *pool, JSContextRef context, JSValueRef value) { return CYPoolCString(pool, CYString(context, value)); } -// XXX: this macro is dangerous +// XXX: this macro is unhygenic #define CYCastCString(context, value) ({ \ JSValueRef exception(NULL); \ JSStringRef string(JSValueToStringCopy(context, value, &exception)); \ @@ -741,16 +746,12 @@ void *CYCastPointer(JSContextRef context, JSValueRef value) { case kJSTypeString: return dlsym(RTLD_DEFAULT, CYCastCString(context, value)); case kJSTypeObject: - // XXX: maybe support more than just pointers, like ffis and sels if (JSValueIsObjectOfClass(context, value, Pointer_)) { 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)); + return reinterpret_cast(static_cast(CYCastDouble(context, value))); } } @@ -761,12 +762,9 @@ void CYPoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, void *da break; #define CYPoolFFI_(primitive, native) \ - case sig::primitive ## _P: { \ - JSValueRef exception(NULL); \ - double number(JSValueToNumber(context, value, &exception)); \ - CYThrow(context, exception); \ - *reinterpret_cast(data) = number; \ - } break; + case sig::primitive ## _P: \ + *reinterpret_cast(data) = CYCastDouble(context, value); \ + break; CYPoolFFI_(uchar, unsigned char) CYPoolFFI_(char, char) @@ -845,26 +843,31 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { if (SEL sel = *reinterpret_cast(data)) { selData *data(new selData(sel)); value = JSObjectMake(context, Selector_, data); - } else value = JSValueMakeNull(context); + } else goto null; } break; case sig::pointer_P: { if (void *pointer = *reinterpret_cast(data)) { ptrData *data(new ptrData(pointer)); value = JSObjectMake(context, Pointer_, data); - } else value = JSValueMakeNull(context); + } else goto null; } break; case sig::string_P: { - char *utf8(*reinterpret_cast(data)); - value = utf8 == NULL ? JSValueMakeNull(context) : JSValueMakeString(context, CYString(utf8)); + if (char *utf8 = *reinterpret_cast(data)) + value = JSValueMakeString(context, CYString(utf8)); + else goto null; } break; case sig::struct_P: goto fail; case sig::void_P: - value = NULL; + value = JSValueMakeUndefined(context); + break; + + null: + value = JSValueMakeNull(context); break; default: fail: @@ -878,7 +881,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { 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"]; + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi function" userInfo:nil]; CYPool pool; void *values[count]; @@ -897,22 +900,22 @@ static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSVal } CYCatch } -static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef *exception) { _pooled +static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { _pooled @try { - NSString *string(CYCastNSString(name)); - if (Class _class = NSClassFromString(string)) + NSString *name(CYCastNSString(property)); + if (Class _class = NSClassFromString(name)) return CYMakeObject(context, _class); - if (NSMutableArray *entry = [Bridge_ objectForKey:string]) + if (NSMutableArray *entry = [Bridge_ objectForKey:name]) switch ([[entry objectAtIndex:0] intValue]) { case 0: return JSEvaluateScript(JSGetContext(), CYString([entry objectAtIndex:1]), NULL, NULL, 0, NULL); case 1: - return CYMakeFunction(context, [string cy$symbol], [[entry objectAtIndex:1] UTF8String]); + return CYMakeFunction(context, [name cy$symbol], [[entry objectAtIndex:1] UTF8String]); case 2: CYPool pool; sig::Signature signature; sig::Parse(pool, &signature, [[entry objectAtIndex:1] UTF8String]); - return CYFromFFI(context, signature.elements[0].type, [string cy$symbol]); + return CYFromFFI(context, signature.elements[0].type, [name cy$symbol]); } return NULL; } CYCatch @@ -930,7 +933,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje @try { if (count < 2) - [NSException raise:NSInvalidArgumentException format:@"too few arguments to objc_msgSend"]; + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"too few arguments to objc_msgSend" userInfo:nil]; id self(CYCastNSObject(context, arguments[0])); if (self == nil) @@ -939,7 +942,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje SEL _cmd(CYCastSEL(context, arguments[1])); NSMethodSignature *method([self methodSignatureForSelector:_cmd]); if (method == nil) - [NSException raise:NSInvalidArgumentException format:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self]; + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil]; type = [[method _typeString] UTF8String]; } CYCatch @@ -964,14 +967,14 @@ static JSValueRef ffi_callAsFunction(JSContextRef context, JSObjectRef object, J 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"]; + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi constructor" userInfo:nil]; void *function(CYCastPointer(context, arguments[0])); const char *type(CYCastCString(context, arguments[1])); return CYMakeFunction(context, function, type); } CYCatch } -JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef *exception) { +JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { ptrData *data(reinterpret_cast(JSObjectGetPrivate(object))); return JSValueMakeNumber(context, reinterpret_cast(data->value_)); } @@ -1044,7 +1047,7 @@ MSInitialize { _pooled CYSetProperty(context, global, "objc_msgSend", JSObjectMakeFunctionWithCallback(context, CYString("objc_msgSend"), &$objc_msgSend)); - Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcyrver.plist"] retain]; + Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; name_ = JSStringCreateWithUTF8CString("name"); message_ = JSStringCreateWithUTF8CString("message");