diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-23 10:03:00 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-01-27 10:42:06 +0100 |
commit | ddba87612d2be25863135669e81bc3391dc40e82 (patch) | |
tree | 839f35beafff47adeb1df12d2958cf8f36e9704a /src | |
parent | 08c086b9977d9275c53b58d6ffc766740e248c2c (diff) |
QML: Turn singleton/type mismatch into a run time type error
There are many ways to "hide" the qmldir from the engine at run time,
which turns singletons into regular types. While all of this is invalid,
we should not assert on it, but rather produce a legible warning.
Furthermore, sharpen the importing of extra modules from qrc as implicit
imports. We should really only import modules the file in question can
ever be part of. Otherwise we needlessly produce the above situation and
hide legitimate warning messages.
Amends commit 7517c1b3ae9aa92f36b19d74a4b2de5e8531309b.
Now we need to teach our tools about the default import paths in the
resorurce file system. They cannot guess any type they may find in any
resource file anymore.
Pick-to: 6.5
Task-number: QTBUG-106929
Change-Id: Ic8c02396d10830a7f461e8a81649bb8c9a1add1f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqml.cpp | 15 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 27 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslinter_p.h | 2 |
3 files changed, 26 insertions, 18 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 07aea5e553..c752adc5a0 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -1573,8 +1573,19 @@ static void initTypeWrapperLookup( } scope.engine->throwTypeError(); } else { - l->qmlContextPropertyGetter(l, context->engine->handle(), nullptr); - Q_ASSERT(l->qmlContextPropertyGetter == qmlContextPropertyGetter); + QV4::ExecutionEngine *v4 = context->engine->handle(); + l->qmlContextPropertyGetter(l, v4, nullptr); + if (l->qmlContextPropertyGetter != qmlContextPropertyGetter) { + const QString error + = QLatin1String(qmlContextPropertyGetter + == QV4::QQmlContextWrapper::lookupSingleton + ? "%1 was a singleton at compile time, " + "but is not a singleton anymore." + : "%1 was not a singleton at compile time, " + "but is a singleton now.") + .arg(context->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); + v4->throwTypeError(error); + } } } diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 7a1a58fc27..f631a28763 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -364,22 +364,17 @@ void QQmlJSImportVisitor::importBaseModules() m_importer->importDirectory(m_implicitImportDirectory); m_rootScopeImports.addTypes(std::move(fromDirectory)); - QQmlJSResourceFileMapper *mapper = m_importer->resourceFileMapper(); - - // In instances where a qmldir entry exists somewhere in the resource files, import that - // directory in order to allow for implicit imports of modules. - if (mapper) { - const QStringList filePaths = mapper->filePaths(QQmlJSResourceFileMapper::Filter { - QString(), QStringList(), - QQmlJSResourceFileMapper::Directory | QQmlJSResourceFileMapper::Recurse }); - auto qmldirEntry = - std::find_if(filePaths.constBegin(), filePaths.constEnd(), - [](const QString &path) { return path.endsWith(u"/qmldir"); }); - - if (qmldirEntry != filePaths.constEnd()) { - QQmlJSScope::ContextualTypes fromDirectory = - m_importer->importDirectory(QFileInfo(*qmldirEntry).absolutePath()); - m_rootScopeImports.addTypes(std::move(fromDirectory)); + // Import all possible resource directories the file may belong to. + // This is somewhat fuzzy, but if you're mapping the same file to multiple resource + // locations, you're on your own anyway. + if (QQmlJSResourceFileMapper *mapper = m_importer->resourceFileMapper()) { + const QStringList resourcePaths = mapper->resourcePaths(QQmlJSResourceFileMapper::Filter { + m_logger->fileName(), QStringList(), QQmlJSResourceFileMapper::Resource }); + for (const QString &path : resourcePaths) { + const qsizetype lastSlash = path.lastIndexOf(QLatin1Char('/')); + if (lastSlash == -1) + continue; + m_rootScopeImports.addTypes(m_importer->importDirectory(path.first(lastSlash))); } } } diff --git a/src/qmlcompiler/qqmljslinter_p.h b/src/qmlcompiler/qqmljslinter_p.h index c174584b34..77a8fe701f 100644 --- a/src/qmlcompiler/qqmljslinter_p.h +++ b/src/qmlcompiler/qqmljslinter_p.h @@ -128,6 +128,8 @@ public: void setPluginsEnabled(bool enablePlugins) { m_enablePlugins = enablePlugins; } bool pluginsEnabled() const { return m_enablePlugins; } + void clearCache() { m_importer.clearCache(); } + private: void parseComments(QQmlJSLogger *logger, const QList<QQmlJS::SourceLocation> &comments); void processMessages(QJsonArray &warnings); |