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) {
|
||||
try {
|
||||
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
|
||||
RJSValidateArgumentCount(argumentCount, 1);
|
||||
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[0]), array->object_schema.name, false));
|
||||
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
|
||||
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) {
|
||||
if (jsException) {
|
||||
|
@ -101,6 +190,10 @@ JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
|
|||
JSClassRef RJSArrayClass() {
|
||||
const JSStaticFunction arrayFuncs[] = {
|
||||
{"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},
|
||||
};
|
||||
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) {
|
||||
if (argumentCount < min || argumentCount > max) {
|
||||
throw std::invalid_argument("Invalid arguments");
|
||||
|
|
|
@ -113,18 +113,48 @@ var ArrayTests = {
|
|||
TestCase.assertEqual(obj.arrayCol.length, 1);
|
||||
|
||||
array = obj.arrayCol;
|
||||
array.push([4]);
|
||||
TestCase.assertEqual(array.push([4]), 2);
|
||||
TestCase.assertEqual(array.length, 2);
|
||||
TestCase.assertEqual(array[1].doubleCol, 4);
|
||||
|
||||
array.push(obj.objectCol);
|
||||
TestCase.assertEqual(array.length, 3);
|
||||
TestCase.assertEqual(array.push(obj.objectCol, obj.objectCol1), 4);
|
||||
TestCase.assertEqual(array.length, 4);
|
||||
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() {
|
||||
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