Skip to content

Commit

Permalink
Objects must now be defined with property keys
Browse files Browse the repository at this point in the history
Property arrays are no longer allowed. This simplifies the API and makes code easier to read and maintain. All tests now pass in simulator and in Chrome.

Resolves #112
  • Loading branch information
appden committed Nov 4, 2015
1 parent 4053f5f commit a19f0e2
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 152 deletions.
7 changes: 1 addition & 6 deletions src/RJSObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,15 @@ JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) {
return JSObjectMakeDate(ctx, 1, &time, NULL);
}

extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);

template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm realm, JSValueRef &val, const std::string &type, bool try_update) {
JSObjectRef object = RJSValidatedValueToObject(ctx, val);
if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) {
return RJSGetInternal<Object *>(object)->row().get_index();
}

auto object_schema = realm->config().schema->find(type);
if (RJSIsValueArray(ctx, object)) {
object = RJSDictForPropertyArray(ctx, *object_schema, object);
}

Object child = Object::create<JSValueRef>(ctx, realm, *object_schema, (JSValueRef)object, try_update);

return child.row().get_index();
}
template<> JSValueRef RJSAccessor::from_object(JSContextRef ctx, Object object) {
Expand Down
27 changes: 1 addition & 26 deletions src/RJSRealm.mm
Original file line number Diff line number Diff line change
Expand Up @@ -279,45 +279,20 @@ JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef this
}
}

JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array) {
// copy to dictionary
if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) {
throw std::runtime_error("Array must contain values for all object properties");
}

JSValueRef exception = NULL;
JSObjectRef dict = JSObjectMake(ctx, NULL, NULL);
for (unsigned int i = 0; i < object_schema.properties.size(); i++) {
JSStringRef nameStr = JSStringCreateWithUTF8CString(object_schema.properties[i].name.c_str());
JSValueRef value = JSObjectGetPropertyAtIndex(ctx, array, i, &exception);
if (exception) {
throw RJSException(ctx, exception);
}
JSObjectSetProperty(ctx, dict, nameStr, value, kJSPropertyAttributeNone, &exception);
if (exception) {
throw RJSException(ctx, exception);
}
JSStringRelease(nameStr);
}
return dict;
}

JSValueRef RealmCreateObject(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
RJSValidateArgumentRange(argumentCount, 2, 3);

std::string className = RJSValidatedStringForValue(ctx, arguments[0], "objectType");
SharedRealm sharedRealm = *RJSGetInternal<SharedRealm *>(thisObject);
auto object_schema = sharedRealm->config().schema->find(className);

if (object_schema == sharedRealm->config().schema->end()) {
*jsException = RJSMakeError(ctx, "Object type '" + className + "' not found in schema.");
return NULL;
}

JSObjectRef object = RJSValidatedValueToObject(ctx, arguments[1]);
if (RJSIsValueArray(ctx, arguments[1])) {
object = RJSDictForPropertyArray(ctx, *object_schema, object);
}

bool update = false;
if (argumentCount == 3) {
Expand Down
146 changes: 107 additions & 39 deletions tests/ArrayTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,43 @@ var schemas = require('./schemas');
module.exports = BaseTest.extend({
testArrayLength: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]);
TestCase.assertEqual(obj.arrayCol.length, 1);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}],
});

array = obj.arrayCol;
TestCase.assertEqual(array.length, 1);

obj.arrayCol = [];
TestCase.assertEqual(obj.arrayCol.length, 0);
TestCase.assertEqual(array.length, 0);

obj.arrayCol = [[1], [2]];
TestCase.assertEqual(obj.arrayCol.length, 2);
obj.arrayCol = [{doubleCol: 1}, {doubleCol: 2}];
TestCase.assertEqual(array.length, 2);

TestCase.assertThrows(function() {
obj.arrayCol.length = 0;
array.length = 0;
}, 'cannot set length property on lists');
});

TestCase.assertEqual(array.length, 2);
},

testArraySubscriptGetters: function() {
var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
});

Expand All @@ -48,26 +63,36 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
array = obj.arrayCol;
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array[0] = [5];
array[1] = [6];
array = obj.arrayCol;
array[0] = {doubleCol: 5};
array[1] = {doubleCol: 6};

TestCase.assertEqual(array[0].doubleCol, 5);
TestCase.assertEqual(array[1].doubleCol, 6);

array[0] = obj.objectCol;
array[1] = obj.objectCol1;

TestCase.assertEqual(array[0].doubleCol, 1);
TestCase.assertEqual(array[1].doubleCol, 2);

TestCase.assertThrows(function() {
array[2] = [1];
array[2] = {doubleCol: 1};
}, 'cannot set list item beyond its bounds');

TestCase.assertThrows(function() {
array[-1] = [1];
array[-1] = {doubleCol: 1};
}, 'cannot set list item with negative index');
});

