X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/d3fa03570a4b2d6e4cc711875920f3ec34f9e492..ca52e3a3a95947a04788d3fce01d8d856e5f1544:/ObjectiveC/Library.mm diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 2428fd5..7b62f70 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -35,6 +35,11 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#endif + #include "Error.hpp" #include "JavaScript.hpp" #include "String.hpp" @@ -46,14 +51,14 @@ #include -#define CYObjectiveTry_(context) { \ - JSContextRef context_(context); \ +#define CYObjectiveTry_ { \ try #define CYObjectiveTry { \ + JSContextRef context(context_); \ try #define CYObjectiveCatch \ catch (const CYException &error) { \ - @throw CYCastNSObject(NULL, context_, error.CastJSValue(context_)); \ + @throw CYCastNSObject(NULL, context, error.CastJSValue(context)); \ } \ } @@ -159,7 +164,7 @@ enum { BLOCK_HAS_SIGNATURE = 1 << 30, }; -JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class super, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception); +JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class super, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize); /* Objective-C Pool Release {{{ */ void CYPoolRelease_(void *data) { @@ -630,11 +635,7 @@ _finline bool CYJSValueIsNSObject(JSContextRef context, JSValueRef value) { } _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSValueRef value, JSStringRef cache) { - JSValueRef exception(NULL); - JSObjectRef constructor(CYGetCachedObject(context, cache)); - bool is(JSValueIsInstanceOfConstructor(context, value, constructor, &exception)); - CYThrow(context, exception); - return is; + return _jsccall(JSValueIsInstanceOfConstructor, context, value, CYGetCachedObject(context, cache)); } NSObject *CYMakeBlock(void (*invoke)(), sig::Signature &signature) { @@ -806,7 +807,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { } - (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { - CYObjectiveTry_(context) { + CYObjectiveTry_ { if ([name isEqualToString:@"length"]) return CYCastJSValue(context, [self count]); } CYObjectiveCatch @@ -853,7 +854,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { return objective ? value : [NSString stringWithFormat:@"@%@", value]; } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return CYCastJSValue(context, (bool) [self boolValue]); } CYObjectiveCatch } @@ -1010,7 +1011,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { return objective ? value : [NSString stringWithFormat:@"@%@", value]; } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return [self cy$JSType] != kJSTypeBoolean ? CYCastJSValue(context, [self doubleValue]) : CYCastJSValue(context, static_cast([self boolValue])); } CYObjectiveCatch } @@ -1028,7 +1029,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { return objective ? value : [NSString stringWithFormat:@"@%@", value]; } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return CYJSNull(context); } CYObjectiveCatch } @@ -1045,7 +1046,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { return [self cy$valueOfInContext:context]; } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return NULL; } CYObjectiveCatch } @@ -1065,7 +1066,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { return nil; } -- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$getProperty:(NSString *)name inContext:(JSContextRef)context { CYObjectiveTry_ { if (NSObject *value = [self cy$getProperty:name]) return CYCastJSValue(context, value); return NULL; @@ -1144,7 +1145,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { } } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return CYCastJSValue(context, CYJSString(context, self)); } CYObjectiveCatch } @@ -1163,7 +1164,7 @@ NSObject *CYCopyNSObject(CYPool &pool, JSContextRef context, JSValueRef value) { //return objective ? value : [NSString stringWithFormat:@"@%@", value]; } -- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_(context) { +- (JSValueRef) cy$valueOfInContext:(JSContextRef)context { CYObjectiveTry_ { return CYJSUndefined(context); } CYObjectiveCatch } @@ -1204,7 +1205,7 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { @implementation CYJSObject -- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry { +- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry_ { if ((self = [super init]) != nil) { object_ = object; context_ = CYGetJSContext(context); @@ -1221,7 +1222,7 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { - (NSString *) cy$toCYON:(bool)objective { CYObjectiveTry { CYPool pool; - const char *cyon(CYPoolCCYON(pool, context_, object_)); + const char *cyon(CYPoolCCYON(pool, context, object_)); if (cyon == NULL) return [super cy$toCYON:objective]; else @@ -1229,46 +1230,44 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { } CYObjectiveCatch } - (NSUInteger) count { CYObjectiveTry { - JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_)); + JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object_)); size_t size(JSPropertyNameArrayGetCount(names)); JSPropertyNameArrayRelease(names); return size; } CYObjectiveCatch } - (id) objectForKey:(id)key { CYObjectiveTry { - JSValueRef value(CYGetProperty(context_, object_, CYJSString(context_, (NSObject *) key))); - if (JSValueIsUndefined(context_, value)) + JSValueRef value(CYGetProperty(context, object_, CYJSString(context, (NSObject *) key))); + if (JSValueIsUndefined(context, value)) return nil; - return CYCastNSObject(NULL, context_, value) ?: [NSNull null]; + return CYCastNSObject(NULL, context, value) ?: [NSNull null]; } CYObjectiveCatch } - (NSEnumerator *) keyEnumerator { CYObjectiveTry { - JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context_, object_)); - NSEnumerator *enumerator([CYCastNSArray(context_, names) objectEnumerator]); + JSPropertyNameArrayRef names(JSObjectCopyPropertyNames(context, object_)); + NSEnumerator *enumerator([CYCastNSArray(context, names) objectEnumerator]); JSPropertyNameArrayRelease(names); return enumerator; } CYObjectiveCatch } - (void) setObject:(id)object forKey:(id)key { CYObjectiveTry { - CYSetProperty(context_, object_, CYJSString(context_, (NSObject *) key), CYCastJSValue(context_, (NSString *) object)); + CYSetProperty(context, object_, CYJSString(context, (NSObject *) key), CYCastJSValue(context, (NSString *) object)); } CYObjectiveCatch } - (void) removeObjectForKey:(id)key { CYObjectiveTry { - JSValueRef exception(NULL); - (void) JSObjectDeleteProperty(context_, object_, CYJSString(context_, (NSObject *) key), &exception); - CYThrow(context_, exception); + (void) _jsccall(JSObjectDeleteProperty, context, object_, CYJSString(context, (NSObject *) key)); } CYObjectiveCatch } @end @implementation CYJSArray -- (NSString *) cy$toCYON:(bool)objective { +- (NSString *) cy$toCYON:(bool)objective { CYObjectiveTry { CYPool pool; - return [NSString stringWithUTF8String:CYPoolCCYON(pool, context_, object_)]; -} + return [NSString stringWithUTF8String:CYPoolCCYON(pool, context, object_)]; +} CYObjectiveCatch } -- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry { +- (id) initWithJSObject:(JSObjectRef)object inContext:(JSContextRef)context { CYObjectiveTry_ { if ((self = [super init]) != nil) { object_ = object; context_ = CYGetJSContext(context); @@ -1284,62 +1283,54 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { } CYObjectiveCatch } - (NSUInteger) count { CYObjectiveTry { - return CYArrayLength(context_, object_); + return CYArrayLength(context, object_); } CYObjectiveCatch } - (id) objectAtIndex:(NSUInteger)index { CYObjectiveTry { size_t bounds([self count]); if (index >= bounds) @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray objectAtIndex:]: index (%zu) beyond bounds (%zu)", static_cast(index), bounds] userInfo:nil]; - JSValueRef exception(NULL); - JSValueRef value(JSObjectGetPropertyAtIndex(context_, object_, index, &exception)); - CYThrow(context_, exception); - return CYCastNSObject(NULL, context_, value) ?: [NSNull null]; + JSValueRef value(_jsccall(JSObjectGetPropertyAtIndex, context, object_, index)); + return CYCastNSObject(NULL, context, value) ?: [NSNull null]; } CYObjectiveCatch } - (void) addObject:(id)object { CYObjectiveTry { - CYArrayPush(context_, object_, CYCastJSValue(context_, (NSObject *) object)); + CYArrayPush(context, object_, CYCastJSValue(context, (NSObject *) object)); } CYObjectiveCatch } - (void) insertObject:(id)object atIndex:(NSUInteger)index { CYObjectiveTry { size_t bounds([self count] + 1); if (index >= bounds) @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray insertObject:atIndex:]: index (%zu) beyond bounds (%zu)", static_cast(index), bounds] userInfo:nil]; - JSValueRef exception(NULL); JSValueRef arguments[3]; - arguments[0] = CYCastJSValue(context_, index); - arguments[1] = CYCastJSValue(context_, 0); - arguments[2] = CYCastJSValue(context_, (NSObject *) object); - JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype"))); - JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, splice_s)), object_, 3, arguments, &exception); - CYThrow(context_, exception); + arguments[0] = CYCastJSValue(context, index); + arguments[1] = CYCastJSValue(context, 0); + arguments[2] = CYCastJSValue(context, (NSObject *) object); + JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); + _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, splice_s)), object_, 3, arguments); } CYObjectiveCatch } - (void) removeLastObject { CYObjectiveTry { - JSValueRef exception(NULL); - JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype"))); - JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, pop_s)), object_, 0, NULL, &exception); - CYThrow(context_, exception); + JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); + _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, pop_s)), object_, 0, NULL); } CYObjectiveCatch } - (void) removeObjectAtIndex:(NSUInteger)index { CYObjectiveTry { size_t bounds([self count]); if (index >= bounds) @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray removeObjectAtIndex:]: index (%zu) beyond bounds (%zu)", static_cast(index), bounds] userInfo:nil]; - JSValueRef exception(NULL); JSValueRef arguments[2]; - arguments[0] = CYCastJSValue(context_, index); - arguments[1] = CYCastJSValue(context_, 1); - JSObjectRef Array(CYGetCachedObject(context_, CYJSString("Array_prototype"))); - JSObjectCallAsFunction(context_, CYCastJSObject(context_, CYGetProperty(context_, Array, splice_s)), object_, 2, arguments, &exception); - CYThrow(context_, exception); + arguments[0] = CYCastJSValue(context, index); + arguments[1] = CYCastJSValue(context, 1); + JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); + _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, splice_s)), object_, 2, arguments); } CYObjectiveCatch } - (void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)object { CYObjectiveTry { size_t bounds([self count]); if (index >= bounds) @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"*** -[CYJSArray replaceObjectAtIndex:withObject:]: index (%zu) beyond bounds (%zu)", static_cast(index), bounds] userInfo:nil]; - CYSetProperty(context_, object_, index, CYCastJSValue(context_, (NSObject *) object)); + CYSetProperty(context, object_, index, CYCastJSValue(context, (NSObject *) object)); } CYObjectiveCatch } @end @@ -1354,18 +1345,18 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { CYPoolTry { @implementation CYInternal -- (void) dealloc { +- (void) dealloc { CYObjectiveTry { JSValueUnprotect(context_, object_); JSGlobalContextRelease(context_); [super dealloc]; -} +} CYObjectiveCatch } -- (id) initInContext:(JSContextRef)context { +- (id) initInContext:(JSContextRef)context { CYObjectiveTry_ { if ((self = [super init]) != nil) { context_ = CYGetJSContext(context); JSGlobalContextRetain(context_); } return self; -} +} CYObjectiveCatch } - (bool) hasProperty:(JSStringRef)name inContext:(JSContextRef)context { if (object_ == NULL) @@ -1558,9 +1549,12 @@ static JSObjectRef CYMakeMessage(JSContextRef context, SEL sel, IMP imp, const c return JSObjectMake(context, Message_, internal); } -static IMP CYMakeMessage(JSContextRef context, JSValueRef value, const char *type) { +static IMP CYMakeMessage(JSContextRef context, JSValueRef value, const char *encoding) { JSObjectRef function(CYCastJSObject(context, value)); - Closure_privateData *internal(CYMakeFunctor_(context, function, type, &MessageClosure_)); + CYPool pool; + sig::Signature signature; + sig::Parse(pool, &signature, encoding, &Structor_); + Closure_privateData *internal(CYMakeFunctor_(context, function, signature, &MessageClosure_)); // XXX: see notes in Library.cpp about needing to leak return reinterpret_cast(internal->GetValue()); } @@ -1739,14 +1733,14 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, if (objc_property_t property = class_getProperty(_class, string)) { PropertyAttributes attributes(property); SEL sel(sel_registerName(attributes.Getter())); - return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false, exception); + return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false); } #endif if (CYHasImplicitProperties(_class)) if (SEL sel = sel_getUid(string)) if (CYImplements(self, _class, sel, true)) - return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false, exception); + return CYSendMessage(pool, context, self, NULL, sel, 0, NULL, false); return NULL; } CYCatch(NULL) } @@ -1774,7 +1768,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr if (const char *setter = attributes.Setter()) { SEL sel(sel_registerName(setter)); JSValueRef arguments[1] = {value}; - CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false, exception); + CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false); return true; } } @@ -1799,7 +1793,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr if (SEL sel = sel_getUid(set)) if (CYImplements(self, _class, sel)) { JSValueRef arguments[1] = {value}; - CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false, exception); + CYSendMessage(pool, context, self, NULL, sel, 1, arguments, false); return true; } @@ -1912,7 +1906,7 @@ static JSValueRef Instance_callAsFunction(JSContextRef context, JSObjectRef obje sig::sig_ffi_cif(pool, &sig::ObjectiveC, &signature, &cif); void (*function)() = reinterpret_cast(literal->invoke); - return CYCallFunction(pool, context, 1, setup, count, arguments, false, exception, &signature, &cif, function); + return CYCallFunction(pool, context, 1, setup, count, arguments, false, &signature, &cif, function); } } @@ -2083,26 +2077,38 @@ static JSValueRef ObjectiveC_Classes_getProperty(JSContextRef context, JSObjectR return NULL; } CYCatch(NULL) } -static void ObjectiveC_Classes_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { #ifdef __APPLE__ - size_t size(objc_getClassList(NULL, 0)); +static Class *CYCopyClassList(size_t &size) { + size = objc_getClassList(NULL, 0); Class *data(reinterpret_cast(malloc(sizeof(Class) * size))); - get: - size_t writ(objc_getClassList(data, size)); - if (size < writ) { + for (;;) { + size_t writ(objc_getClassList(data, size)); + if (writ <= size) { + size = writ; + return data; + } + + Class *copy(reinterpret_cast(realloc(data, sizeof(Class) * writ))); + if (copy == NULL) { + free(data); + return NULL; + } + + data = copy; size = writ; - if (Class *copy = reinterpret_cast(realloc(data, sizeof(Class) * writ))) { - data = copy; - goto get; - } else goto done; } +} +#endif - for (size_t i(0); i != writ; ++i) - JSPropertyNameAccumulatorAddName(names, CYJSString(class_getName(data[i]))); - - done: - free(data); +static void ObjectiveC_Classes_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef names) { +#ifdef __APPLE__ + size_t size; + if (Class *data = CYCopyClassList(size)) { + for (size_t i(0); i != size; ++i) + JSPropertyNameAccumulatorAddName(names, CYJSString(class_getName(data[i]))); + free(data); + } #else void *state(NULL); while (Class _class = objc_next_class(&state)) @@ -2203,6 +2209,96 @@ static void ObjectiveC_Constants_getPropertyNames(JSContextRef context, JSObject JSPropertyNameAccumulatorAddName(names, CYJSString("nil")); } +#ifdef __APPLE__ +static kern_return_t CYReadMemory(task_t task, vm_address_t address, vm_size_t size, void **data) { + *data = reinterpret_cast(address); + return KERN_SUCCESS; +} + +struct CYChoice { + std::set query_; + JSContextRef context_; + JSObjectRef results_; +}; + +struct CYObjectStruct { + Class isa_; +}; + +static void choose_(task_t task, void *baton, unsigned type, vm_range_t *ranges, unsigned count) { + CYChoice *choice(reinterpret_cast(baton)); + JSContextRef context(choice->context_); + + for (unsigned i(0); i != count; ++i) { + vm_range_t &range(ranges[i]); + void *data(reinterpret_cast(range.address)); + size_t size(range.size); + + if (size < sizeof(CYObjectStruct)) + continue; + + uintptr_t *pointers(reinterpret_cast(data)); +#ifdef __arm64__ + Class isa(reinterpret_cast(pointers[0] & 0x1fffffff8)); +#else + Class isa(reinterpret_cast(pointers[0])); +#endif + + std::set::const_iterator result(choice->query_.find(isa)); + if (result == choice->query_.end()) + continue; + + // XXX: if (size < class_getInstanceSize(*result)) + if ((class_getInstanceSize(*result) + 15) / 16 * 16 != size) + continue; + CYArrayPush(context, choice->results_, CYCastJSValue(context, reinterpret_cast(data))); + } +} + +static JSValueRef choose(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (count != 1) + throw CYJSError(context, "choose() takes a class argument"); + + CYPool pool; + Class _class(CYCastNSObject(&pool, context, arguments[0])); + + vm_address_t *zones(NULL); + unsigned size(0); + kern_return_t error(malloc_get_all_zones(0, &CYReadMemory, &zones, &size)); + _assert(error == KERN_SUCCESS); + + JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array"))); + JSObjectRef results(_jsccall(JSObjectCallAsConstructor, context, Array, 0, NULL)); + + CYChoice choice; + choice.context_ = context; + choice.results_ = results; + + size_t number; + Class *classes(CYCopyClassList(number)); + _assert(classes != NULL); + + for (size_t i(0); i != number; ++i) + for (Class current(classes[i]); current != Nil; current = class_getSuperclass(current)) + if (current == _class) { + choice.query_.insert(classes[i]); + break; + } + + free(classes); + + for (unsigned i(0); i != size; ++i) { + const malloc_zone_t *zone(reinterpret_cast(zones[i])); + if (zone == NULL || zone->introspect == NULL) + continue; + + zone->introspect->enumerator(mach_task_self(), &choice, MALLOC_PTR_IN_USE_RANGE_TYPE, zones[i], &CYReadMemory, &choose_); + } + + return results; +} CYCatch(NULL) } +#endif + #ifdef __APPLE__ #if defined(__i386__) || defined(__x86_64__) #define OBJC_MAX_STRUCT_BY_VALUE 8 @@ -2228,7 +2324,7 @@ static bool stret(ffi_type *ffi_type) { #endif #endif -JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _class, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception) { CYTry { +JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _class, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize) { const char *type; if (_class == NULL) @@ -2295,10 +2391,10 @@ JSValueRef CYSendMessage(CYPool &pool, JSContextRef context, id self, Class _cla } void (*function)() = reinterpret_cast(imp); - return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, exception, &signature, &cif, function); -} CYCatch(NULL) } + return CYCallFunction(pool, context, 2, setup, count, arguments, initialize, &signature, &cif, function); +} -static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { +static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[]) { if (count < 2) throw CYJSError(context, "too few arguments to objc_msgSend"); @@ -2333,7 +2429,11 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje _cmd = CYCastSEL(context, arguments[1]); - return CYSendMessage(pool, context, self, _class, _cmd, count - 2, arguments + 2, uninitialized, exception); + return CYSendMessage(pool, context, self, _class, _cmd, count - 2, arguments + 2, uninitialized); +} + +static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + return $objc_msgSend(context, object, _this, count, arguments); } CYCatch(NULL) } static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2341,7 +2441,7 @@ static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef obje setup[0] = _this; setup[1] = object; memcpy(setup + 2, arguments, sizeof(JSValueRef) * count); - return $objc_msgSend(context, NULL, NULL, count + 2, setup, exception); + return $objc_msgSend(context, NULL, NULL, count + 2, setup); } CYCatch(NULL) } static JSValueRef Message_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2355,7 +2455,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, exception, &internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 2, setup, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } static JSObjectRef Super_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2522,9 +2622,9 @@ static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjec return CYCastJSValue(context, sel_getName(internal->GetValue())); } CYCatch(NULL) } -static JSValueRef Selector_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { +static JSValueRef Selector_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { return Selector_callAsFunction_toString(context, object, _this, count, arguments, exception); -} CYCatch(NULL) } +} 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))); @@ -2550,10 +2650,13 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef else method = NULL; - if (const char *type = CYPoolTypeEncoding(pool, context, sel, method)) - return CYCastJSValue(context, CYJSString(type)); + const char *encoding(CYPoolTypeEncoding(pool, context, sel, method)); + if (encoding == NULL) + return CYJSNull(context); - return CYJSNull(context); + sig::Signature signature; + sig::Parse(pool, &signature, encoding, &Structor_); + return CYMakeType(context, &signature); } CYCatch(NULL) } static JSStaticValue Selector_staticValues[2] = { @@ -2598,7 +2701,7 @@ static JSStaticFunction Selector_staticFunctions[5] = { }; #ifdef __APPLE__ -JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSContextRef context) { CYObjectiveTry_(context) { +JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSContextRef context) { CYObjectiveTry_ { return CYCastJSValue(context, [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease]); } CYObjectiveCatch } #endif @@ -2748,8 +2851,13 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { ObjectiveC_Protocols_ = JSClassCreate(&definition); #ifdef __APPLE__ +// XXX: this is horrible; there has to be a better way to do this +#ifdef __LP64__ + class_addMethod(NSCFType_, @selector(cy$toJSON:inContext:), reinterpret_cast(&NSCFType$cy$toJSON$inContext$), "^{OpaqueJSValue=}32@0:8@16^{OpaqueJSContext=}24"); +#else class_addMethod(NSCFType_, @selector(cy$toJSON:inContext:), reinterpret_cast(&NSCFType$cy$toJSON$inContext$), "^{OpaqueJSValue=}16@0:4@8^{OpaqueJSContext=}12"); #endif +#endif } CYPoolCatch() } void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { @@ -2822,8 +2930,8 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { JSObjectRef box(JSObjectMakeFunctionWithCallback(context, CYJSString("box"), &Instance_box_callAsFunction)); CYSetProperty(context, Instance, CYJSString("box"), box); -#if defined(__APPLE__) && defined(__arm__) && 0 - CYSetProperty(context, all, CYJSString("objc_registerClassPair"), &objc_registerClassPair_, kJSPropertyAttributeDontEnum); +#ifdef __APPLE__ + CYSetProperty(context, all, CYJSString("choose"), &choose, kJSPropertyAttributeDontEnum); #endif CYSetProperty(context, all, CYJSString("objc_msgSend"), &$objc_msgSend, kJSPropertyAttributeDontEnum);