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
qqmltypeloaderdata_p.h
Go to the documentation of this file.
1// Copyright (C) 2024 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 QQMLTYPELOADERDATA_P_H
6#define QQMLTYPELOADERDATA_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/qqmlrefcount_p.h>
20#include <private/qqmltypeloaderqmldircontent_p.h>
21#include <private/qqmltypeloaderthread_p.h>
22#include <private/qv4engine_p.h>
23
24#include <QtQml/qtqmlglobal.h>
25#include <QtQml/qqmlengine.h>
26
27#include <QtCore/qcache.h>
28#include <QtCore/qthread.h>
29
30QT_BEGIN_NAMESPACE
31
32class QQmlProfiler;
33class QQmlQmldirData;
34class QQmlScriptBlob;
35class QQmlTypeData;
36
66
68{
70public:
73
80
82
85
86 // Maps from an import to a linked list of qmldir info.
87 // Used in locateLocalQmldir()
89
90 // Modules for which plugins have been loaded and processed in the context of this type
91 // loader's engine. Plugins can have engine-specific initialization callbacks. This is why
92 // we have to keep track of this.
94
95 // Plugins that have been initialized in the context of this engine. In theory, the same
96 // plugin can be used for multiple modules. Therefore, we need to keep track of this
97 // separately from modulesForWhichPluginsHaveBeenProcessed.
99
100#if QT_CONFIG(qml_network)
103#endif
104};
105
107{
109public:
111
114
115 // URL interceptors must be set before loading any types. Otherwise we get data races.
117
118#if QT_CONFIG(qml_debug)
120#endif
121
124 bool isDebugging = false;
125 bool initialized = false;
126};
127
128#if QT_CONFIG(qml_network)
129class QQmlTypeLoaderNetworkAccessManagerData
130{
131 Q_DISABLE_COPY_MOVE(QQmlTypeLoaderNetworkAccessManagerData)
132public:
133 QQmlTypeLoaderNetworkAccessManagerData() = default;
134
135 QQmlNetworkAccessManagerFactory *networkAccessManagerFactory = nullptr;
136
137 // We need a separate mutex because the network access manger factory can be accessed not
138 // only from the engine thread and the type loader thread, but also from any WorkerScripts
139 // running in parallel to both.
140 mutable QMutex networkAccessManagerMutex;
141};
142#endif // QTCONFIG(qml_network)
143
145{
146 template<typename Data, typename LockedData>
148
149 template<typename Data, typename LockedData>
151
152 template<typename Data, typename LockedData>
154
155 template<typename Data, typename LockedData>
157 friend class QQmlNetworkAccessManagerFactoryPtr;
158
160public:
162
163 QQmlTypeLoaderThread *thread() const { return m_thread; }
164
165 void createThread(QQmlTypeLoader *loader)
166 {
167 Q_ASSERT(isCurrentJsEngineThread());
168 m_thread = new QQmlTypeLoaderThread(loader);
169 m_thread->startup();
170 }
171
173 {
174 Q_ASSERT(isCurrentJsEngineThread());
175 Q_ASSERT(m_thread);
176
177 // Shut it down first, then set it to nullptr, then delete it.
178 // This makes sure that any blobs deleted as part of the deletion
179 // do not see the thread anymore.
180 m_thread->shutdown();
181 delete std::exchange(m_thread, nullptr);
182 }
183
185 {
186 Q_ASSERT(isCurrentJsEngineThread());
187 return m_engine;
188 }
189
190private:
191 bool isCurrentJsEngineThread() const
192 {
193 if (QJSEngine *jsEngine = m_engine->jsEngine())
194 return jsEngine->thread()->isCurrentThread();
195
196 // If we can't determine the thread, assume it's the right one
197 return true;
198 }
199
200
201 QQmlTypeLoaderSharedData m_sharedData;
202 QQmlTypeLoaderThreadData m_threadData;
203 QQmlTypeLoaderConfiguredData m_configuredData;
204#if QT_CONFIG(qml_network)
206#endif
207
208 QV4::ExecutionEngine *m_engine = nullptr;
209 QQmlTypeLoaderThread *m_thread = nullptr;
210};
211
212template<typename Data, typename LockedData>
240
243using QQmlTypeLoaderSharedDataConstPtr
246template<typename Data, typename LockedData>
248{
250public:
252 {
253 Q_ASSERT(data);
254
255 // You have to either be on the type loader thread or shut it down before accessing this.
259 Data &operator*() const { return data->m_threadData; }
260 Data *operator->() const { return &data->m_threadData; }
261 operator Data *() const { return &data->m_threadData; }
262
263private:
264 LockedData *data = nullptr;
267using QQmlTypeLoaderThreadDataPtr
269using QQmlTypeLoaderThreadDataConstPtr
271
272
273template<typename Data, typename LockedData>
275{
277public:
279 {
280 Q_ASSERT(data);
281
282 if constexpr (!std::is_const_v<Data>) {
283 // const access is generally fine
284 // For mutable access we first need to make sure the thread is shut down.
286 thread->shutdown();
287 wasShutDown = true;
289 }
290 }
291
293 {
294 if constexpr (!std::is_const_v<Data>) {
295 // After we're done modifying the configuration, we need to restart the thread.
296 if (wasShutDown) {
297 Q_ASSERT(data->thread());
299 data->thread()->restart();
303
304 Data &operator*() const { return data->m_configuredData; }
305 Data *operator->() const { return &data->m_configuredData; }
306 operator Data *() const { return &data->m_configuredData; }
307
308private:
309 LockedData *data = nullptr;
310 bool wasShutDown = false;
311};
312
313using QQmlTypeLoaderConfiguredDataPtr
315using QQmlTypeLoaderConfiguredDataConstPtr
317
318#if QT_CONFIG(qml_network)
319class QQmlEnginePublicAPIToken;
320template<typename Data, typename LockedData>
321class QQmlNetworkAccessManagerFactoryPtrBase
322{
323 Q_DISABLE_COPY_MOVE(QQmlNetworkAccessManagerFactoryPtrBase)
324public:
325 Q_NODISCARD_CTOR QQmlNetworkAccessManagerFactoryPtrBase(LockedData *data) : data(data)
326 {
327 Q_ASSERT(data);
328 data->m_networkAccessManagerData.networkAccessManagerMutex.lock();
329 }
330
331 ~QQmlNetworkAccessManagerFactoryPtrBase()
332 {
333 Q_ASSERT(data);
334 data->m_networkAccessManagerData.networkAccessManagerMutex.unlock();
335 }
336
337 QQmlNetworkAccessManagerFactory &operator*() const
338 {
339 return *data->m_networkAccessManagerData.networkAccessManagerFactory;
340 }
341
342 QQmlNetworkAccessManagerFactory *operator->() const
343 {
344 return data->m_networkAccessManagerData.networkAccessManagerFactory;
345 }
346
347 operator bool() const
348 {
349 return data->m_networkAccessManagerData.networkAccessManagerFactory != nullptr;
350 }
351
352 // This is dangerous since it allows you to subvert the locking.
353 // You must only do this when serving public API that can't be changed for now.
354 QQmlNetworkAccessManagerFactory *get(const QQmlEnginePublicAPIToken &) const
355 {
356 return data->m_networkAccessManagerData.networkAccessManagerFactory;
357 }
358
359protected:
360 LockedData *data = nullptr;
361};
362
363// This is const in the sense that you cannot reset the pointer. Therefore the "Const" postfix.
364// That's in contrast to the other *Ptr classes here that are const in the way that the _data_
365// pointed to cannot be modified.
366using QQmlNetworkAccessManagerFactoryPtrConst
367 = QQmlNetworkAccessManagerFactoryPtrBase<const QQmlTypeLoaderNetworkAccessManagerData, const QQmlTypeLoaderLockedData>;
368
369class QQmlNetworkAccessManagerFactoryPtr
370 : public QQmlNetworkAccessManagerFactoryPtrBase<QQmlTypeLoaderNetworkAccessManagerData, QQmlTypeLoaderLockedData>
371{
372 Q_DISABLE_COPY(QQmlNetworkAccessManagerFactoryPtr)
373public:
374 Q_NODISCARD_CTOR QQmlNetworkAccessManagerFactoryPtr(QQmlTypeLoaderLockedData *lockedData)
375 : QQmlNetworkAccessManagerFactoryPtrBase<QQmlTypeLoaderNetworkAccessManagerData, QQmlTypeLoaderLockedData>(lockedData)
376 {
377 }
378
379 void reset(QQmlNetworkAccessManagerFactory *factory)
380 {
381 data->m_networkAccessManagerData.networkAccessManagerFactory = factory;
382 }
383};
384#endif // QT_CONFIG(qml_network)
385
386QT_END_NAMESPACE
387
388#endif // QQMLTYPELOADERDATA_P_H
QList< QQmlAbstractUrlInterceptor * > urlInterceptors
QV4::ExecutionEngine::DiskCacheOptions diskCacheOptions
friend class QQmlNetworkAccessManagerFactoryPtrBase
friend class QQmlTypeLoaderConfiguredDataPtrBase
QQmlTypeLoaderThread * thread() const
void createThread(QQmlTypeLoader *loader)
QV4::ExecutionEngine * engine() const
bool fileExists(const QString &path, const QString &file)
bool directoryExists(const QString &dirPath)
QQmlTypeLoaderSharedData()=default
ImportQmlDirCache importQmlDirCache
QSet< QString > modulesForWhichPluginsHaveBeenProcessed
QQmlTypeLoaderThreadData()=default
QStringHash< QmldirInfo * > qmldirInfo
Combined button and popup list for selecting options.
FileSetPopulateResult
static FileSetPopulateResult populateFileSet(QCache< QString, bool > *fileSet, const QString &path, const QString &file)
static QT_BEGIN_NAMESPACE constexpr QDirListing::IteratorFlags dirListingFlags()
QQmlTypeLoaderSharedDataPtrBase< QQmlTypeLoaderSharedData, QQmlTypeLoaderLockedData > QQmlTypeLoaderSharedDataPtr