This commit is contained in:
parent
e4f46ec826
commit
f4cb7ec09e
@ -1,239 +0,0 @@
|
||||
From 5b5f6d7b4b00e8e64280b7d66bcc1f63b40edf1c Mon Sep 17 00:00:00 2001
|
||||
From: Ulf Hermann <ulf.hermann@qt.io>
|
||||
Date: Mon, 9 Sep 2024 16:58:24 +0200
|
||||
Subject: [PATCH] QtQml: Re-use memory-cached compilation units across engines
|
||||
|
||||
Since we've eliminated all engine-specific data from these compilation
|
||||
units, we can now do so without fearing crosstalk between the engines.
|
||||
By not re-compiling the CUs we also do not create duplicate property
|
||||
caches which can otherwise show up in inconvenient places and make
|
||||
otherwise equal types mismatch.
|
||||
|
||||
Fixes: QTBUG-128789
|
||||
Change-Id: Ia8a6fefb9a1455f6139265aa3708036adea902f6
|
||||
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
|
||||
(cherry picked from commit 27c2c989a3d10557da15de3d45bb5bd7b96d14e8)
|
||||
---
|
||||
src/qml/qml/qqmltypedata.cpp | 22 ++++++++++--
|
||||
src/qml/qml/qqmltypedata_p.h | 1 +
|
||||
tests/auto/qml/qqmllanguage/CMakeLists.txt | 22 +++++-------
|
||||
.../qml/qqmllanguage/data/InnerObject.qml | 5 +++
|
||||
.../qqmllanguage/data/ObjectWithProperty.qml | 5 +++
|
||||
.../qml/qqmllanguage/data/outerObject.qml | 15 ++++++++
|
||||
.../qml/qqmllanguage/tst_qqmllanguage.cpp | 36 +++++++++++++++++++
|
||||
7 files changed, 90 insertions(+), 16 deletions(-)
|
||||
create mode 100644 tests/auto/qml/qqmllanguage/data/InnerObject.qml
|
||||
create mode 100644 tests/auto/qml/qqmllanguage/data/ObjectWithProperty.qml
|
||||
create mode 100644 tests/auto/qml/qqmllanguage/data/outerObject.qml
|
||||
|
||||
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
|
||||
index 2b189cd2644d..d0e054c5f8d2 100644
|
||||
--- a/src/qml/qml/qqmltypedata.cpp
|
||||
+++ b/src/qml/qml/qqmltypedata.cpp
|
||||
@@ -95,7 +95,12 @@ bool QQmlTypeData::tryLoadFromDiskCache()
|
||||
return true;
|
||||
}
|
||||
|
||||
- m_compiledData = std::move(unit);
|
||||
+ return loadFromDiskCache(unit);
|
||||
+}
|
||||
+
|
||||
+bool QQmlTypeData::loadFromDiskCache(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit)
|
||||
+{
|
||||
+ m_compiledData = unit;
|
||||
|
||||
QVector<QV4::CompiledData::InlineComponent> ics;
|
||||
for (int i = 0, count = m_compiledData->objectCount(); i < count; ++i) {
|
||||
@@ -450,7 +455,12 @@ void QQmlTypeData::done()
|
||||
|
||||
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
|
||||
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
|
||||
- {
|
||||
+
|
||||
+ // If we've pulled the CU from the memory cache, we don't need to do any verification.
|
||||
+ const bool verifyCaches = !m_compiledData
|
||||
+ || (m_compiledData->resolvedTypes.isEmpty() && !m_compiledData->typeNameCache);
|
||||
+
|
||||
+ if (verifyCaches) {
|
||||
QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
|
||||
if (error.isValid()) {
|
||||
setError(error);
|
||||
@@ -469,7 +479,7 @@ void QQmlTypeData::done()
|
||||
};
|
||||
|
||||
// verify if any dependencies changed if we're using a cache
|
||||
- if (m_document.isNull()) {
|
||||
+ if (m_document.isNull() && verifyCaches) {
|
||||
const QQmlError error = createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
|
||||
if (!error.isValid() && m_compiledData->verifyChecksum(dependencyHasher)) {
|
||||
setCompileUnit(m_compiledData);
|
||||
@@ -512,6 +522,7 @@ void QQmlTypeData::done()
|
||||
}
|
||||
|
||||
if (!m_document.isNull()) {
|
||||
+ Q_ASSERT(verifyCaches);
|
||||
// Compile component
|
||||
compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
|
||||
if (isError())
|
||||
@@ -656,6 +667,11 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data)
|
||||
|
||||
void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
|
||||
{
|
||||
+ if (auto cu = QQmlMetaType::obtainCompilationUnit(finalUrl())) {
|
||||
+ if (loadFromDiskCache(cu))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
m_document.reset(new QmlIR::Document(isDebugging()));
|
||||
QQmlIRLoader loader(unit->qmlData, m_document.data());
|
||||
loader.load();
|
||||
diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h
|
||||
index 97419b916bc8..8ca1c4e96104 100644
|
||||
--- a/src/qml/qml/qqmltypedata_p.h
|
||||
+++ b/src/qml/qml/qqmltypedata_p.h
|
||||
@@ -84,6 +84,7 @@ private:
|
||||
using InlineComponentData = QV4::CompiledData::InlineComponentData;
|
||||
|
||||
bool tryLoadFromDiskCache();
|
||||
+ bool loadFromDiskCache(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
|
||||
bool loadFromSource();
|
||||
void restoreIR(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
|
||||
void continueLoadFromIR();
|
||||
diff --git a/tests/auto/qml/qqmllanguage/CMakeLists.txt b/tests/auto/qml/qqmllanguage/CMakeLists.txt
|
||||
index 9fff8f211872..bf5166a66505 100644
|
||||
--- a/tests/auto/qml/qqmllanguage/CMakeLists.txt
|
||||
+++ b/tests/auto/qml/qqmllanguage/CMakeLists.txt
|
||||
@@ -35,14 +35,6 @@ qt_internal_add_test(tst_qqmllanguage
|
||||
|
||||
add_subdirectory(testhelper)
|
||||
|
||||
-#### Keys ignored in scope 1:.:.:qqmllanguage.pro:<TRUE>:
|
||||
-# OTHER_FILES = "data/readonlyObjectProperty.qml"
|
||||
-# QML_IMPORT_NAME = "StaticTest"
|
||||
-# QML_IMPORT_VERSION = "1.0"
|
||||
-
|
||||
-## Scopes:
|
||||
-#####################################################################
|
||||
-
|
||||
if(ANDROID)
|
||||
# Resources:
|
||||
set_source_files_properties("data/I18nType30.qml"
|
||||
@@ -70,9 +62,13 @@ qt_internal_extend_target(tst_qqmllanguage CONDITION NOT ANDROID AND NOT IOS
|
||||
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
)
|
||||
|
||||
-set_target_properties(tst_qqmllanguage PROPERTIES
|
||||
- QT_QML_MODULE_VERSION 1.0
|
||||
- QT_QML_MODULE_URI StaticTest
|
||||
+qt6_add_qml_module(tst_qqmllanguage
|
||||
+ URI StaticTest
|
||||
+ VERSION 1.0
|
||||
+ QML_FILES
|
||||
+ data/InnerObject.qml
|
||||
+ data/ObjectWithProperty.qml
|
||||
+ data/outerObject.qml
|
||||
+ RESOURCE_PREFIX "/"
|
||||
+ NO_GENERATE_EXTRA_QMLDIRS
|
||||
)
|
||||
-
|
||||
-_qt_internal_qml_type_registration(tst_qqmllanguage)
|
||||
diff --git a/tests/auto/qml/qqmllanguage/data/InnerObject.qml b/tests/auto/qml/qqmllanguage/data/InnerObject.qml
|
||||
new file mode 100644
|
||||
index 000000000000..8598b5b8d243
|
||||
--- /dev/null
|
||||
+++ b/tests/auto/qml/qqmllanguage/data/InnerObject.qml
|
||||
@@ -0,0 +1,5 @@
|
||||
+import QtQml
|
||||
+
|
||||
+QtObject {
|
||||
+ required property ObjectWithProperty objectWithProperty
|
||||
+}
|
||||
diff --git a/tests/auto/qml/qqmllanguage/data/ObjectWithProperty.qml b/tests/auto/qml/qqmllanguage/data/ObjectWithProperty.qml
|
||||
new file mode 100644
|
||||
index 000000000000..31089f7dbd05
|
||||
--- /dev/null
|
||||
+++ b/tests/auto/qml/qqmllanguage/data/ObjectWithProperty.qml
|
||||
@@ -0,0 +1,5 @@
|
||||
+import QtQml
|
||||
+
|
||||
+QtObject {
|
||||
+ property int a: 5
|
||||
+}
|
||||
diff --git a/tests/auto/qml/qqmllanguage/data/outerObject.qml b/tests/auto/qml/qqmllanguage/data/outerObject.qml
|
||||
new file mode 100644
|
||||
index 000000000000..ff074fd50988
|
||||
--- /dev/null
|
||||
+++ b/tests/auto/qml/qqmllanguage/data/outerObject.qml
|
||||
@@ -0,0 +1,15 @@
|
||||
+import QtQml
|
||||
+
|
||||
+QtObject {
|
||||
+ id: self
|
||||
+
|
||||
+ property Component delegate
|
||||
+
|
||||
+ property ObjectWithProperty objectWithProperty: ObjectWithProperty {}
|
||||
+
|
||||
+ property InnerObject innerObject: null
|
||||
+
|
||||
+ function doInstantiate() {
|
||||
+ innerObject = delegate.createObject(self, {objectWithProperty: objectWithProperty})
|
||||
+ }
|
||||
+}
|
||||
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||
index ed205447ddb1..4fabc4f64d9a 100644
|
||||
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
|
||||
@@ -466,6 +466,8 @@ private slots:
|
||||
|
||||
void overrideInnerBinding();
|
||||
|
||||
+ void engineTypeCrossTalk();
|
||||
+
|
||||
private:
|
||||
QQmlEngine engine;
|
||||
QStringList defaultImportPathList;
|
||||
@@ -8994,6 +8996,40 @@ void tst_qqmllanguage::overrideInnerBinding()
|
||||
QCOMPARE(o->property("innerWidth").toReal(), 20.0);
|
||||
}
|
||||
|
||||
+class EngineAndObject
|
||||
+{
|
||||
+public:
|
||||
+ EngineAndObject(const QUrl &outer)
|
||||
+ {
|
||||
+ QQmlComponent component(&engine, outer);
|
||||
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
|
||||
+ object.reset(component.create());
|
||||
+ QVERIFY(object);
|
||||
+ }
|
||||
+
|
||||
+ void wreck(const QUrl &inner) {
|
||||
+ QQmlComponent component(&engine, inner);
|
||||
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
|
||||
+ object->setProperty("delegate", QVariant::fromValue(&component));
|
||||
+ QMetaObject::invokeMethod(object.get(), "doInstantiate");
|
||||
+ QVERIFY(object->property("innerObject").value<QObject *>() != nullptr);
|
||||
+ }
|
||||
+
|
||||
+ QQmlEngine engine;
|
||||
+ std::unique_ptr<QObject> object;
|
||||
+};
|
||||
+
|
||||
+void tst_qqmllanguage::engineTypeCrossTalk()
|
||||
+{
|
||||
+ const QUrl outer("qrc:/StaticTest/data/outerObject.qml");
|
||||
+ EngineAndObject first(outer);
|
||||
+ EngineAndObject second(outer);
|
||||
+
|
||||
+ const QUrl inner("qrc:/StaticTest/data/InnerObject.qml");
|
||||
+ first.wreck(inner);
|
||||
+ second.wreck(inner);
|
||||
+}
|
||||
+
|
||||
QTEST_MAIN(tst_qqmllanguage)
|
||||
|
||||
#include "tst_qqmllanguage.moc"
|
||||
--
|
||||
2.47.0
|
||||
|
Loading…
Reference in New Issue
Block a user