X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/3b52fd1a20c639d7a716d3e0f3176a55f2fcba72..7d6921fe1c9d8408380476915e84f6216d90ee08:/Library.mm?ds=inline diff --git a/Library.mm b/Library.mm index eb64e45..973f441 100644 --- a/Library.mm +++ b/Library.mm @@ -1,4 +1,4 @@ -/* Cycript - Remove Execution Server and Disassembler +/* Cycript - Remote Execution Server and Disassembler * Copyright (C) 2009 Jay Freeman (saurik) */ @@ -37,9 +37,9 @@ */ /* }}} */ -#define _GNU_SOURCE - #include +#include + #include "cycript.hpp" #include "sig/parse.hpp" @@ -48,10 +48,14 @@ #include "Pooling.hpp" #include "Struct.hpp" +#ifdef __APPLE__ #include #include - +#include #include +#endif + +#include #include @@ -66,7 +70,7 @@ #include "Parser.hpp" #include "Cycript.tab.hh" -#include +#include #undef _assert #undef _trace @@ -77,7 +81,7 @@ } while (false) #define _trace() do { \ - CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \ + fprintf(stderr, "_trace():%u\n", __LINE__); \ } while (false) #define CYPoolTry { \ @@ -96,8 +100,21 @@ } \ } +#ifndef __APPLE__ +#define class_getSuperclass GSObjCSuper +#define object_getClass GSObjCClass +#endif + void CYThrow(JSContextRef context, JSValueRef value); +const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception); +JSStringRef CYCopyJSString(const char *value); + +void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value); + +JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()); +JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception); + /* JavaScript Properties {{{ */ JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index) { JSValueRef exception(NULL); @@ -126,11 +143,6 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J } /* }}} */ /* JavaScript Strings {{{ */ -JSStringRef CYCopyJSString(id value) { - // XXX: this definition scares me; is anyone using this?! - return value == NULL ? NULL : JSStringCreateWithCFString(reinterpret_cast([value description])); -} - JSStringRef CYCopyJSString(const char *value) { return value == NULL ? NULL : JSStringCreateWithUTF8CString(value); } @@ -194,15 +206,90 @@ class CYJSString { return string_; } }; +/* }}} */ +/* C Strings {{{ */ +// XXX: this macro is unhygenic +#define CYCastCString_(string) ({ \ + char *utf8; \ + if (string == NULL) \ + utf8 = NULL; \ + else { \ + size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ + utf8 = reinterpret_cast(alloca(size)); \ + JSStringGetUTF8CString(string, utf8, size); \ + } \ + utf8; \ +}) +// XXX: this macro is unhygenic +#define CYCastCString(context, value) ({ \ + char *utf8; \ + if (value == NULL) \ + utf8 = NULL; \ + else if (JSStringRef string = CYCopyJSString(context, value)) { \ + utf8 = CYCastCString_(string); \ + JSStringRelease(string); \ + } else \ + utf8 = NULL; \ + utf8; \ +}) +/* }}} */ +/* Objective-C Strings {{{ */ +const char *CYPoolCString(apr_pool_t *pool, NSString *value) { + if (pool == NULL) + return [value UTF8String]; + else { + size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); + char *string(new(pool) char[size]); + if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding]) + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"[NSString getCString:maxLength:encoding:] == NO" userInfo:nil]; + return string; + } +} + +JSStringRef CYCopyJSString_(NSString *value) { +#ifdef __APPLE__ + return JSStringCreateWithCFString(reinterpret_cast(value)); +#else + CYPool pool; + return CYCopyJSString(CYPoolCString(pool, value)); +#endif +} + +JSStringRef CYCopyJSString(id value) { + if (value == nil) + return NULL; + // XXX: this definition scares me; is anyone using this?! + NSString *string([value description]); + return CYCopyJSString_(string); +} + +#ifdef __APPLE__ CFStringRef CYCopyCFString(JSStringRef value) { return JSStringCopyCFString(kCFAllocatorDefault, value); } -CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) { - return CYCopyCFString(CYJSString(context, value)); +CFStringRef CYCopyCFString(const char *value) { + return CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); } +template +NSString *CYCopyNSString(Type_ value) { + return (NSString *) CYCopyCFString(value); +} +#else +NSString *CYCopyNSString(const char *value) { + return [NSString stringWithUTF8String:value]; +} + +NSString *CYCopyNSString(JSStringRef value) { + return CYCopyNSString(CYCastCString_(value)); +} +#endif + +NSString *CYCopyNSString(JSContextRef context, JSValueRef value) { + return CYCopyNSString(CYJSString(context, value)); +} /* }}} */ static JSGlobalContextRef Context_; @@ -219,7 +306,6 @@ static JSClassRef Pointer_; static JSClassRef Runtime_; static JSClassRef Selector_; static JSClassRef Struct_; -static JSClassRef Type_; static JSClassRef ObjectiveC_Classes_; static JSClassRef ObjectiveC_Image_Classes_; @@ -247,9 +333,12 @@ static JSObjectRef Array_pop_; static JSObjectRef Array_push_; static JSObjectRef Array_splice_; -static Class NSArray_; +#ifdef __APPLE__ static Class NSCFBoolean_; static Class NSCFType_; +#endif + +static Class NSArray_; static Class NSDictionary_; static Class NSMessageBuilder_; static Class NSZombie_; @@ -271,8 +360,8 @@ struct CYValue : CYValue() { } - CYValue(void *value) : - value_(value) + CYValue(const void *value) : + value_(const_cast(value)) { } @@ -307,7 +396,7 @@ JSValueRef CYGetClassPrototype(JSContextRef context, id self) { return Instance_prototype_; // XXX: I need to think through multi-context - typedef std::map CacheMap; + typedef std::map CacheMap; static CacheMap cache_; JSValueRef &value(cache_[self]); @@ -358,7 +447,7 @@ struct Instance : static JSObjectRef Make(JSContextRef context, id object, Flags flags = None) { JSObjectRef value(JSObjectMake(context, Instance_, new Instance(object, flags))); - JSObjectSetPrototype(context, value, CYGetClassPrototype(context, object == nil ? nil : object_getClass(object))); + JSObjectSetPrototype(context, value, CYGetClassPrototype(context, object_getClass(object))); return value; } @@ -543,6 +632,8 @@ struct Type_privateData : static Type_privateData *Object; static Type_privateData *Selector; + static JSClassRef Class_; + ffi_type *ffi_; sig::Type *type_; @@ -597,6 +688,7 @@ struct Type_privateData : } }; +JSClassRef Type_privateData::Class_; Type_privateData *Type_privateData::Object; Type_privateData *Type_privateData::Selector; @@ -715,18 +807,6 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { return Instance::Make(context, object, flags); } -const char *CYPoolCString(apr_pool_t *pool, NSString *value) { - if (pool == NULL) - return [value UTF8String]; - else { - size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1); - char *string(new(pool) char[size]); - if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding]) - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"[NSString getCString:maxLength:encoding:] == NO" userInfo:nil]; - return string; - } -} - JSValueRef CYCastJSValue(JSContextRef context, bool value) { return JSValueMakeBoolean(context, value); } @@ -821,6 +901,7 @@ NSString *CYPoolNSCYON(apr_pool_t *pool, id value); - (void *) cy$symbol; @end +#ifdef __APPLE__ struct PropertyAttributes { CYPool pool_; @@ -906,10 +987,33 @@ struct PropertyAttributes { } }; +#endif -NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { +#ifdef __APPLE__ +NSObject *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { return [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]; } +#endif + +#ifndef __APPLE__ +@interface CYWebUndefined : NSObject { +} + ++ (CYWebUndefined *) undefined; + +@end + +@implementation CYWebUndefined + ++ (CYWebUndefined *) undefined { + static CYWebUndefined *instance_([[CYWebUndefined alloc] init]); + return instance_; +} + +@end + +#define WebUndefined CYWebUndefined +#endif /* Bridge: NSArray {{{ */ @implementation NSArray (Cycript) @@ -919,7 +1023,13 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { [json appendString:@"["]; bool comma(false); +#ifdef __APPLE__ for (id object in self) { +#else + id object; + for (size_t index(0), count([self count]); index != count; ++index) { + object = [self objectAtIndex:index]; +#endif if (comma) [json appendString:@","]; else @@ -948,8 +1058,14 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { } - (NSObject *) cy$getProperty:(NSString *)name { - if ([name isEqualToString:@"length"]) - return [NSNumber numberWithUnsignedInteger:[self count]]; + if ([name isEqualToString:@"length"]) { + NSUInteger count([self count]); +#ifdef __APPLE__ + return [NSNumber numberWithUnsignedInteger:count]; +#else + return [NSNumber numberWithUnsignedInt:count]; +#endif + } size_t index(CYGetIndex(NULL, name)); if (index == _not(size_t) || index >= [self count]) @@ -968,7 +1084,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { [json appendString:@"{"]; bool comma(false); +#ifdef __APPLE__ for (id key in self) { +#else + NSEnumerator *keys([self keyEnumerator]); + while (id key = [keys nextObject]) { +#endif if (comma) [json appendString:@","]; else @@ -999,7 +1120,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value { if ([name isEqualToString:@"length"]) { // XXX: is this not intelligent? - NSUInteger size([(NSNumber *)value unsignedIntegerValue]); + NSNumber *number(reinterpret_cast(value)); +#ifdef __APPLE__ + NSUInteger size([number unsignedIntegerValue]); +#else + NSUInteger size([number unsignedIntValue]); +#endif NSUInteger count([self count]); if (size < count) [self removeObjectsInRange:NSMakeRange(size, count - size)]; @@ -1066,8 +1192,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { @implementation NSNumber (Cycript) - (JSType) cy$JSType { +#ifdef __APPLE__ // XXX: this just seems stupid - return [self class] == NSCFBoolean_ ? kJSTypeBoolean : kJSTypeNumber; + if ([self class] == NSCFBoolean_) + return kJSTypeBoolean; +#endif + return kJSTypeNumber; } - (NSObject *) cy$toJSON:(NSString *)key { @@ -1168,18 +1298,19 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (NSString *) cy$toCYON { // XXX: this should use the better code from Output.cpp - CFMutableStringRef json(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef) self)); - CFStringFindAndReplace(json, CFSTR("\\"), CFSTR("\\\\"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\""), CFSTR("\\\""), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\t"), CFSTR("\\t"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\r"), CFSTR("\\r"), CFRangeMake(0, CFStringGetLength(json)), 0); - CFStringFindAndReplace(json, CFSTR("\n"), CFSTR("\\n"), CFRangeMake(0, CFStringGetLength(json)), 0); + NSMutableString *json([self mutableCopy]); + + [json replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\t" withString:@"\\t" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\r" withString:@"\\r" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; + [json replaceOccurrencesOfString:@"\n" withString:@"\\n" options:NSLiteralSearch range:NSMakeRange(0, [json length])]; - CFStringInsert(json, 0, CFSTR("\"")); - CFStringAppend(json, CFSTR("\"")); + [json appendString:@"\""]; + [json insertString:@"\"" atIndex:0]; - return [reinterpret_cast(json) autorelease]; + return json; } - (NSString *) cy$toKey { @@ -1236,6 +1367,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { @end /* }}} */ +/* Bridge: CYJSObject {{{ */ @interface CYJSObject : NSMutableDictionary { JSObjectRef object_; JSContextRef context_; @@ -1243,7 +1375,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context; -- (NSString *) cy$toJSON:(NSString *)key; +- (NSObject *) cy$toJSON:(NSString *)key; - (NSUInteger) count; - (id) objectForKey:(id)key; @@ -1252,7 +1384,8 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (void) removeObjectForKey:(id)key; @end - +/* }}} */ +/* Bridge: CYJSArray {{{ */ @interface CYJSArray : NSMutableArray { JSObjectRef object_; JSContextRef context_; @@ -1270,10 +1403,7 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) { - (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; @end - -CYRange DigitRange_ (0x3ff000000000000LLU, 0x000000000000000LLU); // 0-9 -CYRange WordStartRange_(0x000001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$ -CYRange WordEndRange_ (0x3ff001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$0-9 +/* }}} */ #define CYTry \ @try @@ -1289,7 +1419,7 @@ apr_status_t CYPoolRelease_(void *data) { return APR_SUCCESS; } -id CYPoolRelease(apr_pool_t *pool, id object) { +id CYPoolRelease_(apr_pool_t *pool, id object) { if (object == nil) return nil; else if (pool == NULL) @@ -1300,11 +1430,12 @@ id CYPoolRelease(apr_pool_t *pool, id object) { } } -CFTypeRef CYPoolRelease(apr_pool_t *pool, CFTypeRef object) { - return (CFTypeRef) CYPoolRelease(pool, (id) object); +template +Type_ CYPoolRelease(apr_pool_t *pool, Type_ object) { + return (Type_) CYPoolRelease_(pool, (id) object); } -id CYCastNSObject_(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { +NSObject *CYCastNSObject_(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { JSValueRef exception(NULL); bool array(JSValueIsInstanceOfConstructor(context, object, Array_, &exception)); CYThrow(context, exception); @@ -1312,7 +1443,7 @@ id CYCastNSObject_(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { return CYPoolRelease(pool, [value initWithJSObject:object inContext:context]); } -id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { +NSObject *CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { if (!JSValueIsObjectOfClass(context, object, Instance_)) return CYCastNSObject_(pool, context, object); else { @@ -1340,29 +1471,21 @@ double CYCastDouble(JSContextRef context, JSValueRef value) { return number; } -CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef value) { - double number(CYCastDouble(context, value)); - return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &number); -} - -CFStringRef CYCopyCFString(const char *value) { - return CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); -} - -NSString *CYCastNSString(apr_pool_t *pool, const char *value) { - return (NSString *) CYPoolRelease(pool, CYCopyCFString(value)); +NSNumber *CYCopyNSNumber(JSContextRef context, JSValueRef value) { + return [[NSNumber alloc] initWithDouble:CYCastDouble(context, value)]; } -NSString *CYCastNSString(apr_pool_t *pool, JSStringRef value) { - return (NSString *) CYPoolRelease(pool, CYCopyCFString(value)); +template +NSString *CYCastNSString(apr_pool_t *pool, Type_ value) { + return CYPoolRelease(pool, CYCopyNSString(value)); } bool CYCastBool(JSContextRef context, JSValueRef value) { return JSValueToBoolean(context, value); } -CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { - CFTypeRef object; +id CYNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { + id object; bool copy; switch (JSType type = JSValueGetType(context, value)) { @@ -1376,23 +1499,28 @@ CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, boo break; case kJSTypeBoolean: - object = CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse; +#ifdef __APPLE__ + object = (id) (CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse); copy = false; +#else + object = [[NSNumber alloc] initWithBool:CYCastBool(context, value)]; + copy = true; +#endif break; case kJSTypeNumber: - object = CYCopyCFNumber(context, value); + object = CYCopyNSNumber(context, value); copy = true; break; case kJSTypeString: - object = CYCopyCFString(context, value); + object = CYCopyNSString(context, value); copy = true; break; case kJSTypeObject: // XXX: this might could be more efficient - object = (CFTypeRef) CYCastNSObject(pool, context, (JSObjectRef) value); + object = CYCastNSObject(pool, context, (JSObjectRef) value); copy = false; break; @@ -1406,15 +1534,15 @@ CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, boo else if (copy) return CYPoolRelease(pool, object); else - return CFRetain(object); + return [object retain]; } -CFTypeRef CYCastCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return CYCFType(pool, context, value, true); +NSObject *CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYNSObject(pool, context, value, true); } -CFTypeRef CYCopyCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return CYCFType(pool, context, value, false); +id CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { + return CYNSObject(pool, context, value, false); } NSArray *CYCastNSArray(JSPropertyNameArrayRef names) { @@ -1426,10 +1554,6 @@ NSArray *CYCastNSArray(JSPropertyNameArrayRef names) { return array; } -id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - return reinterpret_cast(CYCastCFType(pool, context, value)); -} - void CYThrow(JSContextRef context, JSValueRef value) { if (value == NULL) return; @@ -1637,9 +1761,9 @@ NSString *CYCopyNSCYON(id value) { Class _class(object_getClass(value)); SEL sel(@selector(cy$toCYON)); - if (Method toCYON = class_getInstanceMethod(_class, sel)) + if (objc_method *toCYON = class_getInstanceMethod(_class, sel)) string = reinterpret_cast(method_getImplementation(toCYON))(value, sel); - else if (Method methodSignatureForSelector = class_getInstanceMethod(_class, @selector(methodSignatureForSelector:))) { + else if (objc_method *methodSignatureForSelector = class_getInstanceMethod(_class, @selector(methodSignatureForSelector:))) { if (reinterpret_cast(method_getImplementation(methodSignatureForSelector))(value, @selector(methodSignatureForSelector:), sel) != nil) string = [value cy$toCYON]; else goto fail; @@ -1779,21 +1903,6 @@ static bool CYGetOffset(apr_pool_t *pool, JSStringRef value, ssize_t &index) { return CYGetOffset(CYPoolCString(pool, value), index); } -// XXX: this macro is unhygenic -#define CYCastCString(context, value) ({ \ - char *utf8; \ - if (value == NULL) \ - utf8 = NULL; \ - else if (JSStringRef string = CYCopyJSString(context, value)) { \ - size_t size(JSStringGetMaximumUTF8CStringSize(string)); \ - utf8 = reinterpret_cast(alloca(size)); \ - JSStringGetUTF8CString(string, utf8, size); \ - JSStringRelease(string); \ - } else \ - utf8 = NULL; \ - utf8; \ -}) - static void *CYCastPointer_(JSContextRef context, JSValueRef value) { switch (JSValueGetType(context, value)) { case kJSTypeNull: @@ -1981,7 +2090,7 @@ static JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi } static bool CYImplements(id object, Class _class, SEL selector, bool devoid) { - if (Method method = class_getInstanceMethod(_class, selector)) { + if (objc_method *method = class_getInstanceMethod(_class, selector)) { if (!devoid) return true; char type[16]; @@ -1994,7 +2103,7 @@ static bool CYImplements(id object, Class _class, SEL selector, bool devoid) { return false; } -static const char *CYPoolTypeEncoding(apr_pool_t *pool, Class _class, SEL sel, Method method) { +static const char *CYPoolTypeEncoding(apr_pool_t *pool, Class _class, SEL sel, objc_method *method) { if (method != NULL) return method_getTypeEncoding(method); else if (NSString *type = [[Bridge_ objectAtIndex:1] objectForKey:CYCastNSString(pool, sel_getName(sel))]) @@ -2108,7 +2217,7 @@ static JSValueRef Messages_getProperty(JSContextRef context, JSObjectRef object, const char *name(CYPoolCString(pool, property)); if (SEL sel = sel_getUid(name)) - if (Method method = class_getInstanceMethod(_class, sel)) + if (objc_method *method = class_getInstanceMethod(_class, sel)) return CYMakeMessage(context, sel, method_getImplementation(method), method_getTypeEncoding(method)); return NULL; @@ -2123,7 +2232,7 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr SEL sel(sel_registerName(name)); - Method method(class_getInstanceMethod(_class, sel)); + objc_method *method(class_getInstanceMethod(_class, sel)); const char *type; IMP imp; @@ -2154,7 +2263,7 @@ static bool Messages_deleteProperty(JSContextRef context, JSObjectRef object, JS const char *name(CYPoolCString(pool, property)); if (SEL sel = sel_getUid(name)) - if (Method method = class_getInstanceMethod(_class, sel)) { + if (objc_method *method = class_getInstanceMethod(_class, sel)) { objc_method_list list = {NULL, 1, {method}}; class_removeMethods(_class, &list); return true; @@ -2169,7 +2278,7 @@ static void Messages_getPropertyNames(JSContextRef context, JSObjectRef object, Class _class(internal->GetValue()); unsigned int size; - Method *data(class_copyMethodList(_class, &size)); + objc_method **data(class_copyMethodList(_class, &size)); for (size_t i(0); i != size; ++i) JSPropertyNameAccumulatorAddName(names, CYJSString(sel_getName(method_getName(data[i])))); free(data); @@ -2233,11 +2342,13 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, const char *string(CYPoolCString(pool, name)); Class _class(object_getClass(self)); +#ifdef __APPLE__ if (objc_property_t property = class_getProperty(_class, string)) { PropertyAttributes attributes(property); SEL sel(sel_registerName(attributes.Getter())); return CYSendMessage(pool, context, self, sel, 0, NULL, false, exception); } +#endif if (SEL sel = sel_getUid(string)) if (CYImplements(self, _class, sel, true)) @@ -2255,7 +2366,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr CYTry { NSString *name(CYCastNSString(pool, property)); - NSString *data(CYCastNSObject(pool, context, value)); + NSObject *data(CYCastNSObject(pool, context, value)); CYPoolTry { if ([self cy$setProperty:name to:data]) @@ -2265,6 +2376,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr const char *string(CYPoolCString(pool, name)); Class _class(object_getClass(self)); +#ifdef __APPLE__ if (objc_property_t property = class_getProperty(_class, string)) { PropertyAttributes attributes(property); if (const char *setter = attributes.Setter()) { @@ -2274,6 +2386,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr return true; } } +#endif size_t length(strlen(string)); @@ -2755,12 +2868,12 @@ static void ObjectiveC_Protocols_getPropertyNames(JSContextRef context, JSObject static JSObjectRef CYMakeType(JSContextRef context, const char *type) { Type_privateData *internal(new Type_privateData(NULL, type)); - return JSObjectMake(context, Type_, internal); + return JSObjectMake(context, Type_privateData::Class_, internal); } static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { Type_privateData *internal(new Type_privateData(type)); - return JSObjectMake(context, Type_, internal); + return JSObjectMake(context, Type_privateData::Class_, internal); } static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { @@ -2822,7 +2935,7 @@ JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _c const char *type; Class _class(object_getClass(self)); - if (Method method = class_getInstanceMethod(_class, _cmd)) + if (objc_method *method = class_getInstanceMethod(_class, _cmd)) type = method_getTypeEncoding(method); else { CYTry { @@ -2915,7 +3028,10 @@ static JSValueRef objc_registerClassPair_(JSContextRef context, JSObjectRef obje if (count != 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to objc_registerClassPair" userInfo:nil]; CYPool pool; - Class _class(CYCastNSObject(pool, context, arguments[0])); + NSObject *value(CYCastNSObject(pool, context, arguments[0])); + if (value == NULL || !CYIsClass(value)) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to objc_registerClassPair" userInfo:nil]; + Class _class((Class) value); $objc_registerClassPair(_class); return CYJSUndefined(context); } CYCatch @@ -3209,11 +3325,20 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil]; CYPool pool; Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - Class _class(CYCastNSObject(pool, context, arguments[0])); - SEL sel(internal->GetValue()); - Method method(class_getInstanceMethod(_class, sel)); - const char *type(CYPoolTypeEncoding(pool, _class, sel, method)); - return type == NULL ? CYJSNull(context) : CYCastJSValue(context, CYJSString(type)); + NSObject *value(CYCastNSObject(pool, context, arguments[0])); + if (value == NULL) lookup: + // XXX: do a lookup of some kind + return CYJSNull(context); + else if (!CYIsClass(value)) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Selector.type takes a Class" userInfo:nil]; + else { + Class _class((Class) value); + SEL sel(internal->GetValue()); + if (objc_method *method = class_getInstanceMethod(_class, sel)) { + const char *type(CYPoolTypeEncoding(pool, _class, sel, method)); + return type == NULL ? CYJSNull(context) : CYCastJSValue(context, CYJSString(type)); + } else goto lookup; + } } CYCatch } @@ -3308,41 +3433,6 @@ static JSStaticFunction Type_staticFunctions[4] = { {NULL, NULL, 0} }; -CYDriver::CYDriver(const std::string &filename) : - state_(CYClear), - data_(NULL), - size_(0), - file_(NULL), - strict_(false), - filename_(filename), - program_(NULL) -{ - ScannerInit(); -} - -CYDriver::~CYDriver() { - ScannerDestroy(); -} - -void CYDriver::Warning(const cy::location &location, const char *message) { - if (!strict_) - return; - - CYDriver::Error error; - error.warning_ = true; - error.location_ = location; - error.message_ = message; - errors_.push_back(error); -} - -void cy::parser::error(const cy::parser::location_type &location, const std::string &message) { - CYDriver::Error error; - error.warning_ = false; - error.location_ = location; - error.message_ = message; - driver.errors_.push_back(error); -} - void CYSetArgs(int argc, const char *argv[]) { JSContextRef context(CYGetJSContext()); JSValueRef args[argc]; @@ -3391,24 +3481,6 @@ const char *CYExecute(apr_pool_t *pool, const char *code) { _pooled return json; } -bool CYRecvAll_(int socket, uint8_t *data, size_t size) { - while (size != 0) if (size_t writ = _syscall(recv(socket, data, size, 0))) { - data += writ; - size -= writ; - } else - return false; - return true; -} - -bool CYSendAll_(int socket, const uint8_t *data, size_t size) { - while (size != 0) if (size_t writ = _syscall(send(socket, data, size, 0))) { - data += writ; - size -= writ; - } else - return false; - return true; -} - static apr_pool_t *Pool_; struct CYExecute_ { @@ -3475,6 +3547,8 @@ struct CYClient : json = NULL; size = _not(size_t); } else { + CYContext context(driver.pool_); + driver.program_->Replace(context); std::ostringstream str; CYOutput out(str); out << *driver.program_; @@ -3517,9 +3591,12 @@ MSInitialize { _pooled Bridge_ = [[NSMutableArray arrayWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; - NSArray_ = objc_getClass("NSArray"); +#ifdef __APPLE__ NSCFBoolean_ = objc_getClass("NSCFBoolean"); NSCFType_ = objc_getClass("NSCFType"); +#endif + + NSArray_ = objc_getClass("NSArray"); NSDictionary_ = objc_getClass("NSDictonary"); NSMessageBuilder_ = objc_getClass("NSMessageBuilder"); NSZombie_ = objc_getClass("_NSZombie_"); @@ -3622,7 +3699,7 @@ JSGlobalContextRef CYGetJSContext() { definition.callAsFunction = &Type_callAsFunction; definition.callAsConstructor = &Type_callAsConstructor; definition.finalize = &Finalize; - Type_ = JSClassCreate(&definition); + Type_privateData::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Runtime"; @@ -3705,11 +3782,13 @@ JSGlobalContextRef CYGetJSContext() { CYSetProperty(context, global, CYJSString("Instance"), Instance); CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); CYSetProperty(context, global, CYJSString("Selector"), Selector); - CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_, &Type_new)); + CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair)); +#ifdef __APPLE__ class_addMethod(NSCFType_, @selector(cy$toJSON:), reinterpret_cast(&NSCFType$cy$toJSON), "@12@0:4@8"); +#endif JSObjectRef cycript(JSObjectMake(context, NULL, NULL)); CYSetProperty(context, global, CYJSString("Cycript"), cycript);