X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/dc5d7cf41a141ba83d66f97957bd7742a8adbc4f..84759b5be9e3925e184005b0be902a8be25b4584:/Execute.cpp?ds=inline diff --git a/Execute.cpp b/Execute.cpp index ca678ae..eb1970e 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -22,6 +22,9 @@ #include "Internal.hpp" #include +#include +#include +#include #include "cycript.hpp" @@ -32,6 +35,7 @@ #include "Execute.hpp" #include +#include #include #include @@ -42,6 +46,7 @@ #include "Parser.hpp" +#include "Decode.hpp" #include "Error.hpp" #include "JavaScript.hpp" #include "String.hpp" @@ -50,29 +55,19 @@ struct CYHooks *hooks_; /* JavaScript Properties {{{ */ JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index) { - JSValueRef exception(NULL); - JSValueRef value(JSObjectGetPropertyAtIndex(context, object, index, &exception)); - CYThrow(context, exception); - return value; + return _jsccall(JSObjectGetPropertyAtIndex, context, object, index); } JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, JSStringRef name) { - JSValueRef exception(NULL); - JSValueRef value(JSObjectGetProperty(context, object, name, &exception)); - CYThrow(context, exception); - return value; + return _jsccall(JSObjectGetProperty, context, object, name); } void CYSetProperty(JSContextRef context, JSObjectRef object, size_t index, JSValueRef value) { - JSValueRef exception(NULL); - JSObjectSetPropertyAtIndex(context, object, index, value, &exception); - CYThrow(context, exception); + _jsccall(JSObjectSetPropertyAtIndex, context, object, index, value); } void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value, JSPropertyAttributes attributes) { - JSValueRef exception(NULL); - JSObjectSetProperty(context, object, name, value, attributes, &exception); - CYThrow(context, exception); + _jsccall(JSObjectSetProperty, context, object, name, value, attributes); } void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef (*callback)(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef *), JSPropertyAttributes attributes) { @@ -96,10 +91,7 @@ JSStringRef CYCopyJSString(CYUTF8String value) { JSStringRef CYCopyJSString(JSContextRef context, JSValueRef value) { if (JSValueIsNull(context, value)) return NULL; - JSValueRef exception(NULL); - JSStringRef string(JSValueToStringCopy(context, value, &exception)); - CYThrow(context, exception); - return string; + return _jsccall(JSValueToStringCopy, context, value); } static CYUTF16String CYCastUTF16String(JSStringRef value) { @@ -284,10 +276,7 @@ JSValueRef CYJSUndefined(JSContextRef context) { } double CYCastDouble(JSContextRef context, JSValueRef value) { - JSValueRef exception(NULL); - double number(JSValueToNumber(context, value, &exception)); - CYThrow(context, exception); - return number; + return _jsccall(JSValueToNumber, context, value); } bool CYCastBool(JSContextRef context, JSValueRef value) { @@ -307,17 +296,11 @@ JSValueRef CYCastJSValue(JSContextRef context, const char *value) { } JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) { - JSValueRef exception(NULL); - JSObjectRef object(JSValueToObject(context, value, &exception)); - CYThrow(context, exception); - return object; + return _jsccall(JSValueToObject, context, value); } JSValueRef CYCallAsFunction(JSContextRef context, JSObjectRef function, JSObjectRef _this, size_t count, const JSValueRef arguments[]) { - JSValueRef exception(NULL); - JSValueRef value(JSObjectCallAsFunction(context, function, _this, count, arguments, &exception)); - CYThrow(context, exception); - return value; + return _jsccall(JSObjectCallAsFunction, context, function, _this, count, arguments); } bool CYIsCallable(JSContextRef context, JSValueRef value) { @@ -329,19 +312,14 @@ size_t CYArrayLength(JSContextRef context, JSObjectRef array) { } JSValueRef CYArrayGet(JSContextRef context, JSObjectRef array, size_t index) { - JSValueRef exception(NULL); - JSValueRef value(JSObjectGetPropertyAtIndex(context, array, index, &exception)); - CYThrow(context, exception); - return value; + return _jsccall(JSObjectGetPropertyAtIndex, context, array, index); } void CYArrayPush(JSContextRef context, JSObjectRef array, JSValueRef value) { - JSValueRef exception(NULL); JSValueRef arguments[1]; arguments[0] = value; JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); - JSObjectCallAsFunction(context, CYCastJSObject(context, CYGetProperty(context, Array, push_s)), array, 1, arguments, &exception); - CYThrow(context, exception); + _jsccall(JSObjectCallAsFunction, context, CYCastJSObject(context, CYGetProperty(context, Array, push_s)), array, 1, arguments); } static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -400,10 +378,7 @@ const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSValueRef value, JS } CYCatch(NULL) } const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSValueRef value) { - JSValueRef exception(NULL); - const char *cyon(CYPoolCCYON(pool, context, value, &exception)); - CYThrow(context, exception); - return cyon; + return _jsccall(CYPoolCCYON, pool, context, value); } const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSObjectRef object) { @@ -417,10 +392,7 @@ const char *CYPoolCCYON(CYPool &pool, JSContextRef context, JSObjectRef object) JSValueRef toJSON(CYGetProperty(context, object, toJSON_s)); if (CYIsCallable(context, toJSON)) { JSValueRef arguments[1] = {CYCastJSValue(context, CYJSString(""))}; - JSValueRef exception(NULL); - const char *cyon(CYPoolCCYON(pool, context, CYCallAsFunction(context, (JSObjectRef) toJSON, object, 1, arguments), &exception)); - CYThrow(context, exception); - return cyon; + return _jsccall(CYPoolCCYON, pool, context, CYCallAsFunction(context, (JSObjectRef) toJSON, object, 1, arguments)); } if (JSObjectIsFunction(context, object)) { @@ -484,18 +456,21 @@ static JSValueRef Array_callAsFunction_toCYON(JSContextRef context, JSObjectRef bool comma(false); for (size_t index(0), count(CYCastDouble(context, length)); index != count; ++index) { - JSValueRef value(CYGetProperty(context, _this, index)); - if (comma) str << ','; else comma = true; - if (!JSValueIsUndefined(context, value)) - str << CYPoolCCYON(pool, context, value); - else { - str << ','; - comma = false; + try { + JSValueRef value(CYGetProperty(context, _this, index)); + if (!JSValueIsUndefined(context, value)) + str << CYPoolCCYON(pool, context, value); + else { + str << ','; + comma = false; + } + } catch (const CYException &error) { + str << "@error"; } } @@ -786,10 +761,7 @@ JSObjectRef CYGetCachedObject(JSContextRef context, JSStringRef name) { static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, const char *type) { JSObjectRef Function(CYGetCachedObject(context, CYJSString("Function"))); - JSValueRef exception(NULL); - bool function(JSValueIsInstanceOfConstructor(context, value, Function, &exception)); - CYThrow(context, exception); - + bool function(_jsccall(JSValueIsInstanceOfConstructor, context, value, Function)); if (function) { JSObjectRef function(CYCastJSObject(context, value)); return CYMakeFunctor(context, function, type); @@ -955,7 +927,7 @@ static void Struct_getPropertyNames(JSContextRef context, JSObjectRef object, JS } } -JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { CYTry { +JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, sig::Signature *signature, ffi_cif *cif, void (*function)()) { if (setups + count != signature->count - 1) throw CYJSError(context, "incorrect number of arguments to ffi function"); @@ -979,16 +951,16 @@ JSValueRef CYCallFunction(CYPool &pool, JSContextRef context, size_t setups, voi ffi_call(cif, function, value, values); return CYFromFFI(context, signature->elements[0].type, cif->rtype, value, initialize); -} CYCatch(NULL) } +} static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CYPool pool; cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYCallFunction(pool, context, 0, NULL, count, arguments, false, exception, &internal->signature_, &internal->cif_, internal->GetValue()); + return CYCallFunction(pool, context, 0, NULL, count, arguments, false, &internal->signature_, &internal->cif_, internal->GetValue()); } CYCatch(NULL) } -JSObjectRef CYMakeType(JSContextRef context, const char *type) { - Type_privateData *internal(new Type_privateData(type)); +JSObjectRef CYMakeType(JSContextRef context, const char *encoding) { + Type_privateData *internal(new Type_privateData(encoding)); return JSObjectMake(context, Type_privateData::Class_, internal); } @@ -997,6 +969,19 @@ JSObjectRef CYMakeType(JSContextRef context, sig::Type *type) { return JSObjectMake(context, Type_privateData::Class_, internal); } +JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature) { + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = sig::function_P; + sig::Copy(pool, type.data.signature, *signature); + + return CYMakeType(context, &type); +} + static JSValueRef All_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { JSObjectRef global(CYGetGlobalObject(context)); JSObjectRef cycript(CYCastJSObject(context, CYGetProperty(context, global, CYJSString("Cycript")))); @@ -1115,6 +1100,38 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef return CYMakeType(context, &type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + CYPool pool; + + sig::Type type; + type.name = NULL; + type.flags = 0; + + type.primitive = sig::function_P; + type.data.signature.elements = new(pool) sig::Element[1 + count]; + type.data.signature.count = 1 + count; + + type.data.signature.elements[0].name = NULL; + type.data.signature.elements[0].type = internal->type_; + type.data.signature.elements[0].offset = _not(size_t); + + for (size_t i(0); i != count; ++i) { + sig::Element &element(type.data.signature.elements[i + 1]); + element.name = NULL; + element.offset = _not(size_t); + + JSObjectRef object(CYCastJSObject(context, arguments[i])); + _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_)); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + + element.type = internal->type_; + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + 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"); @@ -1122,11 +1139,18 @@ static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRe 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; + if (internal->type_->primitive == sig::char_P) { + type.flags = internal->type_->flags; + type.primitive = sig::string_P; + type.data.data.type = NULL; + type.data.data.size = 0; + } else { + type.flags = 0; + type.primitive = sig::pointer_P; + type.data.data.type = internal->type_; + type.data.data.size = 0; + } return CYMakeType(context, &type); } CYCatch(NULL) } @@ -1216,8 +1240,7 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe static JSValueRef Functor_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - CYPool pool; - return CYCastJSValue(context, Unparse(pool, &internal->signature_)); + return CYMakeType(context, &internal->signature_); } CYCatch(NULL) } static JSValueRef Type_getProperty_alignment(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1244,12 +1267,12 @@ static JSValueRef Type_callAsFunction_toString(JSContextRef context, JSObjectRef static JSValueRef Type_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - CYPool pool; - const char *type(sig::Unparse(pool, internal->type_)); - std::ostringstream str; - CYStringify(str, type, strlen(type)); - char *cyon(pool.strcat("new Type(", str.str().c_str(), ")", NULL)); - return CYCastJSValue(context, CYJSString(cyon)); + CYLocalPool pool; + std::ostringstream out; + CYOptions options; + CYOutput output(out, options); + (new(pool) CYEncodedType(Decode(pool, internal->type_)))->Output(output, CYNoFlags); + return CYCastJSValue(context, CYJSString(out.str().c_str())); } CYCatch(NULL) } static JSValueRef Type_callAsFunction_toJSON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { @@ -1291,9 +1314,10 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[8] = { +static JSStaticFunction Type_staticFunctions[9] = { {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -1311,11 +1335,9 @@ void CYSetArgs(int argc, const char *argv[]) { args[i] = CYCastJSValue(context, argv[i]); JSObjectRef array; - if (JSObjectMakeArray$ != NULL) { - JSValueRef exception(NULL); - array = (*JSObjectMakeArray$)(context, argc, args, &exception); - CYThrow(context, exception); - } else { + if (JSObjectMakeArray$ != NULL) + array = _jsccall(*JSObjectMakeArray$, context, argc, args); + else { JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array"))); JSValueRef value(CYCallAsFunction(context, Array, NULL, argc, args)); array = CYCastJSObject(context, value); @@ -1329,9 +1351,8 @@ JSObjectRef CYGetGlobalObject(JSContextRef context) { return JSContextGetGlobalObject(context); } -const char *CYExecute(CYPool &pool, CYUTF8String code) { - JSContextRef context(CYGetJSContext()); - JSValueRef exception(NULL), result; +const char *CYExecute(JSContextRef context, CYPool &pool, CYUTF8String code) { + JSValueRef exception(NULL); void *handle; if (hooks_ != NULL && hooks_->ExecuteStart != NULL) @@ -1339,8 +1360,9 @@ const char *CYExecute(CYPool &pool, CYUTF8String code) { else handle = NULL; - const char *json; + try { + JSValueRef result; try { result = JSEvaluateScript(context, CYJSString(code), NULL, NULL, 0, &exception); } catch (const char *error) { @@ -1353,6 +1375,7 @@ const char *CYExecute(CYPool &pool, CYUTF8String code) { if (JSValueIsUndefined(context, result)) return NULL; + const char *json; try { json = CYPoolCCYON(pool, context, result, &exception); } catch (const char *error) { @@ -1364,9 +1387,13 @@ const char *CYExecute(CYPool &pool, CYUTF8String code) { CYSetProperty(context, CYGetGlobalObject(context), Result_, result); - if (hooks_ != NULL && hooks_->ExecuteEnd != NULL) - (*hooks_->ExecuteEnd)(context, handle); return json; + + } catch (...) { + if (hooks_ != NULL && hooks_->ExecuteEnd != NULL) + (*hooks_->ExecuteEnd)(context, handle); + throw; + } } extern "C" void CydgetSetupContext(JSGlobalContextRef context) { @@ -1471,14 +1498,8 @@ JSValueRef CYJSError::CastJSValue(JSContextRef context) const { JSValueRef CYCastJSError(JSContextRef context, const char *message) { JSObjectRef Error(CYGetCachedObject(context, CYJSString("Error"))); - JSValueRef arguments[1] = {CYCastJSValue(context, message)}; - - JSValueRef exception(NULL); - JSValueRef value(JSObjectCallAsConstructor(context, Error, 1, arguments, &exception)); - CYThrow(context, exception); - - return value; + return _jsccall(JSObjectCallAsConstructor, context, Error, 1, arguments); } JSValueRef CYPoolError::CastJSValue(JSContextRef context) const { @@ -1503,9 +1524,67 @@ JSGlobalContextRef CYGetJSContext(JSContextRef context) { return reinterpret_cast(JSObjectGetPrivate(CYCastJSObject(context, CYGetProperty(context, CYGetGlobalObject(context), cy_s))))->context_; } -extern "C" void CYSetupContext(JSGlobalContextRef context) { - JSValueRef exception(NULL); +extern "C" bool CydgetMemoryParse(const uint16_t **data, size_t *size); + +void *CYMapFile(const char *path, size_t *psize) { + int fd; + _syscall(fd = open(path, O_RDONLY)); + + struct stat stat; + _syscall(fstat(fd, &stat)); + size_t size(stat.st_size); + + *psize = size; + + void *base; + _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); + + _syscall(close(fd)); + return base; +} + +static void CYRunSetups(JSContextRef context) { + std::string folder("/etc/cycript/setup.d"); + DIR *setups(opendir(folder.c_str())); + if (setups == NULL) + return; + + for (;;) { + dirent setup; + dirent *result; + _syscall(readdir_r(setups, &setup, &result)); + + if (result == NULL) + break; + _assert(result == &setup); + const char *name(setup.d_name); + size_t length(strlen(name)); + if (length < 4) + continue; + + if (name[0] == '.') + continue; + if (memcmp(name + length - 3, ".cy", 3) != 0) + continue; + + std::string script(folder + "/" + name); + CYUTF8String utf8; + utf8.data = reinterpret_cast(CYMapFile(script.c_str(), &utf8.size)); + + CYPool pool; + CYUTF16String utf16(CYPoolUTF16String(pool, utf8)); + munmap(const_cast(utf8.data), utf8.size); + + if (CydgetMemoryParse(&utf16.data, &utf16.size)) + CYExecute(context, pool, CYPoolUTF8String(pool, utf16)); + free(const_cast(utf16.data)); + } + + _syscall(closedir(setups)); +} + +extern "C" void CYSetupContext(JSGlobalContextRef context) { CYInitializeDynamic(); JSObjectRef global(CYGetGlobalObject(context)); @@ -1559,8 +1638,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { JSObjectRef all(JSObjectMake(context, All_, NULL)); CYSetProperty(context, cycript, CYJSString("all"), all); - JSObjectRef alls(JSObjectCallAsConstructor(context, Array, 0, NULL, &exception)); - CYThrow(context, exception); + JSObjectRef alls(_jsccall(JSObjectCallAsConstructor, context, Array, 0, NULL)); CYSetProperty(context, cycript, CYJSString("alls"), alls); if (true) { @@ -1595,6 +1673,8 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { (*hooks_->SetupContext)(context); CYArrayPush(context, alls, cycript); + + CYRunSetups(context); } JSGlobalContextRef CYGetJSContext() {