Fix remaining issues in Array.prototype.(un)shift
authorLars Knoll <lars.knoll@digia.com>
Tue, 22 Jan 2013 09:24:58 +0000 (10:24 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 22 Jan 2013 10:45:04 +0000 (11:45 +0100)
Change-Id: I872abc79656511806955337a15d0fc04b8b286f8
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qv4array.cpp
qv4arrayobject.cpp
tests/TestExpectations

index 15150cc..049402c 100644 (file)
@@ -609,7 +609,7 @@ bool Array::setLength(uint newLen) {
                 it = prev;
             }
         } else {
-            PropertyDescriptor *it = values.data() + offset + values.size();
+            PropertyDescriptor *it = values.data() + values.size();
             const PropertyDescriptor *begin = values.constData() + offset + newLen;
             while (--it >= begin) {
                 if (it->type != PropertyDescriptor::Generic && !it->isConfigurable()) {
@@ -618,7 +618,7 @@ bool Array::setLength(uint newLen) {
                     break;
                 }
             }
-            values.resize(newLen);
+            values.resize(newLen + offset);
         }
     } else {
         if (newLen >= 0x100000)
index 3cad1f7..f7c2069 100644 (file)
@@ -272,13 +272,41 @@ Value ArrayPrototype::method_reverse(ExecutionContext *ctx)
 
 Value ArrayPrototype::method_shift(ExecutionContext *ctx)
 {
-    ArrayObject *instance = ctx->thisObject.asArrayObject();
-    if (!instance)
-        ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift"));
+    Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
+    uint len = getLength(ctx, instance);
+
+    if (!len) {
+        if (!instance->isArray)
+            instance->__put__(ctx, ctx->engine->id_length, Value::fromInt32(0));
+        return Value::undefinedValue();
+    }
+
+    Value result = instance->getValueChecked(ctx, instance->array.front());
 
-    Value v = instance->getValueChecked(ctx, instance->array.front());
-    instance->array.pop_front();
-    return v;
+    bool protoHasArray = false;
+    Object *p = instance;
+    while ((p = p->prototype))
+        if (p->array.length())
+            protoHasArray = true;
+
+    if (!protoHasArray && len >= instance->array.length()) {
+        instance->array.pop_front();
+    } else {
+        // do it the slow way
+        for (uint k = 1; k < len; ++k) {
+            bool exists;
+            Value v = instance->__get__(ctx, k, &exists);
+            if (exists)
+                instance->__put__(ctx, k - 1, v);
+            else
+                instance->__delete__(ctx, k - 1);
+        }
+        instance->__delete__(ctx, len - 1);
+    }
+
+    if (!instance->isArray)
+        instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - 1));
+    return result;
 }
 
 Value ArrayPrototype::method_slice(ExecutionContext *ctx)
@@ -393,19 +421,39 @@ Value ArrayPrototype::method_splice(ExecutionContext *ctx)
 
 Value ArrayPrototype::method_unshift(ExecutionContext *ctx)
 {
-    ArrayObject *instance = ctx->thisObject.asArrayObject();
-    if (!instance)
-        ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift"));
+    Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
+    uint len = getLength(ctx, instance);
+
+    bool protoHasArray = false;
+    Object *p = instance;
+    while ((p = p->prototype))
+        if (p->array.length())
+            protoHasArray = true;
 
-    for (int i = ctx->argumentCount - 1; i >= 0; --i) {
-        Value v = ctx->argument(i);
-        instance->array.push_front(v);
+    if (!protoHasArray && len >= instance->array.length()) {
+        for (int i = ctx->argumentCount - 1; i >= 0; --i) {
+            Value v = ctx->argument(i);
+            instance->array.push_front(v);
+        }
+    } else {
+        for (uint k = len; k > 0; --k) {
+            bool exists;
+            Value v = instance->__get__(ctx, k - 1, &exists);
+            if (exists)
+                instance->__put__(ctx, k + ctx->argumentCount - 1, v);
+            else
+                instance->__delete__(ctx, k + ctx->argumentCount - 1);
+        }
+        for (uint i = 0; i < ctx->argumentCount; ++i)
+            instance->__put__(ctx, i, ctx->argument(i));
     }
+    uint newLen = len + ctx->argumentCount;
+    if (!instance->isArray)
+        instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(newLen));
 
-    uint l = instance->array.length();
-    if (l < INT_MAX)
-        return Value::fromInt32(l);
-    return Value::fromDouble((double)l);
+    if (newLen < INT_MAX)
+        return Value::fromInt32(newLen);
+    return Value::fromDouble((double)newLen);
 }
 
 Value ArrayPrototype::method_indexOf(ExecutionContext *ctx)
index b7d8d00..70c1529 100644 (file)
@@ -533,14 +533,6 @@ S15.1.3.2_A5.3 failing
 15.2.3.7-6-a-286 failing
 15.2.3.7-6-a-288 failing
 15.2.3.7-6-a-289 failing
-S15.4.4.13_A2_T1 failing
-S15.4.4.13_A2_T2 failing
-S15.4.4.13_A2_T3 failing
-S15.4.4.13_A3_T1 failing
-S15.4.4.13_A3_T2 failing
-S15.4.4.13_A3_T3 failing
-S15.4.4.13_A4_T1 failing
-S15.4.4.13_A4_T2 failing
 15.4.4.14-9-a-10 failing
 15.4.4.14-9-a-17 failing
 15.4.4.14-9-a-7 failing
@@ -582,17 +574,6 @@ S15.4.4.8_A3_T2 failing
 S15.4.4.8_A3_T3 failing
 S15.4.4.8_A4_T1 failing
 S15.4.4.8_A4_T2 failing
-S15.4.4.9_A1.2_T1 failing
-S15.4.4.9_A2_T1 failing
-S15.4.4.9_A2_T2 failing
-S15.4.4.9_A2_T3 failing
-S15.4.4.9_A2_T4 failing
-S15.4.4.9_A2_T5 failing
-S15.4.4.9_A3_T1 failing
-S15.4.4.9_A3_T2 failing
-S15.4.4.9_A3_T3 failing
-S15.4.4.9_A4_T1 failing
-S15.4.4.9_A4_T2 failing
 S15.5.4.13_A2_T2 failing
 S15.5.4.13_A3_T3 failing
 S15.5.4.14_A1_T1 failing