diff --git a/lib/rpc.js b/lib/rpc.js index 889afcd7..d3813fb5 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -4,7 +4,7 @@ let constants = require('./constants'); let DEVICE_HOST = 'localhost:8082'; -let {keys, objectTypes} = constants; +let {keys, objectTypes, propTypes} = constants; let typeConverters = {}; let XMLHttpRequest = window.XMLHttpRequest; @@ -95,6 +95,10 @@ function serialize(realmId, value) { return {id}; } + if (value instanceof Date) { + return {type: propTypes.DATE, value: value.getTime()}; + } + if (Array.isArray(value)) { let array = value.map((item) => serialize(realmId, item)); return {value: array}; diff --git a/src/RJSObject.mm b/src/RJSObject.mm index b56c2801..567ccc96 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -142,21 +142,8 @@ template<> JSValueRef RJSAccessor::from_string(JSContextRef ctx, StringData s) { } template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) { - JSObjectRef object = RJSValidatedValueToObject(ctx, val, "Property must be a Date"); - - JSValueRef exception = NULL; - static JSStringRef utcString = JSStringCreateWithUTF8CString("getTime"); - JSObjectRef utcGetter = RJSValidatedObjectProperty(ctx, object, utcString); - - JSValueRef utcVal = JSObjectCallAsFunction(ctx, utcGetter, object, 0, NULL, &exception); - if (exception) { - throw RJSException(ctx, exception); - } - - double utc = JSValueToNumber(ctx, utcVal, &exception); - if (exception) { - throw RJSException(ctx, exception); - } + JSObjectRef object = RJSValidatedValueToDate(ctx, val); + double utc = RJSValidatedValueToNumber(ctx, object); return DateTime(utc); } diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 0ff3beeb..5e968d0c 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -99,6 +99,9 @@ JSValueRef RJSMakeError(JSContextRef ctx, RJSException &exp); JSValueRef RJSMakeError(JSContextRef ctx, std::exception &exp); JSValueRef RJSMakeError(JSContextRef ctx, const std::string &message); +bool RJSIsValueArray(JSContextRef ctx, JSValueRef value); +bool RJSIsValueDate(JSContextRef ctx, JSValueRef value); + static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef value, const char *message = NULL) { JSObjectRef object = JSValueToObject(ctx, value, NULL); if (!object) { @@ -107,6 +110,14 @@ static inline JSObjectRef RJSValidatedValueToObject(JSContextRef ctx, JSValueRef return object; } +static inline JSObjectRef RJSValidatedValueToDate(JSContextRef ctx, JSValueRef value, const char *message = NULL) { + JSObjectRef object = JSValueToObject(ctx, value, NULL); + if (!object || !RJSIsValueDate(ctx, object)) { + throw std::runtime_error(message ?: "Value is not a date."); + } + return object; +} + static inline JSObjectRef RJSValidatedValueToFunction(JSContextRef ctx, JSValueRef value, const char *message = NULL) { JSObjectRef object = JSValueToObject(ctx, value, NULL); if (!object || !JSObjectIsFunction(ctx, object)) { @@ -200,6 +211,3 @@ static inline bool RJSIsValueObjectOfType(JSContextRef ctx, JSValueRef value, JS return ret; } - -bool RJSIsValueArray(JSContextRef ctx, JSValueRef value); - diff --git a/src/RJSUtil.mm b/src/RJSUtil.mm index e64dd061..6429cf3d 100644 --- a/src/RJSUtil.mm +++ b/src/RJSUtil.mm @@ -115,6 +115,10 @@ bool RJSIsValueArray(JSContextRef ctx, JSValueRef value) { return RJSIsValueObjectOfType(ctx, value, arrayString); } +bool RJSIsValueDate(JSContextRef ctx, JSValueRef value) { + static JSStringRef dateString = JSStringCreateWithUTF8CString("Date"); + return RJSIsValueObjectOfType(ctx, value, dateString); +} #include diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index 1e914fd1..a66b09b8 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -275,6 +275,12 @@ static const char * const RealmObjectTypesResults = "ObjectTypesRESULTS"; } return @{@"value": array}; } + else if (RJSIsValueDate(_context, value)) { + return @{ + @"type": @(RJSTypeGet(realm::PropertyTypeDate).c_str()), + @"value": @(RJSValidatedValueToNumber(_context, value)), + }; + } else { assert(0); } @@ -305,6 +311,8 @@ static const char * const RealmObjectTypesResults = "ObjectTypesRESULTS"; } NSString *type = dict[@"type"]; + id value = dict[@"value"]; + if ([type isEqualToString:@(RealmObjectTypesFunction)]) { // FIXME: Make this actually call the function by its id once we need it to. JSStringRef jsBody = JSStringCreateWithUTF8CString(""); @@ -313,8 +321,17 @@ static const char * const RealmObjectTypesResults = "ObjectTypesRESULTS"; return jsFunction; } + else if ([type isEqualToString:@(RJSTypeGet(realm::PropertyTypeDate).c_str())]) { + JSValueRef exception = NULL; + JSValueRef time = JSValueMakeNumber(_context, [value doubleValue]); + JSObjectRef date = JSObjectMakeDate(_context, 1, &time, &exception); + + if (exception) { + throw RJSException(_context, exception); + } + return date; + } - id value = dict[@"value"]; if (!value) { return JSValueMakeUndefined(_context); }