diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-06-06 10:45:37 +0200 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-06-17 18:44:42 +0200 |
| commit | f26af148f4ad84f07c193c4200a686e490c60cb5 (patch) | |
| tree | c0d1861f8267fce1faa2c14ce71ea42c21dec00f /src/qml/jsruntime/qv4engine.cpp | |
| parent | 9cc23ca91c404f24fff3c36e8c9425ae674f341d (diff) | |
QtQml: Register all ECMAScript module requests as dependencies
Without this, freeUnusedTypesAndCaches() could drop dependencies of a
live ECMAScript module. This would be unfortunate. Since ECMAScript
modules can form cycles, we now need to clear the dependent scripts
separately before clearing the compilation units.
The downside of this is that actually cyclic ECMAScript modules cannot
be cleared at all without clearing the whole type registry. However,
this situation should be rare.
Change-Id: Ib2d523f7c291bb5c472b6603bd947c3977b77b85
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4engine.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 1f27ca1f1e..afb4355af9 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -13,6 +13,7 @@ #include <private/qqmljsdiagnosticmessage_p.h> #include <private/qqmllist_p.h> #include <private/qqmllistwrapper_p.h> +#include <private/qqmlscriptdata_p.h> #include <private/qqmltypeloader_p.h> #include <private/qqmltypewrapper_p.h> #include <private/qqmlvaluetype_p.h> @@ -2051,6 +2052,9 @@ QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const Q { QQmlMetaType::CachedUnitLookupError cacheError = QQmlMetaType::CachedUnitLookupError::NoError; const DiskCacheOptions options = diskCacheOptions(); + + QQmlRefPointer<ExecutableCompilationUnit> cu; + if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (options & DiskCache::Aot) ? QQmlMetaType::findCachedCompilationUnit( url, @@ -2059,24 +2063,40 @@ QQmlRefPointer<ExecutableCompilationUnit> ExecutionEngine::compileModule(const Q : QQmlMetaType::RequireFullyTyped, &cacheError) : nullptr) { - return executableCompilationUnit( + cu = executableCompilationUnit( QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>( cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, url.fileName(), url.toString())); - } + } else { - QFile f(QQmlFile::urlToLocalFileOrQrc(url)); - if (!f.open(QIODevice::ReadOnly)) { - throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString())); - return nullptr; + QFile f(QQmlFile::urlToLocalFileOrQrc(url)); + if (!f.open(QIODevice::ReadOnly)) { + throwError(QStringLiteral("Could not open module %1 for reading").arg(url.toString())); + return nullptr; + } + + const QDateTime timeStamp = QFileInfo(f).lastModified(); + + const QString sourceCode = QString::fromUtf8(f.readAll()); + f.close(); + + cu = compileModule(url, sourceCode, timeStamp); } - const QDateTime timeStamp = QFileInfo(f).lastModified(); + const auto baseCompilationUnit = cu->baseCompilationUnit(); + const auto data = cu->unitData(); + for (uint i = 0, end = data->moduleRequestTableSize; i < end; ++i) { + cu->baseCompilationUnit()->dependentScripts.append(scriptDataForDependency( + loadModule(cu->urlAt(data->moduleRequestTable()[i]), cu.data()))); + } - const QString sourceCode = QString::fromUtf8(f.readAll()); - f.close(); + // Only register with the type registry when the dependentScripts are ready! + // Otherwise we get thread safety problems. + baseCompilationUnit->qmlType = QQmlMetaType::findCompositeType( + url, baseCompilationUnit, QQmlMetaType::JavaScript); + QQmlMetaType::registerInternalCompositeType(baseCompilationUnit); - return compileModule(url, sourceCode, timeStamp); + return cu; } @@ -2156,6 +2176,17 @@ void ExecutionEngine::trimCompilationUnitsForUrl(const QUrl &url) } } +QQmlRefPointer<QQmlScriptData> ExecutionEngine::scriptDataForDependency( + const ExecutionEngine::Module &dependency) +{ + QQmlRefPointer<QQmlScriptData> scriptData( + new QQmlScriptData, QQmlRefPointer<QQmlScriptData>::Adopt); + scriptData->url = dependency->finalUrl(); + scriptData->urlString = dependency->finalUrlString(); + scriptData->m_precompiledScript = dependency->baseCompilationUnit(); + return scriptData; +} + template<typename NotFound> ExecutionEngine::Module doFindModule( const QMultiHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> &compilationUnits, |
