Implement Array.prototype.splice
authorLars Knoll <lars.knoll@digia.com>
Wed, 16 Jan 2013 16:56:29 +0000 (17:56 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 17 Jan 2013 14:43:26 +0000 (15:43 +0100)
Change-Id: I678e2836b677066b42a05f5b7b5b30eca7e8120c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qv4array.cpp
qv4array.h
qv4ecmaobjects.cpp
tests/TestExpectations

index c9942b0..fae357b 100644 (file)
@@ -473,35 +473,6 @@ Array::Array(const Array &other)
 }
 
 
-void Array::splice(double start, double deleteCount,
-                   const QVector<Value> &/*items*/,
-                   Array &/*other*/)
-{
-    initSparse();
-    uint len = length();
-    if (start < 0)
-        start = qMax(len + start, double(0));
-    else if (start > len)
-        start = len;
-    deleteCount = qMax(qMin(deleteCount, len - start), double(0));
-
-    // ###
-//    const uint st = uint(start);
-//    const uint dc = uint(deleteCount);
-//    other.resize(dc);
-
-//    const uint itemsSize = uint(items.size());
-
-//    for (uint i = 0; i < dc; ++i)
-//        other.assign(i, to_vector.at(st + i));
-//    if (itemsSize > dc)
-//        to_vector.insert(to_vector.begin() + st, itemsSize - dc, Value::undefinedValue());
-//    else if (itemsSize < dc)
-//        to_vector.erase(to_vector.begin() + st, to_vector.begin() + (dc - itemsSize));
-//    for (uint i = 0; i < itemsSize; ++i)
-    //        (*to_vector)[st + i] = items.at(i);
-}
-
 Value Array::indexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
 {
     bool protoHasArray = false;
index 28601ba..a7fc6b7 100644 (file)
@@ -361,6 +361,8 @@ inline SparseArrayNode *SparseArray::upperBound(uint akey)
 
 class Array
 {
+    friend class ArrayPrototype;
+
     uint len;
     PropertyDescriptor *lengthProperty;
     union {
@@ -609,7 +611,6 @@ public:
 
     void concat(const Array &other);
     void sort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint len);
-    void splice(double start, double deleteCount, const QVector<Value> &, Array &);
     Value indexOf(Value v, uint fromIndex, uint len, ExecutionContext *ctx, Object *o);
 };
 
index d898783..b0e7bc3 100644 (file)
@@ -1841,24 +1841,65 @@ Value ArrayPrototype::method_sort(ExecutionContext *ctx)
 
 Value ArrayPrototype::method_splice(ExecutionContext *ctx)
 {
-    if (ctx->argumentCount < 2)
-        // ### check
-        return Value::undefinedValue();
+    Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
+    uint len = getLength(ctx, instance);
 
-    ArrayObject *instance = ctx->thisObject.asArrayObject();
-    if (!instance)
-        ctx->throwUnimplemented(QStringLiteral("Array.prototype.splice"));
-
-    double start = ctx->argument(0).toInteger(ctx);
-    double deleteCount = ctx->argument(1).toInteger(ctx);
-    Value a = Value::fromObject(ctx->engine->newArrayObject(ctx));
-    QVector<Value> items;
-    for (unsigned int i = 2; i < ctx->argumentCount; ++i)
-        items << ctx->argument(i);
-    ArrayObject *otherInstance = a.asArrayObject();
-    assert(otherInstance);
-    instance->array.splice(start, deleteCount, items, otherInstance->array);
-    return a;
+    ArrayObject *newArray = ctx->engine->newArrayObject(ctx);
+
+    double rs = ctx->argument(0).toInteger(ctx);
+    uint start;
+    if (rs < 0)
+        start = (uint) qMax(0., len + rs);
+    else
+        start = (uint) qMin(rs, (double)len);
+
+    uint deleteCount = (uint)qMin(qMax(ctx->argument(1).toInteger(ctx), 0.), (double)(len - start));
+
+    newArray->array.values.resize(deleteCount);
+    PropertyDescriptor *pd = newArray->array.values.data();
+    for (uint i = 0; i < deleteCount; ++i) {
+        pd->type = PropertyDescriptor::Data;
+        pd->writable = PropertyDescriptor::Enabled;
+        pd->enumberable = PropertyDescriptor::Enabled;
+        pd->configurable = PropertyDescriptor::Enabled;
+        pd->value = instance->__get__(ctx, start + i);
+        ++pd;
+    }
+    newArray->array.setLengthUnchecked(deleteCount);
+
+    uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2;
+
+    if (itemCount < deleteCount) {
+        for (uint k = start; k < len - deleteCount; ++k) {
+            bool exists;
+            Value v = instance->__get__(ctx, k + deleteCount, &exists);
+            if (exists)
+                instance->array.set(k + itemCount, v);
+            else
+                instance->__delete__(ctx, k + itemCount);
+        }
+        for (uint k = len; k > len - deleteCount + itemCount; --k)
+            instance->__delete__(ctx, k - 1);
+    } else if (itemCount > deleteCount) {
+        uint k = len - deleteCount;
+        while (k > start) {
+            bool exists;
+            Value v = instance->__get__(ctx, k + deleteCount - 1, &exists);
+            if (exists)
+                instance->array.set(k + itemCount - 1, v);
+            else
+                instance->__delete__(ctx, k + itemCount - 1);
+            --k;
+        }
+    }
+
+    for (uint i = 0; i < itemCount; ++i)
+        instance->array.set(start + i, ctx->argument(i + 2));
+
+    ctx->strictMode = true;
+    instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - deleteCount + itemCount));
+
+    return Value::fromObject(newArray);
 }
 
 Value ArrayPrototype::method_unshift(ExecutionContext *ctx)
