]> git.saurik.com Git - cycript.git/blobdiff - Execute.cpp
Find code library, even when relative in debugger.
[cycript.git] / Execute.cpp
index 5322905ced77509f8ae7cf82c4b251d9ec88da88..e11542abab5757364b7d6e06bf23dc08725cc923 100644 (file)
@@ -1,5 +1,5 @@
-/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2015  Jay Freeman (saurik)
+/* Cycript - The Truly Universal Scripting Language
+ * Copyright (C) 2009-2016  Jay Freeman (saurik)
 */
 
 /* GNU Affero General Public License, Version 3 {{{ */
@@ -143,6 +143,10 @@ CYUTF16String CYCastUTF16String(JSStringRef value) {
     return CYUTF16String(JSStringGetCharactersPtr(value), JSStringGetLength(value));
 }
 
+const char *CYPoolCString(CYPool &pool, CYUTF8String utf8) {
+    return pool.strndup(utf8.data, utf8.size);
+}
+
 CYUTF8String CYPoolUTF8String(CYPool &pool, JSContextRef context, JSStringRef value) {
     return CYPoolUTF8String(pool, CYCastUTF16String(value));
 }
@@ -180,6 +184,7 @@ JSClassRef Functor_;
 static JSClassRef Global_;
 
 JSStringRef Array_s;
+JSStringRef constructor_s;
 JSStringRef cy_s;
 JSStringRef cyi_s;
 JSStringRef cyt_s;
@@ -331,6 +336,11 @@ CYCastJSValue_(unsigned long int)
 CYCastJSValue_(signed long long int)
 CYCastJSValue_(unsigned long long int)
 
+#ifdef __SIZEOF_INT128__
+CYCastJSValue_(signed __int128)
+CYCastJSValue_(unsigned __int128)
+#endif
+
 JSValueRef CYJSUndefined(JSContextRef context) {
     return JSValueMakeUndefined(context);
 }
@@ -416,8 +426,7 @@ _visible void CYGarbageCollect(JSContextRef context) {
 static JSValueRef Cycript_compile_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     CYPool pool;
     CYUTF8String before(CYPoolUTF8String(pool, context, CYJSString(context, arguments[0])));
-    std::stringbuf value(std::string(before.data, before.size));
-    CYUTF8String after(CYPoolCode(pool, value));
+    CYUTF8String after(CYPoolCode(pool, before));
     return CYCastJSValue(context, CYJSString(after));
 } CYCatch_(NULL, "SyntaxError") }
 
@@ -500,6 +509,19 @@ const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSObjectRef object,
 
     std::ostringstream str;
 
+    JSValueRef value(CYGetProperty(context, object, constructor_s));
+    if (JSValueIsObject(context, value)) {
+        JSObjectRef constructor(CYCastJSObject(context, value));
+        JSValueRef theory(CYGetProperty(context, constructor, prototype_s));
+        JSValueRef practice(JSObjectGetPrototype(context, object));
+
+        if (CYIsStrictEqual(context, theory, practice)) {
+            JSValueRef name(CYGetProperty(context, constructor, name_s));
+            if (!JSValueIsUndefined(context, name))
+                str << "new" << ' ' << CYPoolUTF8String(pool, context, CYJSString(context, name));
+        }
+    }
+
     str << '{';
 
     // XXX: this is, sadly, going to leak
@@ -681,6 +703,11 @@ CYPoolFFI_(unsigned long int)
 CYPoolFFI_(unsigned long long int)
 CYPoolFFI_(unsigned short int)
 
+#ifdef __SIZEOF_INT128__
+CYPoolFFI_(signed __int128)
+CYPoolFFI_(unsigned __int128)
+#endif
+
 void Void::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
     _assert(false);
 }
@@ -796,6 +823,11 @@ CYFromFFI_(unsigned long int)
 CYFromFFI_(unsigned long long int)
 CYFromFFI_(unsigned short int)
 
