diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 2ad920b7..3f7cb3f7 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -49,6 +49,14 @@ static inline ObjectArray * RJSVerifiedArray(JSObjectRef object) { return array; } +static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) { + ObjectArray *array = RJSVerifiedArray(object); + if (!array->realm->is_in_transaction()) { + throw std::runtime_error("Can only mutate lists within a transaction."); + } + return array; +} + JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) { try { // index subscripting @@ -89,7 +97,7 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -106,7 +114,7 @@ JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); size_t size = array->size(); @@ -128,7 +136,7 @@ JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCountIsAtLeast(argumentCount, 1); for (size_t i = 0; i < argumentCount; i++) { array->link_view->insert(i, RJSAccessor::to_object_index(ctx, array->realm, const_cast(arguments[i]), array->object_schema.name, false)); @@ -145,7 +153,7 @@ JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef this JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); RJSValidateArgumentCount(argumentCount, 0); if (array->size() == 0) { return JSValueMakeUndefined(ctx); @@ -164,7 +172,7 @@ JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - ObjectArray *array = RJSVerifiedArray(thisObject); + ObjectArray *array = RJSVerifiedMutableArray(thisObject); size_t size = array->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index c07a3d7d..667b594f 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -108,6 +108,7 @@ var ArrayTests = { testPush: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -128,14 +129,15 @@ var ArrayTests = { }); TestCase.assertEqual(array.length, 4); - // TestCase.assertThrows(function() { - // array.push([1]); - // }); + TestCase.assertThrows(function() { + array.push([1]); + }, 'can only push in a write transaction'); }, testPop: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -151,14 +153,15 @@ var ArrayTests = { }); }); - // TestCase.assertThrows(function() { - // array.pop(); - // }); + TestCase.assertThrows(function() { + array.pop(); + }, 'can only pop in a write transaction'); }, testUnshift: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -175,14 +178,15 @@ var ArrayTests = { }); TestCase.assertEqual(array.length, 4); - // TestCase.assertThrows(function() { - // array.unshift([1]); - // }); + TestCase.assertThrows(function() { + array.unshift([1]); + }, 'can only unshift in a write transaction'); }, testShift: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); var array; + realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); array = obj.arrayCol; @@ -198,19 +202,21 @@ var ArrayTests = { }); }); - // TestCase.assertThrows(function() { - // array.shift(); - // }); + TestCase.assertThrows(function() { + array.shift(); + }, 'can only shift in a write transaction'); }, testSplice: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var array; realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); - var array = obj.arrayCol; var removed; + array = obj.arrayCol; + removed = array.splice(0, 0, obj.objectCol, obj.objectCol1); TestCase.assertEqual(removed.length, 0); TestCase.assertEqual(array.length, 4); @@ -248,5 +254,9 @@ var ArrayTests = { array.splice(0, 0, 0); }); }); + + TestCase.assertThrows(function() { + obj.arrayCol.splice(0, 0, obj.objectCol); + }, 'can only splice in a write transaction'); }, };