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