diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-10-25 10:23:01 +0200 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-10-31 09:37:46 +0100 |
commit | 4521be25cd6888f9412c0a6350171dd0383ede0a (patch) | |
tree | 3a22b5ca0d92ecad84aa635d44a33bcb65c7f616 /src/libs | |
parent | a9553c494ef6012cc4c34bd469ff0f20ee2e2671 (diff) | |
download | qt-creator-4521be25cd6888f9412c0a6350171dd0383ede0a.tar.gz |
QmlJS: Avoid an infinite loop if a qmltypes file has a cycle.
The qmltypes files shipped with libraries shouldn't, but could define
components that form a prototype cycle. Use of the new
QmlObjectValue::prototypes() function avoids the code model getting
stuck in an infinite loop for these cases.
For plain ObjectValues this is already solved by using
PrototypeIterator.
Change-Id: I0f562672ab99b454bc3a0121c7a1b9eca43476bb
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.cpp | 32 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.h | 1 |
2 files changed, 25 insertions, 8 deletions
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 581f240b0b..529b66e3a2 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -338,6 +338,22 @@ const QmlObjectValue *QmlObjectValue::prototype() const return static_cast<const QmlObjectValue *>(_prototype); } +/*! + \returns a list started by this object and followed by all its prototypes + + Prefer to use this over calling prototype() in a loop, as it avoids cycles. +*/ +QList<const QmlObjectValue *> QmlObjectValue::prototypes() const +{ + QList<const QmlObjectValue *> protos; + for (const QmlObjectValue *it = this; it; it = it->prototype()) { + if (protos.contains(it)) + break; + protos += it; + } + return protos; +} + const QmlObjectValue *QmlObjectValue::attachedType() const { return _attachedType; @@ -367,7 +383,7 @@ QString QmlObjectValue::defaultPropertyName() const QString QmlObjectValue::propertyType(const QString &propertyName) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { @@ -379,7 +395,7 @@ QString QmlObjectValue::propertyType(const QString &propertyName) const bool QmlObjectValue::isListProperty(const QString &propertyName) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { @@ -391,7 +407,7 @@ bool QmlObjectValue::isListProperty(const QString &propertyName) const FakeMetaEnum QmlObjectValue::getEnum(const QString &typeName, const QmlObjectValue **foundInScope) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; const int index = iter->enumeratorIndex(typeName); if (index != -1) { @@ -407,7 +423,7 @@ FakeMetaEnum QmlObjectValue::getEnum(const QString &typeName, const QmlObjectVal const QmlEnumValue *QmlObjectValue::getEnumValue(const QString &typeName, const QmlObjectValue **foundInScope) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { if (const QmlEnumValue *e = it->_enums.value(typeName)) { if (foundInScope) *foundInScope = it; @@ -421,7 +437,7 @@ const QmlEnumValue *QmlObjectValue::getEnumValue(const QString &typeName, const bool QmlObjectValue::isWritable(const QString &propertyName) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { @@ -433,7 +449,7 @@ bool QmlObjectValue::isWritable(const QString &propertyName) const bool QmlObjectValue::isPointer(const QString &propertyName) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { @@ -453,7 +469,7 @@ bool QmlObjectValue::hasLocalProperty(const QString &typeName) const bool QmlObjectValue::hasProperty(const QString &propertyName) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; int propIdx = iter->propertyIndex(propertyName); if (propIdx != -1) { @@ -465,7 +481,7 @@ bool QmlObjectValue::hasProperty(const QString &propertyName) const bool QmlObjectValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const { - for (const QmlObjectValue *it = this; it; it = it->prototype()) { + foreach (const QmlObjectValue *it, prototypes()) { FakeMetaObject::ConstPtr iter = it->_metaObject; if (iter == base) return true; diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 8f9ec41da6..aa484598f0 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -428,6 +428,7 @@ public: using ObjectValue::prototype; const QmlObjectValue *prototype() const; + QList<const QmlObjectValue *> prototypes() const; const QmlObjectValue *attachedType() const; void setAttachedType(QmlObjectValue *value); |