array mutation functions
This commit is contained in:
parent
36703bebcb
commit
bd39239f00
|
@ -83,8 +83,97 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu
|
||||||
JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||||
RJSValidateArgumentCount(argumentCount, 1);
|
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
|
||||||
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[0]), array->object_schema.name, false));
|
for (size_t i = 0; i < argumentCount; i++) {
|
||||||
|
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[i]), array->object_schema.name, false));
|
||||||
|
}
|
||||||
|
return JSValueMakeNumber(ctx, array->link_view->size());
|
||||||
|
}
|
||||||
|
catch (std::exception &exp) {
|
||||||
|
if (jsException) {
|
||||||
|
*jsException = RJSMakeError(ctx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
|
try {
|
||||||
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||||
|
RJSValidateArgumentCount(argumentCount, 0);
|
||||||
|
if (array->link_view->size() == 0) {
|
||||||
|
return JSValueMakeUndefined(ctx);
|
||||||
|
}
|
||||||
|
size_t index = array->link_view->size()-1;
|
||||||
|
JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(array->link_view->size()-1)));
|
||||||
|
array->link_view->remove(index);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
catch (std::exception &exp) {
|
||||||
|
if (jsException) {
|
||||||
|
*jsException = RJSMakeError(ctx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
|
try {
|
||||||
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(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<JSValueRef &>(arguments[i]), array->object_schema.name, false));
|
||||||
|
}
|
||||||
|
return JSValueMakeNumber(ctx, array->link_view->size());
|
||||||
|
}
|
||||||
|
catch (std::exception &exp) {
|
||||||
|
if (jsException) {
|
||||||
|
*jsException = RJSMakeError(ctx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
|
try {
|
||||||
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||||
|
RJSValidateArgumentCount(argumentCount, 0);
|
||||||
|
if (array->link_view->size() == 0) {
|
||||||
|
return JSValueMakeUndefined(ctx);
|
||||||
|
}
|
||||||
|
JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(0)));
|
||||||
|
array->link_view->remove(0);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
catch (std::exception &exp) {
|
||||||
|
if (jsException) {
|
||||||
|
*jsException = RJSMakeError(ctx, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
|
||||||
|
try {
|
||||||
|
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||||
|
RJSValidateArgumentCountIsAtLeast(argumentCount, 2);
|
||||||
|
long index = RJSValidatedValueToNumber(ctx, arguments[0]);
|
||||||
|
if (index < 0) {
|
||||||
|
index = array->link_view->size() - index;
|
||||||
|
}
|
||||||
|
|
||||||
|
long remove = RJSValidatedValueToNumber(ctx, arguments[1]);
|
||||||
|
if (index + remove >= array->link_view->size()) {
|
||||||
|
throw std::runtime_error("Attempting to slice elements beyond Array bounds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (remove-- > 0) {
|
||||||
|
array->link_view->remove(index);
|
||||||
|
}
|
||||||
|
for (size_t i = 2; i < argumentCount; i++) {
|
||||||
|
array->link_view->insert(index + i - 2, RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[i]), array->object_schema.name, false));
|
||||||
|
}
|
||||||
|
return JSValueMakeNumber(ctx, array->link_view->size());
|
||||||
}
|
}
|
||||||
catch (std::exception &exp) {
|
catch (std::exception &exp) {
|
||||||
if (jsException) {
|
if (jsException) {
|
||||||
|
@ -101,6 +190,10 @@ JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
|
||||||
JSClassRef RJSArrayClass() {
|
JSClassRef RJSArrayClass() {
|
||||||
const JSStaticFunction arrayFuncs[] = {
|
const JSStaticFunction arrayFuncs[] = {
|
||||||
{"push", ArrayPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
{"push", ArrayPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||||
|
{"pop", ArrayPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||||
|
{"shift", ArrayShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||||
|
{"unshift", ArrayUnshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||||
|
{"splice", ArraySplice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
static JSClassRef s_arrayClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames);
|
static JSClassRef s_arrayClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames);
|
||||||
|
|
|
@ -66,6 +66,12 @@ inline void RJSValidateArgumentCount(size_t argumentCount, size_t expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void RJSValidateArgumentCountIsAtLeast(size_t argumentCount, size_t expected) {
|
||||||
|
if (argumentCount < expected) {
|
||||||
|
throw std::invalid_argument("Invalid arguments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void RJSValidateArgumentRange(size_t argumentCount, size_t min, size_t max) {
|
inline void RJSValidateArgumentRange(size_t argumentCount, size_t min, size_t max) {
|
||||||
if (argumentCount < min || argumentCount > max) {
|
if (argumentCount < min || argumentCount > max) {
|
||||||
throw std::invalid_argument("Invalid arguments");
|
throw std::invalid_argument("Invalid arguments");
|
||||||
|
|
|
@ -113,18 +113,48 @@ var ArrayTests = {
|
||||||
TestCase.assertEqual(obj.arrayCol.length, 1);
|
TestCase.assertEqual(obj.arrayCol.length, 1);
|
||||||
|
|
||||||
array = obj.arrayCol;
|
array = obj.arrayCol;
|
||||||
array.push([4]);
|
TestCase.assertEqual(array.push([4]), 2);
|
||||||
TestCase.assertEqual(array.length, 2);
|
TestCase.assertEqual(array.length, 2);
|
||||||
TestCase.assertEqual(array[1].doubleCol, 4);
|
TestCase.assertEqual(array[1].doubleCol, 4);
|
||||||
|
|
||||||
array.push(obj.objectCol);
|
TestCase.assertEqual(array.push(obj.objectCol, obj.objectCol1), 4);
|
||||||
TestCase.assertEqual(array.length, 3);
|
TestCase.assertEqual(array.length, 4);
|
||||||
TestCase.assertEqual(array[2].doubleCol, 1);
|
TestCase.assertEqual(array[2].doubleCol, 1);
|
||||||
|
TestCase.assertEqual(array[3].doubleCol, 2);
|
||||||
|
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
array.push();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
TestCase.assertEqual(array.length, 3);
|
TestCase.assertEqual(array.length, 4);
|
||||||
TestCase.assertThrows(function() {
|
TestCase.assertThrows(function() {
|
||||||
array.push([1]);
|
array.push([1]);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
array = obj.arrayCol;
|
||||||
|
TestCase.assertEqual(array.unshift([5]), 2);
|
||||||
|
TestCase.assertEqual(array.length, 2);
|
||||||
|
TestCase.assertEqual(array[0].doubleCol, 5);
|
||||||
|
|
||||||
|
TestCase.assertEqual(array.unshift(obj.objectCol, obj.objectCol1), 4);
|
||||||
|
TestCase.assertEqual(array.length, 4);
|
||||||
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
||||||
|
TestCase.assertEqual(array[1].doubleCol, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertEqual(array.length, 4);
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
array.unshift([1]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue