Fix qmldir cache inconsistency
If there are multiple qmldir entries for the same QML module in the import list, the one that comes first should take precedence. The same applies when constructing the qmldir cache. We can achieve that by inserting the entries into the cache in the same order they appear in the completeQmldirPaths list. Pick-to: 6.2 Change-Id: Ic56a0952b16c4be016180c695d79089fc132319a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
98e60bef15
commit
dd4a79c36b
|
@ -278,28 +278,27 @@ QQmlImportDatabase::LocalQmldirResult QQmlImportDatabase::locateLocalQmldir(
|
|||
// Check cache first
|
||||
|
||||
LocalQmldirResult result = QmldirNotFound;
|
||||
QmldirCache *cacheHead = nullptr;
|
||||
{
|
||||
QmldirCache **cachePtr = qmldirCache.value(uri);
|
||||
if (cachePtr) {
|
||||
cacheHead = *cachePtr;
|
||||
QmldirCache *cache = cacheHead;
|
||||
while (cache) {
|
||||
if (cache->version == version) {
|
||||
if (cache->qmldirFilePath.isEmpty()) {
|
||||
return cache->qmldirPathUrl.isEmpty()
|
||||
? QmldirNotFound
|
||||
: QmldirInterceptedToRemote;
|
||||
}
|
||||
if (callback(cache->qmldirFilePath, cache->qmldirPathUrl))
|
||||
return QmldirFound;
|
||||
result = QmldirRejected;
|
||||
QmldirCache *cacheTail = nullptr;
|
||||
|
||||
QmldirCache **cachePtr = qmldirCache.value(uri);
|
||||
QmldirCache *cacheHead = cachePtr ? *cachePtr : nullptr;
|
||||
if (cacheHead) {
|
||||
cacheTail = cacheHead;
|
||||
do {
|
||||
if (cacheTail->version == version) {
|
||||
if (cacheTail->qmldirFilePath.isEmpty()) {
|
||||
return cacheTail->qmldirPathUrl.isEmpty()
|
||||
? QmldirNotFound
|
||||
: QmldirInterceptedToRemote;
|
||||
}
|
||||
cache = cache->next;
|
||||
if (callback(cacheTail->qmldirFilePath, cacheTail->qmldirPathUrl))
|
||||
return QmldirFound;
|
||||
result = QmldirRejected;
|
||||
}
|
||||
}
|
||||
} while (cacheTail->next && (cacheTail = cacheTail->next));
|
||||
}
|
||||
|
||||
|
||||
// Do not try to construct the cache if it already had any entries for the URI.
|
||||
// Otherwise we might duplicate cache entries.
|
||||
if (result != QmldirNotFound)
|
||||
|
@ -349,15 +348,15 @@ QQmlImportDatabase::LocalQmldirResult QQmlImportDatabase::locateLocalQmldir(
|
|||
cache->version = version;
|
||||
cache->qmldirFilePath = qmldirAbsoluteFilePath;
|
||||
cache->qmldirPathUrl = url;
|
||||
cache->next = cacheHead;
|
||||
qmldirCache.insert(uri, cache);
|
||||
cacheHead = cache;
|
||||
cache->next = nullptr;
|
||||
if (cacheTail)
|
||||
cacheTail->next = cache;
|
||||
else
|
||||
qmldirCache.insert(uri, cache);
|
||||
cacheTail = cache;
|
||||
|
||||
if (result != QmldirFound) {
|
||||
result = callback(qmldirAbsoluteFilePath, url)
|
||||
? QmldirFound
|
||||
: QmldirRejected;
|
||||
}
|
||||
if (result != QmldirFound)
|
||||
result = callback(qmldirAbsoluteFilePath, url) ? QmldirFound : QmldirRejected;
|
||||
|
||||
// Do not return here. Rather, construct the complete cache for this URI.
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import QtQuick
|
||||
import MyModule
|
||||
|
||||
Item {
|
||||
MyItem { objectName: "myItem1" }
|
||||
MyView {}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import MyModule
|
||||
|
||||
MyItem { objectName: "myItem2" }
|
|
@ -0,0 +1,6 @@
|
|||
import QtQuick
|
||||
|
||||
Item {
|
||||
width: 100
|
||||
height: 100
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module MyModule
|
||||
|
||||
MyItem MyItem.qml
|
|
@ -0,0 +1,6 @@
|
|||
import QtQuick
|
||||
|
||||
Item {
|
||||
width: 200
|
||||
height: 200
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module MyModule
|
||||
|
||||
MyItem MyItem.qml
|
|
@ -205,6 +205,22 @@ void tst_QQmlImport::importPathOrder()
|
|||
engine.addImportPath(qml2Imports);
|
||||
expectedImportPaths.move(expectedImportPaths.indexOf(qml2Imports), 0);
|
||||
QCOMPARE(engine.importPathList(), expectedImportPaths);
|
||||
|
||||
// Verify if the type in the module comes first in the import path list
|
||||
// takes the precedence. In the case below, the width of both items
|
||||
// should be the same to that of the type defined in "path2".
|
||||
engine.addImportPath(testFile("importPathOrder/path1"));
|
||||
engine.addImportPath(testFile("importPathOrder/path2"));
|
||||
QQmlComponent component(&engine, testFile("importPathOrder/MyModuleTest.qml"));
|
||||
QScopedPointer<QObject> rootItem(component.create());
|
||||
QVERIFY(component.errorString().isEmpty());
|
||||
QVERIFY(!rootItem.isNull());
|
||||
QQuickItem *item1 = rootItem->findChild<QQuickItem*>("myItem1");
|
||||
QQuickItem *item2 = rootItem->findChild<QQuickItem*>("myItem2");
|
||||
QVERIFY(item1 != nullptr);
|
||||
QVERIFY(item2 != nullptr);
|
||||
QCOMPARE(item1->width(), 200);
|
||||
QCOMPARE(item2->width(), 200);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QQmlImports::ImportVersion)
|
||||
|
|
Loading…
Reference in New Issue