From 7a5f70d6e5037334813db938eb0f4a646df512e9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 21 May 2014 12:19:15 +0200 Subject: Fix QQmlScriptString::isEmpty for script strings without source code The source code is not strictly required anymore and QQmlScriptString should return true with isEmpty() if the object is conceptually empty (not usable), not only when the source code is empty. It can still have a valid binding id and thus be used in QQmlExpression. Change-Id: I777717f2217d0c46e059c382761a1044881c5978 Reviewed-by: Lars Knoll --- src/qml/qml/qqmlscriptstring.cpp | 4 +- tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 49 ++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/qml/qml/qqmlscriptstring.cpp b/src/qml/qml/qqmlscriptstring.cpp index fd710df52f..af9d8ec265 100644 --- a/src/qml/qml/qqmlscriptstring.cpp +++ b/src/qml/qml/qqmlscriptstring.cpp @@ -126,7 +126,9 @@ Returns whether the QQmlScriptString is empty. */ bool QQmlScriptString::isEmpty() const { - return d->script.isEmpty(); + if (!d->script.isEmpty()) + return false; + return d->bindingId == -1; } /*! diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 3561635351..2ade0b2652 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -146,6 +146,7 @@ private slots: void onCompleted(); void onDestruction(); void scriptString(); + void scriptStringWithoutSourceCode(); void defaultPropertyListOrder(); void declaredPropertyValues(); void dontDoubleCallClassBegin(); @@ -1932,6 +1933,54 @@ void tst_qqmllanguage::scriptString() } } +void tst_qqmllanguage::scriptStringWithoutSourceCode() +{ + QUrl url = testFileUrl("scriptString7.qml"); + { + QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine); + QQmlTypeData *td = eng->typeLoader.getType(url); + Q_ASSERT(td); + + QV4::CompiledData::QmlUnit *qmlUnit = td->compiledData()->qmlUnit; + Q_ASSERT(qmlUnit); + const QV4::CompiledData::Object *rootObject = qmlUnit->objectAt(qmlUnit->indexOfRootObject); + QCOMPARE(qmlUnit->header.stringAt(rootObject->inheritedTypeNameIndex), QString("MyTypeObject")); + quint32 i; + for (i = 0; i < rootObject->nBindings; ++i) { + const QV4::CompiledData::Binding *binding = rootObject->bindingTable() + i; + if (qmlUnit->header.stringAt(binding->propertyNameIndex) != QString("scriptProperty")) + continue; + QCOMPARE(binding->valueAsScriptString(&qmlUnit->header), QString("intProperty")); + const_cast(binding)->stringIndex = 0; // empty string index + QVERIFY(binding->valueAsScriptString(&qmlUnit->header).isEmpty()); + break; + } + QVERIFY(i < rootObject->nBindings); + } + QQmlComponent component(&engine, url); + VERIFY_ERRORS(0); + + MyTypeObject *object = qobject_cast(component.create()); + QVERIFY(object != 0); + QQmlScriptString ss = object->scriptProperty(); + QVERIFY(!ss.isEmpty()); + QCOMPARE(ss.stringLiteral(), QString()); + bool ok; + QCOMPARE(ss.numberLiteral(&ok), qreal(0.)); + QCOMPARE(ok, false); + + const QQmlScriptStringPrivate *scriptPrivate = QQmlScriptStringPrivate::get(ss); + QVERIFY(scriptPrivate != 0); + QVERIFY(scriptPrivate->script.isEmpty()); + QCOMPARE(scriptPrivate->scope, qobject_cast(object)); + QCOMPARE(scriptPrivate->context, qmlContext(object)); + + { + QQmlExpression expr(ss, /*context*/0, object); + QCOMPARE(expr.evaluate().toInt(), int(100)); + } +} + // Check that default property assignments are correctly spliced into explicit // property assignments void tst_qqmllanguage::defaultPropertyListOrder() -- cgit v1.2.3