Correctly iterator over properties of StringObjects
authorLars Knoll <lars.knoll@digia.com>
Mon, 14 Jan 2013 14:54:07 +0000 (15:54 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 14 Jan 2013 15:58:31 +0000 (16:58 +0100)
Change-Id: I16a8065dd0bb9162811ced1bc6c73c07c02a331d
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qmljs_objects.h
qv4ecmaobjects.cpp
qv4objectiterator.cpp
qv4objectiterator.h

index 5d3b9ca..5837da9 100644 (file)
@@ -171,13 +171,12 @@ protected:
 };
 
 struct ForEachIteratorObject: Object {
-    ExecutionContext *context;
     ObjectIterator it;
     ForEachIteratorObject(ExecutionContext *ctx, Object *o)
-        : context(ctx), it(o, ObjectIterator::EnumberableOnly|ObjectIterator::WithProtoChain) {}
+        : it(ctx, o, ObjectIterator::EnumberableOnly|ObjectIterator::WithProtoChain) {}
     virtual QString className() { return QStringLiteral("__ForEachIteratorObject"); }
 
-    Value nextPropertyName() { return it.nextPropertyNameAsString(context); }
+    Value nextPropertyName() { return it.nextPropertyNameAsString(); }
 
 protected:
     virtual void getCollectables(QVector<Object *> &objects);
index 73ff246..99aeb21 100644 (file)
@@ -600,9 +600,9 @@ Value ObjectPrototype::method_getOwnPropertyNames(ExecutionContext *ctx)
 
     ArrayObject *array = ctx->engine->newArrayObject(ctx)->asArrayObject();
     Array &a = array->array;
-    ObjectIterator it(O, ObjectIterator::NoFlags);
+    ObjectIterator it(ctx, O, ObjectIterator::NoFlags);
     while (1) {
-        Value v = it.nextPropertyNameAsString(ctx);
+        Value v = it.nextPropertyNameAsString();
         if (v.isNull())
             break;
         a.push_back(v);
@@ -656,7 +656,7 @@ Value ObjectPrototype::method_defineProperties(ExecutionContext *ctx)
 
     Object *o = ctx->argument(1).toObject(ctx).objectValue();
 
-    ObjectIterator it(o, ObjectIterator::EnumberableOnly);
+    ObjectIterator it(ctx, o, ObjectIterator::EnumberableOnly);
     while (1) {
         uint index;
         String *name;
@@ -682,7 +682,7 @@ Value ObjectPrototype::method_seal(ExecutionContext *ctx)
     Object *o = ctx->argument(0).objectValue();
     o->extensible = false;
 
-    ObjectIterator it(o, ObjectIterator::NoFlags);
+    ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
     while (1) {
         uint index;
         String *name;
@@ -702,7 +702,7 @@ Value ObjectPrototype::method_freeze(ExecutionContext *ctx)
     Object *o = ctx->argument(0).objectValue();
     o->extensible = false;
 
-    ObjectIterator it(o, ObjectIterator::NoFlags);
+    ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
     while (1) {
         uint index;
         String *name;
@@ -735,7 +735,7 @@ Value ObjectPrototype::method_isSealed(ExecutionContext *ctx)
     if (o->extensible)
         return Value::fromBoolean(false);
 
-    ObjectIterator it(o, ObjectIterator::NoFlags);
+    ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
     while (1) {
         uint index;
         String *name;
@@ -757,7 +757,7 @@ Value ObjectPrototype::method_isFrozen(ExecutionContext *ctx)
     if (o->extensible)
         return Value::fromBoolean(false);
 
-    ObjectIterator it(o, ObjectIterator::NoFlags);
+    ObjectIterator it(ctx, o, ObjectIterator::NoFlags);
     while (1) {
         uint index;
         String *name;
@@ -788,7 +788,7 @@ Value ObjectPrototype::method_keys(ExecutionContext *ctx)
 
     ArrayObject *a = ctx->engine->newArrayObject(ctx);
 
-    ObjectIterator it(o, ObjectIterator::EnumberableOnly);
+    ObjectIterator it(ctx, o, ObjectIterator::EnumberableOnly);
     while (1) {
         uint index;
         String *name;
index 3a65718..f324b1d 100644 (file)
 namespace QQmlJS {
 namespace VM {
 
-ObjectIterator::ObjectIterator(Object *o, uint flags)
-    : object(o)
+ObjectIterator::ObjectIterator(ExecutionContext *context, Object *o, uint flags)
+    : context(context)
+    , object(o)
     , current(o)
     , arrayNode(0)
     , arrayIndex(0)
     , tableIndex(0)
     , flags(flags)
 {
+    if (current && current->asStringObject())
+        this->flags |= CurrentIsString;
 }
 
 PropertyDescriptor *ObjectIterator::next(String **name, uint *index)
@@ -63,6 +66,21 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index)
         if (!current)
             break;
 
+        if (flags & CurrentIsString) {
+            StringObject *s = static_cast<StringObject *>(current);
+            uint slen = s->value.stringValue()->toQString().length();
+            while (arrayIndex < slen) {
+                *index = arrayIndex;
+                ++arrayIndex;
+                return s->__getOwnProperty__(context, *index);
+            }
+            flags &= ~CurrentIsString;
+            arrayNode = current->array.sparseBegin();
+            // iterate until we're past the end of the string
+            while (arrayNode && arrayNode->key() < slen)
+                arrayNode = arrayNode->nextNode();
+        }
+
         if (!arrayIndex)
             arrayNode = current->array.sparseBegin();
 
@@ -85,7 +103,7 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index)
         while (arrayIndex < current->array.length()) {
             p = current->array.at(arrayIndex);
             ++arrayIndex;
-            if (p && (!(flags & EnumberableOnly) || p->isEnumerable())) {
+            if (p && p->type != PropertyDescriptor::Generic && (!(flags & EnumberableOnly) || p->isEnumerable())) {
                 *index = arrayIndex - 1;
                 return p;
             }
@@ -96,6 +114,12 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index)
                 current = current->prototype;
             else
                 current = 0;
+            if (current && current->asStringObject())
+                flags |= CurrentIsString;
+            else
+                flags &= ~CurrentIsString;
+
+
             arrayIndex = 0;
             tableIndex = 0;
             continue;
@@ -124,7 +148,7 @@ Value ObjectIterator::nextPropertyName()
     return Value::nullValue();
 }
 
-Value ObjectIterator::nextPropertyNameAsString(ExecutionContext *context)
+Value ObjectIterator::nextPropertyNameAsString()
 {
     uint index;
     String *name;
index db340de..baecc25 100644 (file)
@@ -55,9 +55,11 @@ struct ObjectIterator
     enum Flags {
         NoFlags = 0,
         EnumberableOnly = 0x1,
-        WithProtoChain = 0x2
+        WithProtoChain = 0x2,
+        CurrentIsString = 0x4
     };
 
+    ExecutionContext *context;
     Object *object;
     Object *current;
     SparseArrayNode *arrayNode;
@@ -65,10 +67,10 @@ struct ObjectIterator
     uint tableIndex;
     uint flags;
 
-    ObjectIterator(Object *o, uint flags);
+    ObjectIterator(ExecutionContext *context, Object *o, uint flags);
     PropertyDescriptor *next(String **name, uint *index);
     Value nextPropertyName();
-    Value nextPropertyNameAsString(ExecutionContext *context);
+    Value nextPropertyNameAsString();
 };
 
 }