Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package qt6-declarative for openSUSE:Factory
checked in at 2026-02-21 21:01:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qt6-declarative (Old)
and /work/SRC/openSUSE:Factory/.qt6-declarative.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "qt6-declarative"
Sat Feb 21 21:01:24 2026 rev:60 rq:1334140 version:6.10.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/qt6-declarative/qt6-declarative.changes
2026-02-03 21:27:18.214062947 +0100
+++
/work/SRC/openSUSE:Factory/.qt6-declarative.new.1977/qt6-declarative.changes
2026-02-21 21:02:13.997560801 +0100
@@ -1,0 +2,8 @@
+Thu Feb 19 10:48:08 UTC 2026 - Christophe Marin <[email protected]>
+
+- Add upstream changes (kde#513527, QTBUG-142514):
+ * 0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch
+ * 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
+ * 0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch
+
+-------------------------------------------------------------------
New:
----
0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch
0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch
----------(New B)----------
New: * 0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch
* 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
* 0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch
New:- Add upstream changes (kde#513527, QTBUG-142514):
* 0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch
* 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
New: * 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
* 0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch
----------(New E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ qt6-declarative.spec ++++++
--- /var/tmp/diff_new_pack.tqmdvl/_old 2026-02-21 21:02:15.397618198 +0100
+++ /var/tmp/diff_new_pack.tqmdvl/_new 2026-02-21 21:02:15.401618362 +0100
@@ -41,6 +41,10 @@
Source99: qt6-declarative-rpmlintrc
# PATCH-FIX-OPENSUSE
Patch0: 0001-qmlimportscanner-Include-module-versions-again.patch
+# PATCH-FIX-UPSTREAM
+Patch1: 0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch
+Patch2: 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch
+Patch3: 0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch
BuildRequires: memory-constraints
BuildRequires: pkgconfig
BuildRequires: python3-base
++++++ 0001-QtQml-Do-not-clear-objects-propertyCaches-on-last-GC.patch ++++++
>From 1327fce7e500e3ae2e96ab89eaad7f1727ea77b1 Mon Sep 17 00:00:00 2001
From: Ulf Hermann <[email protected]>
Date: Tue, 13 Jan 2026 11:53:27 +0100
Subject: [PATCH] QtQml: Do not clear objects' propertyCaches on last GC run
The property caches are not specific to the engine. The same object may
be exposed to other engines and still require its property cache. When
the clearing of the property caches on engine destruction was
introduced, the property caches were still engine-specific and we had no
choice but to clear them. Otherwise any further access would lead to a
dereference of a dangling pointer.
Furthermore, when clearing the JS wrapper for a QObject, check if it's
actually the wrapper being deleted. We don't want to clear some other
engine's wrapper.
Amends commit 749a7212e903d8e8c6f256edb1836b9449cc7fe1.
Amends commit c6b2dd879d02b21b18f80faab541f8f04286685a.
Fixes: QTBUG-142514
Change-Id: I40bb1aeca65225d56cb1d2ff498f5f1722216a70
Reviewed-by: Fabian Kosmale <[email protected]>
(cherry picked from commit dc2358e98b8ddab532866a403ffc09d1162ad0f9)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
(cherry picked from commit abd054a491b5f443193033d451dc17e09841277a)
---
src/qml/jsruntime/qv4qobjectwrapper.cpp | 7 +++----
tests/auto/qml/qjsengine/tst_qjsengine.cpp | 2 +-
.../qml/qmlcppcodegen/data/CMakeLists.txt | 1 +
.../data/multiEnginePropertyCache.qml | 20 ++++++++++++++++++
.../qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 21 +++++++++++++++++++
5 files changed, 46 insertions(+), 5 deletions(-)
create mode 100644
tests/auto/qml/qmlcppcodegen/data/multiEnginePropertyCache.qml
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp
b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index bb3d9b1c32..6887d86f4c 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1583,10 +1583,9 @@ void QObjectWrapper::destroyObject(bool lastCall)
o->deleteLater();
} else {
// If the object is C++-owned, we still have to release the
weak reference we have
- // to it.
- ddata->jsWrapper.clear();
- if (lastCall && ddata->propertyCache)
- ddata->propertyCache.reset();
+ // to it. If the "main" wrapper is not ours, we should leave
it alone, though.
+ if (ddata->jsWrapper.as<QObjectWrapper>() == this)
+ ddata->jsWrapper.clear();
}
}
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 2f855213ba..4c1e7e5a86 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1116,7 +1116,7 @@ void tst_QJSEngine::newQObjectPropertyCache()
engine.newQObject(obj.data());
QVERIFY(QQmlData::get(obj.data())->propertyCache);
}
- QVERIFY(!QQmlData::get(obj.data())->propertyCache);
+ QVERIFY(QQmlData::get(obj.data())->propertyCache);
}
void tst_QJSEngine::newQMetaObject() {
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 88cc102509..8949d007e4 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -326,6 +326,7 @@ set(qml_files
stringLength.qml
stringToByteArray.qml
structuredValueType.qml
+ multiEnginePropertyCache.qml
takenumber.qml
testlogger.js
text.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/multiEnginePropertyCache.qml
b/tests/auto/qml/qmlcppcodegen/data/multiEnginePropertyCache.qml
new file mode 100644
index 0000000000..222b2f84de
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/multiEnginePropertyCache.qml
@@ -0,0 +1,20 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: root
+
+ property int foo: 0
+ onFooChanged: root.close1()
+
+ property int bar: 0
+ onBarChanged: close2()
+
+ function close1() {
+ console.log("close1")
+ }
+
+ function close2() {
+ console.log("close2")
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 46696acacf..d602f00f0b 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -280,6 +280,7 @@ private slots:
void stringLength();
void stringToByteArray();
void structuredValueType();
+ void multiEnginePropertyCache();
void takeNumbers();
void takeNumbers_data();
void testIsnan();
@@ -5794,6 +5795,26 @@ void tst_QmlCppCodegen::structuredValueType()
QCOMPARE(o->property("w2").value<WeatherModelUrl>(), w2);
}
+void tst_QmlCppCodegen::multiEnginePropertyCache()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine,
QUrl(u"qrc:/qt/qml/TestTypes/multiEnginePropertyCache.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o(c.create());
+ QVERIFY(o);
+
+ {
+ QJSEngine other;
+ other.newQObject(o.get());
+ }
+
+ QTest::ignoreMessage(QtDebugMsg, "close1");
+ o->setProperty("foo", 1);
+
+ QTest::ignoreMessage(QtDebugMsg, "close2");
+ o->setProperty("bar", 2);
+}
+
void tst_QmlCppCodegen::takeNumbers()
{
QFETCH(QByteArray, method);
--
2.53.0
++++++ 0001-QtQml-Fix-corner-cases-around-dead-contexts-in-AOT-a.patch ++++++
>From 897406ec04b339800765854c6d05cafa3a30cae2 Mon Sep 17 00:00:00 2001
From: Ulf Hermann <[email protected]>
Date: Fri, 9 Jan 2026 16:37:53 +0100
Subject: [PATCH] QtQml: Fix corner cases around dead contexts in AOT adapter
code
When trying to call methods in contexts that have already been torn
down, interesting things happen. We need to check the return value of
the lookup getter in various places and throw the appropriate
exceptions.
We do not actually need to reset the lookups when that happens. In a
different context they can still be valid. Instead of resetting them, we
now check in both, the initialization and the actual call.
Amends commit 4381eaf567337c2b2892adeec0d2fef878c1eed3.
Task-number: QTBUG-142514
Change-Id: Id8dc5079cdfe600310294046f35815c0c4bcba20
Reviewed-by: Fabian Kosmale <[email protected]>
(cherry picked from commit e9f023457c5abd1952025456ed974156068a4590)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
(cherry picked from commit 70252e2481fa48c01f83a0bb8e252dafea065de8)
---
src/qml/qml/qqml.cpp | 56 ++++++++-----------
.../qml/qmlcppcodegen/data/CMakeLists.txt | 2 +
.../qml/qmlcppcodegen/data/deadContext2.qml | 43 ++++++++++++++
.../qml/qmlcppcodegen/data/deadContext3.qml | 46 +++++++++++++++
.../qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 25 +++++++--
5 files changed, 136 insertions(+), 36 deletions(-)
create mode 100644 tests/auto/qml/qmlcppcodegen/data/deadContext2.qml
create mode 100644 tests/auto/qml/qmlcppcodegen/data/deadContext3.qml
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 3f0d9e332b..a3861552a9 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -2247,6 +2247,15 @@ static bool callArrowFunction(
Q_UNREACHABLE_RETURN(false);
}
+static void throwIsNotAFunctionError(
+ const AOTCompiledContext *aotContext, QV4::Lookup *lookup, const
QString &object)
+{
+ aotContext->engine->handle()->throwTypeError(
+ QStringLiteral("Property '%1' of object %2 is not a function").arg(
+
aotContext->compilationUnit->runtimeStrings[lookup->nameIndex]->toQString(),
+ object));
+};
+
bool AOTCompiledContext::callQmlContextPropertyLookup(uint index, void **args,
int argc) const
{
QV4::Lookup *lookup = compilationUnit->runtimeLookups + index;
@@ -2254,17 +2263,18 @@ bool
AOTCompiledContext::callQmlContextPropertyLookup(uint index, void **args, i
if (lookup->call == QV4::Lookup::Call::ContextGetterScopeObjectMethod)
return callQObjectMethod(engine->handle(), lookup, qmlScopeObject,
args, argc);
- const auto doCall = [&](auto &&call) {
+ if (lookup->call == QV4::Lookup::Call::ContextGetterScopeObjectProperty) {
QV4::Scope scope(engine->handle());
QV4::ScopedValue undefined(scope);
QV4::Scoped<QV4::ArrowFunction> function(
scope, lookup->contextGetter(scope.engine, undefined));
- Q_ASSERT(function);
- return call(scope.engine, function, qmlScopeObject, args, argc);
- };
+ if (function)
+ return callArrowFunction(scope.engine, function, qmlScopeObject,
args, argc);
- if (lookup->call == QV4::Lookup::Call::ContextGetterScopeObjectProperty)
- return doCall(&callArrowFunction);
+ QV4::Scoped<QV4::QObjectWrapper> object(
+ scope, QV4::QObjectWrapper::wrap(scope.engine,
qmlScopeObject));
+ throwIsNotAFunctionError(this, lookup, object->toQStringNoThrow());
+ }
return false;
}
@@ -2344,13 +2354,7 @@ void
AOTCompiledContext::initCallQmlContextPropertyLookup(uint index, int relati
QV4::Scoped<QV4::QObjectWrapper> object(
scope, QV4::QObjectWrapper::wrap(scope.engine, qmlScopeObject));
- scope.engine->throwTypeError(
- QStringLiteral("Property '%1' of object %2 is not a function").arg(
-
compilationUnit->runtimeStrings[lookup->nameIndex]->toQString(),
- object->toQStringNoThrow()));
-
- lookup->releasePropertyCache();
- lookup->call = QV4::Lookup::Call::ContextGetterGeneric;
+ throwIsNotAFunctionError(this, lookup, object->toQStringNoThrow());
}
bool AOTCompiledContext::loadContextIdLookup(uint index, void *target) const
@@ -2447,10 +2451,10 @@ bool AOTCompiledContext::callObjectPropertyLookup(
// The getter mustn't touch the asVariant bit
Q_ASSERT(!lookup->asVariant);
- // If the method can't be shadowed, it has to stay the same.
- Q_ASSERT(function);
+ if (function)
+ return callArrowFunction(scope.engine, function, object, args,
argc);
- return callArrowFunction(scope.engine, function, qmlScopeObject, args,
argc);
+ throwIsNotAFunctionError(this, lookup, thisObject->toQStringNoThrow());
}
default:
break;
@@ -2469,16 +2473,10 @@ void
AOTCompiledContext::initCallObjectPropertyLookupAsVariant(uint index, QObje
QV4::Lookup *lookup = compilationUnit->runtimeLookups + index;
QV4::Scope scope(engine->handle());
- const auto throwInvalidObjectError = [&](const QString &object) {
- scope.engine->throwTypeError(
- QStringLiteral("Property '%1' of object %2 is not a
function").arg(
-
compilationUnit->runtimeStrings[lookup->nameIndex]->toQString(), object));
- };
-
const auto *ddata = QQmlData::get(object, false);
if (ddata && ddata->hasVMEMetaObject &&
ddata->jsWrapper.isNullOrUndefined()) {
// We cannot lookup functions on an object with VME metaobject but no
QObjectWrapper
- throwInvalidObjectError(QStringLiteral("[object Object]"));
+ throwIsNotAFunctionError(this, lookup, QStringLiteral("[object
Object]"));
return;
}
@@ -2496,7 +2494,7 @@ void
AOTCompiledContext::initCallObjectPropertyLookupAsVariant(uint index, QObje
return;
}
- throwInvalidObjectError(thisObject->toQStringNoThrow());
+ throwIsNotAFunctionError(this, lookup, thisObject->toQStringNoThrow());
}
void AOTCompiledContext::initCallObjectPropertyLookup(
@@ -2510,16 +2508,10 @@ void AOTCompiledContext::initCallObjectPropertyLookup(
QV4::Lookup *lookup = compilationUnit->runtimeLookups + index;
QV4::Scope scope(engine->handle());
- const auto throwInvalidObjectError = [&]() {
- scope.engine->throwTypeError(
- QStringLiteral("Property '%1' of object [object Object] is not
a function")
-
.arg(compilationUnit->runtimeStrings[lookup->nameIndex]->toQString()));
- };
-
const auto *ddata = QQmlData::get(object, false);
if (ddata && ddata->hasVMEMetaObject &&
ddata->jsWrapper.isNullOrUndefined()) {
// We cannot lookup functions on an object with VME metaobject but no
QObjectWrapper
- throwInvalidObjectError();
+ throwIsNotAFunctionError(this, lookup, QStringLiteral("[object
Object]"));
return;
}
@@ -2538,7 +2530,7 @@ void AOTCompiledContext::initCallObjectPropertyLookup(
return;
}
- throwInvalidObjectError();
+ throwIsNotAFunctionError(this, lookup, thisObject->toQStringNoThrow());
}
bool AOTCompiledContext::loadGlobalLookup(uint index, void *target) const
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 67cdefa30d..88cc102509 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -152,6 +152,8 @@ set(qml_files
dateConstruction.qml
dateConversions.qml
deadContext.qml
+ deadContext2.qml
+ deadContext3.qml
deadShoeSize.qml
deadStoreLoop.qml
destroyAndToString.qml
diff --git a/tests/auto/qml/qmlcppcodegen/data/deadContext2.qml
b/tests/auto/qml/qmlcppcodegen/data/deadContext2.qml
new file mode 100644
index 0000000000..29667585a5
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/deadContext2.qml
@@ -0,0 +1,43 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+
+Item {
+ id: root
+
+ property Component a: Item {
+ Timer {
+ id: timer1
+ interval: 1
+ running: root.choice < 4
+
+ function doit() {}
+ onTriggered: {
+ ++root.choice
+ timer1.doit()
+ }
+ }
+ }
+
+ property Component b: Item {
+ Timer {
+ id: timer2
+ interval: 1
+ running: root.choice < 4
+
+ function doit() {}
+ onTriggered: {
+ ++root.choice
+ timer2.doit()
+ }
+ }
+ }
+
+ property int choice: 0
+
+ Loader {
+ sourceComponent: switch (root.choice % 2) {
+ case 0: return root.a
+ case 1: return root.b
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/deadContext3.qml
b/tests/auto/qml/qmlcppcodegen/data/deadContext3.qml
new file mode 100644
index 0000000000..fcf3228c9f
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/deadContext3.qml
@@ -0,0 +1,46 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+
+Item {
+ id: root
+
+ property Component a: Item {
+ Timer {
+ interval: 1
+ running: root.choice < 8
+
+ function doit() {}
+ onTriggered: {
+ ++root.choice
+ doit()
+ }
+ }
+ }
+
+ property Component b: Item {
+ Timer {
+ id: timer2
+ interval: 1
+ running: root.choice < 8
+
+ function doit() {}
+ onTriggered: {
+ ++root.choice
+ timer2.doit()
+ }
+ }
+ }
+
+ property int choice: 0
+
+ Loader {
+ sourceComponent: switch (root.choice % 4) {
+ case 0:
+ case 1:
+ return root.a
+ case 2:
+ case 3:
+ return root.b
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 2cbcb1d918..46696acacf 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -100,6 +100,7 @@ private slots:
void cppValueTypeList();
void dateConstruction();
void dateConversions();
+ void deadContext_data();
void deadContext();
void deadShoeSize();
void deduplicateConversionOrigins();
@@ -1715,10 +1716,26 @@ void tst_QmlCppCodegen::dateConversions()
}
+void tst_QmlCppCodegen::deadContext_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<int>("end");
+
+ QTest::addRow("Unqualified lookups in dead context")
+ << QUrl(u"qrc:/qt/qml/TestTypes/deadContext.qml"_s) << 4;
+ QTest::addRow("Qualified lookups in dead context")
+ << QUrl(u"qrc:/qt/qml/TestTypes/deadContext2.qml"_s) << 4;
+ QTest::addRow("Alternating lookups in live and dead contexts")
+ << QUrl(u"qrc:/qt/qml/TestTypes/deadContext3.qml"_s) << 8;
+}
+
void tst_QmlCppCodegen::deadContext()
{
+ QFETCH(QUrl, url);
+ QFETCH(int, end);
+
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/deadContext.qml"_s));
+ QQmlComponent c(&engine, url);
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
@@ -1726,15 +1743,15 @@ void tst_QmlCppCodegen::deadContext()
const char *vmeError = "QQmlVMEMetaObject: Internal error "
"- attempted to evaluate a function in an invalid
context";
static const QRegularExpression timerError(
- u"qrc:/qt/qml/TestTypes/deadContext\\.qml:[0-9]+: TypeError:
Property 'doit' of "
- "object QQmlTimer_QML_[0-9]+\\(0x[0-9a-f]+\\) is not a
function"_s);
+ u"qrc:/qt/qml/TestTypes/deadContext[0-9]*\\.qml:[0-9]+:
TypeError: Property 'doit' "
+ "of object QQmlTimer_QML_[0-9]+\\(0x[0-9a-f]+\\) is not a
function"_s);
for (int i = 0; i < 4; ++i) {
QTest::ignoreMessage(QtWarningMsg, vmeError);
QTest::ignoreMessage(QtWarningMsg, timerError);
}
- QTRY_COMPARE(o->property("choice").toInt(), 4);
+ QTRY_COMPARE(o->property("choice").toInt(), end);
}
void tst_QmlCppCodegen::deadShoeSize()
--
2.53.0
++++++ 0001-QtQml-Handle-the-case-of-getFallbackMethod-returning.patch ++++++
>From b3e98b1955b7e5515d938ab9b8c3bafd2e4a035b Mon Sep 17 00:00:00 2001
From: Ulf Hermann <[email protected]>
Date: Mon, 12 Jan 2026 15:36:40 +0100
Subject: [PATCH] QtQml: Handle the case of getFallbackMethod returning
non-methods
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In virtualResolveLookupGetter, we can theoretically encounter an object
without property cache of which we retrieve a property (as opposed to a
method). There have been reports of this case being triggered, but as of
yet it's unknown how this is done. The interpreter will not call the
lookup resolution at all in such a case, and the AOT-generated code
optimizes non-method lookup initialization, and won't call
virtualResolveLookupGetter() either.
However, the code was clearly wrong. If the result of the lookup is not
a QObjectMethod, what we have is a fallback property lookup, which needs
to be initialized as such.
Dissolve getFallbackMethod() since it is misnamed and hardly does any
work to begin with. Since we need the QQmlPropertyData retrieved by it
in the case mentioned above, we could only call it in one place anyway.
Task-number: QTBUG-142514
Change-Id: Ia340ca48be7a87e81fbc2c6e362ef0192d351f05
Reviewed-by: Fabian Kosmale <[email protected]>
Reviewed-by: Olivier De Cannière <[email protected]>
(cherry picked from commit 6e61618b3f601c6e2d580c9be5dd6fdbdb45d2be)
Reviewed-by: Qt Cherry-pick Bot <[email protected]>
(cherry picked from commit 24490553874b0135b9fbd7a235fc10eac4e9e3f1)
---
src/qml/jsruntime/qv4lookup.cpp | 10 ++++++--
src/qml/jsruntime/qv4qobjectwrapper.cpp | 34 ++++++++++++-------------
src/qml/jsruntime/qv4qobjectwrapper_p.h | 4 ---
3 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index e97e40be61..858f9fff7b 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -479,9 +479,15 @@ ReturnedValue Lookup::getterFallbackMethod(Lookup *lookup,
ExecutionEngine *engi
scope,
engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
+ QQmlPropertyData local;
+ const QQmlPropertyData *property = QQmlPropertyCache::property(
+ qobj, name, engine->callingQmlContext(), &local);
+ if (!property)
+ return Encode::undefined();
+
QV4::ScopedValue result(
- scope, QObjectWrapper::getMethodFallback(
- engine, This->d(), qobj, name,
+ scope, QObjectWrapper::getProperty(
+ engine, This->d(), qobj, property,
lookup->forCall ? QObjectWrapper::NoFlag :
QObjectWrapper::AttachMethods));
// In the general case we cannot rely on the method to exist or stay the
same across calls.
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp
b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6887d86f4c..a99a46a627 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -389,18 +389,6 @@ ReturnedValue QObjectWrapper::getProperty(
}
}
-ReturnedValue QObjectWrapper::getMethodFallback(
- ExecutionEngine *engine, Heap::Object *wrapper, QObject *qobject,
- QV4::String *name, Flags flags)
-{
- QQmlPropertyData local;
- const QQmlPropertyData *property = QQmlPropertyCache::property(
- qobject, name, engine->callingQmlContext(), &local);
- return property
- ? getProperty(engine, wrapper, qobject, property, flags)
- : Encode::undefined();
-}
-
static OptionalReturnedValue getDestroyOrToStringMethod(
ExecutionEngine *v4, String *name, Heap::Object *qobj, bool
*hasProperty = nullptr)
{
@@ -1132,12 +1120,24 @@ ReturnedValue
QObjectWrapper::virtualResolveLookupGetter(const Object *object, E
}
if (!ddata || !ddata->propertyCache) {
- QV4::ScopedValue result(scope, getMethodFallback(
- engine, This->d(), qobj, name, lookup->forCall ? NoFlag :
AttachMethods));
- lookup->qobjectMethodLookup.ic.set(engine, object->internalClass());
- if (QObjectMethod *method = result->as<QObjectMethod>())
+ QQmlPropertyData local;
+ const QQmlPropertyData *property = QQmlPropertyCache::property(
+ qobj, name, engine->callingQmlContext(), &local);
+ if (!property)
+ return Encode::undefined();
+ QV4::ScopedValue result(scope, getProperty(
+ engine, This->d(), qobj, property, lookup->forCall ? NoFlag :
AttachMethods));
+ if (QObjectMethod *method = result->as<QObjectMethod>()) {
+ lookup->qobjectMethodLookup.ic.set(engine,
object->internalClass());
lookup->qobjectMethodLookup.method.set(engine, method->d());
- lookup->call = Lookup::Call::GetterQObjectMethodFallback;
+ lookup->call = Lookup::Call::GetterQObjectMethodFallback;
+ } else {
+ lookup->qobjectFallbackLookup.metaObject =
quintptr(qobj->metaObject()) + 1;
+ lookup->qobjectFallbackLookup.coreIndex = property->coreIndex();
+ lookup->qobjectFallbackLookup.notifyIndex =
property->notifyIndex();
+ lookup->qobjectFallbackLookup.isConstant = property->isConstant()
? 1 : 0;
+ lookup->call = Lookup::Call::GetterQObjectPropertyFallback;
+ }
return result->asReturnedValue();
}
const QQmlPropertyData *property =
ddata->propertyCache->property(name.getPointer(), qobj, qmlContext);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h
b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index cf88a2e4ef..1b3eb8bc1f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -180,10 +180,6 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
ExecutionEngine *engine, Heap::Object *wrapper, QObject *object,
const QQmlPropertyData *property, Flags flags);
- static ReturnedValue getMethodFallback(
- ExecutionEngine *engine, Heap::Object *wrapper, QObject *object,
- QV4::String *name, Flags flags);
-
static ReturnedValue virtualResolveLookupGetter(const Object *object,
ExecutionEngine *engine, Lookup *lookup);
template <typename ReversalFunctor> static ReturnedValue
lookupPropertyGetterImpl(
--
2.53.0