X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/d6e14b17d2f8c257a9758eee0cf066ba48949c88..35494a52844a5855eb590e83342c91e7fa83b90f:/Execute.cpp diff --git a/Execute.cpp b/Execute.cpp index 3399c86..81bd6ec 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -217,6 +217,8 @@ static JSStringRef Result_; void CYFinalize(JSObjectRef object) { CYData *internal(reinterpret_cast(JSObjectGetPrivate(object))); + if (internal == NULL) + return; _assert(internal->count_ != _not(unsigned)); if (--internal->count_ == 0) delete internal; @@ -703,6 +705,8 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value, bool *guess) { } } +static JSValueRef FunctionAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function); + namespace sig { // XXX: this is somehow not quite a template :/ @@ -748,12 +752,13 @@ void Primitive::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, CYJSString script(context, value); auto string(CYCastUTF16String(script)); _assert(string.size == 1); + _assert((string.data[0] & 0xff) == string.data[0]); *reinterpret_cast(data) = string.data[0]; } } void Void::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { - _assert(false); + _assert(JSValueIsUndefined(context, value)); } void Unknown::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { @@ -771,17 +776,11 @@ void Bits::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data _assert(false); } -static void CYArrayCopy(CYPool *pool, JSContextRef context, uint8_t *base, size_t length, const sig::Type &type, ffi_type *ffi, JSValueRef value, JSObjectRef object) { +static void CYArrayCopy(CYPool *pool, JSContextRef context, uint8_t *base, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef object) { for (size_t index(0); index != length; ++index) { - JSValueRef rhs; - if (object == NULL) - rhs = value; - else { - rhs = CYGetProperty(context, object, index); - if (JSValueIsUndefined(context, rhs)) - throw CYJSError(context, "unable to extract array value"); - } - + JSValueRef rhs(CYGetProperty(context, object, index)); + if (JSValueIsUndefined(context, rhs)) + throw CYJSError(context, "unable to extract array value"); type.PoolFFI(pool, context, ffi, base, rhs); base += ffi->size; } @@ -792,13 +791,20 @@ void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *d *reinterpret_cast(data) = CYCastPointer(context, value, &guess); if (!guess || pool == NULL || !JSValueIsObject(context, value)) return; + JSObjectRef object(CYCastJSObject(context, value)); - if (CYHasProperty(context, object, length_s)) { + + if (sig::Function *function = dynamic_cast(&type)) { + _assert(!function->variadic); + auto internal(CYMakeFunctor_(context, object, function->signature, &FunctionAdapter_)); + // XXX: see notes in Library.cpp about needing to leak + *reinterpret_cast(data) = internal->value_; + } else if (CYHasProperty(context, object, length_s)) { size_t length(CYArrayLength(context, object)); ffi_type *element(type.GetFFI(*pool)); size_t size(element->size * length); uint8_t *base(pool->malloc(size, element->alignment)); - CYArrayCopy(pool, context, base, length, type, element, value, object); + CYArrayCopy(pool, context, base, length, type, element, object); *reinterpret_cast(data) = base; } } @@ -807,8 +813,7 @@ void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *dat if (size == 0) return; uint8_t *base(reinterpret_cast(data)); - JSObjectRef object(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL); - CYArrayCopy(pool, context, base, size, type, ffi->elements[0], value, object); + CYArrayCopy(pool, context, base, size, type, ffi->elements[0], CYCastJSObject(context, value)); } void Enum::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const { @@ -854,10 +859,12 @@ void Function::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void * #define CYFromFFI_(Type_) \ template <> \ JSValueRef Primitive::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { \ - return CYCastJSValue(context, *reinterpret_cast(data)); \ + JSValueRef value(CYCastJSValue(context, *reinterpret_cast(data))); \ + JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("Number")), 1, &value)); \ + CYSetProperty(context, typed, cyt_s, CYMakeType(context, *this), kJSPropertyAttributeDontEnum); \ + return typed; \ } -CYFromFFI_(bool) CYFromFFI_(wchar_t) CYFromFFI_(float) CYFromFFI_(double) @@ -880,6 +887,11 @@ CYFromFFI_(signed __int128) CYFromFFI_(unsigned __int128) #endif +template <> +JSValueRef Primitive::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { + return CYCastJSValue(context, *reinterpret_cast(data)); +} + template <> JSValueRef Primitive::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { uint16_t string(uint8_t(*reinterpret_cast(data))); @@ -946,8 +958,7 @@ void CYExecuteClosure(ffi_cif *cif, void *result, void **arguments, void *arg) { values[index] = internal->signature_.elements[1 + index].type->FromFFI(context, internal->cif_.arg_types[index], arguments[index]); JSValueRef value(internal->adapter_(context, count, values, internal->function_)); - if (internal->cif_.rtype != &ffi_type_void) - internal->signature_.elements[0].type->PoolFFI(NULL, context, internal->cif_.rtype, result, value); + internal->signature_.elements[0].type->PoolFFI(NULL, context, internal->cif_.rtype, result, value); } static JSValueRef FunctionAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) { @@ -1669,7 +1680,7 @@ static JSValueRef Type_callAsFunction_pointerTo(JSContextRef context, JSObjectRe Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); if (dynamic_cast *>(internal->type_) != NULL) - return CYMakeType(context, sig::String()); + return CYMakeType(context, sig::String((internal->type_->flags & JOC_TYPE_CONST) != 0)); else return CYMakeType(context, sig::Pointer(*internal->type_)); } CYCatch(NULL) } @@ -1706,13 +1717,6 @@ static JSValueRef Type_callAsFunction(JSContextRef context, JSObjectRef object, type->PoolFFI(buffer, context, ffi, data, arguments[0]); JSValueRef value(type->FromFFI(context, ffi, data, false, buffer)); - - if (JSValueGetType(context, value) == kJSTypeNumber) { - JSObjectRef typed(_jsccall(JSObjectCallAsConstructor, context, CYGetCachedObject(context, CYJSString("Number")), 1, &value)); - CYSetProperty(context, typed, cyt_s, object, kJSPropertyAttributeDontEnum); - value = typed; - } - return value; } CYCatch(NULL) } @@ -1858,7 +1862,7 @@ static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef o } CYCatch(NULL) } static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { - return CYMakeType(context, sig::String()); + return CYMakeType(context, sig::String(true)); } CYCatch(NULL) } static JSValueRef CArray_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1985,9 +1989,10 @@ static JSStaticValue Struct_staticValues[2] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Functor_staticFunctions[4] = { +static JSStaticFunction Functor_staticFunctions[5] = { {"$cya", &Functor_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toCYON", &Functor_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"toPointer", &Functor_callAsFunction_$cya, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"valueOf", &Functor_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} }; @@ -2543,7 +2548,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { } #endif - CYSetProperty(context, String_prototype, cyt_s, CYMakeType(context, sig::String()), kJSPropertyAttributeDontEnum); + CYSetProperty(context, String_prototype, cyt_s, CYMakeType(context, sig::String(true)), kJSPropertyAttributeDontEnum); CYSetProperty(context, cache, CYJSString("dlerror"), CYMakeFunctor(context, "dlerror", "*"), kJSPropertyAttributeDontEnum); CYSetProperty(context, cache, CYJSString("RTLD_DEFAULT"), CYCastJSValue(context, reinterpret_cast(RTLD_DEFAULT)), kJSPropertyAttributeDontEnum);