diff options
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 26 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 25 |
3 files changed, 43 insertions, 10 deletions
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 123d1648c2..86995e48f9 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -332,23 +332,31 @@ void String::Data::simplifyString() const int l = length(); QString result(l, Qt::Uninitialized); QChar *ch = const_cast<QChar *>(result.constData()); - recursiveAppend(ch); + append(this, ch); text = result.data_ptr(); text->ref.ref(); identifier = 0; largestSubLength = 0; } -QChar *String::Data::recursiveAppend(QChar *ch) const +void String::Data::append(const String::Data *data, QChar *ch) { - if (largestSubLength) { - ch = left->d()->recursiveAppend(ch); - ch = right->d()->recursiveAppend(ch); - } else { - memcpy(ch, text->data(), text->size*sizeof(QChar)); - ch += text->size; + std::vector<const String::Data *> worklist; + worklist.reserve(32); + worklist.push_back(data); + + while (!worklist.empty()) { + const String::Data *item = worklist.back(); + worklist.pop_back(); + + if (item->largestSubLength) { + worklist.push_back(item->right->d()); + worklist.push_back(item->left->d()); + } else { + memcpy(ch, item->text->data(), item->text->size * sizeof(QChar)); + ch += item->text->size; + } } - return ch; } diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index f9d3cd1cc0..082f296f48 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -79,7 +79,7 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed { mutable uint largestSubLength; uint len; private: - QChar *recursiveAppend(QChar *ch) const; + static void append(const Data *data, QChar *ch); }; // ### FIXME: Should this be a V4_OBJECT V4_OBJECT(QV4::Managed) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 6b37163b40..c68f1190dd 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -325,6 +325,7 @@ private slots: void importedScriptsAccessOnObjectWithInvalidContext(); void contextObjectOnLazyBindings(); void garbageCollectionDuringCreation(); + void qtbug_39520(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7665,6 +7666,30 @@ void tst_qqmlecmascript::garbageCollectionDuringCreation() QCOMPARE(container->dataChildren.count(), 0); } +void tst_qqmlecmascript::qtbug_39520() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\n" + "Item {\n" + " property string s\n" + " Component.onCompleted: test()\n" + " function test() {\n" + " var count = 1 * 1000 * 1000\n" + " var t = ''\n" + " for (var i = 0; i < count; ++i)\n" + " t += 'testtest ' + i + '\n'\n" + " s = t\n" + " }\n" + "}\n", + QUrl()); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + QString s = object->property("s").toString(); + QCOMPARE(s.count('\n'), 1 * 1000 * 1000); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" |