Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlscriptblob.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <private/qqmlengine_p.h>
5#include <private/qqmlirbuilder_p.h>
6#include <private/qqmlscriptblob_p.h>
7#include <private/qqmlscriptdata_p.h>
8#include <private/qqmlsourcecoordinate_p.h>
9#include <private/qqmlcontextdata_p.h>
10#include <private/qv4runtimecodegen_p.h>
11#include <private/qv4script_p.h>
12
13#include <QtCore/qloggingcategory.h>
14
15Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
16Q_LOGGING_CATEGORY(DBG_DISK_CACHE, "qt.qml.diskcache")
17
19
21 : QQmlTypeLoader::Blob(url, JavaScriptFile, loader)
22 , m_isModule(url.path().endsWith(QLatin1String(".mjs")))
23{
24}
25
27{
28}
29
31{
32 return m_scriptData;
33}
34
36{
37 if (readCacheFile()) {
41 if (unit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
42 initializeFromCompilationUnit(unit);
43 return;
44 } else {
45 qCDebug(DBG_DISK_CACHE()) << "Error loading" << urlString() << "from disk cache:" << error;
46 }
47 }
48
49 if (!data.exists()) {
51 setError(QQmlTypeLoader::tr("File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile"));
52 else
53 setError(QQmlTypeLoader::tr("No such file or directory"));
54 return;
55 }
56
58 QString source = data.readAll(&error);
59 if (!error.isEmpty()) {
61 return;
62 }
63
65
66 if (m_isModule) {
69 data.sourceTimeStamp(), &diagnostics);
71 if (!errors.isEmpty()) {
73 return;
74 }
75 } else {
77
78 irUnit.jsModule.sourceTimeStamp = data.sourceTimeStamp();
79
80 QmlIR::ScriptDirectivesCollector collector(&irUnit);
81 irUnit.jsParserEngine.setDirectives(&collector);
82
85 &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(),
87
88 source.clear();
89 if (!errors.isEmpty()) {
91 return;
92 }
93
94 QmlIR::QmlUnitGenerator qmlGenerator;
95 qmlGenerator.generate(irUnit);
96 unit = std::move(irUnit.javaScriptCompilationUnit);
97 }
98
99 auto executableUnit = QV4::ExecutableCompilationUnit::create(std::move(unit));
100
101 if (writeCacheFile()) {
102 QString errorString;
103 if (executableUnit->saveToDisk(url(), &errorString)) {
105 if (!executableUnit->loadFromDisk(url(), data.sourceTimeStamp(), &error)) {
106 // ignore error, keep using the in-memory compilation unit.
107 }
108 } else {
109 qCDebug(DBG_DISK_CACHE()) << "Error saving cached version of"
110 << executableUnit->fileName() << "to disk:" << errorString;
111 }
112 }
113
114 initializeFromCompilationUnit(executableUnit);
115}
116
118{
119 initializeFromCompilationUnit(QV4::ExecutableCompilationUnit::create(
121}
122
124{
125 if (isError())
126 return;
127
128 // Check all script dependencies for errors
129 for (int ii = 0; ii < m_scripts.size(); ++ii) {
130 const ScriptReference &script = m_scripts.at(ii);
132 if (script.script->isError()) {
135 error.setUrl(url());
138 error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
141 return;
142 }
143 }
144
145 if (!m_isModule) {
147
149
150 for (int scriptIndex = 0; scriptIndex < m_scripts.size(); ++scriptIndex) {
151 const ScriptReference &script = m_scripts.at(scriptIndex);
152
153 m_scriptData->scripts.append(script.script);
154
155 if (!script.nameSpace.isNull()) {
156 if (!ns.contains(script.nameSpace)) {
157 ns.insert(script.nameSpace);
158 m_scriptData->typeNameCache->add(script.nameSpace);
159 }
160 }
161 m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace);
162 }
163
165 }
166 m_scripts.clear();
167}
168
170{
171 return m_scriptData->m_precompiledScript->stringAt(index);
172}
173
175{
177 ref.script = blob;
178 ref.location = location;
179 ref.qualifier = qualifier;
180 ref.nameSpace = nameSpace;
181
182 m_scripts << ref;
183}
184
185void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit)
186{
187 Q_ASSERT(!m_scriptData);
188 m_scriptData.adopt(new QQmlScriptData());
189 m_scriptData->url = finalUrl();
190 m_scriptData->urlString = finalUrlString();
191 m_scriptData->m_precompiledScript = unit;
192
194
195 QQmlRefPointer<QV4::ExecutableCompilationUnit> script = m_scriptData->m_precompiledScript;
196
197 if (!m_isModule) {
199 for (quint32 i = 0, count = script->importCount(); i < count; ++i) {
200 const QV4::CompiledData::Import *import = script->importAt(i);
201 if (!addImport(import, {}, &errors)) {
204 error.setUrl(m_importCache->baseUrl());
205 error.setLine(import->location.line());
206 error.setColumn(import->location.column());
207 errors.prepend(error); // put it back on the list after filling out information.
209 return;
210 }
211 }
212 }
213
215
216 v4->injectCompiledModule(unit);
217
218 for (const QString &request: unit->moduleRequests()) {
219 const auto module = v4->moduleForUrl(QUrl(request), unit.data());
220 if (module.compiled || module.native)
221 continue;
222
223 const QUrl absoluteRequest = unit->finalUrl().resolved(QUrl(request));
224 QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(absoluteRequest);
225 addDependency(blob.data());
226 scriptImported(blob, /* ### */QV4::CompiledData::Location(), /*qualifier*/QString(), /*namespace*/QString());
227 }
228}
229
238void QQmlScriptBlob::initializeFromNative(const QV4::Value &value)
239{
240 Q_ASSERT(!m_scriptData);
241 m_scriptData.adopt(new QQmlScriptData());
242 m_scriptData->url = finalUrl();
243 m_scriptData->urlString = finalUrlString();
244 m_scriptData->m_loaded = true;
245 m_scriptData->m_value.set(QQmlEnginePrivate::getV4Engine(typeLoader()->engine()), value);
247}
248
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
value_type takeFirst()
Definition qlist.h:549
void prepend(rvalue_ref t)
Definition qlist.h:456
bool isError() const
Returns true if the status is Error.
bool isCompleteOrError() const
Returns true if the status is Complete or Error.
void addDependency(QQmlDataBlob *)
Wait for blob to become complete or to error.
QList< QQmlError > errors() const
Return the errors on this blob.
QUrl url() const
Returns the physical url of the data.
QQmlTypeLoader * typeLoader() const
QUrl finalUrl() const
Returns the logical URL to be used for resolving further URLs referred to in the code.
QString finalUrlString() const
Returns the finalUrl() as a string.
void setError(const QQmlError &)
Mark this blob as having errors.
QString urlString() const
static QList< QQmlError > qmlErrorFromDiagnostics(const QString &fileName, const QList< QQmlJS::DiagnosticMessage > &diagnosticMessages)
static QV4::ExecutionEngine * getV4Engine(QQmlEngine *e)
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
void populateCache(QQmlTypeNameCache *cache) const
void setBaseUrl(const QUrl &url, const QString &urlString=QString())
Sets the base URL to be used for all relative file imports added.
QUrl baseUrl() const
void setDirectives(Directives *directives)
T * data() const
QQmlRefPointer< T > & adopt(T *)
Takes ownership of other.
void scriptImported(const QQmlRefPointer< QQmlScriptBlob > &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override
QQmlRefPointer< QQmlScriptData > scriptData() const
~QQmlScriptBlob() override
void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override
void dataReceived(const SourceCodeData &) override
Invoked when data for the blob is received.
QString stringAt(int index) const override
void done() override
Invoked once data has either been received or a network error occurred, and all dependencies are comp...
QVector< QQmlRefPointer< QQmlScriptBlob > > scripts
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags, QList< QQmlError > *errors)
QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus
QQmlRefPointer< QQmlImports > m_importCache
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl)
Return a QQmlScriptBlob for url.
void add(const QHashedString &name, int sciptIndex=-1, const QHashedString &nameSpace=QHashedString())
Definition qset.h:18
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
\inmodule QtCore
Definition qurl.h:94
static QV4::CompiledData::CompilationUnit compileModule(bool debugMode, const QString &url, const QString &sourceCode, const QDateTime &sourceTimeStamp, QList< QQmlJS::DiagnosticMessage > *diagnostics)
static QQmlRefPointer< ExecutableCompilationUnit > create()
void set(ExecutionEngine *engine, const Value &value)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLint location
GLuint index
[2]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint ref
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(*) void arg)
unsigned int quint32
Definition qtypes.h:45
QUrl url("example.com")
[constructor-url-reference]
QNetworkRequest request(url)
QJSEngine engine
[0]
const AOTCompiledFunction * aotCompiledFunctions
const QV4::CompiledData::Unit * qmlData
QQmlRefPointer< QQmlScriptBlob > script
QV4::CompiledData::Location location
static QV4::CompiledData::CompilationUnit precompile(QV4::Compiler::Module *module, QQmlJS::Engine *jsEngine, Compiler::JSUnitGenerator *unitGenerator, const QString &fileName, const QString &finalUrl, const QString &source, QList< QQmlError > *reportedErrors=nullptr, QV4::Compiler::ContextType contextType=QV4::Compiler::ContextType::Global)
QV4::Compiler::Module jsModule
QV4::CompiledData::CompilationUnit javaScriptCompilationUnit
QV4::Compiler::JSUnitGenerator jsGenerator
QQmlJS::Engine jsParserEngine
void generate(Document &output, const QV4::CompiledData::DependentTypesHasher &dependencyHasher=QV4::CompiledData::DependentTypesHasher())