]> git.saurik.com Git - cycript.git/blobdiff - Execute.cpp
Use correct variable to verify thread state access.
[cycript.git] / Execute.cpp
index 2d77e213777ba03c6c4e930d43e57878a81912ab..74f29f229358d098fc08688df04f064e28ead47c 100644 (file)
@@ -131,7 +131,7 @@ size_t CYGetIndex(apr_pool_t *pool, JSContextRef context, JSStringRef value) {
 
 static JSClassRef All_;
 static JSClassRef Context_;
-static JSClassRef Functor_;
+JSClassRef Functor_;
 static JSClassRef Global_;
 static JSClassRef Pointer_;
 static JSClassRef Struct_;
@@ -401,6 +401,16 @@ const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSObjectRef obje
         return cyon;
     }
 
+    if (JSObjectIsFunction(context, object)) {
+        JSValueRef toString(CYGetProperty(context, object, toString_s));
+        if (CYIsCallable(context, toString)) {
+            JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))};
+            JSValueRef value(CYCallAsFunction(context, (JSObjectRef) toString, object, 1, arguments));
+            _assert(value != NULL);
+            return CYPoolCString(pool, context, value);
+        }
+    }
+
     std::ostringstream str;
 
     str << '{';
@@ -675,7 +685,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, ffi_type *ffi, void
     }
 }
 
-static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
+void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg, JSValueRef (*adapter)(JSContextRef, size_t, JSValueRef[], JSObjectRef)) {
     Closure_privateData *internal(reinterpret_cast<Closure_privateData *>(arg));
 
     JSContextRef context(internal->context_);
@@ -686,10 +696,18 @@ static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void
     for (size_t index(0); index != count; ++index)
         values[index] = CYFromFFI(context, internal->signature_.elements[1 + index].type, internal->cif_.arg_types[index], arguments[index]);
 
-    JSValueRef value(CYCallAsFunction(context, internal->function_, NULL, count, values));
+    JSValueRef value(adapter(context, count, values, internal->function_));
     CYPoolFFI(NULL, context, internal->signature_.elements[0].type, internal->cif_.rtype, result, value);
 }
 
+static JSValueRef FunctionAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) {
+    return CYCallAsFunction(context, function, NULL, count, values);
+}
+
+static void FunctionClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) {
+    CYExecuteClosure(cif, result, arguments, arg, &FunctionAdapter_);
+}
+
 Closure_privateData *CYMakeFunctor_(JSContextRef context, JSObjectRef function, const char *type, void (*callback)(ffi_cif *, void *, void **, void *)) {
     // XXX: in case of exceptions this will leak
     // XXX: in point of fact, this may /need/ to leak :(
@@ -937,12 +955,12 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec
     return CYCallFunction(pool, context, 0, NULL, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue());
 }
 
-static JSObjectRef CYMakeType(JSContextRef context, const char *type) {
+JSObjectRef CYMakeType(JSContextRef context, const char *type) {
     Type_privateData *internal(new Type_privateData(type));
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
 
-static JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
+JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) {
     Type_privateData *internal(new Type_privateData(type));
     return JSObjectMake(context, Type_privateData::Class_, internal);
 }
@@ -1019,7 +1037,7 @@ static void All_getPropertyNames(JSContextRef context, JSObjectRef object, JSPro
 
 static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     if (count != 2)
-        throw CYJSError(context, "incorrect number of arguments to Functor constructor");
+        throw CYJSError(context, "incorrect number of arguments to Pointer constructor");
 
     CYPool pool;
 
@@ -1040,36 +1058,71 @@ static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t cou
     return CYMakeType(context, type);
 } CYCatch }
 
-static JSValueRef Type_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 1)
+        throw CYJSError(context, "incorrect number of arguments to Type.arrayOf");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+
+    CYPool pool;
+    size_t index(CYGetIndex(pool, context, CYJSString(context, arguments[0])));
+    if (index == _not(size_t))
+        throw CYJSError(context, "invalid array size used with Type.arrayOf");
 
     sig::Type type;
+    type.name = NULL;
+    type.flags = 0;
 