+#ifdef __SIZEOF_INT128__
+CYFromFFI_(signed __int128)
+CYFromFFI_(unsigned __int128)
+#endif
+
 JSValueRef Void::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const {
     return CYJSUndefined(context);
 }
@@ -1465,8 +1497,12 @@ static JSValueRef Type_callAsFunction_arrayOf(JSContextRef context, JSObjectRef
 } CYCatch(NULL) }
 
 static JSValueRef Type_callAsFunction_blockWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+#ifdef CY_OBJECTIVEC
     sig::Block type;
     return Type_callAsFunction_$With(context, object, _this, count, arguments, type, exception);
+#else
+    _assert(false);
+#endif
 }
 
 static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
@@ -1515,10 +1551,11 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object,
         return CYMakeFunctor(context, arguments[0], function->variadic, function->signature);
 
     CYPool pool;
+
     sig::Type *type(internal->type_);
     ffi_type *ffi(internal->GetFFI());
-
     void *data(pool.malloc<void>(ffi->size, ffi->alignment));
+
     type->PoolFFI(&pool, context, ffi, data, arguments[0]);
     JSValueRef value(type->FromFFI(context, ffi, data));
 
@@ -1532,15 +1569,22 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object,
 } CYCatch(NULL) }
 
 static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
-    if (count != 0)
+    if (count > 1)
         throw CYJSError(context, "incorrect number of arguments to Type allocator");
     Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
 
     JSObjectRef pointer(CYMakePointer(context, NULL, *internal->type_, NULL, NULL));
     Pointer *value(reinterpret_cast<Pointer *>(JSObjectGetPrivate(pointer)));
+
+    sig::Type *type(internal->type_);
     ffi_type *ffi(internal->GetFFI());
     value->value_ = value->pool_->malloc<void>(ffi->size, ffi->alignment);
-    memset(value->value_, 0, ffi->size);
+
+    if (count == 0)
+        memset(value->value_, 0, ffi->size);
+    else
+        type->PoolFFI(value->pool_, context, ffi, value->value_, arguments[0]);
+
     return pointer;
 } CYCatch(NULL) }
 
@@ -1598,18 +1642,34 @@ static JSValueRef Functor_callAsFunction_valueOf(JSContextRef context, JSObjectR
 static JSValueRef Functor_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
     cy::Functor *internal(reinterpret_cast<cy::Functor *>(JSObjectGetPrivate(_this)));
     uint8_t *value(reinterpret_cast<uint8_t *>(internal->value_));
-    std::ostringstream str;
-    Dl_info info;
-    if (internal->value_ == NULL)
-        str << "NULL";
-    else if (dladdr(value, &info) == 0)
-        str << internal->value_;
-    else {
-        str << info.dli_sname;
-        off_t offset(value - reinterpret_cast<uint8_t *>(info.dli_saddr));
-        if (offset != 0)
-            str << "+0x" << std::hex << offset;
+
+    CYLocalPool pool;
+
+    sig::Function function(internal->variadic_);
+    sig::Copy(pool, function.signature, internal->signature_);
+
+    auto typed(CYDecodeType(pool, &function)); {
+        std::ostringstream str;
+        Dl_info info;
+        if (internal->value_ == NULL)
+            str << "NULL";
+        else if (dladdr(value, &info) == 0)
+            str << internal->value_;
+        else {
+            str << info.dli_sname;
+            off_t offset(value - reinterpret_cast<uint8_t *>(info.dli_saddr));
+            if (offset != 0)
+                str << "+0x" << std::hex << offset;
+        }
+
+        typed->identifier_ = new(pool) CYIdentifier(pool.strdup(str.str().c_str()));
     }
+
+    std::ostringstream str;
+    CYOptions options;
+    CYOutput output(*str.rdbuf(), options);
+    output.pretty_ = true;
+    (new(pool) CYExternalExpression(new(pool) CYString("C"), typed))->Output(output, CYNoFlags);
     return CYCastJSValue(context, CYJSString(str.str()));
 } CYCatch(NULL) }
 
