wrap list properties

This commit is contained in:
Ari Lazier 2016-03-30 14:18:44 -07:00
parent c249eea505
commit 29213f1d87
3 changed files with 52 additions and 60 deletions

View File

@ -42,6 +42,10 @@ struct List {
using ValueType = typename T::Value; using ValueType = typename T::Value;
using ReturnType = typename T::Return; using ReturnType = typename T::Return;
static void GetLength(ContextType ctx, ObjectType thisObject, ReturnType &ret);
static void GetIndex(ContextType ctx, ObjectType thisObject, size_t index, ReturnType &ret);
static void SetIndex(ContextType ctx, ObjectType thisObject, size_t index, ValueType value);
static void Push(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret); static void Push(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret);
static void Pop(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret); static void Pop(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret);
static void Unshift(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret); static void Unshift(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret);
@ -52,6 +56,24 @@ struct List {
static void Sorted(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret); static void Sorted(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret);
}; };
template<typename T>
void List<T>::GetLength(ContextType ctx, ObjectType object, ReturnType &ret) {
realm::List *list = RJSGetInternal<realm::List *>(object);
RJSSetReturnNumber(ctx, ret, list->size());
}
template<typename T>
void List<T>::GetIndex(ContextType ctx, ObjectType object, size_t index, ReturnType &ret) {
realm::List *list = RJSGetInternal<realm::List *>(object);
ret = RJSObjectCreate(ctx, Object(list->get_realm(), list->get_object_schema(), list->get(index)));
}
template<typename T>
void List<T>::SetIndex(ContextType ctx, ObjectType object, size_t index, ValueType value) {
realm::List *list = RJSGetInternal<realm::List *>(object);
list->set(ctx, value, index);
}
template<typename T> template<typename T>
void List<T>::Push(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject) { void List<T>::Push(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject) {
realm::List *list = RJSGetInternal<realm::List *>(thisObject); realm::List *list = RJSGetInternal<realm::List *>(thisObject);

View File

@ -64,6 +64,31 @@ bool CLASS_NAME ## METHOD_NAME(JSContextRef ctx, JSObjectRef object, JSStringRef
return true; \ return true; \
} }
// for stol failure (std::invalid_argument) this could be another property that is handled externally, so ignore
#define WRAP_INDEXED_GETTER(CLASS_NAME, METHOD_NAME) \
JSValueRef CLASS_NAME ## METHOD_NAME(JSContextRef ctx, JSObjectRef object, JSStringRef property, JSValueRef* ex) { \
JSValueRef returnValue = NULL; \
try { \
size_t index = RJSValidatedPositiveIndex(RJSStringForJSString(property)); \
CLASS_NAME::METHOD_NAME(ctx, object, index, returnValue); return returnValue; \
} \
catch (std::out_of_range &exp) { return JSValueMakeUndefined(ctx); } \
catch (std::invalid_argument &exp) { return NULL; } \
catch (std::exception &e) { RJSSetException(ctx, *ex, e); return NULL; } \
}
#define WRAP_INDEXED_SETTER(CLASS_NAME, METHOD_NAME) \
bool CLASS_NAME ## METHOD_NAME(JSContextRef ctx, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef* ex) { \
try { \
size_t index = RJSValidatedPositiveIndex(RJSStringForJSString(property)); \
{ CLASS_NAME::METHOD_NAME(ctx, object, index, value); return true; } \
} \
catch (std::out_of_range &exp) { RJSSetException(ctx, *ex, exp); } \
catch (std::invalid_argument &exp) { *ex = RJSMakeError(ctx, "Invalid index"); } \
catch (std::exception &e) { RJSSetException(ctx, *ex, e); } \
return false; \
}
template<typename T> template<typename T>
inline void RJSFinalize(JSObjectRef object) { inline void RJSFinalize(JSObjectRef object) {

View File

@ -24,64 +24,6 @@
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>; using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm; using namespace realm;
JSValueRef ListGetLength(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
try {
List *list = RJSGetInternal<List *>(object);
return JSValueMakeNumber(ctx, list->size());
}
catch (std::exception &exp) {
if (exception) {
*exception = RJSMakeError(ctx, exp);
}
return NULL;
}
}
JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
try {
List *list = RJSGetInternal<List *>(object);
std::string indexStr = RJSStringForJSString(propertyName);
return RJSObjectCreate(ctx, Object(list->get_realm(), list->get_object_schema(), list->get(RJSValidatedPositiveIndex(indexStr))));
}
catch (std::out_of_range &exp) {
// getters for nonexistent properties in JS should always return undefined
return JSValueMakeUndefined(ctx);
}
catch (std::invalid_argument &exp) {
// for stol failure this could be another property that is handled externally, so ignore
return NULL;
}
catch (std::exception &exp) {
if (jsException) {
*jsException = RJSMakeError(ctx, exp);
}
return NULL;
}
}
bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
try {
List *list = RJSGetInternal<List *>(object);
std::string indexStr = RJSStringForJSString(propertyName);
if (indexStr == "length") {
throw std::runtime_error("The 'length' property is readonly.");
}
list->set(ctx, value, RJSValidatedPositiveIndex(indexStr));
return true;
}
catch (std::invalid_argument &exp) {
// for stol failure this could be another property that is handled externally, so ignore
return false;
}
catch (std::exception &exp) {
if (jsException) {
*jsException = RJSMakeError(ctx, exp);
}
return false;
}
}
void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
List *list = RJSGetInternal<List *>(object); List *list = RJSGetInternal<List *>(object);
size_t size = list->size(); size_t size = list->size();
@ -96,6 +38,9 @@ void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccum
} }
using RJSList = realm::js::List<realm::jsc::Types>; using RJSList = realm::js::List<realm::jsc::Types>;
WRAP_PROPERTY_GETTER(RJSList, GetLength)
WRAP_INDEXED_GETTER(RJSList, GetIndex)
WRAP_INDEXED_SETTER(RJSList, SetIndex)
WRAP_CLASS_METHOD(RJSList, Push) WRAP_CLASS_METHOD(RJSList, Push)
WRAP_CLASS_METHOD(RJSList, Pop) WRAP_CLASS_METHOD(RJSList, Pop)
WRAP_CLASS_METHOD(RJSList, Unshift) WRAP_CLASS_METHOD(RJSList, Unshift)
@ -122,12 +67,12 @@ static const JSStaticFunction RJSListFuncs[] = {
}; };
static const JSStaticValue RJSListProps[] = { static const JSStaticValue RJSListProps[] = {
{"length", ListGetLength, nullptr, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"length", RJSListGetLength, nullptr, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL}, {NULL, NULL},
}; };
JSClassRef RJSListClass() { JSClassRef RJSListClass() {
static JSClassRef s_listClass = RJSCreateWrapperClass<List *>("List", ListGetProperty, ListSetProperty, RJSListFuncs, ListPropertyNames, RJSCollectionClass(), RJSListProps); static JSClassRef s_listClass = RJSCreateWrapperClass<List *>("List", RJSListGetIndex, RJSListSetIndex, RJSListFuncs, ListPropertyNames, RJSCollectionClass(), RJSListProps);
return s_listClass; return s_listClass;
} }