From d6848e7305f443c0d55fc83ad93beccdb8a572ea Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Wed, 30 Dec 2015 19:48:06 -0800 Subject: [PATCH] Use variadic templates to better organize Classes. --- Execute.cpp | 145 +++++++++++++++++----------------------- Internal.hpp | 65 ++++++++++++++---- ObjectiveC/Internal.hpp | 56 +++++----------- ObjectiveC/Library.mm | 140 ++++++++++++++++---------------------- Utility.hpp | 49 ++++++++++++++ 5 files changed, 238 insertions(+), 217 deletions(-) create mode 100644 Utility.hpp diff --git a/Execute.cpp b/Execute.cpp index 41550ba..dfc0158 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -168,12 +168,8 @@ static JSObjectRef CYObjectMakeArray(JSContextRef context, size_t length, const static JSClassRef All_; static JSClassRef Context_; -static JSClassRef CArray_; -static JSClassRef CString_; JSClassRef Functor_; static JSClassRef Global_; -static JSClassRef Pointer_; -static JSClassRef Struct_; JSStringRef Array_s; JSStringRef cy_s; @@ -222,91 +218,82 @@ struct Context : }; struct CArray : - CYOwned + CYValue_ { + CYProtect owner_; Type_privateData *type_; size_t length_; - CArray(void *value, JSContextRef context, JSObjectRef owner, size_t length, const sig::Type &type, ffi_type *ffi) : - CYOwned(value, context, owner), + CArray(void *value, size_t length, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) : + CYValue_(value), + owner_(context, owner), type_(new(*pool_) Type_privateData(type, ffi)), length_(length) { + if (owner == NULL) { + size_t size(ffi->size * length); + void *copy(pool_->malloc(size, ffi->alignment)); + memcpy(copy, GetValue(), size); + value_ = copy; + } } }; struct CString : - CYOwned + CYValue_ { + CYProtect owner_; + CString(char *value, JSContextRef context, JSObjectRef owner) : - CYOwned(value, context, owner) + CYValue_(value), + owner_(context, owner) { + if (owner == NULL) + value_ = pool_->strdup(GetValue()); } }; struct Pointer : - CYOwned + CYValue_ { + CYProtect owner_; Type_privateData *type_; - Pointer(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type) : - CYOwned(value, context, owner), + Pointer(void *value, const sig::Type &type, JSContextRef context, JSObjectRef owner) : + CYValue_(value), + owner_(context, owner), type_(new(*pool_) Type_privateData(type)) { } - Pointer(void *value, JSContextRef context, JSObjectRef owner, const char *encoding) : - CYOwned(value, context, owner), + Pointer(void *value, const char *encoding, JSContextRef context, JSObjectRef owner) : + CYValue_(value), + owner_(context, owner), type_(new(*pool_) Type_privateData(encoding)) { } }; struct Struct_privateData : - CYOwned + CYValue_ { + CYProtect owner_; Type_privateData *type_; - Struct_privateData(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type, ffi_type *ffi) : - CYOwned(value, context, owner), + Struct_privateData(void *value, const sig::Type &type, ffi_type *ffi, JSContextRef context, JSObjectRef owner) : + CYValue_(value), + owner_(context, owner), type_(new(*pool_) Type_privateData(type, ffi)) { + if (owner == NULL) { + size_t size(ffi->size); + void *copy(pool_->malloc(size, ffi->alignment)); + memcpy(copy, GetValue(), size); + value_ = copy; + } } }; -JSObjectRef CYMakeCArray(JSContextRef context, void *data, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) { - CArray *internal(new CArray(data, context, owner, length, type, ffi)); - - if (owner == NULL) { - size_t size(ffi->size * length); - void *copy(internal->pool_->malloc(size, ffi->alignment)); - memcpy(copy, internal->value_, size); - internal->value_ = copy; - } - - return JSObjectMake(context, CArray_, internal); -} - -JSObjectRef CYMakeCString(JSContextRef context, char *pointer, JSObjectRef owner) { - CString *internal(new CString(pointer, context, owner)); - if (owner == NULL) - internal->value_ = internal->pool_->strdup(static_cast(internal->value_)); - return JSObjectMake(context, CString_, internal); -} - -JSObjectRef CYMakeStruct(JSContextRef context, void *data, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) { - Struct_privateData *internal(new Struct_privateData(data, context, owner, type, ffi)); - - if (owner == NULL) { - size_t size(ffi->size); - void *copy(internal->pool_->malloc(size, ffi->alignment)); - memcpy(copy, internal->value_, size); - internal->value_ = copy; - } - - return JSObjectMake(context, Struct_, internal); -} - static void *CYCastSymbol(const char *name) { for (CYHook *hook : GetHooks()) if (hook->CastSymbol != NULL) @@ -641,13 +628,7 @@ static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef } CYCatch(NULL) } JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) { - Pointer *internal(new Pointer(pointer, context, owner, type)); - return JSObjectMake(context, Pointer_, internal); -} - -JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const char *encoding, JSObjectRef owner) { - Pointer *internal(new Pointer(pointer, context, owner, encoding)); - return JSObjectMake(context, Pointer_, internal); + return Pointer::Make(context, pointer, type, context, owner); } static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), bool variadic, const sig::Signature &signature) { @@ -676,7 +657,7 @@ void *CYCastPointer_(JSContextRef context, JSValueRef value, bool *guess) { return NULL; case kJSTypeObject: { JSObjectRef object((JSObjectRef) value); - if (JSValueIsObjectOfClass(context, value, Pointer_)) { + if (JSValueIsObjectOfClass(context, value, Pointer::Class_)) { Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); return internal->value_; } @@ -856,7 +837,7 @@ JSValueRef Unknown::FromFFI(JSContextRef context, ffi_type *ffi, void *data, boo JSValueRef String::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { if (char *value = *reinterpret_cast(data)) - return CYMakeCString(context, value, owner); + return CString::Make(context, value, context, owner); return CYJSNull(context); } @@ -871,11 +852,11 @@ JSValueRef Pointer::FromFFI(JSContextRef context, ffi_type *ffi, void *data, boo } JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { - return CYMakeCArray(context, data, size, type, ffi->elements[0], owner); + return CArray::Make(context, data, size, type, ffi->elements[0], context, owner); } JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { - return CYMakeStruct(context, data, *this, ffi, owner); + return Struct_privateData::Make(context, data, *this, ffi, context, owner); } JSValueRef Function::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { @@ -978,26 +959,24 @@ static JSObjectRef CYMakeFunctor(JSContextRef context, JSValueRef value, bool va static JSValueRef CString_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { CYPool pool; CString *internal(reinterpret_cast(JSObjectGetPrivate(object))); - char *string(static_cast(internal->value_)); ssize_t offset; if (!CYGetOffset(pool, context, property, offset)) return NULL; - return CYCastJSValue(context, CYJSString(CYUTF8String(&string[offset], 1))); + return CYCastJSValue(context, CYJSString(CYUTF8String(&internal->GetValue()[offset], 1))); } CYCatch(NULL) } static bool CString_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { CYPool pool; CString *internal(reinterpret_cast(JSObjectGetPrivate(object))); - char *string(static_cast(internal->value_)); ssize_t offset; if (!CYGetOffset(pool, context, property, offset)) return false; const char *data(CYPoolCString(pool, context, value)); - string[offset] = *data; + internal->GetValue()[offset] = *data; return true; } CYCatch(false) } @@ -1080,7 +1059,7 @@ static JSValueRef CArray_getProperty(JSContextRef context, JSObjectRef object, J if (JSStringIsEqual(property, length_s)) return CYCastJSValue(context, internal->length_); Type_privateData *typical(internal->type_); - JSObjectRef owner(internal->GetOwner() ?: object); + JSObjectRef owner(internal->owner_ ?: object); return Offset_getProperty(pool, context, property, internal->value_, typical, owner); } CYCatch(NULL) } @@ -1103,7 +1082,7 @@ static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, return CYMakeFunctor(context, reinterpret_cast(internal->value_), function->variadic, function->signature); } - JSObjectRef owner(internal->GetOwner() ?: object); + JSObjectRef owner(internal->owner_ ?: object); return Offset_getProperty(pool, context, property, internal->value_, typical, owner); } CYCatch(NULL) } @@ -1137,7 +1116,7 @@ static JSValueRef Struct_getProperty(JSContextRef context, JSObjectRef object, J if (!Index_(pool, context, internal, property, index, base)) return NULL; - JSObjectRef owner(internal->GetOwner() ?: object); + JSObjectRef owner(internal->owner_ ?: object); return type->signature.elements[index].type->FromFFI(context, typical->GetFFI()->elements[index], base, false, owner); } CYCatch(NULL) } @@ -1609,13 +1588,13 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t static JSValueRef CArray_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CArray *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - JSObjectRef owner(internal->GetOwner() ?: object); + JSObjectRef owner(internal->owner_ ?: object); return CYMakePointer(context, internal->value_, *internal->type_->type_, NULL, owner); } CYCatch(NULL) } static JSValueRef CString_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { CString *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - JSObjectRef owner(internal->GetOwner() ?: object); + JSObjectRef owner(internal->owner_ ?: object); return CYMakePointer(context, internal->value_, sig::Primitive(), NULL, owner); } CYCatch(NULL) } @@ -1691,8 +1670,7 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe static JSValueRef CString_getProperty_length(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { CString *internal(reinterpret_cast(JSObjectGetPrivate(object))); - char *string(static_cast(internal->value_)); - return CYCastJSValue(context, strlen(string)); + return CYCastJSValue(context, strlen(internal->GetValue())); } CYCatch(NULL) } static JSValueRef CString_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1712,8 +1690,8 @@ static JSValueRef Pointer_getProperty_$cyt(JSContextRef context, JSObjectRef obj } CYCatch(NULL) } static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - Pointer *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - const char *string(static_cast(internal->value_)); + CString *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + const char *string(internal->GetValue()); std::ostringstream str; if (string == NULL) str << "NULL"; @@ -1726,9 +1704,8 @@ static JSValueRef CString_callAsFunction_toCYON(JSContextRef context, JSObjectRe } CYCatch(NULL) } static JSValueRef CString_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - Pointer *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - const char *string(static_cast(internal->value_)); - return CYCastJSValue(context, string); + CString *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + return CYCastJSValue(context, internal->GetValue()); } CYCatch(NULL) } static JSValueRef Functor_getProperty_$cyt(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1985,7 +1962,7 @@ void CYInitializeDynamic() { definition.getProperty = &CArray_getProperty; definition.setProperty = &CArray_setProperty; definition.finalize = &CYFinalize; - CArray_ = JSClassCreate(&definition); + CArray::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "CString"; @@ -1994,7 +1971,7 @@ void CYInitializeDynamic() { definition.getProperty = &CString_getProperty; definition.setProperty = &CString_setProperty; definition.finalize = &CYFinalize; - CString_ = JSClassCreate(&definition); + CString::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Functor"; @@ -2012,7 +1989,7 @@ void CYInitializeDynamic() { definition.getProperty = &Pointer_getProperty; definition.setProperty = &Pointer_setProperty; definition.finalize = &CYFinalize; - Pointer_ = JSClassCreate(&definition); + Pointer::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Struct"; @@ -2022,7 +1999,7 @@ void CYInitializeDynamic() { definition.setProperty = &Struct_setProperty; definition.getPropertyNames = &Struct_getPropertyNames; definition.finalize = &CYFinalize; - Struct_ = JSClassCreate(&definition); + Struct_privateData::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Type"; @@ -2257,11 +2234,11 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { CYSetProperty(context, cycript, CYJSString("compile"), &Cycript_compile_callAsFunction); CYSetProperty(context, cycript, CYJSString("gc"), &Cycript_gc_callAsFunction); - JSObjectRef CArray(JSObjectMakeConstructor(context, CArray_, &CArray_new)); + JSObjectRef CArray(JSObjectMakeConstructor(context, CArray::Class_, &CArray_new)); CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CArray, prototype_s)), Array_prototype); CYSetProperty(context, cycript, CYJSString("CArray"), CArray); - JSObjectRef CString(JSObjectMakeConstructor(context, CString_, &CString_new)); + JSObjectRef CString(JSObjectMakeConstructor(context, CString::Class_, &CString_new)); CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CString, prototype_s)), String_prototype); CYSetProperty(context, cycript, CYJSString("CString"), CString); @@ -2269,7 +2246,7 @@ extern "C" void CYSetupContext(JSGlobalContextRef context) { CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, Functor, prototype_s)), Function_prototype); CYSetProperty(context, cycript, CYJSString("Functor"), Functor); - CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer_, &Pointer_new)); + CYSetProperty(context, cycript, CYJSString("Pointer"), JSObjectMakeConstructor(context, Pointer::Class_, &Pointer_new)); CYSetProperty(context, cycript, CYJSString("Type"), JSObjectMakeConstructor(context, Type_privateData::Class_, &Type_new)); JSObjectRef modules(JSObjectMake(context, NULL, NULL)); diff --git a/Internal.hpp b/Internal.hpp index 3c5d5f5..9819b53 100644 --- a/Internal.hpp +++ b/Internal.hpp @@ -30,7 +30,9 @@ #include #include +#include "JavaScript.hpp" #include "Pooling.hpp" +#include "Utility.hpp" JSGlobalContextRef CYGetJSContext(JSContextRef context); sig::Type *Structor_(CYPool &pool, sig::Aggregate *aggregate); @@ -110,32 +112,71 @@ struct CYValue : } }; -struct CYOwned : +template +struct CYValue_ : CYValue { + static JSClassRef Class_; + static Type_privateData *Type_; + + using CYValue::CYValue; + + _finline Value_ GetValue() const { + return reinterpret_cast(value_); + } + + virtual Type_privateData *GetType() const { + return Type_; + } + + _finline JSValueRef GetPrototype(JSContextRef context) const { + return NULL; + } + + template + _finline static JSClassRef GetClass(Args_ &&... args) { + return Class_; + } + + template + static JSObjectRef Make(JSContextRef context, Args_ &&... args) { + Internal_ *internal(new Internal_(cy::Forward(args)...)); + JSObjectRef object(JSObjectMake(context, Internal_::GetClass(cy::Forward(args)...), internal)); + if (JSValueRef prototype = internal->GetPrototype(context)) + CYSetPrototype(context, object, prototype); + return object; + } +}; + +template +JSClassRef CYValue_::Class_; + +template +Type_privateData *CYValue_::Type_; + +struct CYProtect { private: JSGlobalContextRef context_; - JSObjectRef owner_; + JSObjectRef object_; public: - CYOwned(void *value, JSContextRef context, JSObjectRef owner) : - CYValue(value), + CYProtect(JSContextRef context, JSObjectRef object) : context_(CYGetJSContext(context)), - owner_(owner) + object_(object) { //XXX:JSGlobalContextRetain(context_); - if (owner_ != NULL) - JSValueProtect(context_, owner_); + if (object_ != NULL) + JSValueProtect(context_, object_); } - virtual ~CYOwned() { - if (owner_ != NULL) - JSValueUnprotect(context_, owner_); + ~CYProtect() { + if (object_ != NULL) + JSValueUnprotect(context_, object_); //XXX:JSGlobalContextRelease(context_); } - JSObjectRef GetOwner() const { - return owner_; + operator JSObjectRef() const { + return object_; } }; diff --git a/ObjectiveC/Internal.hpp b/ObjectiveC/Internal.hpp index 9cffb48..4946148 100644 --- a/ObjectiveC/Internal.hpp +++ b/ObjectiveC/Internal.hpp @@ -27,22 +27,16 @@ #include "../Internal.hpp" struct Selector_privateData : - CYValue + CYValue_ { _finline Selector_privateData(SEL value) : - CYValue(value) + CYValue_(value) { } - - _finline SEL GetValue() const { - return reinterpret_cast(value_); - } - - virtual Type_privateData *GetType() const; }; struct Instance : - CYValue + CYValue_ { enum Flags { None = 0, @@ -52,70 +46,52 @@ struct Instance : Flags flags_; - _finline Instance(id value, Flags flags) : - CYValue(value), - flags_(flags) - { - } - + Instance(id value, Flags flags); virtual ~Instance(); - static JSObjectRef Make(JSContextRef context, id object, Flags flags = None); + JSValueRef GetPrototype(JSContextRef context) const; - _finline id GetValue() const { - return reinterpret_cast(value_); - } + static JSClassRef GetClass(id value, Flags flags); _finline bool IsUninitialized() const { return (flags_ & Uninitialized) != 0; } - - virtual Type_privateData *GetType() const; }; namespace cy { struct Super : - Instance + CYValue_ { Class class_; _finline Super(id value, Class _class) : - Instance(value, Instance::Permanent), + CYValue_(value), class_(_class) { } - - static JSObjectRef Make(JSContextRef context, id object, Class _class); }; } struct Messages : - CYValue + CYValue_ { _finline Messages(Class value) : - CYValue(value) + CYValue_(value) { } - static JSObjectRef Make(JSContextRef context, Class _class); - - _finline Class GetValue() const { - return reinterpret_cast(value_); - } + JSValueRef GetPrototype(JSContextRef context) const; }; struct Internal : - CYOwned + CYValue_ { + CYProtect owner_; + _finline Internal(id value, JSContextRef context, JSObjectRef owner) : - CYOwned(value, context, owner) + CYValue_(value), + owner_(context, owner) { } - - static JSObjectRef Make(JSContextRef context, id object, JSObjectRef owner); - - _finline id GetValue() const { - return reinterpret_cast(value_); - } }; #endif/*CYCRIPT_OBJECTIVEC_INTERNAL_HPP*/ diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index a2a3190..01f9240 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -243,22 +243,14 @@ bool CYGetOffset(CYPool &pool, JSContextRef context, NSString *value, ssize_t &i return CYGetOffset(CYPoolCString(pool, context, value), index); } -static JSClassRef Instance_; - static JSClassRef ArrayInstance_; static JSClassRef BooleanInstance_; +static JSClassRef ClassInstance_; static JSClassRef FunctionInstance_; static JSClassRef NumberInstance_; static JSClassRef ObjectInstance_; static JSClassRef StringInstance_; -static JSClassRef Class_; -static JSClassRef Internal_; -static JSClassRef Message_; -static JSClassRef Messages_; -static JSClassRef Selector_; -static JSClassRef Super_; - static JSClassRef ObjectiveC_Classes_; static JSClassRef ObjectiveC_Constants_; static JSClassRef ObjectiveC_Protocols_; @@ -285,24 +277,13 @@ static Class NSString_; static Class NSZombie_; static Class Object_; -static Type_privateData *Object_type; -static Type_privateData *Selector_type; - -Type_privateData *Instance::GetType() const { - return Object_type; -} - -Type_privateData *Selector_privateData::GetType() const { - return Selector_type; -} - static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception); JSValueRef CYGetClassPrototype(JSContextRef context, Class self, bool meta) { if (self == nil) return CYGetCachedObject(context, CYJSString("Instance_prototype")); else if (meta && !class_isMetaClass(self)) - return CYGetCachedObject(context, CYJSString("Class_prototype")); + return CYGetCachedObject(context, CYJSString("ClassInstance_prototype")); JSObjectRef global(CYGetGlobalObject(context)); JSObjectRef cy(CYCastJSObject(context, CYGetProperty(context, global, cy_s))); @@ -348,23 +329,12 @@ _finline JSValueRef CYGetClassPrototype(JSContextRef context, Class self) { return CYGetClassPrototype(context, self, class_isMetaClass(self)); } -JSObjectRef Messages::Make(JSContextRef context, Class _class) { - JSObjectRef value(JSObjectMake(context, Messages_, new Messages(_class))); - if (Class super = class_getSuperclass(_class)) - CYSetPrototype(context, value, Messages::Make(context, super)); - return value; -} - -JSObjectRef Internal::Make(JSContextRef context, id object, JSObjectRef owner) { - return JSObjectMake(context, Internal_, new Internal(object, context, owner)); +JSValueRef Messages::GetPrototype(JSContextRef context) const { + if (Class super = class_getSuperclass(GetValue())) + return Messages::Make(context, super); + return NULL; } -namespace cy { -JSObjectRef Super::Make(JSContextRef context, id object, Class _class) { - JSObjectRef value(JSObjectMake(context, Super_, new Super(object, _class))); - return value; -} } - bool CYIsKindOfClass(id object, Class _class) { for (Class isa(object_getClass(object)); isa != NULL; isa = class_getSuperclass(isa)) if (isa == _class) @@ -372,10 +342,20 @@ bool CYIsKindOfClass(id object, Class _class) { return false; } -JSObjectRef Instance::Make(JSContextRef context, id object, Flags flags) { - JSObjectRef value(JSObjectMake(context, CYIsKindOfClass(object, NSBlock_) ? FunctionInstance_ : Instance_, new Instance(object, flags))); - CYSetPrototype(context, value, CYGetClassPrototype(context, object_getClass(object))); - return value; +JSValueRef Instance::GetPrototype(JSContextRef context) const { + return CYGetClassPrototype(context, object_getClass(GetValue())); +} + +JSClassRef Instance::GetClass(id object, Flags flags) { + return CYIsKindOfClass(object, NSBlock_) ? FunctionInstance_ : Instance::Class_; +} + +Instance::Instance(id value, Flags flags) : + CYValue_(value), + flags_(flags) +{ + if ((flags & Instance::Permanent) == 0) + value_ = [GetValue() retain]; } Instance::~Instance() { @@ -386,15 +366,21 @@ Instance::~Instance() { struct Message_privateData : cy::Functor { + static JSClassRef Class_; + SEL sel_; - Message_privateData(SEL sel, const char *type, IMP value = NULL) : + Message_privateData(SEL sel, const char *type, IMP value) : cy::Functor(reinterpret_cast(value), type), sel_(sel) { } + + static JSObjectRef Make(JSContextRef context, SEL sel, const char *type, IMP value); }; +JSClassRef Message_privateData::Class_; + JSObjectRef CYMakeInstance(JSContextRef context, id object, Instance::Flags flags = Instance::None) { _assert(object != nil); @@ -406,9 +392,6 @@ JSObjectRef CYMakeInstance(JSContextRef context, id object, Instance::Flags flag return instance; #endif - if ((flags & Instance::Permanent) == 0) - object = [object retain]; - JSObjectRef instance(Instance::Make(context, object, flags)); #ifdef __APPLE__ @@ -626,7 +609,7 @@ struct PropertyAttributes { /* }}} */ _finline bool CYJSValueIsNSObject(JSContextRef context, JSValueRef value) { - return JSValueIsObjectOfClass(context, value, Instance_) || JSValueIsObjectOfClass(context, value, FunctionInstance_); + return JSValueIsObjectOfClass(context, value, Instance::Class_) || JSValueIsObjectOfClass(context, value, FunctionInstance_); } _finline bool CYJSValueIsInstanceOfCachedConstructor(JSContextRef context, JSValueRef value, JSStringRef cache) { @@ -1483,19 +1466,14 @@ JSValueRef CYCastJSValue(JSContextRef context, NSObject *value) { @end -static JSObjectRef CYMakeSelector(JSContextRef context, SEL sel) { - Selector_privateData *internal(new Selector_privateData(sel)); - return JSObjectMake(context, Selector_, internal); -} - static JSValueRef CYCastJSValue(JSContextRef context, SEL sel) { if (sel == NULL) return CYJSNull(context); - return CYMakeSelector(context, sel); + return Selector_privateData::Make(context, sel); } static SEL CYCastSEL(JSContextRef context, JSValueRef value) { - if (JSValueIsObjectOfClass(context, value, Selector_)) { + if (JSValueIsObjectOfClass(context, value, Selector_privateData::Class_)) { Selector_privateData *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); return reinterpret_cast(internal->value_); } else { @@ -1525,7 +1503,7 @@ static NSBlock *CYCastNSBlock(CYPool &pool, JSContextRef context, JSValueRef val if (JSValueIsObjectOfClass(context, object, FunctionInstance_)) return reinterpret_cast(JSObjectGetPrivate(object))->GetValue(); - if (JSValueIsObjectOfClass(context, object, Instance_)) { + if (JSValueIsObjectOfClass(context, object, Instance::Class_)) { _assert(reinterpret_cast(JSObjectGetPrivate(object))->GetValue() == nil); return nil; } @@ -1628,9 +1606,9 @@ static JSValueRef MessageAdapter_(JSContextRef context, size_t count, JSValueRef return CYCallAsFunction(context, function, _this, count - 2, values + 2); } -static JSObjectRef CYMakeMessage(JSContextRef context, SEL sel, IMP imp, const char *type) { - Message_privateData *internal(new Message_privateData(sel, type, imp)); - return JSObjectMake(context, Message_, internal); +JSObjectRef Message_privateData::Make(JSContextRef context, SEL sel, const char *type, IMP value) { + Message_privateData *internal(new Message_privateData(sel, type, value)); + return JSObjectMake(context, Message_privateData::Class_, internal); } static IMP CYMakeMessage(JSContextRef context, JSValueRef value, const char *encoding) { @@ -1666,7 +1644,7 @@ static JSValueRef Messages_getProperty(JSContextRef context, JSObjectRef object, if (SEL sel = sel_getUid(name)) if (objc_method *method = class_getInstanceMethod(_class, sel)) - return CYMakeMessage(context, sel, method_getImplementation(method), method_getTypeEncoding(method)); + return Message_privateData::Make(context, sel, method_getTypeEncoding(method), method_getImplementation(method)); return NULL; } CYCatch(NULL) } @@ -1682,7 +1660,7 @@ static bool Messages_setProperty(JSContextRef context, JSObjectRef object, JSStr const char *type; IMP imp; - if (JSValueIsObjectOfClass(context, value, Message_)) { + if (JSValueIsObjectOfClass(context, value, Message_privateData::Class_)) { Message_privateData *message(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) value))); type = sig::Unparse(pool, &message->signature_); imp = reinterpret_cast(message->GetValue()); @@ -1768,7 +1746,7 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, id self(internal->GetValue()); if (JSStringIsEqualToUTF8CString(property, "$cyi")) - return Internal::Make(context, self, object); + return Internal::Make(context, self, context, object); CYPool pool; NSString *name(CYCastNSString(&pool, context, property)); @@ -2121,7 +2099,7 @@ static void Internal_getPropertyNames(JSContextRef context, JSObjectRef object, static JSValueRef Internal_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Internal *internal(reinterpret_cast(JSObjectGetPrivate(object))); - return internal->GetOwner(); + return internal->owner_; } CYCatch(NULL) } static bool ObjectiveC_Classes_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) { @@ -2440,7 +2418,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje SEL _cmd; Class _class; - if (JSValueIsObjectOfClass(context, arguments[0], Super_)) { + if (JSValueIsObjectOfClass(context, arguments[0], cy::Super::Class_)) { cy::Super *internal(reinterpret_cast(JSObjectGetPrivate((JSObjectRef) arguments[0]))); self = internal->GetValue(); _class = internal->class_;; @@ -2506,7 +2484,7 @@ static JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t throw CYJSError(context, "incorrect number of arguments to Selector constructor"); CYPool pool; const char *name(CYPoolCString(pool, context, arguments[0])); - return CYMakeSelector(context, sel_registerName(name)); + return Selector_privateData::Make(context, sel_registerName(name)); } CYCatch(NULL) } static JSObjectRef Instance_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -2767,8 +2745,8 @@ JSValueRef NSCFType$cy$toJSON$inContext$(id self, SEL sel, JSValueRef key, JSCon void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { CYPool &pool(CYGetGlobalPool()); - Object_type = new(pool) Type_privateData(sig::Object()); - Selector_type = new(pool) Type_privateData(sig::Selector()); + Instance::Type_ = new(pool) Type_privateData(sig::Object()); + Selector_privateData::Type_ = new(pool) Type_privateData(sig::Selector()); NSArray_ = objc_getClass("NSArray"); NSBlock_ = objc_getClass("NSBlock"); @@ -2807,7 +2785,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.callAsConstructor = &Instance_callAsConstructor; definition.hasInstance = &Instance_hasInstance; definition.finalize = &CYFinalize; - Instance_ = JSClassCreate(&definition); + Instance::Class_ = JSClassCreate(&definition); definition.className = "ArrayInstance"; ArrayInstance_ = JSClassCreate(&definition); @@ -2832,7 +2810,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition = kJSClassDefinitionEmpty; definition.className = "Class"; definition.staticFunctions = Class_staticFunctions; - Class_ = JSClassCreate(&definition); + ClassInstance_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Internal"; @@ -2842,7 +2820,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.setProperty = &Internal_setProperty; definition.getPropertyNames = &Internal_getPropertyNames; definition.finalize = &CYFinalize; - Internal_ = JSClassCreate(&definition); + Internal::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Message"; @@ -2850,7 +2828,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.staticValues = cy::Functor::StaticValues; definition.callAsFunction = &Message_callAsFunction; definition.finalize = &CYFinalize; - Message_ = JSClassCreate(&definition); + Message_privateData::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Messages"; @@ -2859,7 +2837,7 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.setProperty = &Messages_setProperty; definition.getPropertyNames = &Messages_getPropertyNames; definition.finalize = &CYFinalize; - Messages_ = JSClassCreate(&definition); + Messages::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Selector"; @@ -2867,13 +2845,12 @@ void CYObjectiveC_Initialize() { /*XXX*/ JSContextRef context(NULL); CYPoolTry { definition.staticFunctions = Selector_staticFunctions; definition.callAsFunction = &Selector_callAsFunction; definition.finalize = &CYFinalize; - Selector_ = JSClassCreate(&definition); + Selector_privateData::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "Super"; - definition.staticFunctions = Internal_staticFunctions; definition.finalize = &CYFinalize; - Super_ = JSClassCreate(&definition); + cy::Super::Class_ = JSClassCreate(&definition); definition = kJSClassDefinitionEmpty; definition.className = "ObjectiveC::Classes"; @@ -2946,11 +2923,10 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { CYSetProperty(context, ObjectiveC, CYJSString("images"), JSObjectMake(context, ObjectiveC_Images_, NULL)); #endif - JSObjectRef Class(JSObjectMakeConstructor(context, Class_, NULL)); - JSObjectRef Instance(JSObjectMakeConstructor(context, Instance_, &Instance_new)); - JSObjectRef Message(JSObjectMakeConstructor(context, Message_, NULL)); - JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_, &Selector_new)); - JSObjectRef Super(JSObjectMakeConstructor(context, Super_, &Super_new)); + JSObjectRef Instance(JSObjectMakeConstructor(context, Instance::Class_, &Instance_new)); + JSObjectRef Message(JSObjectMakeConstructor(context, Message_privateData::Class_, NULL)); + JSObjectRef Selector(JSObjectMakeConstructor(context, Selector_privateData::Class_, &Selector_new)); + JSObjectRef Super(JSObjectMakeConstructor(context, cy::Super::Class_, &Super_new)); JSObjectRef Instance_prototype(CYCastJSObject(context, CYGetProperty(context, Instance, prototype_s))); CYSetProperty(context, cy, CYJSString("Instance_prototype"), Instance_prototype); @@ -2967,6 +2943,12 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { JSObjectRef Boolean_prototype(CYGetCachedObject(context, CYJSString("Boolean_prototype"))); CYSetPrototype(context, BooleanInstance_prototype, Boolean_prototype); + JSObjectRef ClassInstance(JSObjectMakeConstructor(context, ClassInstance_, NULL)); + JSObjectRef ClassInstance_prototype(CYCastJSObject(context, CYGetProperty(context, ClassInstance, prototype_s))); + CYSetProperty(context, cy, CYJSString("ClassInstance_prototype"), ClassInstance_prototype); + // XXX: this doesn't fit the pattern of the other ones; maybe it sort of should? + CYSetPrototype(context, ClassInstance_prototype, Instance_prototype); + JSObjectRef FunctionInstance(JSObjectMakeConstructor(context, FunctionInstance_, NULL)); JSObjectRef FunctionInstance_prototype(CYCastJSObject(context, CYGetProperty(context, FunctionInstance, prototype_s))); CYSetProperty(context, cy, CYJSString("FunctionInstance_prototype"), FunctionInstance_prototype); @@ -2991,10 +2973,6 @@ void CYObjectiveC_SetupContext(JSContextRef context) { CYPoolTry { JSObjectRef String_prototype(CYGetCachedObject(context, CYJSString("String_prototype"))); CYSetPrototype(context, StringInstance_prototype, String_prototype); - JSObjectRef Class_prototype(CYCastJSObject(context, CYGetProperty(context, Class, prototype_s))); - CYSetProperty(context, cy, CYJSString("Class_prototype"), Class_prototype); - CYSetPrototype(context, Class_prototype, Instance_prototype); - CYSetProperty(context, cycript, CYJSString("Instance"), Instance); CYSetProperty(context, cycript, CYJSString("Selector"), Selector); CYSetProperty(context, cycript, CYJSString("objc_super"), Super); diff --git a/Utility.hpp b/Utility.hpp new file mode 100644 index 0000000..c2aa4e3 --- /dev/null +++ b/Utility.hpp @@ -0,0 +1,49 @@ +/* Cycript - Optimizing JavaScript Compiler/Runtime + * Copyright (C) 2009-2015 Jay Freeman (saurik) +*/ + +/* GNU Affero General Public License, Version 3 {{{ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . +**/ +/* }}} */ + +#ifndef CYCRIPT_UTILITY_HPP +#define CYCRIPT_UTILITY_HPP + +// XXX: this is required because Apple is bad at developer tools (I hate them so much) + +namespace cy { + +template struct is_lvalue_reference { static const bool value = false; }; +template struct is_lvalue_reference { static const bool value = true; }; + +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template +inline T &&Forward(typename cy::remove_reference::type &t) noexcept { + return static_cast(t); +} + +template +inline T &&Forward(typename cy::remove_reference::type &&t) noexcept { + static_assert(!cy::is_lvalue_reference::value, "Can not forward an rvalue as an lvalue."); + return static_cast(t); +} + +} + +#endif/*CYCRIPT_UTILITY_HPP*/ -- 2.45.2