index e00b0bb..a3d65d6 100644 (file)
@@ -691,23 +691,6 @@ S15.1.3.2_A5.3 failing
 15.2.3.7-6-a-289 failing
 15.3.4.5-2-7 failing
 15.4.3.2-1-11 failing
-15.4.4.12-9-c-ii-1 failing
-S15.4.4.12_A1.1_T4 failing
-S15.4.4.12_A1.1_T6 failing
-S15.4.4.12_A1.4_T4 failing
-S15.4.4.12_A1.4_T6 failing
-S15.4.4.12_A2.1_T1 failing
-S15.4.4.12_A2.2_T1 failing
-S15.4.4.12_A2_T1 failing
-S15.4.4.12_A2_T2 failing
-S15.4.4.12_A2_T3 failing
-S15.4.4.12_A2_T4 failing
-S15.4.4.12_A3_T1 failing
-S15.4.4.12_A3_T2 failing
-S15.4.4.12_A3_T3 failing
-S15.4.4.12_A4_T1 failing
-S15.4.4.12_A4_T2 failing
-S15.4.4.12_A4_T3 failing
 S15.4.4.13_A2_T1 failing
 S15.4.4.13_A2_T2 failing
 S15.4.4.13_A2_T3 failing
@@ -2584,26 +2567,6 @@ S15.2.4.4_A14 failing
 S15.2.4.4_A15 failing
 
 # Array regressions
-15.4.4.12-9-a-1 failing
-S15.4.4.12_A1.1_T1 failing
-S15.4.4.12_A1.1_T2 failing
-S15.4.4.12_A1.1_T3 failing
-S15.4.4.12_A1.1_T5 failing
-S15.4.4.12_A1.2_T3 failing
-S15.4.4.12_A1.2_T4 failing
-S15.4.4.12_A1.2_T5 failing
-S15.4.4.12_A1.3_T3 failing
-S15.4.4.12_A1.3_T4 failing
-S15.4.4.12_A1.3_T5 failing
-S15.4.4.12_A1.4_T1 failing
-S15.4.4.12_A1.4_T2 failing
-S15.4.4.12_A1.4_T3 failing
-S15.4.4.12_A1.4_T5 failing
-S15.4.4.12_A2.1_T2 failing
-S15.4.4.12_A2.1_T4 failing
-S15.4.4.12_A2.1_T5 failing
-S15.4.4.12_A2.2_T3 failing
-S15.4.4.12_A2.2_T5 failing
 S15.4.4.4_A1_T2 failing
 
 # Regressions due to Object/property refactoring
@@ -2639,4 +2602,4 @@ S15.4.4.13_A1_T2 failing
 # Bugs in Array.prototype
 15.4.4.14-9-b-i-5 failing
 15.4.4.16-7-c-i-6 failing
-15.4.4.17-7-c-i-6 failing
\ No newline at end of file
+15.4.4.17-7-c-i-6 failing