RPC now keeps object keys in the same order
Maintaining insertion order when passing objects through the RPC is essential to make the new schema API work.
This commit is contained in:
parent
43e14093cc
commit
c928ab716e
|
@ -17,6 +17,7 @@ let propTypes = {};
|
|||
});
|
||||
|
||||
[
|
||||
'DICT',
|
||||
'FUNCTION',
|
||||
'REALM',
|
||||
'RESULTS',
|
||||
|
|
25
lib/rpc.js
25
lib/rpc.js
|
@ -10,6 +10,7 @@ const constants = require('./constants');
|
|||
const DEVICE_HOST = 'localhost:8082';
|
||||
|
||||
const {keys, objectTypes, propTypes} = constants;
|
||||
const {id: idKey, realm: realmKey} = keys;
|
||||
const typeConverters = {};
|
||||
|
||||
let XMLHttpRequest = global.originalXMLHttpRequest || global.XMLHttpRequest;
|
||||
|
@ -40,6 +41,7 @@ module.exports = {
|
|||
|
||||
registerTypeConverter(propTypes.DATA, (_, {value}) => base64.decode(value));
|
||||
registerTypeConverter(propTypes.DATE, (_, {value}) => new Date(value));
|
||||
registerTypeConverter(objectTypes.DICT, deserializeDict);
|
||||
|
||||
function registerTypeConverter(type, handler) {
|
||||
typeConverters[type] = handler;
|
||||
|
@ -106,9 +108,9 @@ function serialize(realmId, value) {
|
|||
return {value: value};
|
||||
}
|
||||
|
||||
let id = value[keys.id];
|
||||
let id = value[idKey];
|
||||
if (id) {
|
||||
if (value[keys.realm] != realmId) {
|
||||
if (value[realmKey] != realmId) {
|
||||
throw new Error('Unable to serialize value from another Realm');
|
||||
}
|
||||
|
||||
|
@ -128,11 +130,9 @@ function serialize(realmId, value) {
|
|||
return {type: propTypes.DATA, value: base64.encode(value)};
|
||||
}
|
||||
|
||||
let object = {};
|
||||
for (let key in value) {
|
||||
object[key] = serialize(realmId, value[key]);
|
||||
}
|
||||
return {value: object};
|
||||
let keys = Object.keys(value);
|
||||
let values = keys.map((key) => serialize(realmId, value[key]));
|
||||
return {type: objectTypes.DICT, keys, values};
|
||||
}
|
||||
|
||||
function deserialize(realmId, info) {
|
||||
|
@ -150,6 +150,17 @@ function deserialize(realmId, info) {
|
|||
return value;
|
||||
}
|
||||
|
||||
function deserializeDict(realmId, info) {
|
||||
let {keys, values} = info;
|
||||
let object = {};
|
||||
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
object[keys[i]] = values[i];
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
function sendRequest(command, data) {
|
||||
data = Object.assign({}, data, sessionId ? {sessionId} : null);
|
||||
|
||||
|
|
53
src/rpc.cpp
53
src/rpc.cpp
|
@ -22,6 +22,7 @@
|
|||
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
|
||||
using namespace realm_js;
|
||||
|
||||
static const char * const RealmObjectTypesDictionary = "ObjectTypesDICT";
|
||||
static const char * const RealmObjectTypesFunction = "ObjectTypesFUNCTION";
|
||||
static const char * const RealmObjectTypesResults = "ObjectTypesRESULTS";
|
||||
|
||||
|
@ -262,6 +263,28 @@ json RPCServer::serialize_json_value(JSValueRef value) {
|
|||
{"value", RJSValidatedValueToNumber(m_context, value)},
|
||||
};
|
||||
}
|
||||
else {
|
||||
JSPropertyNameArrayRef js_keys = JSObjectCopyPropertyNames(m_context, js_object);
|
||||
size_t count = JSPropertyNameArrayGetCount(js_keys);
|
||||
std::vector<std::string> keys;
|
||||
std::vector<json> values;
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
JSStringRef js_key = JSPropertyNameArrayGetNameAtIndex(js_keys, i);
|
||||
JSValueRef js_value = RJSValidatedPropertyValue(m_context, js_object, js_key);
|
||||
|
||||
keys.push_back(RJSStringForJSString(js_key));
|
||||
values.push_back(serialize_json_value(js_value));
|
||||
}
|
||||
|
||||
JSPropertyNameArrayRelease(js_keys);
|
||||
|
||||
return {
|
||||
{"type", RealmObjectTypesDictionary},
|
||||
{"keys", keys},
|
||||
{"values", values},
|
||||
};
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
@ -299,6 +322,22 @@ JSValueRef RPCServer::deserialize_json_value(const json dict)
|
|||
|
||||
return js_function;
|
||||
}
|
||||
else if (type_string == RealmObjectTypesDictionary) {
|
||||
JSObjectRef js_object = JSObjectMake(m_context, NULL, NULL);
|
||||
json keys = dict["keys"];
|
||||
json values = dict["values"];
|
||||
size_t count = keys.size();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
JSStringRef js_key = RJSStringForString(keys.at(i));
|
||||
JSValueRef js_value = deserialize_json_value(values.at(i));
|
||||
|
||||
JSObjectSetProperty(m_context, js_object, js_key, js_value, 0, NULL);
|
||||
JSStringRelease(js_key);
|
||||
}
|
||||
|
||||
return js_object;
|
||||
}
|
||||
else if (type_string == RJSTypeGet(realm::PropertyTypeData)) {
|
||||
std::string bytes;
|
||||
if (!base64_decode(value.get<std::string>(), &bytes)) {
|
||||
|
@ -344,19 +383,5 @@ JSValueRef RPCServer::deserialize_json_value(const json dict)
|
|||
|
||||
return JSObjectMakeArray(m_context, count, js_values, NULL);
|
||||
}
|
||||
else if (value.is_object()) {
|
||||
JSObjectRef js_object = JSObjectMake(m_context, NULL, NULL);
|
||||
|
||||
for (json::iterator it = value.begin(); it != value.end(); ++it) {
|
||||
JSValueRef js_value = deserialize_json_value(it.value());
|
||||
JSStringRef js_key = JSStringCreateWithUTF8CString(it.key().c_str());
|
||||
|
||||
JSObjectSetProperty(m_context, js_object, js_key, js_value, 0, NULL);
|
||||
JSStringRelease(js_key);
|
||||
}
|
||||
|
||||
return js_object;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue