From 29213f1d8797dfb02610d9503edb395d5151c206 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Wed, 30 Mar 2016 14:18:44 -0700 Subject: [PATCH] wrap list properties --- src/js_list.hpp | 22 +++++++++++++++ src/js_util.hpp | 25 +++++++++++++++++ src/jsc/jsc_list.cpp | 65 ++++---------------------------------------- 3 files changed, 52 insertions(+), 60 deletions(-) diff --git a/src/js_list.hpp b/src/js_list.hpp index dbfdaf83..9bf07f48 100644 --- a/src/js_list.hpp +++ b/src/js_list.hpp @@ -41,6 +41,10 @@ struct List { using ObjectType = typename T::Object; using ValueType = typename T::Value; 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 Pop(ContextType ctx, ObjectType thisObject, size_t argCount, const ValueType args[], ReturnType &ret); @@ -51,6 +55,24 @@ struct List { static void Filtered(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 +void List::GetLength(ContextType ctx, ObjectType object, ReturnType &ret) { + realm::List *list = RJSGetInternal(object); + RJSSetReturnNumber(ctx, ret, list->size()); +} + +template +void List::GetIndex(ContextType ctx, ObjectType object, size_t index, ReturnType &ret) { + realm::List *list = RJSGetInternal(object); + ret = RJSObjectCreate(ctx, Object(list->get_realm(), list->get_object_schema(), list->get(index))); +} + +template +void List::SetIndex(ContextType ctx, ObjectType object, size_t index, ValueType value) { + realm::List *list = RJSGetInternal(object); + list->set(ctx, value, index); +} template void List::Push(ContextType ctx, ObjectType thisObject, size_t argumentCount, const ValueType arguments[], ReturnType &returnObject) { diff --git a/src/js_util.hpp b/src/js_util.hpp index d416827f..fd6beba1 100644 --- a/src/js_util.hpp +++ b/src/js_util.hpp @@ -64,6 +64,31 @@ bool CLASS_NAME ## METHOD_NAME(JSContextRef ctx, JSObjectRef object, JSStringRef 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 inline void RJSFinalize(JSObjectRef object) { diff --git a/src/jsc/jsc_list.cpp b/src/jsc/jsc_list.cpp index da2ef3f9..347c8688 100644 --- a/src/jsc/jsc_list.cpp +++ b/src/jsc/jsc_list.cpp @@ -24,64 +24,6 @@ using RJSAccessor = realm::NativeAccessor; using namespace realm; -JSValueRef ListGetLength(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { - try { - List *list = RJSGetInternal(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(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(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) { List *list = RJSGetInternal(object); size_t size = list->size(); @@ -96,6 +38,9 @@ void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccum } using RJSList = realm::js::List; +WRAP_PROPERTY_GETTER(RJSList, GetLength) +WRAP_INDEXED_GETTER(RJSList, GetIndex) +WRAP_INDEXED_SETTER(RJSList, SetIndex) WRAP_CLASS_METHOD(RJSList, Push) WRAP_CLASS_METHOD(RJSList, Pop) WRAP_CLASS_METHOD(RJSList, Unshift) @@ -122,12 +67,12 @@ static const JSStaticFunction RJSListFuncs[] = { }; static const JSStaticValue RJSListProps[] = { - {"length", ListGetLength, nullptr, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"length", RJSListGetLength, nullptr, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL}, }; JSClassRef RJSListClass() { - static JSClassRef s_listClass = RJSCreateWrapperClass("List", ListGetProperty, ListSetProperty, RJSListFuncs, ListPropertyNames, RJSCollectionClass(), RJSListProps); + static JSClassRef s_listClass = RJSCreateWrapperClass("List", RJSListGetIndex, RJSListSetIndex, RJSListFuncs, ListPropertyNames, RJSCollectionClass(), RJSListProps); return s_listClass; }