@@ -1718,7 +1778,8 @@ static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef o
     std::stringbuf out;
     CYOptions options;
     CYOutput output(out, options);
-    (new(pool) CYTypeExpression(CYDecodeType(pool, internal->type_)))->Output(output, CYNoFlags);
+    output.pretty_ = true;
+    (new(pool) CYTypeExpression(CYDecodeType(pool, internal->type_->Copy(pool, ""))))->Output(output, CYNoFlags);
     return CYCastJSValue(context, CYJSString(out.str().c_str()));
 } CYCatch(NULL) }
 
@@ -1857,18 +1918,22 @@ class ExecutionHandle {
     }
 };
 
+#ifndef __ANDROID__
 static volatile bool cancel_;
 
 static bool CYShouldTerminate(JSContextRef context, void *arg) {
     return cancel_;
 }
+#endif
 
 _visible const char *CYExecute(JSContextRef context, CYPool &pool, CYUTF8String code) {
     ExecutionHandle handle(context);
 
+#ifndef __ANDROID__
     cancel_ = false;
     if (&JSContextGroupSetExecutionTimeLimit != NULL)
         JSContextGroupSetExecutionTimeLimit(JSContextGetGroup(context), 0.5, &CYShouldTerminate, NULL);
+#endif
 
     try {
         JSValueRef result(_jsccall(JSEvaluateScript, context, CYJSString(code), NULL, NULL, 0));
@@ -1885,9 +1950,11 @@ _visible const char *CYExecute(JSContextRef context, CYPool &pool, CYUTF8String
     }
 }
 
+#ifndef __ANDROID__
 _visible void CYCancel() {
     cancel_ = true;
 }
+#endif
 
 const char *CYPoolLibraryPath(CYPool &pool);
 
@@ -1981,6 +2048,7 @@ void CYInitializeDynamic() {
     Global_ = JSClassCreate(&definition);
 
     Array_s = JSStringCreateWithUTF8CString("Array");
+    constructor_s = JSStringCreateWithUTF8CString("constructor");
     cy_s = JSStringCreateWithUTF8CString("$cy");
     cyi_s = JSStringCreateWithUTF8CString("$cyi");
     cyt_s = JSStringCreateWithUTF8CString("$cyt");
@@ -2054,12 +2122,16 @@ const char *CYPoolLibraryPath(CYPool &pool) {
     char *lib(pool.strdup(addr.dli_fname));
 
     char *slash(strrchr(lib, '/'));
-    _assert(slash != NULL);
+    if (slash == NULL)
+        return ".";
     *slash = '\0';
 
     slash = strrchr(lib, '/');
-    if (slash != NULL && strcmp(slash, "/.libs") == 0)
-        *slash = '\0';
+    if (slash != NULL) {
+        if (strcmp(slash, "/.libs") == 0)
+            *slash = '\0';
+    } else if (strcmp(lib, ".libs") == 0)
+        return ".";
 
     return lib;
 }
@@ -2283,6 +2355,11 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) {
     CYSetProperty(context, cache, CYJSString("ulong"), CYMakeType(context, sig::Primitive<unsigned long>()), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("ulonglong"), CYMakeType(context, sig::Primitive<unsigned long long>()), kJSPropertyAttributeDontEnum);
 
+#ifdef __SIZEOF_INT128__
+    CYSetProperty(context, cache, CYJSString("int128"), CYMakeType(context, sig::Primitive<__int128>()), kJSPropertyAttributeDontEnum);
+    CYSetProperty(context, cache, CYJSString("uint128"), CYMakeType(context, sig::Primitive<unsigned __int128>()), kJSPropertyAttributeDontEnum);
+#endif
+
     CYSetProperty(context, cache, CYJSString("float"), CYMakeType(context, sig::Primitive<float>()), kJSPropertyAttributeDontEnum);
     CYSetProperty(context, cache, CYJSString("double"), CYMakeType(context, sig::Primitive<double>()), kJSPropertyAttributeDontEnum);