]> git.saurik.com Git - cycript.git/blobdiff - Execute.cpp
Somewhat better iconv handling on the Mac when MacPorts is in the path (aka Horrible...
[cycript.git] / Execute.cpp
index dfe0600d0a2e0bf79dfc1ba74d4dd68c7f3d8938..8ac1b14657925697d8624e9c56de008a7d014a9c 100644 (file)
@@ -165,11 +165,14 @@ JSStringRef push_s;
 JSStringRef splice_s;
 JSStringRef toCYON_s;
 JSStringRef toJSON_s;
+JSStringRef toPointer_s;
 
 static JSStringRef Result_;
 
 void CYFinalize(JSObjectRef object) {
-    delete reinterpret_cast<CYData *>(JSObjectGetPrivate(object));
+    CYData *internal(reinterpret_cast<CYData *>(JSObjectGetPrivate(object)));
+    if (--internal->count_ == 0)
+        delete internal;
 }
 
 void Structor_(apr_pool_t *pool, sig::Type *&type) {
@@ -486,8 +489,21 @@ JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, si
     return JSObjectMake(context, Pointer_, internal);
 }
 
-static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type) {
-    cy::Functor *internal(new cy::Functor(type, function));
+static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const char *type, void **cache = NULL) {
+    cy::Functor *internal;
+
+    if (cache != NULL && *cache != NULL) {
+        internal = reinterpret_cast<cy::Functor *>(*cache);
+        ++internal->count_;
+    } else {
+        internal = new cy::Functor(type, function);
+
+        if (cache != NULL) {
+            *cache = internal;
+            ++internal->count_;
+        }
+    }
+
     return JSObjectMake(context, Functor_, internal);
 }
 
@@ -499,12 +515,19 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value) {
     switch (JSValueGetType(context, value)) {
         case kJSTypeNull:
             return NULL;
-        /*case kJSTypeObject:
+        case kJSTypeObject: {
+            JSObjectRef object((JSObjectRef) value);
             if (JSValueIsObjectOfClass(context, value, Pointer_)) {
-                Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate((JSObjectRef) value)));
+                Pointer *internal(reinterpret_cast<Pointer *>(JSObjectGetPrivate(object)));
                 return internal->value_;
-            }*/
-        default:
+            }
+            JSValueRef toPointer(CYGetProperty(context, object, toPointer_s));
+            if (CYIsCallable(context, toPointer)) {
+                JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toPointer, object, 0, NULL));
+                _assert(value != NULL);
+                return CYCastPointer_(context, value);
+            }
+        } default:
             double number(CYCastDouble(context, value));
             if (std::isnan(number))
                 throw CYJSError(context, "cannot convert value to pointer");
@@ -954,7 +977,7 @@ static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSSt
 
                 case '1':
                     if (void (*symbol)() = reinterpret_cast<void (*)()>(CYCastSymbol(name.data)))
-                        return CYMakeFunctor(context, symbol, entry->value_);
+                        return CYMakeFunctor(context, symbol, entry->value_, &entry->cache_);
                     else return NULL;
 
                 case '2':
@@ -1293,6 +1316,7 @@ void CYInitializeDynamic() {
     splice_s = JSStringCreateWithUTF8CString("splice");
     toCYON_s = JSStringCreateWithUTF8CString("toCYON");
     toJSON_s = JSStringCreateWithUTF8CString("toJSON");
+    toPointer_s = JSStringCreateWithUTF8CString("toPointer");
 
     Result_ = JSStringCreateWithUTF8CString("_");
 
@@ -1414,7 +1438,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     CYSetProperty(context, global, CYJSString("$cyq"), &$cyq);
 
     JSObjectRef System(JSObjectMake(context, NULL, NULL));
-    CYSetProperty(context, cy, CYJSString("System"), Function);
+    CYSetProperty(context, cy, CYJSString("System"), System);
 
     CYSetProperty(context, global, CYJSString("system"), System);
     CYSetProperty(context, System, CYJSString("args"), CYJSNull(context));