TestCase.assertThrows(function() {
array[0] = [3];
array[0] = {doubleCol: 1};
}, 'cannot set list item outside write transaction');
},

Expand All @@ -76,7 +101,12 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
});

Expand All @@ -88,21 +118,26 @@ module.exports = BaseTest.extend({
var obj;

realm.write(function() {
obj = realm.create('LinkTypesObject', [[1], [2], []]);
obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [],
});
});

for (var index in obj.arrayCol) {
var index;
for (index in obj.arrayCol) {
TestCase.assertTrue(false, "No objects should have been enumerated: " + index);
}

realm.write(function() {
obj.arrayCol = [[0], [1]];
obj.arrayCol = [{doubleCol: 0}, {doubleCol: 1}];
TestCase.assertEqual(obj.arrayCol.length, 2);
});

var count = 0;
var keys = Object.keys(obj.arrayCol);
for (var index in obj.arrayCol) {
for (index in obj.arrayCol) {
TestCase.assertEqual(count++, +index);
TestCase.assertEqual(keys[index], index);
}
Expand All @@ -116,11 +151,16 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]);
TestCase.assertEqual(obj.arrayCol.length, 1);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}],
});

array = obj.arrayCol;
TestCase.assertEqual(array.push([4]), 2);
TestCase.assertEqual(array.length, 1);

TestCase.assertEqual(array.push({doubleCol: 4}), 2);
TestCase.assertEqual(array.length, 2);
TestCase.assertEqual(array[1].doubleCol, 4);

Expand All @@ -145,9 +185,13 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
array = obj.arrayCol;
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
TestCase.assertEqual(array.pop().doubleCol, 4);
TestCase.assertEqual(array.pop().doubleCol, 3);
TestCase.assertEqual(array.length, 0);
Expand All @@ -169,11 +213,16 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]);
TestCase.assertEqual(obj.arrayCol.length, 1);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}],
});

array = obj.arrayCol;
TestCase.assertEqual(array.unshift([5]), 2);
TestCase.assertEqual(array.length, 1);

TestCase.assertEqual(array.unshift({doubleCol: 5}), 2);
TestCase.assertEqual(array.length, 2);
TestCase.assertEqual(array[0].doubleCol, 5);

Expand All @@ -185,7 +234,7 @@ module.exports = BaseTest.extend({

TestCase.assertEqual(array.length, 4);
TestCase.assertThrows(function() {
array.unshift([1]);
array.unshift({doubleCol: 1});
}, 'can only unshift in a write transaction');
},

Expand All @@ -194,9 +243,13 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
array = obj.arrayCol;
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
TestCase.assertEqual(array.shift().doubleCol, 3);
TestCase.assertEqual(array.shift().doubleCol, 4);
TestCase.assertEqual(array.length, 0);
Expand All @@ -218,18 +271,22 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
var removed;
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
var removed;

removed = array.splice(0, 0, obj.objectCol, obj.objectCol1);
TestCase.assertEqual(removed.length, 0);
TestCase.assertEqual(array.length, 4);
TestCase.assertEqual(array[0].doubleCol, 1);
TestCase.assertEqual(array[1].doubleCol, 2);

removed = array.splice(2, 2, [5], [6]);
removed = array.splice(2, 2, {doubleCol: 5}, {doubleCol: 6});
TestCase.assertEqual(removed.length, 2);
TestCase.assertEqual(removed[0].doubleCol, 3);
TestCase.assertEqual(removed[1].doubleCol, 4);
Expand Down Expand Up @@ -270,7 +327,7 @@ module.exports = BaseTest.extend({
});

TestCase.assertThrows(function() {
array.splice(0, 0, [1]);
array.splice(0, 0, {doubleCol: 1});
}, 'can only splice in a write transaction');
},

Expand All @@ -279,7 +336,12 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
});

Expand All @@ -304,21 +366,27 @@ module.exports = BaseTest.extend({
var array;

realm.write(function() {
var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]);
var obj = realm.create('LinkTypesObject', {
objectCol: {doubleCol: 1},
objectCol1: {doubleCol: 2},
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
});

array = obj.arrayCol;
});

TestCase.assertEqual(array.length, 2);
TestCase.assertEqual(objects.length, 4);

try {
realm.write(function() {
array.push([5]);
array.push({doubleCol: 5});
TestCase.assertEqual(objects.length, 5);

array.unshift([2]);
array.unshift({doubleCol: 2});
TestCase.assertEqual(objects.length, 6);

array.splice(0, 0, [1]);
array.splice(0, 0, {doubleCol: 1});
TestCase.assertEqual(objects.length, 7);

array.push(objects[0], objects[1]);
Expand Down
Loading

0 comments on commit a19f0e2

Please sign in to comment.