From 953647c120fbe1d8b7c59941ef5df5d35031c2af Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Fri, 9 Oct 2009 02:52:29 +0000 Subject: [PATCH] Tried to unify naming of classes, removed usages of JSC-specific parentClass, added a separate obc. namespace, moved Global's functionality out to a Runtime prototype, refactored Bridge to keep separate selector/C namespaces, registered dlfcn names, typed up a quick todo list, and started using .valueOf() to get pointer values. --- Bridge.def | 22 ++++++- Library.mm | 170 +++++++++++++++++++++++++++++++++++------------------ makefile | 7 ++- todo.txt | 3 + 4 files changed, 143 insertions(+), 59 deletions(-) create mode 100644 todo.txt diff --git a/Bridge.def b/Bridge.def index 5dea275..922b0a6 100644 --- a/Bridge.def +++ b/Bridge.def @@ -2,6 +2,8 @@ C YES true C NO false C nil null +: applicationDidFinishLaunching: v@:@ + l objc F class_addIvar B#*LC* @@ -507,4 +509,22 @@ C MKPinAnnotationColorPurple 2 # MKCoordinateRegionMakeWithDistance # MKCoordinateSpanMake -: applicationDidFinishLaunching: v@:@ +C RTLD_LAZY 0x1 +C RTLD_NOW 0x2 +C RTLD_LOCAL 0x4 +C RTLD_GLOBAL 0x8 + +C RTLD_NOLOAD 0x10 +C RTLD_NODELETE 0x80 +C RTLD_FIRST 0x100 + +C RTLD_NEXT -1 +C RTLD_DEFAULT -2 +C RTLD_SELF -3 + +# XXX: dladdr +F dlclose i^v +F dlerror * +F dlopen ^v*i +F dlsym ^v^v* +F dlopen_preflight B* diff --git a/Library.mm b/Library.mm index aa65697..4b6b7bc 100644 --- a/Library.mm +++ b/Library.mm @@ -104,7 +104,9 @@ static JSObjectRef System_; static JSClassRef Functor_; static JSClassRef Instance_; static JSClassRef Pointer_; +static JSClassRef Runtime_; static JSClassRef Selector_; +static JSClassRef Struct_; static JSObjectRef Array_; static JSObjectRef Function_; @@ -115,60 +117,71 @@ static JSStringRef length_; static Class NSCFBoolean_; -static NSMutableDictionary *Bridge_; +static NSArray *Bridge_; struct Client { CFHTTPMessageRef message_; CFSocketRef socket_; }; -struct ptrData { +struct CYData { apr_pool_t *pool_; - void *value_; - sig::Type type_; + + virtual ~CYData() { + } void *operator new(size_t size) { apr_pool_t *pool; apr_pool_create(&pool, NULL); void *data(apr_palloc(pool, size)); - reinterpret_cast(data)->pool_ = pool; + reinterpret_cast(data)->pool_ = pool; return data;; } - ptrData(void *value) : - value_(value) - { + static void Finalize(JSObjectRef object) { + CYData *data(reinterpret_cast(JSObjectGetPrivate(object))); + data->~CYData(); + apr_pool_destroy(data->pool_); } +}; + +struct Pointer_privateData : + CYData +{ + void *value_; + sig::Type type_; - virtual ~ptrData() { + Pointer_privateData(void *value) : + value_(value) + { } }; -struct ffiData : ptrData { +struct Functor_privateData : Pointer_privateData { sig::Signature signature_; ffi_cif cif_; - ffiData(const char *type, void (*value)()) : - ptrData(reinterpret_cast(value)) + Functor_privateData(const char *type, void (*value)()) : + Pointer_privateData(reinterpret_cast(value)) { sig::Parse(pool_, &signature_, type); sig::sig_ffi_cif(pool_, &sig::ObjectiveC, &signature_, &cif_); } }; -struct ffoData : ffiData { +struct ffoData : Functor_privateData { JSContextRef context_; JSObjectRef function_; ffoData(const char *type) : - ffiData(type, NULL) + Functor_privateData(type, NULL) { } }; -struct selData : ptrData { - selData(SEL value) : - ptrData(value) +struct Selector_privateData : Pointer_privateData { + Selector_privateData(SEL value) : + Pointer_privateData(value) { } @@ -177,15 +190,15 @@ struct selData : ptrData { } }; -struct jocData : ptrData { +struct Instance_privateData : Pointer_privateData { bool transient_; - jocData(id value, bool transient) : - ptrData(value) + Instance_privateData(id value, bool transient) : + Pointer_privateData(value) { } - virtual ~jocData() { + virtual ~Instance_privateData() { if (!transient_) [GetValue() release]; } @@ -195,10 +208,13 @@ struct jocData : ptrData { } }; +struct Struct_privateData : CYData { +}; + JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { if (!transient) object = [object retain]; - jocData *data(new jocData(object, transient)); + Instance_privateData *data(new Instance_privateData(object, transient)); return JSObjectMake(context, Instance_, data); } @@ -274,7 +290,8 @@ JSValueRef CYJSUndefined(JSContextRef context) { } - (NSObject *) cy$getProperty:(NSString *)name { - NSLog(@"get:%@", name); + if (![name isEqualToString:@"prototype"]) + NSLog(@"get:%@", name); return nil; } @@ -518,9 +535,13 @@ id CYPoolRelease(apr_pool_t *pool, id object) { } } +CFTypeRef CYPoolRelease(apr_pool_t *pool, CFTypeRef object) { + return (CFTypeRef) CYPoolRelease(pool, (id) object); +} + id CYCastNSObject(apr_pool_t *pool, JSContextRef context, JSObjectRef object) { if (JSValueIsObjectOfClass(context, object, Instance_)) { - jocData *data(reinterpret_cast(JSObjectGetPrivate(object))); + Instance_privateData *data(reinterpret_cast(JSObjectGetPrivate(object))); return data->GetValue(); } @@ -618,8 +639,16 @@ CFNumberRef CYCopyCFNumber(JSContextRef context, JSValueRef 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)); +} + NSString *CYCastNSString(apr_pool_t *pool, JSStringRef value) { - return CYPoolRelease(pool, reinterpret_cast(CYCopyCFString(value))); + return (NSString *) CYPoolRelease(pool, CYCopyCFString(value)); } bool CYCastBool(JSContextRef context, JSValueRef value) { @@ -669,7 +698,7 @@ CFTypeRef CYCFType(apr_pool_t *pool, JSContextRef context, JSValueRef value, boo if (cast != copy) return object; else if (copy) - return CYPoolRelease(pool, (id) object); + return CYPoolRelease(pool, object); else return CFRetain(object); } @@ -926,29 +955,23 @@ static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JS static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - jocData *data(reinterpret_cast(JSObjectGetPrivate(object))); + Instance_privateData *data(reinterpret_cast(JSObjectGetPrivate(object))); return CYMakeInstance(context, [data->GetValue() alloc], true); } CYCatch } JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) { - selData *data(new selData(sel)); + Selector_privateData *data(new Selector_privateData(sel)); return JSObjectMake(context, Selector_, data); } JSObjectRef CYMakePointer(JSContextRef context, void *pointer) { - ptrData *data(new ptrData(pointer)); + Pointer_privateData *data(new Pointer_privateData(pointer)); return JSObjectMake(context, Pointer_, data); } -static void Pointer_finalize(JSObjectRef object) { - ptrData *data(reinterpret_cast(JSObjectGetPrivate(object))); - data->~ptrData(); - apr_pool_destroy(data->pool_); -} - JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) { - ffiData *data(new ffiData(type, function)); + Functor_privateData *data(new Functor_privateData(type, function)); return JSObjectMake(context, Functor_, data); } @@ -988,7 +1011,7 @@ SEL CYCastSEL(JSContextRef context, JSValueRef value) { if (JSValueIsNull(context, value)) return NULL; else if (JSValueIsObjectOfClass(context, value, Selector_)) { - selData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); + Selector_privateData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); return reinterpret_cast(data->value_); } else return sel_registerName(CYCastCString(context, value)); @@ -998,15 +1021,18 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value) { switch (JSValueGetType(context, value)) { case kJSTypeNull: return NULL; - case kJSTypeString: + /*case kJSTypeString: return dlsym(RTLD_DEFAULT, CYCastCString(context, value)); case kJSTypeObject: if (JSValueIsObjectOfClass(context, value, Pointer_)) { - ptrData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); + Pointer_privateData *data(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); return data->value_; - } + }*/ default: - return reinterpret_cast(static_cast(CYCastDouble(context, value))); + double number(CYCastDouble(context, value)); + if (isnan(number)) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"cannot convert value to pointer" userInfo:nil]; + return reinterpret_cast(static_cast(static_cast(number))); } } @@ -1203,13 +1229,13 @@ JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char return JSObjectMake(context, Functor_, data); } -static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { +static JSValueRef Runtime_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { CYPool pool; NSString *name(CYCastNSString(pool, property)); if (Class _class = NSClassFromString(name)) return CYMakeInstance(context, _class, true); - if (NSMutableArray *entry = [Bridge_ objectForKey:name]) + if (NSMutableArray *entry = [[Bridge_ objectAtIndex:0] objectForKey:name]) switch ([[entry objectAtIndex:0] intValue]) { case 0: return JSEvaluateScript(CYGetJSContext(), CYJSString([entry objectAtIndex:1]), NULL, NULL, 0, NULL); @@ -1304,7 +1330,7 @@ static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef obje } static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - ffiData *data(reinterpret_cast(JSObjectGetPrivate(object))); + Functor_privateData *data(reinterpret_cast(JSObjectGetPrivate(object))); return CYCallFunction(context, count, arguments, exception, &data->signature_, &data->cif_, reinterpret_cast(data->value_)); } @@ -1336,7 +1362,7 @@ JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, } JSValueRef Pointer_getProperty_value(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - ptrData *data(reinterpret_cast(JSObjectGetPrivate(object))); + Pointer_privateData *data(reinterpret_cast(JSObjectGetPrivate(object))); return CYCastJSValue(context, reinterpret_cast(data->value_)); } @@ -1344,9 +1370,16 @@ JSValueRef Selector_getProperty_prototype(JSContextRef context, JSObjectRef obje return Function_; } +static JSValueRef Pointer_callAsFunction_valueOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + Pointer_privateData *data(reinterpret_cast(JSObjectGetPrivate(_this))); + return CYCastJSValue(context, reinterpret_cast(data->value_)); + } CYCatch +} + static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - jocData *data(reinterpret_cast(JSObjectGetPrivate(_this))); + Instance_privateData *data(reinterpret_cast(JSObjectGetPrivate(_this))); NSString *description; CYPoolTry { description = [data->GetValue() description]; } CYPoolCatch(NULL) @@ -1356,7 +1389,7 @@ static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjec static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - selData *data(reinterpret_cast(JSObjectGetPrivate(_this))); + Selector_privateData *data(reinterpret_cast(JSObjectGetPrivate(_this))); return CYCastJSValue(context, sel_getName(data->GetValue())); } CYCatch } @@ -1366,13 +1399,13 @@ static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil]; CYPool pool; - selData *data(reinterpret_cast(JSObjectGetPrivate(_this))); + Selector_privateData *data(reinterpret_cast(JSObjectGetPrivate(_this))); Class _class(CYCastNSObject(pool, context, arguments[0])); bool instance(CYCastBool(context, arguments[1])); SEL sel(data->GetValue()); if (Method method = (*(instance ? &class_getInstanceMethod : class_getClassMethod))(_class, sel)) return CYCastJSValue(context, method_getTypeEncoding(method)); - else if (NSString *type = [Bridge_ objectForKey:CYPoolRelease(pool, [[NSString alloc] initWithFormat:@":%s", sel_getName(sel)])]) + else if (NSString *type = [[Bridge_ objectAtIndex:1] objectForKey:CYCastNSString(pool, sel_getName(sel))]) return CYCastJSValue(context, CYJSString(type)); else return CYJSNull(context); @@ -1384,6 +1417,11 @@ static JSStaticValue Pointer_staticValues[2] = { {NULL, NULL, NULL, 0} }; +static JSStaticFunction Pointer_staticFunctions[2] = { + {"valueOf", &Pointer_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, 0} +}; + /*static JSStaticValue Selector_staticValues[2] = { {"prototype", &Selector_getProperty_prototype, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete}, {NULL, NULL, NULL, 0} @@ -1435,6 +1473,8 @@ void CYSetArgs(int argc, const char *argv[]) { MSInitialize { _pooled apr_initialize(); + Bridge_ = [[NSMutableArray arrayWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; + NSCFBoolean_ = objc_getClass("NSCFBoolean"); pid_t pid(getpid()); @@ -1461,35 +1501,52 @@ MSInitialize { _pooled definition = kJSClassDefinitionEmpty; definition.className = "Pointer"; definition.staticValues = Pointer_staticValues; - definition.finalize = &Pointer_finalize; + definition.staticFunctions = Pointer_staticFunctions; + definition.finalize = &CYData::Finalize; Pointer_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Functor"; - definition.parentClass = Pointer_; + definition.staticValues = Pointer_staticValues; + definition.staticFunctions = Pointer_staticFunctions; definition.callAsFunction = &Functor_callAsFunction; + definition.finalize = &CYData::Finalize; Functor_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; + definition.className = "Struct"; + //definition.getProperty = &Struct_getProperty; + //definition.setProperty = &Struct_setProperty; + definition.finalize = &CYData::Finalize; + Struct_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; definition.className = "Selector"; - definition.parentClass = Pointer_; + definition.staticValues = Pointer_staticValues; //definition.staticValues = Selector_staticValues; definition.staticFunctions = Selector_staticFunctions; definition.callAsFunction = &Selector_callAsFunction; + definition.finalize = &CYData::Finalize; Selector_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Instance"; - definition.parentClass = Pointer_; + definition.staticValues = Pointer_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; Instance_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; - definition.getProperty = &Global_getProperty; + definition.className = "Runtime"; + definition.getProperty = &Runtime_getProperty; + Runtime_ = JSClassCreate(&definition); + + definition = kJSClassDefinitionEmpty; + //definition.getProperty = &Global_getProperty; JSClassRef Global(JSClassCreate(&definition)); JSGlobalContextRef context(JSGlobalContextCreate(Global)); @@ -1497,6 +1554,9 @@ MSInitialize { _pooled JSObjectRef global(JSContextGetGlobalObject(context)); + JSObjectSetPrototype(context, global, JSObjectMake(context, Runtime_, NULL)); + CYSetProperty(context, global, CYJSString("obc"), JSObjectMake(context, Runtime_, NULL)); + CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new)); CYSetProperty(context, global, CYJSString("Functor"), JSObjectMakeConstructor(context, Functor_, &Functor_new)); @@ -1510,8 +1570,6 @@ MSInitialize { _pooled CYSetProperty(context, System_, CYJSString("print"), JSObjectMakeFunctionWithCallback(context, CYJSString("print"), &System_print)); - Bridge_ = [[NSMutableDictionary dictionaryWithContentsOfFile:@"/usr/lib/libcycript.plist"] retain]; - name_ = JSStringCreateWithUTF8CString("name"); message_ = JSStringCreateWithUTF8CString("message"); length_ = JSStringCreateWithUTF8CString("length"); diff --git a/makefile b/makefile index 607adef..8494011 100644 --- a/makefile +++ b/makefile @@ -16,6 +16,7 @@ clean: libcycript.plist: Bridge.def { \ + echo '({'; \ sed -e 's/^C/0/;s/^F/1/;s/^V/2/' Bridge.def | while read -r line; do \ if [[ $$line == '' ]]; then \ continue; \ @@ -26,7 +27,9 @@ libcycript.plist: Bridge.def fi; \ echo "$$2 = ($$1, \"$$3\");"; \ done; \ - grep ^: Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/":\1" = "\2";/'; \ + echo '},{'; \ + grep ^: Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/"\1" = "\2";/'; \ + echo '})'; \ } >$@ Cycript.tab.cc Cycript.tab.hh location.hh position.hh: Cycript.y @@ -88,6 +91,6 @@ package: all test: package dpkg -i $(shell grep ^Package: control | cut -d ' ' -f 2-)_$(shell grep ^Version: control | cut -d ' ' -f 2)_iphoneos-arm.deb - cycript /Applications/HelloCycript.app/HelloCycript + cycript test.cy .PHONY: all clean extra package diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..d3f6a4e --- /dev/null +++ b/todo.txt @@ -0,0 +1,3 @@ +labelled statements don't get labelled +blocks and empty statements are poorly factored +functors use both ffiData and ffoData... -- 2.45.2