mirror of
https://github.com/status-im/realm-js.git
synced 2025-01-10 22:36:01 +00:00
Support (de)serialization of objects in RPC
Everything is a dictionary with either a `value` key or an `id` key. If it's a value, then it will recursively be (de)serialized.
This commit is contained in:
parent
a9cac20f79
commit
31fc14d602
@ -181,10 +181,11 @@ static JSGlobalContextRef s_context;
|
||||
JSValueRef exception = NULL;
|
||||
|
||||
NSArray *arguments = dict[@"arguments"];
|
||||
JSValueRef argumentValues[arguments.count];
|
||||
JSContext *context = [JSContext contextWithJSGlobalContextRef:s_context];
|
||||
for (int i = 0; i < arguments.count; i++) {
|
||||
argumentValues[i] = [JSValue valueWithObject:arguments[i] inContext:context].JSValueRef;
|
||||
NSUInteger count = arguments.count;
|
||||
JSValueRef argumentValues[count];
|
||||
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
argumentValues[i] = [self valueFromDictionary:arguments[i]];
|
||||
}
|
||||
|
||||
JSValueRef ret;
|
||||
@ -302,4 +303,53 @@ static JSGlobalContextRef s_context;
|
||||
};
|
||||
}
|
||||
|
||||
+ (JSValueRef)valueFromDictionary:(NSDictionary *)dict {
|
||||
RPCObjectID oid = [dict[@"id"] longValue];
|
||||
if (oid) {
|
||||
return s_objects[oid];
|
||||
}
|
||||
|
||||
id value = dict[@"value"];
|
||||
if (!value) {
|
||||
return JSValueMakeUndefined(s_context);
|
||||
}
|
||||
else if ([value isKindOfClass:[NSNull class]]) {
|
||||
return JSValueMakeNull(s_context);
|
||||
}
|
||||
else if ([value isKindOfClass:[@YES class]]) {
|
||||
return JSValueMakeBoolean(s_context, [value boolValue]);
|
||||
}
|
||||
else if ([value isKindOfClass:[NSNumber class]]) {
|
||||
return JSValueMakeNumber(s_context, [value doubleValue]);
|
||||
}
|
||||
else if ([value isKindOfClass:[NSString class]]) {
|
||||
return RJSValueForString(s_context, std::string([value UTF8String]));
|
||||
}
|
||||
else if ([value isKindOfClass:[NSArray class]]) {
|
||||
NSUInteger count = [value count];
|
||||
std::vector<JSValueRef> jsValues(count);
|
||||
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
jsValues[i] = [self valueFromDictionary:value[i]];
|
||||
}
|
||||
|
||||
return JSObjectMakeArray(s_context, count, jsValues.data(), NULL);
|
||||
}
|
||||
else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
JSObjectRef jsObject = JSObjectMake(s_context, NULL, NULL);
|
||||
|
||||
for (NSString *key in value) {
|
||||
JSValueRef jsValue = [self valueFromDictionary:value[key]];
|
||||
JSStringRef jsKey = JSStringCreateWithCFString((__bridge CFStringRef)key);
|
||||
|
||||
JSObjectSetProperty(s_context, jsObject, jsKey, jsValue, 0, NULL);
|
||||
JSStringRelease(jsKey);
|
||||
}
|
||||
|
||||
return jsObject;
|
||||
}
|
||||
|
||||
return JSValueMakeUndefined(s_context);
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -3,8 +3,9 @@
|
||||
let rpc = require('./rpc');
|
||||
let util = require('./util');
|
||||
|
||||
let idKey = Symbol();
|
||||
let realmKey = Symbol();
|
||||
let idKey = util.idKey;
|
||||
let realmKey = util.realmKey;
|
||||
let resizeListKey = util.resizeListKey;
|
||||
let prototype = {};
|
||||
|
||||
exports.create = create;
|
||||
@ -26,7 +27,7 @@ exports.create = create;
|
||||
}
|
||||
|
||||
let result = rpc.callListMethod(realmId, listId, name, Array.from(arguments));
|
||||
this[util.resizeListKey]();
|
||||
this[resizeListKey]();
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -40,7 +41,7 @@ function create(realmId, info) {
|
||||
list[realmKey] = realmId;
|
||||
list[idKey] = info.id;
|
||||
|
||||
list[util.resizeListKey](size);
|
||||
list[resizeListKey](size);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
let rpc = require('./rpc');
|
||||
let util = require('./util');
|
||||
|
||||
let idKey = Symbol();
|
||||
let realmKey = Symbol();
|
||||
let schemaKey = Symbol();
|
||||
let idKey = util.idKey;
|
||||
let realmKey = util.realmKey;
|
||||
let registeredConstructors = {};
|
||||
|
||||
exports.create = create;
|
||||
@ -18,7 +18,6 @@ function create(realmId, info) {
|
||||
|
||||
object[realmKey] = realmId;
|
||||
object[idKey] = info.id;
|
||||
object[schemaKey] = schema;
|
||||
|
||||
for (let prop of schema.properties) {
|
||||
let name = prop.name;
|
||||
|
@ -5,8 +5,9 @@ let objects = require('./objects');
|
||||
let results = require('./results');
|
||||
let rpc = require('./rpc');
|
||||
let types = require('./types');
|
||||
let util = require('./util');
|
||||
|
||||
let realmKey = Symbol();
|
||||
let realmKey = util.realmKey;
|
||||
|
||||
// TODO: DATA
|
||||
rpc.registerTypeConverter(types.DATE, (_, info) => new Date(info.value));
|
||||
|
@ -3,8 +3,9 @@
|
||||
let rpc = require('./rpc');
|
||||
let util = require('./util');
|
||||
|
||||
let idKey = Symbol();
|
||||
let realmKey = Symbol();
|
||||
let idKey = util.idKey;
|
||||
let realmKey = util.realmKey;
|
||||
let resizeListKey = util.resizeListKey;
|
||||
|
||||
exports.create = create;
|
||||
|
||||
@ -15,7 +16,7 @@ function create(realmId, info) {
|
||||
results[realmKey] = realmId;
|
||||
results[idKey] = info.resultsId;
|
||||
|
||||
results[util.resizeListKey](size);
|
||||
results[resizeListKey](size);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
60
lib/rpc.js
60
lib/rpc.js
@ -1,7 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
let util = require('./util');
|
||||
|
||||
let DEVICE_HOST = 'localhost:8082';
|
||||
|
||||
let idKey = util.idKey;
|
||||
let realmKey = util.realmKey;
|
||||
let typeConverters = {};
|
||||
let XMLHttpRequest = window.XMLHttpRequest;
|
||||
|
||||
@ -52,7 +56,7 @@ function getObjects(realmId, type, predicate) {
|
||||
|
||||
function getObjectProperty(realmId, objectId, name) {
|
||||
let result = sendRequest('get_property', {realmId, objectId, name});
|
||||
return convert(realmId, result);
|
||||
return deserialize(realmId, result);
|
||||
}
|
||||
|
||||
function setObjectProperty(realmId, objectId, name, value) {
|
||||
@ -61,7 +65,7 @@ function setObjectProperty(realmId, objectId, name, value) {
|
||||
|
||||
function getListItem(realmId, listId, index) {
|
||||
let result = sendRequest('get_list_item', {realmId, listId, index});
|
||||
return convert(realmId, result);
|
||||
return deserialize(realmId, result);
|
||||
}
|
||||
|
||||
function setListItem(realmId, listId, index, value) {
|
||||
@ -73,13 +77,17 @@ function getListSize(realmId, listId) {
|
||||
}
|
||||
|
||||
function callListMethod(realmId, listId, name, args) {
|
||||
if (args) {
|
||||
args = args.map((arg) => serialize(realmId, arg));
|
||||
}
|
||||
|
||||
let result = sendRequest('call_list_method', {realmId, listId, name, arguments: args});
|
||||
return convert(realmId, result);
|
||||
return deserialize(realmId, result);
|
||||
}
|
||||
|
||||
function getResultsItem(realmId, resultsId, index) {
|
||||
let result = sendRequest('get_results_item', {realmId, resultsId, index});
|
||||
return convert(realmId, result);
|
||||
return deserialize(realmId, result);
|
||||
}
|
||||
|
||||
function getResultsSize(realmId, resultsId) {
|
||||
@ -98,9 +106,45 @@ function commitTransaction(realmId) {
|
||||
sendRequest('commit_transaction', {realmId});
|
||||
}
|
||||
|
||||
function convert(realmId, info) {
|
||||
let handler = typeConverters[info.type];
|
||||
return handler ? handler(realmId, info) : info.value;
|
||||
function serialize(realmId, value) {
|
||||
if (!value || typeof value != 'object') {
|
||||
return {value: value};
|
||||
}
|
||||
|
||||
let id = value[idKey];
|
||||
if (id) {
|
||||
if (value[realmKey] != realmId) {
|
||||
throw new Error('Unable to serialize value from another Realm');
|
||||
}
|
||||
|
||||
return {id: id};
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
let array = value.map((item) => serialize(realmId, item));
|
||||
return {value: array};
|
||||
}
|
||||
|
||||
let object = {};
|
||||
for (let key in value) {
|
||||
object[key] = serialize(realmId, value[key]);
|
||||
}
|
||||
return {value: object};
|
||||
}
|
||||
|
||||
function deserialize(realmId, info) {
|
||||
let type = info.type;
|
||||
let handler = type && typeConverters[type];
|
||||
if (handler) {
|
||||
return handler(realmId, info);
|
||||
}
|
||||
|
||||
let value = info.value;
|
||||
if (value && Array.isArray(value)) {
|
||||
return value.map((item) => deserialize(realmId, item));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function sendRequest(command, data) {
|
||||
@ -116,7 +160,7 @@ function sendRequest(command, data) {
|
||||
}
|
||||
|
||||
let response = JSON.parse(request.responseText);
|
||||
|
||||
|
||||
if (!response || response.error) {
|
||||
throw new Error((response && response.error) || 'Invalid response for "' + command + '"');
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
let idKey = exports.idKey = Symbol();
|
||||
let realmKey = exports.realmKey = Symbol();
|
||||
let resizeListKey = exports.resizeListKey = Symbol();
|
||||
|
||||
exports.createList = createList;
|
||||
|
Loading…
x
Reference in New Issue
Block a user