Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmltypeloader_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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#ifndef QQMLTYPELOADER_P_H
5#define QQMLTYPELOADER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qqmldatablob_p.h>
19#include <private/qqmlimport_p.h>
20#include <private/qqmlmetatype_p.h>
21#include <private/qqmltypeloaderdata_p.h>
22#include <private/qqmltypeloaderthread_p.h>
23#include <private/qv4compileddata_p.h>
24#include <private/qv4engine_p.h>
25
26#include <QtQml/qtqmlglobal.h>
27#include <QtQml/qqmlerror.h>
28
29#include <memory>
30
31QT_BEGIN_NAMESPACE
32
33class QQmlEngine;
34class QQmlEngineExtensionInterface;
35class QQmlExtensionInterface;
36class QQmlNetworkAccessManagerFactory;
37class QQmlProfiler;
38class QQmlQmldirData;
39class QQmlScriptBlob;
40class QQmlTypeData;
42
43class Q_QML_EXPORT QQmlTypeLoader
44{
45 Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
46public:
47 using ChecksumCache = QQmlTypeLoaderThreadData::ChecksumCache;
49
50 class Q_QML_EXPORT Blob : public QQmlDataBlob
51 {
52 public:
53 Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader);
54 ~Blob() override;
55
56 const QQmlImports *imports() const { return m_importCache.data(); }
57
58 void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status) { m_cachedUnitStatus = status; }
59
60 struct PendingImport
61 {
62 QString uri;
63 QString qualifier;
64
65 QV4::CompiledData::Import::ImportType type
66 = QV4::CompiledData::Import::ImportType::ImportLibrary;
67 QV4::CompiledData::Location location;
68
69 QQmlImports::ImportFlags flags;
70 quint8 precedence = 0;
71 int priority = 0;
72
73 QTypeRevision version;
74
75 PendingImport() = default;
76 PendingImport(const QQmlRefPointer<Blob> &blob, const QV4::CompiledData::Import *import,
77 QQmlImports::ImportFlags flags);
78 };
79 using PendingImportPtr = std::shared_ptr<PendingImport>;
80
81 void importQmldirScripts(const PendingImportPtr &import, const QQmlTypeLoaderQmldirContent &qmldir, const QUrl &qmldirUrl);
82 bool handleLocalQmldirForImport(
83 const PendingImportPtr &import, const QString &qmldirFilePath,
84 const QString &qmldirUrl, QList<QQmlError> *errors);
85
86 protected:
87 bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags,
88 QList<QQmlError> *errors);
89 bool addImport(const PendingImportPtr &import, QList<QQmlError> *errors);
90
91 bool fetchQmldir(
92 const QUrl &url, const PendingImportPtr &import, int priority,
93 QList<QQmlError> *errors);
94 bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const PendingImportPtr &import, QList<QQmlError> *errors);
95
96 private:
97 bool addScriptImport(const PendingImportPtr &import);
98 bool addFileImport(const PendingImportPtr &import, QList<QQmlError> *errors);
99 bool addLibraryImport(const PendingImportPtr &import, QList<QQmlError> *errors);
100
101 virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
102
103 virtual void scriptImported(
104 const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &,
105 const QString &, const QString &)
106 {
107 assertTypeLoaderThread();
108 }
109
110 void dependencyComplete(const QQmlDataBlob::Ptr &) override;
111
112 bool loadImportDependencies(
113 const PendingImportPtr &currentImport, const QString &qmldirUri,
114 QQmlImports::ImportFlags flags, QList<QQmlError> *errors);
115
116 protected:
117
118 bool registerPendingTypes(const PendingImportPtr &import);
119
120 bool loadDependentImports(
121 const QList<QQmlDirParser::Import> &imports, const QString &qualifier,
122 QTypeRevision version, quint8 precedence, QQmlImports::ImportFlags flags,
123 QList<QQmlError> *errors);
124 virtual QString stringAt(int) const { return QString(); }
125
126 QQmlRefPointer<QQmlImports> m_importCache;
127 QVector<PendingImportPtr> m_unresolvedImports;
128 QVector<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
129 QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
130 };
131
132 QQmlTypeLoader(QV4::ExecutionEngine *engine);
133 ~QQmlTypeLoader();
134
135 template<
136 typename Engine,
137 typename EnginePrivate = QQmlEnginePrivate,
139 static QQmlTypeLoader *get(Engine *engine)
140 {
141 return engine->handle()->typeLoader();
142 }
143
144 template<
145 typename Engine,
147 static QQmlTypeLoader *get(Engine *engine)
148 {
149 return Engine::get(engine)->handle()->typeLoader();
150 }
151
152 static void sanitizeUNCPath(QString *path)
153 {
154 // This handles the UNC path case as when the path is retrieved from the QUrl it
155 // will convert the host name from upper case to lower case. So the absoluteFilePath
156 // is changed at this point to make sure it will match later on in that case.
157 if (path->startsWith(QStringLiteral("//"))) {
158 // toLocalFile() since that faithfully restores all the things you can do to a
159 // path but not a URL, in particular weird characters like '%'.
160 *path = QUrl::fromLocalFile(*path).toLocalFile();
161 }
162 }
163
164 // We can't include QQmlTypeData here.
165 // Use a template specialized only for QQmlTypeData::TypeReference instead.
166 template<typename TypeReference>
168 QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
169 const QList<TypeReference> &compositeSingletons)
170 {
171 QQmlTypeLoaderThreadDataPtr data(&m_data);
172
173 QCryptographicHash hash(QCryptographicHash::Md5);
174 return (resolvedTypeCache->addToHash(&hash, &data->checksumCache)
175 && addTypeReferenceChecksumsToHash(
176 compositeSingletons, &data->checksumCache, &hash))
177 ? hash.result()
178 : QByteArray();
179 }
180
182 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
184 const QByteArray &data, const QUrl &url, Mode mode = PreferSynchronous);
185
187 const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
188
190 const QUrl &relativeUrl, const QV4::CompiledData::Unit *unit);
191
192 QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl, const QUrl &relativeUrl);
194
195 QString absoluteFilePath(const QString &path);
196
197 bool fileExists(const QString &filePath)
198 {
199 Q_ASSERT(!filePath.endsWith(QLatin1Char('/')));
200 const qsizetype pastLastSlash = filePath.lastIndexOf(QLatin1Char('/')) + 1;
201 return fileExists(
202 filePath.left(pastLastSlash - 1),
203 filePath.mid(pastLastSlash, filePath.size() - pastLastSlash));
204 }
205
206 bool fileExists(const QString &dirPath, const QString &file);
207 bool directoryExists(const QString &path);
208
209 const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath);
210 void setQmldirContent(const QString &filePath, const QString &content);
211
212 void clearCache();
213 void trimCache();
214
215 bool isTypeLoaded(const QUrl &url) const;
216 bool isScriptLoaded(const QUrl &url) const;
217
219 const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode = PreferSynchronous);
220
221 void drop(const QQmlDataBlob::Ptr &blob);
222
223 void initializeEngine(QQmlEngineExtensionInterface *, const char *);
224 void initializeEngine(QQmlExtensionInterface *, const char *);
225 void invalidate();
226
227 void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
228 void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
230 QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const;
231 bool hasUrlInterceptors() const;
232
233#if !QT_CONFIG(qml_debug)
234 quintptr profiler() const { return 0; }
235 void setProfiler(quintptr) {}
236#else
237 QQmlProfiler *profiler() const
238 {
239 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
240 return data->profiler.data();
241 }
242 void setProfiler(QQmlProfiler *profiler);
243#endif // QT_CONFIG(qml_debug)
244
246 {
247 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
248 return data->importPaths;
249 }
250 void setImportPathList(const QStringList &paths);
251 void addImportPath(const QString& dir);
252
254 {
255 QQmlTypeLoaderConfiguredDataConstPtr data(&m_data);
256 return data->pluginPaths;
257 }
258 void setPluginPathList(const QStringList &paths);
259 void addPluginPath(const QString& path);
260
261 void setPluginInitialized(const QString &plugin)
262 {
263 QQmlTypeLoaderThreadDataPtr data(&m_data);
264 data->initializedPlugins.insert(plugin);
265 }
266 bool isPluginInitialized(const QString &plugin) const
267 {
268 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
269 return data->initializedPlugins.contains(plugin);
270 }
271
272 void setModulePluginProcessingDone(const QString &module)
273 {
274 QQmlTypeLoaderThreadDataPtr data(&m_data);
275 data->modulesForWhichPluginsHaveBeenProcessed.insert(module);
276 }
277 bool isModulePluginProcessingDone(const QString &module)
278 {
279 QQmlTypeLoaderThreadDataConstPtr data(&m_data);
280 return data->modulesForWhichPluginsHaveBeenProcessed.contains(module);
281 }
282
283#if QT_CONFIG(qml_network)
284 QQmlNetworkAccessManagerFactoryPtrConst networkAccessManagerFactory() const;
285 void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory);
286 QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
287#endif
288
289 bool writeCacheFile();
290 bool readCacheFile();
291 bool isDebugging();
292
293private:
294 friend struct PlainLoader;
295 friend struct CachedLoader;
296 friend struct StaticLoader;
297
298 friend class QQmlDataBlob;
300#if QT_CONFIG(qml_network)
301 friend class QQmlTypeLoaderNetworkReplyProxy;
302#endif // qml_network
303
304 enum PathType { Local, Remote, LocalOrRemote };
305
306 enum LocalQmldirResult {
307 QmldirFound,
308 QmldirNotFound,
309 QmldirInterceptedToRemote,
310 QmldirRejected
311 };
312
313 QQmlTypeLoaderThread *thread() const { return m_data.thread(); }
314 QV4::ExecutionEngine *engine() const { return m_data.engine(); }
315
316 void startThread();
317 void shutdownThread();
318 QQmlTypeLoaderThread *ensureThread()
319 {
320 if (!thread())
321 startThread();
322 return thread();
323 }
324
325 void trimCache(const QQmlTypeLoaderSharedDataPtr &data);
326
327 void loadThread(const QQmlDataBlob::Ptr &);
328 void loadWithStaticDataThread(const QQmlDataBlob::Ptr &, const QByteArray &);
329 void loadWithCachedUnitThread(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
330#if QT_CONFIG(qml_network)
331 void networkReplyFinished(QNetworkReply *);
332 void networkReplyProgress(QNetworkReply *, qint64, qint64);
333#endif
334
335 enum class DataOrigin { Device, Static };
336 void setData(const QQmlDataBlob::Ptr &, const QByteArray &, DataOrigin);
337 void setData(const QQmlDataBlob::Ptr &, const QString &fileName);
338 void setData(const QQmlDataBlob::Ptr &, const QQmlDataBlob::SourceCodeData &);
339 void setCachedUnit(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit);
340
341 QStringList importPathList(PathType type) const;
342 void clearQmldirInfo();
343
344 LocalQmldirResult locateLocalQmldir(
345 QQmlTypeLoader::Blob *blob, const QQmlTypeLoader::Blob::PendingImportPtr &import,
346 QList<QQmlError> *errors);
347
348 void load(const QQmlDataBlob::Ptr &blob, Mode mode = PreferSynchronous);
349 void loadWithCachedUnit(
350 const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit,
351 Mode mode = PreferSynchronous);
352
353 template<typename Loader>
354 void doLoad(const Loader &loader, const QQmlDataBlob::Ptr &blob, Mode mode);
355 void updateTypeCacheTrimThreshold(const QQmlTypeLoaderSharedDataPtr &data);
356
357 template<typename TypeReference>
358 static bool addTypeReferenceChecksumsToHash(
359 const QList<TypeReference> &typeRefs,
360 QHash<quintptr, QByteArray> *checksums, QCryptographicHash *hash)
361 {
362 for (const auto &typeRef: typeRefs) {
363 if (typeRef.typeData) {
364 const auto unit = typeRef.typeData->compilationUnit()->unitData();
365 hash->addData({unit->md5Checksum, sizeof(unit->md5Checksum)});
366 } else if (const QMetaObject *mo = typeRef.type.metaObject()) {
367 const auto propertyCache = QQmlMetaType::propertyCache(mo);
368 bool ok = false;
369 hash->addData(propertyCache->checksum(checksums, &ok));
370 if (!ok)
371 return false;
372 }
373 }
374 return true;
375 }
376
377 template<typename Blob>
378 QQmlRefPointer<Blob> finalizeBlob(QQmlRefPointer<Blob> &&blob, QQmlTypeLoader::Mode mode)
379 {
380 QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
381 const QQmlMetaType::CacheMode cacheMode = aotCacheMode();
382 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
383 ? QQmlMetaType::findCachedCompilationUnit(blob->url(), cacheMode, &error)
384 : nullptr) {
385 loadWithCachedUnit(QQmlDataBlob::Ptr(blob.data()), cachedUnit, mode);
386 } else {
387 blob->setCachedUnitStatus(error);
388 load(QQmlDataBlob::Ptr(blob.data()), mode);
389 }
390
391 return blob;
392 }
393
394 QQmlMetaType::CacheMode aotCacheMode();
395
396 QQmlTypeLoaderLockedData m_data;
397};
398
399QT_END_NAMESPACE
400
401#endif // QQMLTYPELOADER_P_H
QQmlEngine * engine() const
Return the QQmlEngine this incubation controller is set on, or 0 if it has not been set on any engine...
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
void setModulePluginProcessingDone(const QString &module)
bool isPluginInitialized(const QString &plugin) const
bool fileExists(const QString &filePath)
QStringList pluginPathList() const
void drop(const QQmlDataBlob::Ptr &blob)
void initializeEngine(QQmlExtensionInterface *, const char *)
bool fileExists(const QString &dirPath, const QString &file)
void loadWithStaticData(const QQmlDataBlob::Ptr &blob, const QByteArray &data, Mode mode=PreferSynchronous)
Load the provided blob with data.
bool isTypeLoaded(const QUrl &url) const
QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
QQmlRefPointer< QV4::CompiledData::CompilationUnit > injectModule(const QUrl &relativeUrl, const QV4::CompiledData::Unit *unit)
QQmlRefPointer< QQmlTypeData > getType(const QByteArray &data, const QUrl &url, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the given data with the provided base url.
static void sanitizeUNCPath(QString *path)
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
bool isScriptLoaded(const QUrl &url) const
QString absoluteFilePath(const QString &path)
Returns the absolute filename of path via a directory cache.
bool isModulePluginProcessingDone(const QString &module)
void setPluginInitialized(const QString &plugin)
friend class QQmlDataBlob
static QQmlTypeLoader * get(Engine *engine)
bool directoryExists(const QString &path)
Returns true if the path is a directory via a directory cache.
void setImportPathList(const QStringList &paths)
void addImportPath(const QString &dir)
void setPluginPathList(const QStringList &paths)
bool hasUrlInterceptors() const
QList< QQmlAbstractUrlInterceptor * > urlInterceptors() const
void initializeEngine(QQmlEngineExtensionInterface *, const char *)
QByteArray hashDependencies(QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QList< TypeReference > &compositeSingletons)
void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QQmlRefPointer< QQmlQmldirData > getQmldir(const QUrl &)
Returns a QQmlQmldirData for url.
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl, const QUrl &relativeUrl)
Return a QQmlScriptBlob for unNormalizedUrl or relativeUrl.
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath)
Return a QQmlTypeLoaderQmldirContent for absoluteFilePath.
void clearCache()
Clears cached information about loaded files, including any type data, scripts and qmldir information...
static QQmlTypeLoader * get(Engine *engine)
void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
void addPluginPath(const QString &path)
void setQmldirContent(const QString &filePath, const QString &content)
QStringList importPathList() const