Fix remaining test failures in Array.prototype.push/pop
authorLars Knoll <lars.knoll@digia.com>
Tue, 22 Jan 2013 09:57:38 +0000 (10:57 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 22 Jan 2013 10:46:08 +0000 (11:46 +0100)
Change-Id: If645e8d4628f252ffc3e96037cdc3749d6cf2ddd
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qv4arrayobject.cpp
tests/TestExpectations

index f7c2069..8d3757b 100644 (file)
@@ -209,48 +209,68 @@ Value ArrayPrototype::method_join(ExecutionContext *ctx)
 
 Value ArrayPrototype::method_pop(ExecutionContext *ctx)
 {
-    Value self = ctx->thisObject;
-    if (ArrayObject *instance = self.asArrayObject()) {
-        Value v = instance->getValueChecked(ctx, instance->array.back());
-        instance->array.pop_back();
-        return v;
-    }
+    Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
+    uint len = getLength(ctx, instance);
 
-    Value r1 = self.property(ctx, ctx->engine->id_length);
-    quint32 r2 = !r1.isUndefined() ? r1.toUInt32(ctx) : 0;
-    if (r2) {
-        String *r6 = Value::fromDouble(r2 - 1).toString(ctx);
-        Value r7 = self.property(ctx, r6);
-        self.objectValue()->__delete__(ctx, r6);
-        self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(2 - 1));
-        return r7;
+    if (!len) {
+        if (!instance->isArray)
+            instance->__put__(ctx, ctx->engine->id_length, Value::fromInt32(0));
+        return Value::undefinedValue();
     }
 
-    self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(0));
-    return Value::undefinedValue();
+    Value result = instance->__get__(ctx, len - 1);
+
+    instance->__delete__(ctx, len - 1);
+    if (instance->isArray)
+        instance->array.setLengthUnchecked(len - 1);
+    else
+        instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - 1));
+    return result;
 }
 
 Value ArrayPrototype::method_push(ExecutionContext *ctx)
 {
-    Value self = ctx->thisObject;
-    if (ArrayObject *instance = self.asArrayObject()) {
-        for (unsigned int i = 0; i < ctx->argumentCount; ++i) {
-            Value val = ctx->argument(i);
-            instance->array.push_back(val);
+    Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue();
+    uint len = getLength(ctx, instance);
+
+    if (len + ctx->argumentCount < len) {
+        // ughh...
+        double l = len;
+        for (double i = 0; i < ctx->argumentCount; ++i) {
+            Value idx = Value::fromDouble(l + i);
+            instance->__put__(ctx, idx.toString(ctx), ctx->argument(i));
         }
-        return Value::fromDouble(instance->array.length());
+        double newLen = l + ctx->argumentCount;
+        if (!instance->isArray)
+            instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(newLen));
+        else
+            ctx->throwRangeError(Value::fromString(ctx, QStringLiteral("Array.prototype.push: Overflow")));
+        return Value::fromDouble(newLen);
     }
 
-    Value r1 = self.property(ctx, ctx->engine->id_length);
-    quint32 n = !r1.isUndefined() ? r1.toUInt32(ctx) : 0;
-    for (unsigned int index = 0; index < ctx->argumentCount; ++index, ++n) {
-        Value r3 = ctx->argument(index);
-        String *name = Value::fromDouble(n).toString(ctx);
-        self.objectValue()->__put__(ctx, name, r3);
+    bool protoHasArray = false;
+    Object *p = instance;
+    while ((p = p->prototype))
+        if (p->array.length())
+            protoHasArray = true;
+
+    if (!protoHasArray && len == instance->array.length()) {
+        for (uint i = 0; i < ctx->argumentCount; ++i) {
+            Value v = ctx->argument(i);
+            instance->array.push_back(v);
+        }
+    } else {
+        for (uint i = 0; i < ctx->argumentCount; ++i)
+            instance->__put__(ctx, len + i, ctx->argument(i));
     }
-    Value r = Value::fromDouble(n);
-    self.objectValue()->__put__(ctx, ctx->engine->id_length, r);
-    return r;
+    uint newLen = len + ctx->argumentCount;
+    if (!instance->isArray)
+        instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(newLen));
+
+    if (newLen < INT_MAX)
+        return Value::fromInt32(newLen);
+    return Value::fromDouble((double)newLen);
+
 }
 
 Value ArrayPrototype::method_reverse(ExecutionContext *ctx)
index 70c1529..4694aa2 100644 (file)
@@ -555,14 +555,6 @@ S15.4.4.3_A3_T1 failing
 S15.4.4.4_A2_T1 failing
 S15.4.4.4_A2_T2 failing
 S15.4.4.4_A3_T1 failing
-S15.4.4.6_A1.2_T1 failing
-S15.4.4.6_A3_T2 failing
-S15.4.4.6_A3_T3 failing
-S15.4.4.6_A4_T1 failing
-S15.4.4.6_A4_T2 failing
-S15.4.4.7_A3 failing
-S15.4.4.7_A4_T2 failing
-S15.4.4.7_A4_T3 failing
 S15.5.4.11_A5_T1 failing
 S15.4.4.8_A1_T1 failing
 S15.4.4.8_A1_T2 failing