aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-08-16 10:57:25 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-17 11:06:12 +0000
commitf43c1d902d908c6cd523b0174338ac0c98a30647 (patch)
tree50fa2c720dd86aa073efcb935e22bb967e01b5de /src/qml/jsruntime
parent29275ef53ec8e1edb7aad66af94058786c7d1e2f (diff)
Add support for importing ES modules in .qml files
This is a straight-forward hook into the module implementation in QV4::ExecutionEngine. Modules are pre-compiled in the QML type loader thread. That thread keeps track of all pending loading scripts through the type loader's m_scriptCache. Once a module is compiled, it's thread-safely registered with the execution engine. Script instantiation and evaluation is done solely in the QQmlEngine's thread. ES Modules are identified in imports as well as qmldir files by the .mjs extension. Change-Id: Ie9c59785118afcb49f43a1e176a9f7db00f09428 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp24
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4script.cpp18
3 files changed, 26 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 90c75b204d..14bc5f084e 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1682,6 +1682,7 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(boo
using namespace QV4::Compiler;
Compiler::Module compilerModule(debugMode);
+ compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
JSUnitGenerator jsGenerator(&compilerModule);
Codegen cg(&jsGenerator, /*strictMode*/true);
cg.generateFromModule(url.fileName(), url.toString(), sourceCode, moduleNode, &compilerModule);
@@ -1697,22 +1698,43 @@ QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::compileModule(boo
void ExecutionEngine::injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit)
{
+ // 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);
}
+QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer) const
+{
+ QUrl url = QQmlTypeLoader::normalize(_url);
+ if (referrer)
+ url = referrer->finalUrl().resolved(url);
+
+ QMutexLocker moduleGuard(&moduleMutex);
+ auto existingModule = modules.find(url);
+ if (existingModule == modules.end())
+ return nullptr;
+ return *existingModule;
+}
+
QQmlRefPointer<CompiledData::CompilationUnit> ExecutionEngine::loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer)
{
QUrl url = QQmlTypeLoader::normalize(_url);
if (referrer)
url = referrer->finalUrl().resolved(url);
+ QMutexLocker moduleGuard(&moduleMutex);
auto existingModule = modules.find(url);
if (existingModule != modules.end())
return *existingModule;
+ moduleGuard.unlock();
+
auto newModule = compileModule(url);
- if (newModule)
+ if (newModule) {
+ moduleGuard.relock();
modules.insert(url, newModule);
+ }
return newModule;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 4cd7e40013..8312adee48 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -580,8 +580,10 @@ public:
QQmlRefPointer<CompiledData::CompilationUnit> compileModule(const QUrl &url, const QString &sourceCode);
static QQmlRefPointer<CompiledData::CompilationUnit> compileModule(bool debugMode, const QUrl &url, const QString &sourceCode, QList<QQmlJS::DiagnosticMessage> *diagnostics);
+ mutable QMutex moduleMutex;
QHash<QUrl, QQmlRefPointer<CompiledData::CompilationUnit>> modules;
void injectModule(const QQmlRefPointer<CompiledData::CompilationUnit> &moduleUnit);
+ QQmlRefPointer<CompiledData::CompilationUnit> moduleForUrl(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr) const;
QQmlRefPointer<CompiledData::CompilationUnit> loadModule(const QUrl &_url, const CompiledData::CompilationUnit *referrer = nullptr);
#endif
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 37c4f27ca9..070c048c8f 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -185,23 +185,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(QV4::Compi
parser.parseProgram();
- QList<QQmlError> errors;
-
- const auto diagnosticMessages = parser.diagnosticMessages();
- for (const DiagnosticMessage &m : diagnosticMessages) {
- if (m.isWarning()) {
- qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
- continue;
- }
-
- QQmlError error;
- error.setUrl(QUrl(fileName));
- error.setDescription(m.message);
- error.setLine(m.loc.startLine);
- error.setColumn(m.loc.startColumn);
- errors << error;
- }
-
+ QList<QQmlError> errors = QQmlEnginePrivate::qmlErrorFromDiagnostics(fileName, parser.diagnosticMessages());
if (!errors.isEmpty()) {
if (reportedErrors)
*reportedErrors << errors;