summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-07-01 15:56:35 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-07-01 16:45:36 +0200
commitcca5d1ec2f2c1f038c7c933b6c57d89888fc683b (patch)
treed66ba34deee4ba4a6eb9bb68b641d671eb094bf8
parent2ca5ea6aaff9bfe0b92184454788698602e470bb (diff)
Fix bindings not being re-evaluated when changing context property
Commit 7cb6dce1f3e140ea68d6b05281950f212fc99d38 introduced an optimization to remove bindings that after their initial evaluation had no dependencies or errors (such as when accessing properties not set yet). However when accessing a context property in a silent way -- using typeof -- then no error state is set and the binding is removed. Any later change of the context property results therefore in no binding re-evaluation. This patch skips the optimization on bindings that are associated with a context that has unresolved names. This fixes the concrete bug at the expense of disabling further optimizations in the context if other bindings access unresolved context properties. However since context properties are discouraged anyway, this may be an acceptable price to pay. Change-Id: I95e120a4f71e8ebe0ec1fc44e8703c75f920dd28 Fixes: QTBUG-76796 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp3
-rw-r--r--tests/auto/qml/qqmlecmascript/data/preserveBindingWithUnresolvedNames.qml4
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp13
3 files changed, 19 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index d5b15a7a5a..1b2aa8ea3b 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1353,7 +1353,8 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
QQmlPropertyData::DontRemoveBinding);
if (!b->isValueTypeProxy()) {
QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
- if (!binding->hasError() && !binding->hasDependencies())
+ if (!binding->hasError() && !binding->hasDependencies()
+ && binding->context() && !binding->context()->unresolvedNames)
b->removeFromObject();
}
diff --git a/tests/auto/qml/qqmlecmascript/data/preserveBindingWithUnresolvedNames.qml b/tests/auto/qml/qqmlecmascript/data/preserveBindingWithUnresolvedNames.qml
new file mode 100644
index 0000000000..a57bafb07b
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/preserveBindingWithUnresolvedNames.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ property string testTypeOf: typeof(contextProp)
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 18ff10b6f4..15bd9584df 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -356,6 +356,7 @@ private slots:
void callPropertyOnUndefined();
void jumpStrictNotEqualUndefined();
void removeBindingsWithNoDependencies();
+ void preserveBindingWithUnresolvedNames();
void temporaryDeadZone();
void importLexicalVariables_data();
void importLexicalVariables();
@@ -8815,6 +8816,18 @@ void tst_qqmlecmascript::removeBindingsWithNoDependencies()
}
+void tst_qqmlecmascript::preserveBindingWithUnresolvedNames()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("preserveBindingWithUnresolvedNames.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("testTypeOf").toString(), QString("undefined"));
+ QObject obj;
+ engine.rootContext()->setContextProperty("contextProp", &obj);
+ QCOMPARE(object->property("testTypeOf").toString(), QString("object"));
+}
+
void tst_qqmlecmascript::temporaryDeadZone()
{
QJSEngine engine;