From: Jay Freeman (saurik) Date: Thu, 15 Oct 2009 07:33:09 +0000 (+0000) Subject: Added Instance constructor instance (for Instance.prototype), implemented Type class... X-Git-Tag: v0.9.432~347 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/bce8339b629582dd04df0570468ac746adc0fcf7?hp=967067aad721ea46d36b756333ac2dd8183eb571 Added Instance constructor instance (for Instance.prototype), implemented Type class, refactored memory management of Type_privateData, fixed a couple missing spaces in serialization (such as 'newnew'), and dealt with the extra bad exceptions that weren't being caught (unrecognized selectors). --- diff --git a/Library.mm b/Library.mm index c4bc8e9..c4289e7 100644 --- a/Library.mm +++ b/Library.mm @@ -114,6 +114,7 @@ static JSClassRef Pointer_; static JSClassRef Runtime_; static JSClassRef Selector_; static JSClassRef Struct_; +static JSClassRef Type_; static JSObjectRef Array_; static JSObjectRef Function_; @@ -136,14 +137,18 @@ struct CYData { virtual ~CYData() { } - static void *operator new(size_t size) { - apr_pool_t *pool; - apr_pool_create(&pool, NULL); + static void *operator new(size_t size, apr_pool_t *pool) { void *data(apr_palloc(pool, size)); reinterpret_cast(data)->pool_ = pool; return data; } + static void *operator new(size_t size) { + apr_pool_t *pool; + apr_pool_create(&pool, NULL); + return operator new(size, pool); + } + static void operator delete(void *data) { apr_pool_destroy(reinterpret_cast(data)->pool_); } @@ -289,29 +294,56 @@ struct CStringMapLess : } }; -struct Type_privateData { - apr_pool_t *pool_; +void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) { + if (name == NULL) + return; + CYPoolTry { + if (NSMutableArray *entry = [[Bridge_ objectAtIndex:2] objectForKey:[NSString stringWithUTF8String:name]]) + switch ([[entry objectAtIndex:0] intValue]) { + case 0: { + sig::Parse(pool, &type->data.signature, [[entry objectAtIndex:1] UTF8String], &Structor_); + } break; + + case 1: { + sig::Signature signature; + sig::Parse(pool, &signature, [[entry objectAtIndex:1] UTF8String], &Structor_); + type = signature.elements[0].type; + } break; + } + } CYPoolCatch() +} + +struct Type_privateData : + CYData +{ ffi_type *ffi_; sig::Type *type_; - Type_privateData(apr_pool_t *pool, sig::Type *type) : - pool_(pool), + void Set(sig::Type *type) { + type_ = new(pool_) sig::Type; + sig::Copy(pool_, *type_, *type); + } + + Type_privateData(const char *type) : ffi_(NULL) { - if (type != NULL) { - type_ = new(pool) sig::Type; - sig::Copy(pool, *type_, *type); - } + sig::Signature signature; + sig::Parse(pool_, &signature, type, &Structor_); + type_ = signature.elements[0].type; } - Type_privateData(apr_pool_t *pool, sig::Type *type, ffi_type *ffi) : - pool_(pool) + Type_privateData(sig::Type *type) : + ffi_(NULL) { - ffi_ = new(pool) ffi_type; - sig::Copy(pool, *ffi_, *ffi); - type_ = new(pool) sig::Type; - sig::Copy(pool, *type_, *type); + if (type != NULL) + Set(type); + } + + Type_privateData(sig::Type *type, ffi_type *ffi) { + ffi_ = new(pool_) ffi_type; + sig::Copy(pool_, *ffi_, *ffi); + Set(type); } ffi_type *GetFFI() { @@ -345,7 +377,7 @@ struct Pointer : Pointer(void *value, sig::Type *type, JSObjectRef owner) : CYValue(value), owner_(owner), - type_(new(pool_) Type_privateData(pool_, type)) + type_(new(pool_) Type_privateData(type)) { } }; @@ -368,7 +400,7 @@ static TypeMap Types_; JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_type *ffi, JSObjectRef owner) { Struct_privateData *internal(new Struct_privateData(owner)); apr_pool_t *pool(internal->pool_); - Type_privateData *typical(new(pool) Type_privateData(pool, type, ffi)); + Type_privateData *typical(new(pool) Type_privateData(type, ffi)); internal->type_ = typical; if (owner != NULL) @@ -383,26 +415,6 @@ JSObjectRef CYMakeStruct(JSContextRef context, void *data, sig::Type *type, ffi_ return JSObjectMake(context, Struct_, internal); } -void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) { - if (name == NULL) - return; - - CYPoolTry { - if (NSMutableArray *entry = [[Bridge_ objectAtIndex:2] objectForKey:[NSString stringWithUTF8String:name]]) - switch ([[entry objectAtIndex:0] intValue]) { - case 0: { - sig::Parse(pool, &type->data.signature, [[entry objectAtIndex:1] UTF8String], &Structor_); - } break; - - case 1: { - sig::Signature signature; - sig::Parse(pool, &signature, [[entry objectAtIndex:1] UTF8String], &Structor_); - type = signature.elements[0].type; - } break; - } - } CYPoolCatch() -} - struct Functor_privateData : CYValue { @@ -1936,12 +1948,14 @@ JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _c if (Method method = class_getInstanceMethod(_class, _cmd)) type = method_getTypeEncoding(method); else { - CYPoolTry { - NSMethodSignature *method([self methodSignatureForSelector:_cmd]); - if (method == nil) - @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil]; - type = CYPoolCString(pool, [method _typeString]); - } CYPoolCatch(NULL) + CYTry { + CYPoolTry { + NSMethodSignature *method([self methodSignatureForSelector:_cmd]); + if (method == nil) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil]; + type = CYPoolCString(pool, [method _typeString]); + } CYPoolCatch(NULL) + } CYCatch } void *setup[2]; @@ -2059,6 +2073,46 @@ JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } +JSObjectRef CYMakeType(JSContextRef context, JSObjectRef object, const char *type) { + Type_privateData *internal(new Type_privateData(type)); + return JSObjectMake(context, Type_, internal); +} + +JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + if (count != 1) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Type constructor" userInfo:nil]; + const char *type(CYCastCString(context, arguments[0])); + return CYMakeType(context, object, type); + } CYCatch +} + +static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + if (count != 1) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to type cast function" userInfo:nil]; + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + sig::Type *type(internal->type_); + ffi_type *ffi(internal->GetFFI()); + // XXX: alignment? + uint8_t value[ffi->size]; + CYPool pool; + CYPoolFFI(pool, context, type, ffi, value, arguments[0]); + return CYFromFFI(context, type, ffi, value, false); + } CYCatch +} + +static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + if (count > 1) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to type cast function" userInfo:nil]; + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + // XXX: alignment? + void *value(malloc(internal->GetFFI()->size)); + return CYMakePointer(context, value, internal->type_, NULL); + } CYCatch +} + JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 2) @@ -2396,6 +2450,13 @@ static void * APR_THREAD_FUNC Cyrver(apr_thread_t *thread, void *data) { return NULL; } +void Unlink() { + pid_t pid(getpid()); + char path[104]; + sprintf(path, "/tmp/.s.cy.%u", pid); + unlink(path); +} + MSInitialize { _pooled _aprcall(apr_initialize()); _aprcall(apr_pool_create(&Pool_, NULL)); @@ -2414,6 +2475,7 @@ MSInitialize { _pooled try { _syscall(bind(Socket_, reinterpret_cast(&address), SUN_LEN(&address))); + atexit(&Unlink); _syscall(listen(Socket_, 0)); apr_threadattr_t *attr; @@ -2430,14 +2492,6 @@ JSGlobalContextRef CYGetJSContext() { if (Context_ == NULL) { JSClassDefinition definition; - definition = kJSClassDefinitionEmpty; - definition.className = "Pointer"; - definition.staticFunctions = Pointer_staticFunctions; - definition.getProperty = &Pointer_getProperty; - definition.setProperty = &Pointer_setProperty; - definition.finalize = &CYData::Finalize; - Pointer_ = JSClassCreate(&definition); - definition = kJSClassDefinitionEmpty; definition.className = "Functor"; definition.staticFunctions = Functor_staticFunctions; @@ -2446,12 +2500,23 @@ JSGlobalContextRef CYGetJSContext() { Functor_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; - definition.className = "Struct"; - definition.getProperty = &Struct_getProperty; - definition.setProperty = &Struct_setProperty; - definition.getPropertyNames = &Struct_getPropertyNames; + definition.className = "Instance"; + definition.staticValues = CYValue_staticValues; + definition.staticFunctions = Instance_staticFunctions; + definition.getProperty = &Instance_getProperty; + definition.setProperty = &Instance_setProperty; + definition.deleteProperty = &Instance_deleteProperty; + definition.callAsConstructor = &Instance_callAsConstructor; definition.finalize = &CYData::Finalize; - Struct_ = JSClassCreate(&definition); + Instance_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Pointer"; + definition.staticFunctions = Pointer_staticFunctions; + definition.getProperty = &Pointer_getProperty; + definition.setProperty = &Pointer_setProperty; + definition.finalize = &CYData::Finalize; + Pointer_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Selector"; @@ -2463,15 +2528,19 @@ JSGlobalContextRef CYGetJSContext() { Selector_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; - definition.className = "Instance"; - definition.staticValues = CYValue_staticValues; - definition.staticFunctions = Instance_staticFunctions; - definition.getProperty = &Instance_getProperty; - definition.setProperty = &Instance_setProperty; - definition.deleteProperty = &Instance_deleteProperty; - definition.callAsConstructor = &Instance_callAsConstructor; + definition.className = "Struct"; + definition.getProperty = &Struct_getProperty; + definition.setProperty = &Struct_setProperty; + definition.getPropertyNames = &Struct_getPropertyNames; definition.finalize = &CYData::Finalize; - Instance_ = JSClassCreate(&definition); + Struct_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + definition.className = "Type"; + definition.callAsFunction = &Type_callAsFunction; + definition.callAsConstructor = &Type_callAsConstructor; + definition.finalize = &CYData::Finalize; + Type_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Runtime"; @@ -2491,8 +2560,10 @@ JSGlobalContextRef CYGetJSContext() { CYSetProperty(context, global, CYJSString("ObjectiveC"), JSObjectMake(context, Runtime_, NULL)); CYSetProperty(context, global, CYJSString("Functor"), JSObjectMakeConstructor(context, Functor_, &Functor_new)); + CYSetProperty(context, global, CYJSString("Instance"), JSObjectMakeConstructor(context, Instance_, NULL)); CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new)); + CYSetProperty(context, global, CYJSString("Type"), JSObjectMakeConstructor(context, Type_, &Type_new)); MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair)); diff --git a/Output.cpp b/Output.cpp index b2cfee5..e8112c4 100644 --- a/Output.cpp +++ b/Output.cpp @@ -379,6 +379,8 @@ void CYMessage::Output(std::ostream &out) const { } void CYNew::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << "new"; constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader); out << '('; @@ -448,6 +450,8 @@ void CYReturn::Output(std::ostream &out) const { } void CYSelector::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << "new Selector(\""; if (name_ != NULL) name_->Output(out);