aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/common/qv4compileddata.cpp9
-rw-r--r--src/qml/common/qv4compileddata_p.h39
-rw-r--r--src/qml/jsruntime/qv4engine.cpp15
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp17
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h30
-rw-r--r--src/qml/qml/qqmlscriptblob.cpp61
-rw-r--r--src/qml/qml/qqmlscriptblob_p.h4
-rw-r--r--src/qml/qml/qqmltypeloader.cpp35
-rw-r--r--src/qml/qml/qqmltypeloader_p.h3
10 files changed, 129 insertions, 85 deletions
diff --git a/src/qml/common/qv4compileddata.cpp b/src/qml/common/qv4compileddata.cpp
index 4ed53e6907..14315084bd 100644
--- a/src/qml/common/qv4compileddata.cpp
+++ b/src/qml/common/qv4compileddata.cpp
@@ -108,6 +108,15 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
});
}
+QStringList CompilationUnit::moduleRequests() const
+{
+ QStringList requests;
+ requests.reserve(data->moduleRequestTableSize);
+ for (uint i = 0; i < data->moduleRequestTableSize; ++i)
+ requests << stringAt(data->moduleRequestTable()[i]);
+ return requests;
+}
+
} // namespace CompiledData
} // namespace QV4
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index f7654661e2..0c7b07936c 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -16,14 +16,15 @@
#include <functional>
+#include <QtCore/qhash.h>
#include <QtCore/qhashfunctions.h>
-#include <QtCore/qstring.h>
+#include <QtCore/qlocale.h>
#include <QtCore/qscopeguard.h>
-#include <QtCore/qvector.h>
+#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
-#include <QtCore/qhash.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvector.h>
#include <QtCore/qversionnumber.h>
-#include <QtCore/qlocale.h>
#if QT_CONFIG(temporaryfile)
#include <QtCore/qsavefile.h>
@@ -33,6 +34,7 @@
#include <private/qqmlrefcount_p.h>
#include <private/qv4staticvalue_p.h>
#include <private/qv4compilationunitmapper_p.h>
+#include <private/qqmlnullablevalue_p.h>
#include <functional>
#include <limits.h>
@@ -1558,9 +1560,38 @@ public:
const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString);
+ int importCount() const { return qmlData->nImports; }
+ const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
+
+ Q_QML_EXPORT QStringList moduleRequests() const;
+
+ // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
+ // warnings about that code. They include any potential URL interceptions and thus represent the
+ // "physical" location of the code.
+ //
+ // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
+ // They are _not_ intercepted and thus represent the "logical" name for the code.
+
+ QUrl url() const
+ {
+ if (!m_url.isValid())
+ m_url = QUrl(fileName());
+ return m_url;
+ }
+
+ QUrl finalUrl() const
+ {
+ if (!m_finalUrl.isValid())
+ m_finalUrl = QUrl(finalUrlString());
+ return m_finalUrl;
+ }
+
private:
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex
+
+ mutable QQmlNullableValue<QUrl> m_url;
+ mutable QQmlNullableValue<QUrl> m_finalUrl;
};
class SaveableUnitPointer
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 378306a7c9..6b01e83bdf 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -2124,14 +2124,12 @@ void ExecutionEngine::injectCompiledModule(const QQmlRefPointer<ExecutableCompil
{
// Injection can happen from the QML type loader thread for example, but instantiation and
// evaluation must be limited to the ExecutionEngine's thread.
- QMutexLocker moduleGuard(&moduleMutex);
modules.insert(moduleUnit->finalUrl(), moduleUnit);
}
ExecutionEngine::Module ExecutionEngine::moduleForUrl(
const QUrl &url, const ExecutableCompilationUnit *referrer) const
{
- QMutexLocker moduleGuard(&moduleMutex);
const auto nativeModule = nativeModules.find(url);
if (nativeModule != nativeModules.end())
return Module { nullptr, *nativeModule };
@@ -2147,7 +2145,6 @@ ExecutionEngine::Module ExecutionEngine::moduleForUrl(
ExecutionEngine::Module ExecutionEngine::loadModule(const QUrl &url, const ExecutableCompilationUnit *referrer)
{
- QMutexLocker moduleGuard(&moduleMutex);
const auto nativeModule = nativeModules.find(url);
if (nativeModule != nativeModules.end())
return Module { nullptr, *nativeModule };
@@ -2159,20 +2156,15 @@ ExecutionEngine::Module ExecutionEngine::loadModule(const QUrl &url, const Execu
if (existingModule != modules.end())
return Module { *existingModule, nullptr };
- moduleGuard.unlock();
-
auto newModule = compileModule(resolved);
- if (newModule) {
- moduleGuard.relock();
+ if (newModule)
modules.insert(resolved, newModule);
- }
return Module { newModule, nullptr };
}
QV4::Value *ExecutionEngine::registerNativeModule(const QUrl &url, const QV4::Value &module)
{
- QMutexLocker moduleGuard(&moduleMutex);
const auto existingModule = nativeModules.find(url);
if (existingModule != nativeModules.end())
return nullptr;
@@ -2180,6 +2172,11 @@ QV4::Value *ExecutionEngine::registerNativeModule(const QUrl &url, const QV4::Va
QV4::Value *val = this->memoryManager->m_persistentValues->allocate();
*val = module.asReturnedValue();
nativeModules.insert(url, val);
+
+ // Make sure the type loader doesn't try to resolve the script anymore.
+ if (m_qmlEngine)
+ QQmlEnginePrivate::get(m_qmlEngine)->typeLoader.injectScript(url, *val);
+
return val;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 8ab3d62311..25484f2773 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -862,7 +862,6 @@ private:
QVector<Deletable *> m_extensionData;
- mutable QMutex moduleMutex;
QHash<QUrl, QQmlRefPointer<ExecutableCompilationUnit>> modules;
// QV4::PersistentValue would be preferred, but using QHash will create copies,
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index ebd0ae3d4a..7f44182a57 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -534,17 +534,6 @@ QQmlType ExecutableCompilationUnit::qmlTypeForComponent(const QString &inlineCom
return inlineComponentData[inlineComponentName].qmlType;
}
-QStringList ExecutableCompilationUnit::moduleRequests() const
-{
- const CompiledData::Unit *data = m_compilationUnit->data;
-
- QStringList requests;
- requests.reserve(data->moduleRequestTableSize);
- for (uint i = 0; i < data->moduleRequestTableSize; ++i)
- requests << stringAt(data->moduleRequestTable()[i]);
- return requests;
-}
-
Heap::Module *ExecutableCompilationUnit::instantiate()
{
const CompiledData::Unit *data = m_compilationUnit->data;
@@ -565,7 +554,8 @@ Heap::Module *ExecutableCompilationUnit::instantiate()
if (isESModule())
setModule(module->d());
- for (const QString &request: moduleRequests()) {
+ const QStringList moduleRequests = m_compilationUnit->moduleRequests();
+ for (const QString &request: moduleRequests) {
const QUrl url(request);
const auto dependentModuleUnit = engine->loadModule(url, this);
if (engine->hasException)
@@ -848,7 +838,8 @@ void ExecutableCompilationUnit::evaluateModuleRequests()
{
Q_ASSERT(engine);
- for (const QString &request: moduleRequests()) {
+ const QStringList moduleRequests = m_compilationUnit->moduleRequests();
+ for (const QString &request: moduleRequests) {
auto dependentModule = engine->loadModule(QUrl(request), this);
if (dependentModule.native)
continue;
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 69cac2974c..4f79f12030 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -109,29 +109,8 @@ public:
QString finalUrlString() const { return m_compilationUnit->finalUrlString(); }
QString fileName() const { return m_compilationUnit->fileName(); }
- // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
- // warnings about that code. They include any potential URL interceptions and thus represent the
- // "physical" location of the code.
- //
- // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
- // They are _not_ intercepted and thus represent the "logical" name for the code.
-
- QUrl url() const
- {
- if (!m_url.isValid())
- m_url = QUrl(m_compilationUnit->fileName());
- return m_url;
- }
-
- QUrl finalUrl() const
- {
- if (!m_finalUrl.isValid())
- m_finalUrl = QUrl(m_compilationUnit->finalUrlString());
- return m_finalUrl;
- }
-
- mutable QQmlNullableValue<QUrl> m_url;
- mutable QQmlNullableValue<QUrl> m_finalUrl;
+ QUrl url() const { return m_compilationUnit->url(); }
+ QUrl finalUrl() const { return m_compilationUnit->finalUrl(); }
// QML specific fields
QQmlPropertyCacheVector propertyCaches;
@@ -243,10 +222,10 @@ public:
return qmlData()->objectAt(index);
}
- int importCount() const { return qmlData()->nImports; }
+ int importCount() const { return m_compilationUnit->importCount(); }
const CompiledData::Import *importAt(int index) const
{
- return qmlData()->importAt(index);
+ return m_compilationUnit->importAt(index);
}
Heap::Object *templateObjectAt(int index) const;
@@ -289,7 +268,6 @@ public:
return unitData()->flags & CompiledData::Unit::IsSharedLibrary;
}
- QStringList moduleRequests() const;
Heap::Module *instantiate();
const Value *resolveExport(QV4::String *exportName)
{
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp
index c0117cb24a..89f9eee1cd 100644
--- a/src/qml/qml/qqmlscriptblob.cpp
+++ b/src/qml/qml/qqmlscriptblob.cpp
@@ -32,15 +32,18 @@ QQmlRefPointer<QQmlScriptData> QQmlScriptBlob::scriptData() const
return m_scriptData;
}
+bool QQmlScriptBlob::isNative() const
+{
+ return m_scriptData && !m_scriptData->m_value.isEmpty();
+}
+
void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
{
- auto *v4 = QQmlEnginePrivate::getV4Engine(typeLoader()->engine());
if (readCacheFile()) {
auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
QString error;
if (unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
- initializeFromCompilationUnit(
- QV4::ExecutableCompilationUnit::create(std::move(unit), v4));
+ initializeFromCompilationUnit(std::move(unit));
return;
} else {
qCDebug(DBG_DISK_CACHE()) << "Error loading" << urlString() << "from disk cache:" << error;
@@ -110,15 +113,13 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
}
}
- initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create(std::move(unit), v4));
+ initializeFromCompilationUnit(std::move(unit));
}
-void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *cachedUnit)
{
- initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create(
- QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>(
- unit->qmlData, unit->aotCompiledFunctions, urlString(), finalUrlString()),
- QQmlEnginePrivate::getV4Engine(typeLoader()->engine())));
+ initializeFromCompilationUnit(QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>(
+ cachedUnit->qmlData, cachedUnit->aotCompiledFunctions, urlString(), finalUrlString()));
}
void QQmlScriptBlob::done()
@@ -167,6 +168,14 @@ void QQmlScriptBlob::done()
m_scripts.clear();
}
+void QQmlScriptBlob::completed()
+{
+ if (m_scriptData && m_scriptData->m_precompiledScript) {
+ QQmlEnginePrivate::getV4Engine(typeLoader()->engine())
+ ->injectCompiledModule(m_scriptData->m_precompiledScript);
+ }
+}
+
QString QQmlScriptBlob::stringAt(int index) const
{
return m_scriptData->m_precompiledScript->stringAt(index);
@@ -183,17 +192,22 @@ void QQmlScriptBlob::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob,
m_scripts << ref;
}
-void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit)
+void QQmlScriptBlob::initializeFromCompilationUnit(
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&unit)
{
Q_ASSERT(!m_scriptData);
+ Q_ASSERT(unit);
+
m_scriptData.adopt(new QQmlScriptData());
m_scriptData->url = finalUrl();
m_scriptData->urlString = finalUrlString();
- m_scriptData->m_precompiledScript = unit;
+ m_scriptData->m_precompiledScript = QV4::ExecutableCompilationUnit::create(
+ std::move(unit), QQmlEnginePrivate::getV4Engine(typeLoader()->engine()));
m_importCache->setBaseUrl(finalUrl(), finalUrlString());
- QQmlRefPointer<QV4::ExecutableCompilationUnit> script = m_scriptData->m_precompiledScript;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> script
+ = m_scriptData->m_precompiledScript->baseCompilationUnit();
if (!m_isModule) {
QList<QQmlError> errors;
@@ -212,22 +226,25 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::Exe
}
}
- auto *v4 = QQmlEnginePrivate::getV4Engine(typeLoader()->engine());
-
- v4->injectCompiledModule(unit);
+ const QStringList moduleRequests = script->moduleRequests();
+ for (const QString &request: moduleRequests) {
+ const QUrl relativeRequest = QUrl(request);
+ if (m_typeLoader->injectedScript(relativeRequest))
+ continue;
- for (const QString &request: unit->moduleRequests()) {
- const auto module = v4->moduleForUrl(QUrl(request), unit.data());
- if (module.compiled || module.native)
+ const QUrl absoluteRequest = script->finalUrl().resolved(relativeRequest);
+ QQmlRefPointer<QQmlScriptBlob> absoluteBlob = typeLoader()->getScript(absoluteRequest);
+ if (absoluteBlob->m_scriptData && absoluteBlob->m_scriptData->m_precompiledScript)
continue;
- const QUrl absoluteRequest = unit->finalUrl().resolved(QUrl(request));
- QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(absoluteRequest);
- addDependency(blob.data());
- scriptImported(blob, /* ### */QV4::CompiledData::Location(), /*qualifier*/QString(), /*namespace*/QString());
+ addDependency(absoluteBlob.data());
+ scriptImported(
+ absoluteBlob, /* ### */QV4::CompiledData::Location(), /*qualifier*/QString(),
+ /*namespace*/QString());
}
}
+
/*!
\internal
diff --git a/src/qml/qml/qqmlscriptblob_p.h b/src/qml/qml/qqmlscriptblob_p.h
index ad9c573400..356fe23675 100644
--- a/src/qml/qml/qqmlscriptblob_p.h
+++ b/src/qml/qml/qqmlscriptblob_p.h
@@ -39,17 +39,19 @@ public:
};
QQmlRefPointer<QQmlScriptData> scriptData() const;
+ bool isNative() const;
protected:
void dataReceived(const SourceCodeData &) override;
void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override;
void done() override;
+ void completed() override;
QString stringAt(int index) const override;
private:
void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
- void initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit);
+ void initializeFromCompilationUnit(QQmlRefPointer<QV4::CompiledData::CompilationUnit> &&cu);
void initializeFromNative(const QV4::Value &value);
QList<ScriptReference> m_scripts;
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 4f84fa6be4..b76fcd9409 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -554,15 +554,12 @@ bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &da
bool QQmlTypeLoader::Blob::addScriptImport(const QQmlTypeLoader::Blob::PendingImportPtr &import)
{
const QUrl url(import->uri);
- const auto module = m_typeLoader->engine()->handle()->moduleForUrl(url);
- QQmlRefPointer<QQmlScriptBlob> blob;
- if (module.native) {
- blob.adopt(new QQmlScriptBlob(url, m_typeLoader));
- blob->initializeFromNative(*module.native);
- blob->tryDone();
- } else {
- blob = typeLoader()->getScript(finalUrl().resolved(url));
- }
+ QQmlTypeLoader *loader = typeLoader();
+ QQmlRefPointer<QQmlScriptBlob> blob = loader->injectedScript(url);
+ if (!blob)
+ blob = loader->getScript(finalUrl().resolved(url));
+ else
+ Q_ASSERT(blob->status() == QQmlDataBlob::Status::Complete);
addDependency(blob.data());
scriptImported(blob, import->location, import->qualifier, QString());
return true;
@@ -998,6 +995,26 @@ QQmlRefPointer<QQmlTypeData> QQmlTypeLoader::getType(const QByteArray &data, con
return QQmlRefPointer<QQmlTypeData>(typeData, QQmlRefPointer<QQmlTypeData>::Adopt);
}
+void QQmlTypeLoader::injectScript(const QUrl &relativeUrl, const QV4::Value &value)
+{
+ LockHolder<QQmlTypeLoader> holder(this);
+
+ QQmlScriptBlob *blob = new QQmlScriptBlob(relativeUrl, this);
+ blob->initializeFromNative(value);
+ blob->m_isDone = true;
+ blob->m_data.setStatus(QQmlDataBlob::Complete);
+ m_scriptCache.insert(relativeUrl, blob);
+}
+
+QQmlRefPointer<QQmlScriptBlob> QQmlTypeLoader::injectedScript(const QUrl &relativeUrl)
+{
+ LockHolder<QQmlTypeLoader> holder(this);
+ const auto it = m_scriptCache.constFind(relativeUrl);
+ return (it != m_scriptCache.constEnd() && (*it)->isNative())
+ ? *it
+ : QQmlRefPointer<QQmlScriptBlob>();
+}
+
/*!
Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached.
*/
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 6c53437d86..7f6e43bcfb 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -131,6 +131,9 @@ public:
QQmlRefPointer<QQmlTypeData> getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
QQmlRefPointer<QQmlTypeData> getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
+ void injectScript(const QUrl &relativeUrl, const QV4::Value &value);
+ QQmlRefPointer<QQmlScriptBlob> injectedScript(const QUrl &relativeUrl);
+
QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl);
QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &);