From ae9ae4dc77dcd0729cfcf44f263a08378ea5267a Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 12 Oct 2015 02:55:37 -0700 Subject: [PATCH] Add list item setters in JS Added a test and made other array tests syntactically consistent. Resolves #45 --- src/RJSArray.cpp | 31 ++++++++++++++++++++- tests/ArrayTests.js | 66 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 3f7cb3f7..9a10c3c0 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -82,6 +82,35 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr } } +bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { + try { + ObjectArray *array = RJSVerifiedMutableArray(object); + size_t size = array->size(); + std::string indexStr = RJSStringForJSString(propertyName); + if (indexStr == "length") { + throw std::runtime_error("The 'length' property is readonly."); + } + + size_t index = std::stol(indexStr); + if (index >= size) { + throw std::out_of_range("Cannot set list item beyond its bounds."); + } + + array->link_view->set(index, RJSAccessor::to_object_index(ctx, array->realm, const_cast(value), array->object_schema.name, false)); + return true; + } + catch (std::invalid_argument &exp) { + // for stol failure this could be another property that is handled externally, so ignore + return false; + } + catch (std::exception &exp) { + if (jsException) { + *jsException = RJSMakeError(ctx, exp); + } + return false; + } +} + void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) { ObjectArray *array = RJSVerifiedArray(object); size_t size = array->size(); @@ -216,6 +245,6 @@ const JSStaticFunction RJSArrayFuncs[] = { }; JSClassRef RJSArrayClass() { - static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, NULL, RJSArrayFuncs, NULL, ArrayPropertyNames); + static JSClassRef s_arrayClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, ArraySetProperty, RJSArrayFuncs, NULL, ArrayPropertyNames); return s_arrayClass; } diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 4d3f0b5f..7a4c4f7f 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -30,35 +30,74 @@ var ArrayTests = { obj.arrayCol = [[1], [2]]; TestCase.assertEqual(obj.arrayCol.length, 2); - }); + }); }, - testArraySubscript: function() { + testArraySubscriptGetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); }); + var array; + + realm.write(function() { + var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = obj.arrayCol; + }); - var array = realm.objects('LinkTypesObject')[0].arrayCol; TestCase.assertEqual(array[0].doubleCol, 3); TestCase.assertEqual(array[1].doubleCol, 4); TestCase.assertThrows(function() { array[2]; }, 'Invalid index'); TestCase.assertThrows(function() { array[-1]; }, 'Invalid index'); }, - testArrayInvalidProperty: function() { + testArraySubscriptSetters: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); }); + var array; + + realm.write(function() { + var obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]]]); + array = obj.arrayCol; + + array[0] = [5]; + array[1] = [6]; + + TestCase.assertEqual(array[0].doubleCol, 5); + TestCase.assertEqual(array[1].doubleCol, 6); + + TestCase.assertThrows(function() { + array.length = 0; + }, 'cannot set length property on lists'); + + TestCase.assertThrows(function() { + array[2] = [1]; + }, 'cannot set list item beyond its bounds'); + }); + + TestCase.assertThrows(function() { + array[0] = [3]; + }, 'cannot set list item outside write transaction'); + }, + + testArrayInvalidProperty: 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; + }); - var array = realm.objects('LinkTypesObject')[0].arrayCol; TestCase.assertEqual(undefined, array.ablasdf); }, testArrayEnumerate: function() { var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); - realm.write(function() { realm.create('LinkTypesObject', [[1], [2], []]); }); + var obj; - var obj = realm.objects('LinkTypesObject')[0]; - for (var object in obj.arrayCol) { - TestCase.assertTrue(false, "No objects should have been enumerated: " + object); + realm.write(function() { + obj = realm.create('LinkTypesObject', [[1], [2], []]); + }); + + for (var index in obj.arrayCol) { + TestCase.assertTrue(false, "No objects should have been enumerated: " + index); } realm.write(function() { @@ -67,10 +106,9 @@ var ArrayTests = { }); var count = 0; - for (var object in obj.arrayCol) { + for (var index in obj.arrayCol) { count++; - //TestCase.assertTrue(object instanceof Object); - } + } TestCase.assertEqual(2, count); },