From d3760804d3e2a4287c71d5e9a5aa6425a967a956 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Wed, 28 Oct 2009 01:27:41 +0000 Subject: [PATCH] Added getPropertyNames bridging (albeit lame) and fixed exception handling through ffi_call for Objective-C (via hooks_). --- Handler.mm | 9 +++---- Library.cpp | 10 ++++--- ObjectiveC/Library.mm | 61 ++++++++++++++++++++++++++++++++++++------- cycript.hpp | 7 +++-- todo.txt | 3 ++- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/Handler.mm b/Handler.mm index 39825fa..016f0c8 100644 --- a/Handler.mm +++ b/Handler.mm @@ -89,8 +89,9 @@ struct CYClient : } void Handle() { - CYClient_ *client = [[CYClient_ alloc] init]; - @try { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + CYClient_ *client = [[[CYClient_ alloc] init] autorelease]; for (;;) { size_t size; @@ -133,9 +134,7 @@ struct CYClient : return; } - } @finally { - [client release]; - } + [pool release]; } }; diff --git a/Library.cpp b/Library.cpp index 555cd8a..eba549a 100644 --- a/Library.cpp +++ b/Library.cpp @@ -1036,7 +1036,11 @@ JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, } uint8_t value[cif->rtype->size]; - ffi_call(cif, function, value, values); + + if (hooks_ != NULL && hooks_->CallFunction != NULL) + (*hooks_->CallFunction)(context, cif, function, value, values); + else + ffi_call(cif, function, value, values); return CYFromFFI(context, signature->elements[0].type, cif->rtype, value, initialize); } CYCatch } @@ -1309,7 +1313,7 @@ const char *CYExecute(apr_pool_t *pool, const char *code) { void *handle; if (hooks_ != NULL && hooks_->ExecuteStart != NULL) - handle = (*hooks_->ExecuteStart)(); + handle = (*hooks_->ExecuteStart)(context); else handle = NULL; @@ -1341,7 +1345,7 @@ const char *CYExecute(apr_pool_t *pool, const char *code) { CYSetProperty(context, CYGetGlobalObject(context), Result_, result); if (hooks_ != NULL && hooks_->ExecuteEnd != NULL) - (*hooks_->ExecuteEnd)(handle); + (*hooks_->ExecuteEnd)(context, handle); return json; } diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index ee511c2..bec1730 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -307,6 +307,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; @end @@ -641,6 +642,19 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return [self objectAtIndex:index]; } +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { + [super cy$getPropertyNames:names]; + + for (size_t index(0), count([self count]); index != count; ++index) { + id object([self objectAtIndex:index]); + if (object == nil || [object cy$JSType] != kJSTypeUndefined) { + char name[32]; + sprintf(name, "%zu", index); + JSPropertyNameAccumulatorAddName(names, CYJSString(name)); + } + } +} + @end /* }}} */ /* Bridge: NSDictionary {{{ */ @@ -679,6 +693,19 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return [self objectForKey:name]; } +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { + [super cy$getPropertyNames:names]; + +#ifdef __APPLE__ + for (NSString *key in self) { +#else + NSEnumerator *keys([self keyEnumerator]); + while (NSString *key = [keys nextObject]) { +#endif + JSPropertyNameAccumulatorAddName(names, CYJSString(key)); + } +} + @end /* }}} */ /* Bridge: NSMutableArray {{{ */ @@ -837,6 +864,9 @@ NSObject *CYCopyNSObject(apr_pool_t *pool, JSContextRef context, JSValueRef valu return false; } +- (void) cy$getPropertyNames:(JSPropertyNameAccumulatorRef)names { +} + @end /* }}} */ /* Bridge: NSProxy {{{ */ @@ -1150,23 +1180,29 @@ static SEL CYCastSEL(JSContextRef context, JSValueRef value) { return CYCastPointer(context, value); } -void *CYObjectiveC_ExecuteStart() { +void *CYObjectiveC_ExecuteStart(JSContextRef context) { + // XXX: deal with exceptions! return (void *) [[NSAutoreleasePool alloc] init]; } -void CYObjectiveC_ExecuteEnd(void *handle) { +void CYObjectiveC_ExecuteEnd(JSContextRef context, void *handle) { + // XXX: deal with exceptions! return [(NSAutoreleasePool *) handle release]; } -JSValueRef CYObjectiveC_RuntimeProperty(JSContextRef context, CYUTF8String name) { +JSValueRef CYObjectiveC_RuntimeProperty(JSContextRef context, CYUTF8String name) { CYObjectiveTry_(context) { if (name == "nil") return Instance::Make(context, nil); if (Class _class = objc_getClass(name.data)) return CYMakeInstance(context, _class, true); return NULL; -} +} CYObjectiveCatch } + +static void CYObjectiveC_CallFunction(JSContextRef context, ffi_cif *cif, void (*function)(), uint8_t *value, void **values) { CYObjectiveTry_(context) { + ffi_call(cif, function, value, values); +} CYObjectiveCatch } -static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { +static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { CYObjectiveTry_(context) { switch (type->primitive) { case sig::object_P: case sig::typename_P: @@ -1182,9 +1218,9 @@ static bool CYObjectiveC_PoolFFI(apr_pool_t *pool, JSContextRef context, sig::Ty } return true; -} +} CYObjectiveCatch } -static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) { +static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) { CYObjectiveTry_(context) { switch (type->primitive) { case sig::object_P: if (id object = *reinterpret_cast(data)) { @@ -1207,12 +1243,13 @@ static JSValueRef CYObjectiveC_FromFFI(JSContextRef context, sig::Type *type, ff default: return NULL; } -} +} CYObjectiveCatch } -CYHooks CYObjectiveCHooks = { +static CYHooks CYObjectiveCHooks = { &CYObjectiveC_ExecuteStart, &CYObjectiveC_ExecuteEnd, &CYObjectiveC_RuntimeProperty, + &CYObjectiveC_CallFunction, &CYObjectiveC_PoolFFI, &CYObjectiveC_FromFFI, }; @@ -1543,6 +1580,12 @@ static void Instance_getPropertyNames(JSContextRef context, JSObjectRef object, free(data); } #endif + + 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]; + } CYPoolCatch() } static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { diff --git a/cycript.hpp b/cycript.hpp index 316a37d..87d8d2c 100644 --- a/cycript.hpp +++ b/cycript.hpp @@ -119,9 +119,12 @@ JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObject const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef object); struct CYHooks { - void *(*ExecuteStart)(); - void (*ExecuteEnd)(void *); + void *(*ExecuteStart)(JSContextRef); + void (*ExecuteEnd)(JSContextRef, void *); + JSValueRef (*RuntimeProperty)(JSContextRef, CYUTF8String); + void (*CallFunction)(JSContextRef, ffi_cif *, void (*)(), uint8_t *, void **); + bool (*PoolFFI)(apr_pool_t *, JSContextRef, sig::Type *, ffi_type *, void *, JSValueRef); JSValueRef (*FromFFI)(JSContextRef, sig::Type *, ffi_type *, void *, bool, JSObjectRef); }; diff --git a/todo.txt b/todo.txt index b6ee18d..2308e3d 100644 --- a/todo.txt +++ b/todo.txt @@ -4,4 +4,5 @@ support unions (right now 0-1 fields parsed as struct) \\\n escapes in strings aren't handled in the console look into what String is, and whether to bridge it the console frontend's error handling, well, doesn't -Objective-C needs to be able to hook ffi_call for errors +setup a default hook mechanism for ffi_call passthrough +some JS callbacks don't use exception pointers at all... -- 2.45.2