From 9ebca0a01a76e046969f31a376737d075707e3a2 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Tue, 29 Dec 2015 09:21:22 -0800 Subject: [PATCH] Improve CString/Pointer consistency, using CArray. --- Execute.cpp | 238 ++++++++++++++++++++++++++---------------- JavaScript.hpp | 2 +- ObjectiveC/Library.mm | 2 +- sig/types.hpp | 9 -- 4 files changed, 148 insertions(+), 103 deletions(-) diff --git a/Execute.cpp b/Execute.cpp index 86009fc..a17cd55 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -168,6 +168,7 @@ 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_; @@ -219,6 +220,20 @@ struct Context : } }; +struct CArray : + CYOwned +{ + 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), + type_(new(*pool_) Type_privateData(type, ffi)), + length_(length) + { + } +}; + struct CString : CYOwned { @@ -232,19 +247,16 @@ struct Pointer : CYOwned { Type_privateData *type_; - size_t length_; - Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, const sig::Type &type) : + Pointer(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type) : CYOwned(value, context, owner), - type_(new(*pool_) Type_privateData(type)), - length_(length) + type_(new(*pool_) Type_privateData(type)) { } - Pointer(void *value, JSContextRef context, JSObjectRef owner, size_t length, const char *encoding) : + Pointer(void *value, JSContextRef context, JSObjectRef owner, const char *encoding) : CYOwned(value, context, owner), - type_(new(*pool_) Type_privateData(encoding)), - length_(length) + type_(new(*pool_) Type_privateData(encoding)) { } }; @@ -254,24 +266,40 @@ struct Struct_privateData : { Type_privateData *type_; - Struct_privateData(JSContextRef context, JSObjectRef owner) : - CYOwned(NULL, context, owner) + Struct_privateData(void *value, JSContextRef context, JSObjectRef owner, const sig::Type &type, ffi_type *ffi) : + CYOwned(value, context, owner), + type_(new(*pool_) Type_privateData(type, ffi)) { } }; +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(context, owner)); - CYPool &pool(*internal->pool_); - Type_privateData *typical(new(pool) Type_privateData(type, ffi)); - internal->type_ = typical; + Struct_privateData *internal(new Struct_privateData(data, context, owner, type, ffi)); - if (owner != NULL) - internal->value_ = data; - else { - ffi_type *ffi(typical->GetFFI()); - void *copy(internal->pool_->malloc(ffi->size, ffi->alignment)); - memcpy(copy, data, ffi->size); + if (owner == NULL) { + size_t size(ffi->size); + void *copy(internal->pool_->malloc(size, ffi->alignment)); + memcpy(copy, internal->value_, size); internal->value_ = copy; } @@ -609,21 +637,16 @@ static JSValueRef String_callAsFunction_toCYON(JSContextRef context, JSObjectRef return CYCastJSValue(context, CYJSString(CYUTF8String(value.c_str(), value.size()))); } CYCatch(NULL) } -JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner) { - Pointer *internal(new Pointer(pointer, context, owner, length, type)); +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, size_t length, const char *encoding, JSObjectRef owner) { - Pointer *internal(new Pointer(pointer, context, owner, length, encoding)); +JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const char *encoding, JSObjectRef owner) { + Pointer *internal(new Pointer(pointer, context, owner, encoding)); return JSObjectMake(context, Pointer_, internal); } -JSObjectRef CYMakeCString(JSContextRef context, char *pointer, JSObjectRef owner) { - CString *internal(new CString(pointer, context, owner)); - return JSObjectMake(context, CString_, internal); -} - static JSObjectRef CYMakeFunctor(JSContextRef context, void (*function)(), const sig::Signature &signature) { return JSObjectMake(context, Functor_, new cy::Functor(signature, function)); } @@ -822,13 +845,12 @@ JSValueRef Bits::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool i JSValueRef Pointer::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { if (void *value = *reinterpret_cast(data)) - return CYMakePointer(context, value, _not(size_t), type, NULL, owner); + return CYMakePointer(context, value, type, NULL, owner); return CYJSNull(context); } JSValueRef Array::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { - _assert(data != NULL); - return CYMakePointer(context, data, size, type, NULL, owner); + return CYMakeCArray(context, data, size, type, ffi->elements[0], owner); } JSValueRef Aggregate::FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const { @@ -993,65 +1015,77 @@ static bool Index_(CYPool &pool, JSContextRef context, Struct_privateData *inter return true; } -static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { - CYPool pool; - Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); - - if (JSStringIsEqual(property, length_s)) - return internal->length_ == _not(size_t) ? CYJSUndefined(context) : CYCastJSValue(context, internal->length_); - - Type_privateData *typical(internal->type_); - if (typical->type_ == NULL) - return NULL; - - if (sig::Function *function = dynamic_cast(typical->type_)) { - if (!JSStringIsEqualToUTF8CString(property, "$cyi")) - return NULL; - return CYMakeFunctor(context, reinterpret_cast(internal->value_), function->signature); - } - +static void *Offset_(CYPool &pool, JSContextRef context, JSStringRef property, void *data, ffi_type *ffi) { ssize_t offset; if (JSStringIsEqualToUTF8CString(property, "$cyi")) offset = 0; else if (!CYGetOffset(pool, context, property, offset)) return NULL; + return reinterpret_cast(data) + ffi->size * offset; +} +static JSValueRef Offset_getProperty(CYPool &pool, JSContextRef context, JSStringRef property, void *data, Type_privateData *typical, JSObjectRef owner) { ffi_type *ffi(typical->GetFFI()); + void *base(Offset_(pool, context, property, data, ffi)); + if (base == NULL) + return NULL; + return typical->type_->FromFFI(context, ffi, base, false, owner); +} - uint8_t *base(reinterpret_cast(internal->value_)); - base += ffi->size * offset; +static bool Offset_setProperty(CYPool &pool, JSContextRef context, JSStringRef property, void *data, Type_privateData *typical, JSValueRef value) { + ffi_type *ffi(typical->GetFFI()); + void *base(Offset_(pool, context, property, data, ffi)); + if (base == NULL) + return false; + typical->type_->PoolFFI(NULL, context, ffi, base, value); + return true; +} + +static JSValueRef CArray_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYPool pool; + CArray *internal(reinterpret_cast(JSObjectGetPrivate(object))); + if (JSStringIsEqual(property, length_s)) + return CYCastJSValue(context, internal->length_); + Type_privateData *typical(internal->type_); JSObjectRef owner(internal->GetOwner() ?: object); - return typical->type_->FromFFI(context, ffi, base, false, owner); + return Offset_getProperty(pool, context, property, internal->value_, typical, owner); } CYCatch(NULL) } -static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { +static bool CArray_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { CYPool pool; Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); Type_privateData *typical(internal->type_); + return Offset_setProperty(pool, context, property, internal->value_, typical, value); +} CYCatch(false) } - if (typical->type_ == NULL) - return false; +static JSValueRef Pointer_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CYPool pool; + Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); - ssize_t offset; - if (JSStringIsEqualToUTF8CString(property, "$cyi")) - offset = 0; - else if (!CYGetOffset(pool, context, property, offset)) - return false; + Type_privateData *typical(internal->type_); - ffi_type *ffi(typical->GetFFI()); + if (sig::Function *function = dynamic_cast(typical->type_)) { + if (!JSStringIsEqualToUTF8CString(property, "$cyi")) + return NULL; + return CYMakeFunctor(context, reinterpret_cast(internal->value_), function->signature); + } - uint8_t *base(reinterpret_cast(internal->value_)); - base += ffi->size * offset; + JSObjectRef owner(internal->GetOwner() ?: object); + return Offset_getProperty(pool, context, property, internal->value_, typical, owner); +} CYCatch(NULL) } - typical->type_->PoolFFI(NULL, context, ffi, base, value); - return true; +static bool Pointer_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { CYTry { + CYPool pool; + Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); + Type_privateData *typical(internal->type_); + return Offset_setProperty(pool, context, property, internal->value_, typical, value); } CYCatch(false) } static JSValueRef Struct_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { Struct_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); Type_privateData *typical(internal->type_); - return CYMakePointer(context, internal->value_, _not(size_t), *typical->type_, typical->ffi_, _this); + return CYMakePointer(context, internal->value_, *typical->type_, typical->ffi_, _this); } CYCatch(NULL) } static JSValueRef Struct_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { @@ -1325,26 +1359,16 @@ static void All_getPropertyNames(JSContextRef context, JSObjectRef object, JSPro } } +static JSObjectRef CArray_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + _assert(false); +} CYCatch(NULL) } + static JSObjectRef CString_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (count != 1) - throw CYJSError(context, "incorrect number of arguments to CString constructor"); - char *value(CYCastPointer(context, arguments[0])); - return CYMakeCString(context, value, NULL); + _assert(false); } CYCatch(NULL) } static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { - if (count != 2) - throw CYJSError(context, "incorrect number of arguments to Pointer constructor"); - - CYPool pool; - - void *value(CYCastPointer(context, arguments[0])); - const char *type(CYPoolCString(pool, context, arguments[1])); - - sig::Signature signature; - sig::Parse(pool, &signature, type, &Structor_); - - return CYMakePointer(context, value, _not(size_t), *signature.elements[0].type, NULL, NULL); + _assert(false); } CYCatch(NULL) } static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1491,10 +1515,7 @@ static JSObjectRef Type_callAsConstructor(JSContextRef context, JSObjectRef obje throw CYJSError(context, "incorrect number of arguments to Type allocator"); Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(object))); - sig::Type *type(internal->type_); - size_t length(type->Translate(type)); - - JSObjectRef pointer(CYMakePointer(context, NULL, length, *type, NULL, NULL)); + JSObjectRef pointer(CYMakePointer(context, NULL, *internal->type_, NULL, NULL)); Pointer *value(reinterpret_cast(JSObjectGetPrivate(pointer))); ffi_type *ffi(internal->GetFFI()); value->value_ = value->pool_->malloc(ffi->size, ffi->alignment); @@ -1512,9 +1533,16 @@ static JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t return CYMakeFunctor(context, arguments[0], signature); } CYCatch(NULL) } +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); + 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))); - return CYMakePointer(context, internal->value_, _not(size_t), sig::Primitive(), NULL, NULL); + JSObjectRef owner(internal->GetOwner() ?: object); + return CYMakePointer(context, internal->value_, sig::Primitive(), NULL, owner); } CYCatch(NULL) } static JSValueRef Functor_callAsFunction_$cya(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1524,7 +1552,7 @@ static JSValueRef Functor_callAsFunction_$cya(JSContextRef context, JSObjectRef sig::Function type; sig::Copy(pool, type.signature, internal->signature_); - return CYMakePointer(context, internal->value_, _not(size_t), type, NULL, NULL); + return CYMakePointer(context, internal->value_, type, NULL, NULL); } CYCatch(NULL) } static JSValueRef Pointer_callAsFunction_toPointer(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { @@ -1562,11 +1590,6 @@ static JSValueRef Pointer_callAsFunction_toCYON(JSContextRef context, JSObjectRe std::set *objects(CYCastObjects(context, _this, count, arguments)); Pointer *internal(reinterpret_cast(JSObjectGetPrivate(_this))); - if (internal->length_ != _not(size_t)) { - JSObjectRef Array(CYGetCachedObject(context, CYJSString("Array_prototype"))); - JSObjectRef toCYON(CYCastJSObject(context, CYGetProperty(context, Array, toCYON_s))); - return CYCallAsFunction(context, toCYON, _this, count, arguments); - } try { JSValueRef value(CYGetProperty(context, _this, cyi_s)); @@ -1602,6 +1625,12 @@ static JSValueRef CString_getProperty_type(JSContextRef context, JSObjectRef obj return CYMakeType(context, sig::String()); } CYCatch(NULL) } +static JSValueRef CArray_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { + CArray *internal(reinterpret_cast(JSObjectGetPrivate(object))); + sig::Array type(*internal->type_->type_, internal->length_); + return CYMakeType(context, type); +} CYCatch(NULL) } + static JSValueRef Pointer_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { Pointer *internal(reinterpret_cast(JSObjectGetPrivate(object))); sig::Pointer type(*internal->type_->type_); @@ -1674,6 +1703,18 @@ static JSStaticFunction All_staticFunctions[2] = { {NULL, NULL, 0} }; +static JSStaticFunction CArray_staticFunctions[4] = { + {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"toPointer", &CArray_callAsFunction_toPointer, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"valueOf", &CYValue_callAsFunction_valueOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, 0} +}; + +static JSStaticValue CArray_staticValues[2] = { + {"type", &CArray_getProperty_type, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {NULL, NULL, NULL, 0} +}; + static JSStaticFunction CString_staticFunctions[6] = { {"toCYON", &CString_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toJSON", &CYValue_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, @@ -1860,6 +1901,15 @@ void CYInitializeDynamic() { definition.finalize = &CYFinalize; Context_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; + definition.className = "CArray"; + definition.staticFunctions = CArray_staticFunctions; + definition.staticValues = CArray_staticValues; + definition.getProperty = &CArray_getProperty; + definition.setProperty = &CArray_setProperty; + definition.finalize = &CYFinalize; + CArray_ = JSClassCreate(&definition); + definition = kJSClassDefinitionEmpty; definition.className = "CString"; definition.staticFunctions = CString_staticFunctions; @@ -2129,6 +2179,10 @@ 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)); + CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CArray, prototype_s)), Array_prototype); + CYSetProperty(context, cycript, CYJSString("CArray"), CArray); + JSObjectRef CString(JSObjectMakeConstructor(context, CString_, &CString_new)); CYSetPrototype(context, CYCastJSObject(context, CYGetProperty(context, CString, prototype_s)), String_prototype); CYSetProperty(context, cycript, CYJSString("CString"), CString); diff --git a/JavaScript.hpp b/JavaScript.hpp index 43c6be0..08020fe 100644 --- a/JavaScript.hpp +++ b/JavaScript.hpp @@ -135,7 +135,7 @@ struct CYRegisterHook { CYRegisterHook(CYHook *hook); }; -JSObjectRef CYMakePointer(JSContextRef context, void *pointer, size_t length, const sig::Type &type, ffi_type *ffi, JSObjectRef owner); +JSObjectRef CYMakePointer(JSContextRef context, void *pointer, const sig::Type &type, ffi_type *ffi, JSObjectRef owner); JSObjectRef CYMakeType(JSContextRef context, const sig::Type &type); JSObjectRef CYMakeType(JSContextRef context, sig::Signature *signature); diff --git a/ObjectiveC/Library.mm b/ObjectiveC/Library.mm index a21aa6e..580660e 100644 --- a/ObjectiveC/Library.mm +++ b/ObjectiveC/Library.mm @@ -2550,7 +2550,7 @@ static JSValueRef CYValue_callAsFunction_$cya(JSContextRef context, JSObjectRef ffi = typical->ffi_; } - return CYMakePointer(context, &internal->value_, _not(size_t), *type, ffi, object); + return CYMakePointer(context, &internal->value_, *type, ffi, object); } CYCatch(NULL) } static JSValueRef FunctionInstance_getProperty_type(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { CYTry { diff --git a/sig/types.hpp b/sig/types.hpp index d437475..3bed8fd 100644 --- a/sig/types.hpp +++ b/sig/types.hpp @@ -65,10 +65,6 @@ struct Type { virtual ffi_type *GetFFI(CYPool &pool) const = 0; virtual void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const = 0; virtual JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize = false, JSObjectRef owner = NULL) const = 0; - - virtual size_t Translate(Type *&type) const { - return _not(size_t); - } }; template @@ -223,11 +219,6 @@ struct Array : ffi_type *GetFFI(CYPool &pool) const override; void PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const override; JSValueRef FromFFI(JSContextRef context, ffi_type *ffi, void *data, bool initialize, JSObjectRef owner) const override; - - size_t Translate(Type *&type) const override { - type = &this->type; - return size; - } }; struct Object : -- 2.45.2