aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp4
-rw-r--r--src/qml/compiler/qv4isel_p.cpp13
-rw-r--r--src/qml/compiler/qv4jsir_p.h4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml14
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp9
5 files changed, 40 insertions, 4 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index 7ebe4dcba2..8693c32c92 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -1595,7 +1595,7 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
return 0;
if (pd) {
if (!pd->isConstant())
- _function->scopeObjectDependencies.insert(pd);
+ _function->scopeObjectDependencyCandidates.insert(pd); // We don't know if we'll ever read from there or just write, hence candidate
V4IR::Temp *base = _block->TEMP(_scopeObjectTemp);
initMetaObjectResolver(&base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd);
@@ -1609,7 +1609,7 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
return 0;
if (pd) {
if (!pd->isConstant())
- _function->contextObjectDependencies.insert(pd);
+ _function->contextObjectDependencyCandidates.insert(pd); // We don't know if we'll ever read from there or just write, hence candidate
V4IR::Temp *base = _block->TEMP(_contextObjectTemp);
initMetaObjectResolver(&base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 7ba43dd552..78eb9ba0f5 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -149,8 +149,17 @@ void IRDecoder::visitMove(V4IR::Move *s)
if (m->property) {
bool captureRequired = true;
if (_function && m->attachedPropertiesId == 0) {
- captureRequired = !_function->contextObjectDependencies.contains(m->property)
- && !_function->scopeObjectDependencies.contains(m->property);
+ if (_function->contextObjectDependencyCandidates.remove(m->property)) {
+ _function->contextObjectDependencies.insert(m->property);
+ captureRequired = false;
+ } else if (_function->scopeObjectDependencyCandidates.remove(m->property)) {
+ _function->scopeObjectDependencies.insert(m->property);
+ captureRequired = false;
+ }
+
+ if (captureRequired)
+ captureRequired = !_function->contextObjectDependencies.contains(m->property)
+ && !_function->scopeObjectDependencies.contains(m->property);
}
getQObjectProperty(m->base, m->property->coreIndex, captureRequired, m->attachedPropertiesId, t);
return;
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 59e8d02bbc..b0ca4c0478 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -782,6 +782,10 @@ struct Function {
// Qml extension:
QSet<int> idObjectDependencies;
+ // Context/Scope properties discovered during identifier resolution
+ QSet<QQmlPropertyData*> contextObjectDependencyCandidates;
+ QSet<QQmlPropertyData*> scopeObjectDependencyCandidates;
+ // Context/Scope properties actually being read from, not only written
QSet<QQmlPropertyData*> contextObjectDependencies;
QSet<QQmlPropertyData*> scopeObjectDependencies;
diff --git a/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml b/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml
new file mode 100644
index 0000000000..8b8601692d
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml
@@ -0,0 +1,14 @@
+import QtQml 2.0
+QtObject {
+ property bool somePropertyEvaluated: false;
+
+ property int someProperty: {
+ // It's sort of evil to set the property here, but that doesn't mean that
+ // this expression should get re-evaluated when unrelatedProperty changes later.
+ somePropertyEvaluated = true
+ return 20;
+ }
+ Component.onCompleted: {
+ somePropertyEvaluated = false
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 1e18e3c269..7b89709923 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -319,6 +319,7 @@ private slots:
void stackLimits();
void idsAsLValues();
void qtbug_34792();
+ void noCaptureWhenWritingProperty();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7498,6 +7499,14 @@ void tst_qqmlecmascript::qtbug_34792()
delete object;
}
+void tst_qqmlecmascript::noCaptureWhenWritingProperty()
+{
+ QQmlComponent component(&engine, testFileUrl("noCaptureWhenWritingProperty.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("somePropertyEvaluated").toBool(), false);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"