From 1b445d35fa304e5e34722b1c46d0733d9b292419 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 14 Jan 2013 15:54:07 +0100 Subject: [PATCH] Correctly iterator over properties of StringObjects Change-Id: I16a8065dd0bb9162811ced1bc6c73c07c02a331d Reviewed-by: Simon Hausmann --- qmljs_objects.h | 5 ++--- qv4ecmaobjects.cpp | 16 ++++++++-------- qv4objectiterator.cpp | 32 ++++++++++++++++++++++++++++---- qv4objectiterator.h | 8 +++++--- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/qmljs_objects.h b/qmljs_objects.h index 5d3b9ca..5837da9 100644 --- a/qmljs_objects.h +++ b/qmljs_objects.h @@ -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 &objects); diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 73ff246..99aeb21 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -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; diff --git a/qv4objectiterator.cpp b/qv4objectiterator.cpp index 3a65718..f324b1d 100644 --- a/qv4objectiterator.cpp +++ b/qv4objectiterator.cpp @@ -44,14 +44,17 @@ 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(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; diff --git a/qv4objectiterator.h b/qv4objectiterator.h index db340de..baecc25 100644 --- a/qv4objectiterator.h +++ b/qv4objectiterator.h @@ -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(); }; } -- 2.7.4