From f7c38a297012f1f25c59243d39a5a6dc31da4cf7 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Mon, 12 Oct 2009 19:32:44 +0000 Subject: [PATCH] Protect bash glob expansions while generating libcycript.plist (thanks to kennytm), reorganized makefile gcc arguments slightly, removed CYApplicatonMain hack, support new Pointer to associate types to addresses, setup sig::Parse callbacks to later support circular type definitions, began reworking objc_registerClassPair to support tacking on extra Cycript features, and implemented a horrid temporary hack to allow @class objects to have a single JavaScript Instance object (at the extreme cost of simply leaking the entire Objective-C object). --- Library.mm | 91 ++++++++++++++++++++++++++++++++++----------------- makefile | 35 ++++++++++---------- sig/parse.hpp | 2 +- 3 files changed, 79 insertions(+), 49 deletions(-) diff --git a/Library.mm b/Library.mm index 6605c56..e66f581 100644 --- a/Library.mm +++ b/Library.mm @@ -366,7 +366,7 @@ 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) { +void Structor_(apr_pool_t *pool, const char *name, const char *types, sig::Type *&type) { if (name == NULL) return; @@ -408,7 +408,7 @@ struct ffoData : } }; -JSValueRef CYMakeInstance(JSContextRef context, id object, bool transient) { +JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { Instance::Flags flags; if (transient) @@ -487,14 +487,16 @@ bool CYGetIndex(apr_pool_t *pool, NSString *value, ssize_t &index) { - (NSString *) cy$toCYON; - (NSString *) cy$toKey; -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context; - - (NSObject *) cy$getProperty:(NSString *)name; - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value; - (bool) cy$deleteProperty:(NSString *)name; @end +@protocol Cycript +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context; +@end + @interface NSString (Cycript) - (void *) cy$symbol; @end @@ -607,10 +609,6 @@ struct PropertyAttributes { return [self cy$toCYON]; } -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return CYMakeInstance(context, self, false); -} - - (NSObject *) cy$getProperty:(NSString *)name { /*if (![name isEqualToString:@"prototype"]) NSLog(@"get:%@", name);*/ @@ -1144,7 +1142,12 @@ JSValueRef CYCastJSValue(JSContextRef context, const char *value) { } JSValueRef CYCastJSValue(JSContextRef context, id value) { - return value == nil ? CYJSNull(context) : [value cy$JSValueInContext:context]; + if (value == nil) + return CYJSNull(context); + else if ([value respondsToSelector:@selector(cy$JSValueInContext:)]) + return [value cy$JSValueInContext:context]; + else + return CYMakeInstance(context, value, false); } JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) { @@ -1864,25 +1867,6 @@ static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjec } CYCatch } -static JSValueRef CYApplicationMain(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - CYTry { - CYPool pool; - - int argc(CYCastDouble(context, arguments[0])); - char **argv(CYCastPointer(context, arguments[1])); - NSString *principal(CYCastNSObject(pool, context, arguments[2])); - NSString *delegate(CYCastNSObject(pool, context, arguments[3])); - - argc = *_NSGetArgc() - 1; - argv = *_NSGetArgv() + 1; - for (int i(0); i != argc; ++i) - NSLog(@"argv[%i]=%s", i, argv[i]); - - _pooled - return CYCastJSValue(context, UIApplicationMain(argc, argv, principal, delegate)); - } CYCatch -} - JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception) { const char *type; @@ -1944,6 +1928,35 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje return CYSendMessage(pool, context, self, _cmd, count - 2, arguments + 2, uninitialized, exception); } +static JSValueRef CYJSValueInContext(id self, SEL _cmd, JSContextRef context) { + // XXX: the offset of this Ivar could be recomputed and stored in some form of closure during $objc_registerClassPair + + JSObjectRef value; + object_getInstanceVariable(self, "cy$value_", reinterpret_cast(&value)); + + if (value == NULL) { + value = CYMakeInstance(context, self, false); + object_setInstanceVariable(self, "cy$value_", value); + } + + return value; +} + +static JSValueRef $objc_registerClassPair(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + CYPool pool; + + Class _class(CYCastNSObject(pool, context, object)); + if (class_getInstanceMethod(_class, @selector(cy$JSValueInContext:)) == NULL) { + class_addIvar(_class, "cy$value_", sizeof(JSObjectRef), log2(sizeof(JSObjectRef)), "^v"); + class_addMethod(_class, @selector(cy$JSValueInContext:), reinterpret_cast(&CYJSValueInContext), "^v12@0:4^v8"); + } + + objc_registerClassPair(_class); + return CYJSUndefined(context); + } CYCatch +} + static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { JSValueRef setup[count + 2]; setup[0] = _this; @@ -1967,6 +1980,23 @@ JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, } CYCatch } +JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { + if (count != 2) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil]; + + void *value(CYCastPointer(context, arguments[0])); + const char *type(CYCastCString(context, arguments[1])); + + CYPool pool; + + sig::Signature signature; + sig::Parse(pool, &signature, type, &Structor_); + + return CYMakePointer(context, value, signature.elements[0].type, NULL); + } CYCatch +} + JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { if (count != 2) @@ -2225,10 +2255,11 @@ MSInitialize { _pooled JSObjectSetPrototype(context, global, JSObjectMake(context, Runtime_, NULL)); CYSetProperty(context, global, CYJSString("ObjectiveC"), JSObjectMake(context, Runtime_, NULL)); - CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new)); CYSetProperty(context, global, CYJSString("Functor"), JSObjectMakeConstructor(context, Functor_, &Functor_new)); + CYSetProperty(context, global, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); + CYSetProperty(context, global, CYJSString("Selector"), JSObjectMakeConstructor(context, Selector_, &Selector_new)); - CYSetProperty(context, global, CYJSString("CYApplicationMain"), JSObjectMakeFunctionWithCallback(context, CYJSString("CYApplicationMain"), &CYApplicationMain)); + CYSetProperty(context, global, CYJSString("objc_registerClassPair"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_registerClassPair"), &$objc_registerClassPair)); CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend)); System_ = JSObjectMake(context, NULL, NULL); diff --git a/makefile b/makefile index 3b3229d..20c4123 100644 --- a/makefile +++ b/makefile @@ -12,6 +12,8 @@ flags += -F${PKG_ROOT}/System/Library/PrivateFrameworks svn := $(shell svnversion) deb := $(shell grep ^Package: control | cut -d ' ' -f 2-)_$(shell grep ^Version: control | cut -d ' ' -f 2 | sed -e 's/\#/$(svn)/')_iphoneos-arm.deb +header := Cycript.tab.hh Parser.hpp Pooling.hpp Struct.hpp cycript.hpp + all: cycript libcycript.dylib libcycript.plist clean: @@ -20,20 +22,11 @@ clean: libcycript.plist: Bridge.def { \ echo '({'; \ - grep '^[CFV]' Bridge.def | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | while read -r line; do \ - if [[ $$line == '' ]]; then \ - continue; \ - fi; \ - set $$line; \ - echo "$$2 = ($$1, \"$${3//\"/\\\"}\");"; \ - done; \ + grep '^[CFV]' Bridge.def | sed -e 's/^C/0/;s/^F/1/;s/^V/2/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$$/\2 = (\1, \"\3\");/'; \ echo '},{'; \ grep '^:' Bridge.def | sed -e 's/^: \([^ ]*\) \(.*\)/"\1" = "\2";/'; \ echo '},{'; \ - grep '^S' Bridge.def | sed -e 's/^S/0/' | while read -r line; do \ - set $$line; \ - echo "$$2 = ($$1, \"$${3//\"/\\\"}\");"; \ - done; \ + grep '^S' Bridge.def | sed -e 's/^S/0/' | sed -e 's/"/\\"/g;s/^\([^ ]*\) \([^ ]*\) \(.*\)$$/\2 = (\1, \"\3\");/'; \ echo '})'; \ } >$@ @@ -58,21 +51,27 @@ Cycript.tab.o: Cycript.tab.cc Cycript.tab.hh Parser.hpp Pooling.hpp lex.cy.o: lex.cy.c Cycript.tab.hh Parser.hpp Pooling.hpp $(target)g++ $(flags) -c -o $@ $< -Output.o: Output.cpp Parser.hpp Pooling.hpp - $(target)g++ $(flags) -c -o $@ $< - -Library.o: Library.mm Cycript.tab.hh Parser.hpp Pooling.hpp Struct.hpp cycript.hpp +%.o: %.cpp $(header) $(target)g++ $(flags) -c -o $@ $< -Application.o: Application.mm Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp +%.o: %.mm $(header) $(target)g++ $(flags) -c -o $@ $< libcycript.dylib: ffi_type.o parse.o Output.o Cycript.tab.o lex.cy.o Library.o - $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) -lobjc -framework CFNetwork -framework JavaScriptCore -framework WebCore -install_name /usr/lib/libcycript.dylib -framework CoreFoundation -framework Foundation -L$(menes)/mobilesubstrate -lsubstrate -lapr-1 -lffi -framework UIKit + $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) \ + -install_name /usr/lib/libcycript.dylib \ + -lobjc -lapr-1 -lffi \ + -framework CoreFoundation -framework Foundation \ + -framework CFNetwork \ + -framework JavaScriptCore -framework WebCore ldid -S $@ cycript: Application.o libcycript.dylib - $(target)g++ $(flags) -o $@ $(filter %.o,$^) -framework UIKit -framework Foundation -framework CoreFoundation -lobjc libcycript.dylib -lreadline -framework JavaScriptCore -lapr-1 + $(target)g++ $(flags) -o $@ $(filter %.o,$^) \ + -lobjc -lapr-1 -lreadline \ + -L. -lcycript \ + -framework Foundation -framework CoreFoundation \ + -framework JavaScriptCore -framework UIKit ldid -S cycript package: all diff --git a/sig/parse.hpp b/sig/parse.hpp index 230d9b6..5607ad3 100644 --- a/sig/parse.hpp +++ b/sig/parse.hpp @@ -46,7 +46,7 @@ namespace sig { -typedef void (*Callback)(apr_pool_t *pool, const char *name, const char *types, Type *type); +typedef void (*Callback)(apr_pool_t *pool, const char *name, const char *types, Type *&type); void Parse(apr_pool_t *pool, struct Signature *signature, const char *name, Callback callback); const char *Unparse(apr_pool_t *pool, struct Signature *signature); -- 2.45.2