X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/67110a156d28581856737ca3de13b4dbe4718288..bf76f58056b53ca590b619a7488a1648e554fcb4:/ObjectiveC/Library.mm diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index 1904f24..b6410c7 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -638,30 +638,46 @@ _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSVal return _jsccall(JSValueIsInstanceOfConstructor, context, value, CYGetCachedObject(context, cache)); } -NSObject *CYMakeBlock(void (*invoke)(), sig::Signature &signature) { - BlockLiteral *literal(reinterpret_cast(malloc(sizeof(BlockLiteral)))); +struct CYBlockDescriptor { + struct { + BlockDescriptor1 one_; + BlockDescriptor2 two_; + BlockDescriptor3 three_; + } d_; + + Closure_privateData *internal_; +}; + +void CYDisposeBlock(BlockLiteral *literal) { + delete reinterpret_cast(literal->descriptor)->internal_; +} - struct Descriptor { - struct { - BlockDescriptor1 one_; - BlockDescriptor2 two_; - BlockDescriptor3 three_; - } d_; +static JSValueRef BlockAdapter_(JSContextRef context, size_t count, JSValueRef values[], JSObjectRef function) { + JSObjectRef _this(CYCastJSObject(context, values[0])); + return CYCallAsFunction(context, function, _this, count - 1, values + 1); +} + +static void BlockClosure_(ffi_cif *cif, void *result, void **arguments, void *arg) { + CYExecuteClosure(cif, result, arguments, arg, &BlockAdapter_); +} - CYPool pool_; - }; +NSObject *CYMakeBlock(JSContextRef context, JSObjectRef function, sig::Signature &signature) { + BlockLiteral *literal(reinterpret_cast(malloc(sizeof(BlockLiteral)))); - Descriptor *descriptor(new Descriptor); + CYBlockDescriptor *descriptor(new CYBlockDescriptor); memset(&descriptor->d_, 0, sizeof(descriptor->d_)); - literal->isa = objc_getClass("__NSGlobalBlock__"); + descriptor->internal_ = CYMakeFunctor_(context, function, signature, &BlockClosure_); + literal->invoke = reinterpret_cast(descriptor->internal_->GetValue()); + + literal->isa = objc_getClass("__NSMallocBlock__"); literal->flags = BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL; literal->reserved = 0; - literal->invoke = reinterpret_cast(invoke); literal->descriptor = descriptor; descriptor->d_.one_.size = sizeof(descriptor->d_); - descriptor->d_.three_.signature = sig::Unparse(descriptor->pool_, &signature); + descriptor->d_.two_.dispose_helper = &CYDisposeBlock; + descriptor->d_.three_.signature = sig::Unparse(*descriptor->internal_->pool_, &signature); return reinterpret_cast(literal); } @@ -672,11 +688,6 @@ NSObject *CYCastNSObject(CYPool *pool, JSContextRef context, JSObjectRef object) return internal->GetValue(); } - if (JSValueIsObjectOfClass(context, object, Functor_)) { - cy::Functor *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return CYMakeBlock(internal->GetValue(), internal->signature_); - } - bool array(CYJSValueIsInstanceOfCachedConstructor(context, object, Array_s)); id value(array ? [CYJSArray alloc] : [CYJSObject alloc]); return CYPoolRelease(pool, [value initWithJSObject:object inContext:context]); @@ -1452,12 +1463,32 @@ static void CYObjectiveC_CallFunction(JSContextRef context, ffi_cif *cif, void ( } CYSadCatch() } static bool CYObjectiveC_PoolFFI(CYPool *pool, JSContextRef context, sig::Type *type, ffi_type *ffi, void *data, JSValueRef value) { CYSadTry { + // XXX: assigning to an indirect id * works for return values, but not for properties and fields + switch (type->primitive) { - // XXX: do something epic about blocks - case sig::block_P: + case sig::block_P: { + _assert(type->data.signature.count != 0); + sig::Signature signature; + sig::Copy(*pool, signature, type->data.signature); + + sig::Element *elements(new(*pool) sig::Element[++signature.count]); + elements[0] = signature.elements[0]; + memcpy(elements + 2, signature.elements + 1, sizeof(sig::Element) * (signature.count - 2)); + signature.elements = elements; + + elements[1].name = NULL; + elements[1].type = new(*pool) sig::Type(); + elements[1].offset = _not(size_t); + + memset(elements[1].type, 0, sizeof(sig::Type)); + elements[1].type->primitive = sig::object_P; + + JSObjectRef function(CYCastJSObject(context, value)); + *reinterpret_cast(data) = CYMakeBlock(context, function, signature); + } break; + case sig::object_P: case sig::typename_P: - // XXX: this works for return values, but not for properties and fields *reinterpret_cast(data) = CYCastNSObject(pool, context, value); break; @@ -2930,10 +2961,6 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { JSObjectRef box(JSObjectMakeFunctionWithCallback(context, CYJSString("box"), &Instance_box_callAsFunction)); CYSetProperty(context, Instance, CYJSString("box"), box); -#if defined(__APPLE__) && defined(__arm__) && 0 - CYSetProperty(context, all, CYJSString("objc_registerClassPair"), &objc_registerClassPair_, kJSPropertyAttributeDontEnum); -#endif - #ifdef __APPLE__ CYSetProperty(context, all, CYJSString("choose"), &choose, kJSPropertyAttributeDontEnum); #endif @@ -2961,3 +2988,25 @@ struct CYObjectiveC { _assert(hooks_ != NULL); } } CYObjectiveC; + +extern "C" void CydgetSetupContext(JSGlobalContextRef context) { CYObjectiveTry_ { + CYSetupContext(context); +} CYObjectiveCatch } + +extern "C" void CydgetMemoryParse(const uint16_t **data, size_t *size) { try { + CYPool pool; + + CYUTF8String utf8(CYPoolUTF8String(pool, CYUTF16String(*data, *size))); + utf8 = CYPoolCode(pool, utf8); + + CYUTF16String utf16(CYPoolUTF16String(pool, CYUTF8String(utf8.data, utf8.size))); + size_t bytes(utf16.size * sizeof(uint16_t)); + uint16_t *copy(reinterpret_cast(malloc(bytes))); + memcpy(copy, utf16.data, bytes); + + *data = copy; + *size = utf16.size; +} catch (const CYException &exception) { + CYPool pool; + @throw [NSException exceptionWithName:NSRangeException reason:[NSString stringWithFormat:@"%s", exception.PoolCString(pool)] userInfo:nil]; +} }