-    if (JSStringIsEqualToUTF8CString(property, "$cyi")) {
-        type.primitive = sig::pointer_P;
-        type.data.data.size = 0;
-    } else {
-        CYPool pool;
-        size_t index(CYGetIndex(pool, context, property));
-        if (index == _not(size_t))
-            return NULL;
-        type.primitive = sig::array_P;
-        type.data.data.size = index;
-    }
+    type.primitive = sig::array_P;
+    type.data.data.type = internal->type_;
+    type.data.data.size = index;
+
+    return CYMakeType(context, &type);
+} CYCatch }
+
+static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 0)
+        throw CYJSError(context, "incorrect number of arguments to Type.constant");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+
+    sig::Type type(*internal->type_);
+    type.flags |= JOC_TYPE_CONST;
+    return CYMakeType(context, &type);
+} CYCatch }
+
+static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 0)
+        throw CYJSError(context, "incorrect number of arguments to Type.pointerTo");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
 
+    sig::Type type;
     type.name = NULL;
     type.flags = 0;
 
+    type.primitive = sig::pointer_P;
     type.data.data.type = internal->type_;
+    type.data.data.size = 0;
 
     return CYMakeType(context, &type);
 } CYCatch }
 
-static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+static JSValueRef Type_callAsFunction_withName(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+    if (count != 1)
+        throw CYJSError(context, "incorrect number of arguments to Type.withName");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
+
+    CYPool pool;
+    const char *name(CYPoolCString(pool, context, arguments[0]));
 
+    sig::Type type(*internal->type_);
+    type.name = name;
+    return CYMakeType(context, &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 CYJSError(context, "incorrect number of arguments to type cast function");
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+
     sig::Type *type(internal->type_);
     ffi_type *ffi(internal->GetFFI());
     // XXX: alignment?
@@ -1081,7 +1134,7 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object,
 
 static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     if (count != 0)
-        throw CYJSError(context, "incorrect number of arguments to type cast function");
+        throw CYJSError(context, "incorrect number of arguments to Type allocator");
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
 
     sig::Type *type(internal->type_);
@@ -1135,6 +1188,21 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe
     }
 } CYCatch }
 
+static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+    return CYCastJSValue(context, internal->GetFFI()->alignment);
+}
+
+static JSValueRef Type_getProperty_name(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+    return CYCastJSValue(context, internal->type_->name);
+}
+
+static JSValueRef Type_getProperty_size(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) {
+    Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+    return CYCastJSValue(context, internal->GetFFI()->size);
+}
+
 static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
     CYPool pool;
@@ -1146,13 +1214,9 @@ static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef o
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(_this)));
     CYPool pool;
     const char *type(sig::Unparse(pool, internal->type_));
-    size_t size(strlen(type));
-    char *cyon(new(pool) char[12 + size + 1]);
-    memcpy(cyon, "new Type(\"", 10);
-    cyon[12 + size] = '\0';
-    cyon[12 + size - 2] = '"';
-    cyon[12 + size - 1] = ')';
-    memcpy(cyon + 10, type, size);
+    std::ostringstream str;
+    CYStringify(str, type, strlen(type));
+    char *cyon(apr_pstrcat(pool, "new Type(", str.str().c_str(), ")", NULL));
     return CYCastJSValue(context, CYJSString(cyon));
 } CYCatch }
 
@@ -1183,7 +1247,18 @@ namespace cy {
     JSStaticFunction const * const Functor::StaticFunctions = Functor_staticFunctions;
 }
 
-static JSStaticFunction Type_staticFunctions[4] = {
+static JSStaticValue Type_staticValues[4] = {
+    {"alignment", &Type_getProperty_alignment, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"name", &Type_getProperty_name, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"size", &Type_getProperty_size, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {NULL, NULL, NULL, 0}
+};
+
+static JSStaticFunction Type_staticFunctions[8] = {
+    {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+    {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
     {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
@@ -1311,8 +1386,8 @@ void CYInitializeDynamic() {
 
     definition = kJSClassDefinitionEmpty;
     definition.className = "Type";
+    definition.staticValues = Type_staticValues;
     definition.staticFunctions = Type_staticFunctions;
-    definition.getProperty = &Type_getProperty;
     definition.callAsFunction = &Type_callAsFunction;
     definition.callAsConstructor = &Type_callAsConstructor;
     definition.finalize = &CYFinalize;