X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/aabea98c2f0415ea5882dad2b9ff9fc3b1d5c97c..bc60fb46c3973f1c8d84994d9f98a6270f9ae803:/ObjectiveC/Library.mm?ds=sidebyside diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index a718bb8..a3c1d66 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -1,4 +1,8 @@ +#if defined(__APPLE__) && defined(__arm__) #include +#else +#include +#endif #include "ObjectiveC/Internal.hpp" @@ -16,7 +20,6 @@ #ifdef __APPLE__ #include -#include #include #include #endif @@ -71,13 +74,17 @@ #define method_getTypeEncoding(method) ((method)->method_types) #define method_setImplementation(method, imp) ((void) ((method)->method_imp = (imp))) +#undef objc_getClass +#define objc_getClass GSClassFromName + #define objc_getProtocol GSProtocolFromName #define object_getClass GSObjCClass #define object_getInstanceVariable(object, name, value) ({ \ objc_ivar *ivar(class_getInstanceVariable(object_getClass(object), name)); \ - GSObjCGetVariable(object, ivar_getOffset(ivar), sizeof(void *), value); \ + if (ivar != NULL) \ + GSObjCGetVariable(object, ivar_getOffset(ivar), sizeof(void *), value); \ ivar; \ }) @@ -138,12 +145,12 @@ JSStringRef CYCopyJSString(JSContextRef context, NSString *value) { #endif } -JSStringRef CYCopyJSString(NSObject *value) { +JSStringRef CYCopyJSString(JSContextRef context, NSObject *value) { if (value == nil) return NULL; // XXX: this definition scares me; is anyone using this?! NSString *string([value description]); - return CYCopyJSString(string); + return CYCopyJSString(context, string); } NSString *CYCopyNSString(const CYUTF8String &value) { @@ -186,6 +193,8 @@ CYUTF8String CYCastUTF8String(NSString *value) { } /* }}} */ +JSValueRef CYCastJSValue(JSContextRef context, NSObject *value); + void CYThrow(JSContextRef context, NSException *error, JSValueRef *exception) { if (exception == NULL) throw error; @@ -220,12 +229,14 @@ static JSObjectRef Instance_prototype_; #ifdef __APPLE__ static Class NSCFBoolean_; static Class NSCFType_; +static Class NSMessageBuilder_; +static Class NSZombie_; +#else +static Class NSBoolNumber_; #endif static Class NSArray_; static Class NSDictionary_; -static Class NSMessageBuilder_; -static Class NSZombie_; static Class Object_; static Type_privateData *Object_type; @@ -346,7 +357,7 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { - (NSObject *) cy$getProperty:(NSString *)name; - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value; - (bool) cy$deleteProperty:(NSString *)name; -- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names; +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context; @end @@ -370,13 +381,16 @@ NSString *CYCastNSCYON(id value) { string = [value cy$toCYON]; else goto fail; } else fail: { - if (value == NSZombie_) + if (false); +#ifdef __APPLE__ + else if (value == NSZombie_) string = @"_NSZombie_"; else if (_class == NSZombie_) string = [NSString stringWithFormat:@"<_NSZombie_: %p>", value]; // XXX: frowny /in/ the pants else if (value == NSMessageBuilder_ || value == Object_) string = nil; +#endif else string = [NSString stringWithFormat:@"%@", value]; } @@ -562,6 +576,12 @@ NSNumber *CYCopyNSNumber(JSContextRef context, JSValueRef value) { return [[NSNumber alloc] initWithDouble:CYCastDouble(context, value)]; } +#ifndef __APPLE__ +@interface NSBoolNumber : NSNumber { +} +@end +#endif + id CYNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cast) { id object; bool copy; @@ -581,7 +601,7 @@ id CYNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef value, bool cas object = (id) (CYCastBool(context, value) ? kCFBooleanTrue : kCFBooleanFalse); copy = false; #else - object = [[NSNumber alloc] initWithBool:CYCastBool(context, value)]; + object = [[NSBoolNumber alloc] initWithBool:CYCastBool(context, value)]; copy = true; #endif break; @@ -681,8 +701,8 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return [self objectAtIndex:index]; } -- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { - [super cy$getPropertyNames:names]; +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context { + [super cy$getPropertyNames:names inContext:context]; for (size_t index(0), count([self count]); index != count; ++index) { id object([self objectAtIndex:index]); @@ -696,6 +716,29 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu @end /* }}} */ +/* Bridge: NSBoolNumber {{{ */ +#ifndef __APPLE__ +@implementation NSBoolNumber (Cycript) + +- (JSType) cy$JSType { + return kJSTypeBoolean; +} + +- (NSObject *) cy$toJSON:(NSString *)key { + return self; +} + +- (NSString *) cy$toCYON { + return [self boolValue] ? @"true" : @"false"; +} + +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context { CYObjectiveTry_(context) { + return CYCastJSValue(context, (bool) [self boolValue]); +} CYObjectiveCatch } + +@end +#endif +/* }}} */ /* Bridge: NSDictionary {{{ */ @implementation NSDictionary (Cycript) @@ -732,8 +775,8 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return [self objectForKey:name]; } -- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { - [super cy$getPropertyNames:names]; +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context { + [super cy$getPropertyNames:names inContext:context]; #ifdef __APPLE__ for (NSString *key in self) { @@ -741,7 +784,7 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu NSEnumerator *keys([self keyEnumerator]); while (NSString *key = [keys nextObject]) { #endif - JSPropertyNameAccumulatorAddName(names, CYJSString(key)); + JSPropertyNameAccumulatorAddName(names, CYJSString(context, key)); } } @@ -903,7 +946,7 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return false; } -- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names inContext:(JSContextRef)context { } @end @@ -996,27 +1039,29 @@ NSArray *CYCastNSArray(JSContextRef context, JSPropertyNameArrayRef names) { return array; } -JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { +JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { if (value == nil) return CYJSNull(context); else if ([value respondsToSelector:@selector(cy$JSValueInContext:)]) return [value cy$JSValueInContext:context]; else return CYMakeInstance(context, value, false); -} CYPoolCatch(NULL) } +} CYPoolCatch(NULL) return /*XXX*/ NULL; } @implementation CYJSObject - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry { if ((self = [super init]) != nil) { object_ = object; - context_ = context; + context_ = CYGetJSContext(context); + //XXX:JSGlobalContextRetain(context_); JSValueProtect(context_, object_); } return self; } CYObjectiveCatch } - (void) dealloc { CYObjectiveTry { JSValueUnprotect(context_, object_); + //XXX:JSGlobalContextRelease(context_); [super dealloc]; } CYObjectiveCatch } @@ -1052,7 +1097,7 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { - (id) objectForKey:(id)key { CYObjectiveTry { // XXX: are NSDictionary keys always NSString *? - JSValueRef value(CYGetProperty(context_, object_, CYJSString((NSString *) key))); + JSValueRef value(CYGetProperty(context_, object_, CYJSString(context_, (NSString *) key))); if (JSValueIsUndefined(context_, value)) return nil; return CYCastNSObject(NULL, context_, value) ?: [NSNull null]; @@ -1060,20 +1105,20 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { - (NSEnumerator *) keyEnumerator { CYObjectiveTry { JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_)); - NSEnumerator *enumerator([CYCastNSArray(names) objectEnumerator]); + NSEnumerator *enumerator([CYCastNSArray(context_, names) objectEnumerator]); JSPropertyNameArrayRelease(names); return enumerator; } CYObjectiveCatch } - (void) setObject:(id)object forKey:(id)key { CYObjectiveTry { // XXX: are NSDictionary keys always NSString *? - CYSetProperty(context_, object_, CYJSString((NSString *) key), CYCastJSValue(context_, object)); + CYSetProperty(context_, object_, CYJSString(context_, (NSString *) key), CYCastJSValue(context_, (NSString *) object)); } CYObjectiveCatch } - (void) removeObjectForKey:(id)key { CYObjectiveTry { JSValueRef exception(NULL); // XXX: are NSDictionary keys always NSString *? - (void) JSObjectDeleteProperty(context_, object_, CYJSString((NSString *) key), &exception); + (void) JSObjectDeleteProperty(context_, object_, CYJSString(context_, (NSString *) key), &exception); CYThrow(context_, exception); } CYObjectiveCatch } @@ -1084,13 +1129,15 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { - (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry { if ((self = [super init]) != nil) { object_ = object; - context_ = context; + context_ = CYGetJSContext(context); + //XXX:JSGlobalContextRetain(context_); JSValueProtect(context_, object_); } return self; } CYObjectiveCatch } - (void) dealloc { CYObjectiveTry { JSValueUnprotect(context_, object_); + //XXX:JSGlobalContextRelease(context_); [super dealloc]; } CYObjectiveCatch } @@ -1111,7 +1158,7 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { - (void) addObject:(id)object { CYObjectiveTry { JSValueRef exception(NULL); JSValueRef arguments[1]; - arguments[0] = CYCastJSValue(context_, object); + arguments[0] = CYCastJSValue(context_, (NSObject *) object); JSObjectCallAsFunction(context_, Array_push_, object_, 1, arguments, &exception); CYThrow(context_, exception); } CYObjectiveCatch } @@ -1124,7 +1171,7 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { JSValueRef arguments[3]; arguments[0] = CYCastJSValue(context_, index); arguments[1] = CYCastJSValue(context_, 0); - arguments[2] = CYCastJSValue(context_, object); + arguments[2] = CYCastJSValue(context_, (NSObject *) object); JSObjectCallAsFunction(context_, Array_splice_, object_, 3, arguments, &exception); CYThrow(context_, exception); } CYObjectiveCatch } @@ -1151,7 +1198,7 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { CYPoolTry { size_t bounds([self count]); if (index >= bounds) @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray replaceObjectAtIndex:withObject:]: index (%zu) beyond bounds (%zu)", index, bounds] userInfo:nil]; - CYSetProperty(context_, object_, index, CYCastJSValue(context_, object)); + CYSetProperty(context_, object_, index, CYCastJSValue(context_, (NSObject *) object)); } CYObjectiveCatch } @end @@ -1236,19 +1283,21 @@ void CYObjectiveC_ExecuteEnd(JSContextRef context, void *handle) { return [(NSAutoreleasePool *) handle release]; } -JSValueRef CYObjectiveC_RuntimeProperty(JSContextRef context, CYUTF8String name) { CYObjectiveTry_(context) { +JSValueRef CYObjectiveC_RuntimeProperty(JSContextRef context, CYUTF8String name) { CYPoolTry { if (name == "nil") return Instance::Make(context, nil); if (Class _class = objc_getClass(name.data)) return CYMakeInstance(context, _class, true); return NULL; -} CYObjectiveCatch } +} CYPoolCatch(NULL) return /*XXX*/ NULL; } -static void CYObjectiveC_CallFunction(JSContextRef context, ffi_cif *cif, void (*function)(), uint8_t *value, void **values) { CYObjectiveTry_(context) { +static void CYObjectiveC_CallFunction(JSContextRef context, ffi_cif *cif, void (*function)(), uint8_t *value, void **values) { @try { ffi_call(cif, function, value, values); -} CYObjectiveCatch } +} @catch (NSException *error ) { + throw CYJSError(context, CYCastJSValue(context, error)); +} } -static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { CYObjectiveTry_(context) { +static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { CYPoolTry { switch (type->primitive) { case sig::object_P: case sig::typename_P: @@ -1264,12 +1313,12 @@ static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Ty } return true; -} CYObjectiveCatch } +} CYPoolCatch(false) return /*XXX*/ NULL; } -static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) { CYObjectiveTry_(context) { +static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) { CYPoolTry { switch (type->primitive) { case sig::object_P: - if (id object = *reinterpret_cast(data)) { + if (NSObject *object = *reinterpret_cast(data)) { JSValueRef value(CYCastJSValue(context, object)); if (initialize) [object release]; @@ -1289,23 +1338,18 @@ static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ff default: return NULL; } -} CYObjectiveCatch } - -static CYHooks CYObjectiveCHooks = { - &CYObjectiveC_ExecuteStart, - &CYObjectiveC_ExecuteEnd, - &CYObjectiveC_RuntimeProperty, - &CYObjectiveC_CallFunction, - &CYObjectiveC_PoolFFI, - &CYObjectiveC_FromFFI, -}; +} CYPoolCatch(NULL) return /*XXX*/ NULL; } static bool CYImplements(id object, Class _class, SEL selector, bool devoid) { if (objc_method *method = class_getInstanceMethod(_class, selector)) { if (!devoid) return true; +#if OBJC_API_VERSION >= 2 char type[16]; method_getReturnType(method, type, sizeof(type)); +#else + const char *type(method_getTypeEncoding(method)); +#endif if (type[0] != 'v') return true; } @@ -1433,13 +1477,21 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr if (method != NULL) method_setImplementation(method, imp); - else - class_replaceMethod(_class, sel, imp, type); + else { +#ifdef GNU_RUNTIME + GSMethodList list(GSAllocMethodList(1)); + GSAppendMethodToList(list, sel, type, imp, YES); + GSAddMethodList(_class, list, YES); + GSFlushMethodCacheForClass(_class); +#else + class_addMethod(_class, sel, imp, type); +#endif + } return true; } -#if 0 && !__OBJC2__ +#if 0 && OBJC_API_VERSION < 2 static bool Messages_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); Class _class(internal->GetValue()); @@ -1462,7 +1514,7 @@ static void Messages_getPropertyNames(JSContextRef context, JSObjectRef object, Messages *internal(reinterpret_cast(JSObjectGetPrivate(object))); Class _class(internal->GetValue()); -#ifdef __OBJC2__ +#if OBJC_API_VERSION >= 2 unsigned int size; objc_method **data(class_copyMethodList(_class, &size)); for (size_t i(0); i != size; ++i) @@ -1616,7 +1668,7 @@ static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JS NSString *name(CYCastNSString(NULL, context, property)); return [self cy$deleteProperty:name]; } CYPoolCatch(NULL) -} CYCatch } +} CYCatch return /*XXX*/ NULL; } static void Instance_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); @@ -1637,8 +1689,8 @@ static void Instance_getPropertyNames(JSContextRef context, JSObjectRef object, CYPoolTry { // XXX: this is an evil hack to deal with NSProxy; fix elsewhere - if (CYImplements(self, _class, @selector(cy$getPropertyNames:), false)) - [self cy$getPropertyNames:names]; + if (CYImplements(self, _class, @selector(cy$getPropertyNames:inContext:), false)) + [self cy$getPropertyNames:names inContext:context]; } CYPoolCatch() } @@ -1685,6 +1737,7 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object, if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) { Type_privateData type(pool, ivar_getTypeEncoding(ivar)); + // XXX: if this fails and throws an exception the person we are throwing it to gets the wrong exception return CYFromFFI(context, type.type_, type.GetFFI(), reinterpret_cast(self) + ivar_getOffset(ivar)); } @@ -1711,11 +1764,17 @@ static void Internal_getPropertyNames_(Class _class, JSPropertyNameAccumulatorRe if (Class super = class_getSuperclass(_class)) Internal_getPropertyNames_(super, names); +#if OBJC_API_VERSION >= 2 unsigned int size; objc_ivar **data(class_copyIvarList(_class, &size)); for (size_t i(0); i != size; ++i) JSPropertyNameAccumulatorAddName(names, CYJSString(ivar_getName(data[i]))); free(data); +#else + if (objc_ivar_list *ivars = _class->ivars) + for (int i(0); i != ivars->ivar_count; ++i) + JSPropertyNameAccumulatorAddName(names, CYJSString(ivar_getName(&ivars->ivar_list[i]))); +#endif } static void Internal_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { @@ -1768,7 +1827,7 @@ static void ObjectiveC_Classes_getPropertyNames(JSContextRef context, JSObjectRe #endif } -#ifdef __OBJC2__ +#if OBJC_API_VERSION >= 2 static JSValueRef ObjectiveC_Image_Classes_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { const char *internal(reinterpret_cast(JSObjectGetPrivate(object))); @@ -1838,7 +1897,7 @@ static JSValueRef ObjectiveC_Protocols_getProperty(JSContextRef context, JSObjec } CYCatch } static void ObjectiveC_Protocols_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { -#ifdef __OBJC2__ +#if OBJC_API_VERSION >= 2 unsigned int size; Protocol **data(objc_copyProtocolList(&size)); for (size_t i(0); i != size; ++i) @@ -1880,11 +1939,8 @@ JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, Class } CYPoolCatch(NULL) } - objc_super super = {self, _class}; - void *arg0 = &super; - void *setup[2]; - setup[0] = &arg0; + setup[0] = &self; setup[1] = &_cmd; sig::Signature signature; @@ -1893,15 +1949,17 @@ JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, Class ffi_cif cif; sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); - if (imp == NULL) + if (imp == NULL) { #ifdef __APPLE__ if (stret(cif.rtype)) imp = class_getMethodImplementation_stret(_class, _cmd); else imp = class_getMethodImplementation(_class, _cmd); #else + objc_super super = {self, _class}; imp = objc_msg_lookup_super(&super, _cmd); #endif + } void (*function)() = reinterpret_cast(imp); return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, exception, &signature, &cif, function); @@ -1946,6 +2004,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje } CYCatch } /* Hook: objc_registerClassPair {{{ */ +#if defined(__APPLE__) && defined(__arm__) // XXX: replace this with associated objects MSHook(void, CYDealloc, id self, SEL sel) { @@ -1977,6 +2036,7 @@ static JSValueRef objc_registerClassPair_(JSContextRef context, JSObjectRef obje $objc_registerClassPair(_class); return CYJSUndefined(context); } CYCatch } +#endif /* }}} */ static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @@ -2045,12 +2105,12 @@ static JSValueRef CYValue_callAsFunction_$cya(JSContextRef context, JSObjectRef ffi = typical->ffi_; } - return CYMakePointer(context, &internal->value_, type, ffi, object); + return CYMakePointer(context, &internal->value_, _not(size_t), type, ffi, object); } static JSValueRef Instance_getProperty_constructor(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return Instance::Make(context, object_getClass(internal->GetValue())); + return Instance::Make(context, (id) object_getClass(internal->GetValue())); } static JSValueRef Instance_getProperty_protocol(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -2064,9 +2124,9 @@ static JSValueRef Instance_getProperty_protocol(JSContextRef context, JSObjectRe static JSValueRef Instance_getProperty_messages(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { Instance *internal(reinterpret_cast(JSObjectGetPrivate(object))); id self(internal->GetValue()); - if (class_getInstanceMethod(object_getClass(self), @selector(alloc)) == NULL) + if (!CYIsClass(self)) return CYJSUndefined(context); - return Messages::Make(context, self); + return Messages::Make(context, (Class) self); } static JSValueRef Instance_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2074,7 +2134,7 @@ static JSValueRef Instance_callAsFunction_toCYON(JSContextRef context, JSObjectR return NULL; Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - return CYCastJSValue(context, CYJSString(CYCastNSCYON(internal->GetValue()))); + return CYCastJSValue(context, CYJSString(context, CYCastNSCYON(internal->GetValue()))); } CYCatch } static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2084,11 +2144,15 @@ static JSValueRef Instance_callAsFunction_toJSON(JSContextRef context, JSObjectR Instance *internal(reinterpret_cast(JSObjectGetPrivate(_this))); CYPoolTry { - NSString *key(count == 0 ? nil : CYCastNSString(NULL, context, CYJSString(context, arguments[0]))); + NSString *key; + if (count == 0) + key = nil; + else + key = CYCastNSString(NULL, context, CYJSString(context, arguments[0])); // XXX: check for support of cy$toJSON? - return CYCastJSValue(context, CYJSString([internal->GetValue() cy$toJSON:key])); + return CYCastJSValue(context, CYJSString(context, [internal->GetValue() cy$toJSON:key])); } CYPoolCatch(NULL) -} CYCatch } +} CYCatch return /*XXX*/ NULL; } static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (!JSValueIsObjectOfClass(context, _this, Instance_)) @@ -2098,9 +2162,9 @@ static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjec CYPoolTry { // XXX: this seems like a stupid implementation; what if it crashes? why not use the CYONifier backend? - return CYCastJSValue(context, CYJSString([internal->GetValue() description])); + return CYCastJSValue(context, CYJSString(context, [internal->GetValue() description])); } CYPoolCatch(NULL) -} CYCatch } +} CYCatch return /*XXX*/ NULL; } 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))); @@ -2116,9 +2180,10 @@ static JSValueRef Selector_callAsFunction_toCYON(JSContextRef context, JSObjectR const char *name(sel_getName(internal->GetValue())); CYPoolTry { - return CYCastJSValue(context, CYJSString((NSString *) [NSString stringWithFormat:@"@selector(%s)", name])); + NSString *string([NSString stringWithFormat:@"@selector(%s)", name]); + return CYCastJSValue(context, CYJSString(context, string)); } CYPoolCatch(NULL) -} CYCatch } +} CYCatch return /*XXX*/ NULL; } static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 1) @@ -2174,23 +2239,24 @@ static JSStaticFunction Selector_staticFunctions[5] = { {NULL, NULL, 0} }; -void CYObjectiveC(JSContextRef context, JSObjectRef global) { +void CYObjectiveC_SetupContext(JSContextRef context) { + JSObjectRef global(CYGetGlobalObject(context)); apr_pool_t *pool(CYGetGlobalPool()); - hooks_ = &CYObjectiveCHooks; - - Object_type = new(pool) Type_privateData(pool, "@"); - Selector_type = new(pool) Type_privateData(pool, ":"); + Object_type = new(pool) Type_privateData("@"); + Selector_type = new(pool) Type_privateData(":"); #ifdef __APPLE__ NSCFBoolean_ = objc_getClass("NSCFBoolean"); NSCFType_ = objc_getClass("NSCFType"); + NSMessageBuilder_ = objc_getClass("NSMessageBuilder"); + NSZombie_ = objc_getClass("_NSZombie_"); +#else + NSBoolNumber_ = objc_getClass("NSBoolNumber"); #endif NSArray_ = objc_getClass("NSArray"); - NSDictionary_ = objc_getClass("NSDictonary"); - NSMessageBuilder_ = objc_getClass("NSMessageBuilder"); - NSZombie_ = objc_getClass("_NSZombie_"); + NSDictionary_ = objc_getClass("NSDictionary"); Object_ = objc_getClass("Object"); JSClassDefinition definition; @@ -2231,7 +2297,7 @@ void CYObjectiveC(JSContextRef context, JSObjectRef global) { definition.hasProperty = &Messages_hasProperty; definition.getProperty = &Messages_getProperty; definition.setProperty = &Messages_setProperty; -#if 0 && !__OBJC2__ +#if 0 && OBJC_API_VERSION < 2 definition.deleteProperty = &Messages_deleteProperty; #endif definition.getPropertyNames = &Messages_getPropertyNames; @@ -2270,7 +2336,7 @@ void CYObjectiveC(JSContextRef context, JSObjectRef global) { CYSetProperty(context, ObjectiveC, CYJSString("classes"), JSObjectMake(context, ObjectiveC_Classes_, NULL)); CYSetProperty(context, ObjectiveC, CYJSString("protocols"), JSObjectMake(context, ObjectiveC_Protocols_, NULL)); -#ifdef __OBJC2__ +#if OBJC_API_VERSION >= 2 definition = kJSClassDefinitionEmpty; definition.className = "ObjectiveC::Images"; definition.getProperty = &ObjectiveC_Images_getProperty; @@ -2298,15 +2364,33 @@ void CYObjectiveC(JSContextRef context, JSObjectRef global) { CYSetProperty(context, global, CYJSString("Selector"), Selector); CYSetProperty(context, global, CYJSString("Super"), Super); +#if defined(__APPLE__) && defined(__arm__) CYSetProperty(context, global, CYJSString("objc_registerClassPair"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_registerClassPair"), &objc_registerClassPair_)); + MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair)); +#endif + CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend)); JSObjectSetPrototype(context, (JSObjectRef) CYGetProperty(context, Message, prototype_), Function_prototype_); JSObjectSetPrototype(context, (JSObjectRef) CYGetProperty(context, Selector, prototype_), Function_prototype_); - MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair)); - #ifdef __APPLE__ class_addMethod(NSCFType_, @selector(cy$toJSON:), reinterpret_cast(&NSCFType$cy$toJSON), "@12@0:4@8"); #endif } + +static CYHooks CYObjectiveCHooks = { + &CYObjectiveC_ExecuteStart, + &CYObjectiveC_ExecuteEnd, + &CYObjectiveC_RuntimeProperty, + &CYObjectiveC_CallFunction, + &CYObjectiveC_SetupContext, + &CYObjectiveC_PoolFFI, + &CYObjectiveC_FromFFI, +}; + +struct CYObjectiveC { + CYObjectiveC() { + hooks_ = &CYObjectiveCHooks; + } +} CYObjectiveC;