Improve the Array prototype
authorRoberto Raggi <roberto.raggi@nokia.com>
Mon, 21 May 2012 11:21:35 +0000 (13:21 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Mon, 21 May 2012 11:21:35 +0000 (13:21 +0200)
qv4array_p.h
qv4ecmaobjects.cpp

index a80c8a6..d820ce5 100644 (file)
@@ -26,6 +26,7 @@ public:
     inline void resize(uint size);
     inline void concat(const Array &other);
     inline Value pop();
+    inline Value takeFirst();
     inline void sort(Context *context, const Value &comparefn);
     inline void splice(double start, double deleteCount,
                        const QVector<Value> &items,
@@ -138,9 +139,9 @@ inline Value Array::at(uint index) const
     if (m_mode == VectorMode) {
         if (index < uint(to_vector->size()))
             return to_vector->at(index);
-        return Value();
+        return Value::undefinedValue();
     } else {
-        return to_map->value(index, Value());
+        return to_map->value(index, Value::undefinedValue());
     }
 }
 
@@ -188,7 +189,9 @@ inline void Array::resize(uint s)
 
     if (m_mode == VectorMode) {
         if (s < N) {
-            to_vector->resize (s); // ### init
+            to_vector->resize(s);
+            for (uint i = oldSize; i < s; ++i)
+                assign(i, Value::undefinedValue());
         } else {
             // switch to MapMode
             QMap<uint, Value> *m = new QMap<uint, Value>();
@@ -196,7 +199,7 @@ inline void Array::resize(uint s)
                 if (! to_vector->at(i).isUndefined())
                     m->insert(i, to_vector->at(i));
             }
-            m->insert(s, Value());
+            m->insert(s, Value::undefinedValue());
             delete to_vector;
             to_map = m;
             m_mode = MapMode;
@@ -227,7 +230,7 @@ inline void Array::resize(uint s)
                         to_map->erase(it);
                 }
             }
-            to_map->insert(s, Value());
+            to_map->insert(s, Value::undefinedValue());
         }
     }
 }
@@ -246,7 +249,7 @@ inline void Array::concat(const Array &other)
 inline Value Array::pop()
 {
     if (isEmpty())
-        return Value();
+        return Value::undefinedValue();
 
     Value v;
 
@@ -260,6 +263,22 @@ inline Value Array::pop()
     return v;
 }
 
+inline Value Array::takeFirst()
+{
+    if (isEmpty())
+        return Value::undefinedValue();
+
+    Value v;
+    if (m_mode == VectorMode) {
+        v = to_vector->first();
+        to_vector->remove(0, 1);
+    } else {
+        v = *to_map->begin();
+        to_map->erase(to_map->begin());
+    }
+    return v;
+}
+
 inline void Array::sort(Context *context, const Value &comparefn)
 {
     ArrayElementLessThan lessThan(context, comparefn);
@@ -296,7 +315,7 @@ inline void Array::splice(double start, double deleteCount,
         for (uint i = 0; i < dc; ++i)
             other.assign(i, to_vector->at(st + i));
         if (itemsSize > dc)
-            to_vector->insert(st, itemsSize - dc, Value());
+            to_vector->insert(st, itemsSize - dc, Value::undefinedValue());
         else if (itemsSize < dc)
             to_vector->remove(st, dc - itemsSize);
         for (uint i = 0; i < itemsSize; ++i)
index 3b4890c..cb06b46 100644 (file)
@@ -1094,12 +1094,31 @@ ArrayCtor::ArrayCtor(Context *scope)
 
 void ArrayCtor::construct(Context *ctx)
 {
-    ctx->thisObject = Value::fromObject(ctx->engine->newArrayObject());
+    call(ctx);
+    ctx->thisObject = ctx->result;
 }
 
 void ArrayCtor::call(Context *ctx)
 {
-    ctx->result = Value::fromObject(ctx->engine->newArrayObject());
+    Array value;
+    if (ctx->argumentCount == 1 && ctx->argument(0).isNumber()) {
+        double size = ctx->argument(0).numberValue;
+        quint32 isize = Value::toUInt32(size);
+
+        if (size != double(isize)) {
+            assert(!"invlaid array length exception");
+            return;
+        }
+
+        qDebug() << "size:" << isize;
+        value.resize(isize);
+    } else {
+        for (size_t i = 0; i < ctx->argumentCount; ++i) {
+            value.assign(i, ctx->argument(i));
+        }
+    }
+
+    ctx->result = Value::fromObject(ctx->engine->newArrayObject(value));
 }
 
 ArrayPrototype::ArrayPrototype(Context *ctx, FunctionObject *ctor)
@@ -1184,7 +1203,7 @@ void ArrayPrototype::method_join(Context *ctx)
 
     if (ArrayObject *a = self.objectValue->asArrayObject()) {
         for (uint i = 0; i < a->value.size(); ++i) {
-            if (! R.isEmpty())
+            if (i)
                 R += r4;
 
             Value e = a->value.at(i);
@@ -1239,30 +1258,89 @@ void ArrayPrototype::method_pop(Context *ctx)
 
 void ArrayPrototype::method_push(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+        uint pos = instance->value.size();
+        for (size_t i = 0; i < ctx->argumentCount; ++i) {
+            Value val = ctx->argument(i);
+            instance->value.assign(pos++, val);
+        }
+        ctx->result = Value::fromNumber(pos);
+    } else {
+        String *id_length = ctx->engine->identifier(QLatin1String("length"));
+        Value *r1 = self.objectValue->getProperty(id_length);
+        quint32 n = r1 ? r1->toUInt32(ctx) : 0;
+        for (int index = 0; index < ctx->argumentCount; ++index, ++n) {
+            Value r3 = ctx->argument(index);
+            String *name = Value::fromNumber(n).toString(ctx);
+            self.objectValue->put(name, r3);
+        }
+        Value r = Value::fromNumber(n);
+        self.objectValue->put(id_length, r);
+        ctx->result = r;
+    }
 }
 
 void ArrayPrototype::method_reverse(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+        int lo = 0, hi = instance->value.count() - 1;
+
+        for (; lo < hi; ++lo, --hi) {
+            Value tmp = instance->value.at(lo);
+            instance->value.assign(lo, instance->value.at(hi));
+            instance->value.assign(hi, tmp);
+        }
+    } else {
+        assert(!"generic implementation of Array.prototype.reverse");
+    }
 }
 
 void ArrayPrototype::method_shift(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+        ctx->result = instance->value.takeFirst();
+    } else {
+        assert(!"generic implementation of Array.prototype.reverse");
+    }
 }
 
 void ArrayPrototype::method_slice(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+    } else {
+        assert(!"generic implementation of Array.prototype.slice");
+    }
 }
 
 void ArrayPrototype::method_sort(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+    } else {
+        assert(!"generic implementation of Array.prototype.sort");
+    }
 }
 
 void ArrayPrototype::method_splice(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+    } else {
+        assert(!"generic implementation of Array.prototype.splice");
+    }
 }
 
 void ArrayPrototype::method_unshift(Context *ctx)
 {
+    Value self = ctx->thisObject;
+    if (ArrayObject *instance = self.asArrayObject()) {
+    } else {
+        assert(!"generic implementation of Array.prototype.unshift");
+    }
 }
 
 //