diff options
-rw-r--r-- | src/qml/compiler/qqmlcodegenerator.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_p.cpp | 13 | ||||
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/data/noCaptureWhenWritingProperty.qml | 14 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 9 |
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" |