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
57
59{
61public:
64
71
73
76
77 // Maps from an import to a linked list of qmldir info.
78 // Used in locateLocalQmldir()
80
81 // Modules for which plugins have been loaded and processed in the context of this type
82 // loader's engine. Plugins can have engine-specific initialization callbacks. This is why
83 // we have to keep track of this.
85
86 // Plugins that have been initialized in the context of this engine. In theory, the same
87 // plugin can be used for multiple modules. Therefore, we need to keep track of this
88 // separately from modulesForWhichPluginsHaveBeenProcessed.
90
91#if QT_CONFIG(qml_network)
94#endif
95};
96
98{
100public:
102
105
106 // URL interceptors must be set before loading any types. Otherwise we get data races.
108
109#if QT_CONFIG(qml_debug)
111#endif
112
115 bool isDebugging = false;
116 bool initialized = false;
117};
118
119#if QT_CONFIG(qml_network)
120class QQmlTypeLoaderNetworkAccessManagerData
121{
122 Q_DISABLE_COPY_MOVE(QQmlTypeLoaderNetworkAccessManagerData)
123public:
124 QQmlTypeLoaderNetworkAccessManagerData() = default;
125
126 QQmlNetworkAccessManagerFactory *networkAccessManagerFactory = nullptr;
127
128 // We need a separate mutex because the network access manger factory can be accessed not
129 // only from the engine thread and the type loader thread, but also from any WorkerScripts
130 // running in parallel to both.
131 mutable QMutex networkAccessManagerMutex;
132};
133#endif // QTCONFIG(qml_network)
134
136{
137 template<typename Data, typename LockedData>
139
140 template<typename Data, typename LockedData>
142
143 template<typename Data, typename LockedData>
145
146 template<typename Data, typename LockedData>
148 friend class QQmlNetworkAccessManagerFactoryPtr;
149
151public:
153
154 QQmlTypeLoaderThread *thread() const { return m_thread; }
155
156 void createThread(QQmlTypeLoader *loader)
157 {
158 Q_ASSERT(isCurrentJsEngineThread());
159 m_thread = new QQmlTypeLoaderThread(loader);
160 m_thread->startup();
161 }
162
164 {
165 Q_ASSERT(isCurrentJsEngineThread());
166 Q_ASSERT(m_thread);
167
168 // Shut it down first, then set it to nullptr, then delete it.
169 // This makes sure that any blobs deleted as part of the deletion
170 // do not see the thread anymore.
171 m_thread->shutdown();
172 delete std::exchange(m_thread, nullptr);
173 }
174
176 {
177 Q_ASSERT(isCurrentJsEngineThread());
178 return m_engine;
179 }
180
181private:
182 bool isCurrentJsEngineThread() const
183 {
184 if (QJSEngine *jsEngine = m_engine->jsEngine())
185 return jsEngine->thread()->isCurrentThread();
186
187 // If we can't determine the thread, assume it's the right one
188 return true;
189 }
190
191
192 QQmlTypeLoaderSharedData m_sharedData;
193 QQmlTypeLoaderThreadData m_threadData;
194 QQmlTypeLoaderConfiguredData m_configuredData;
195#if QT_CONFIG(qml_network)
197#endif
198
199 QV4::ExecutionEngine *m_engine = nullptr;
200 QQmlTypeLoaderThread *m_thread = nullptr;
201};
202
203template<typename Data, typename LockedData>
231
234using QQmlTypeLoaderSharedDataConstPtr
237template<typename Data, typename LockedData>
239{
241public:
243 {
244 Q_ASSERT(data);
245
246 // You have to either be on the type loader thread or shut it down before accessing this.
250 Data &operator*() const { return data->m_threadData; }
251 Data *operator->() const { return &data->m_threadData; }
252 operator Data *() const { return &data->m_threadData; }
253
254private:
255 LockedData *data = nullptr;
258using QQmlTypeLoaderThreadDataPtr
260using QQmlTypeLoaderThreadDataConstPtr
262
263
264template<typename Data, typename LockedData>
266{
268public:
270 {
271 Q_ASSERT(data);
272
273 if constexpr (!std::is_const_v<Data>) {
274 // const access is generally fine
275 // For mutable access we first need to make sure the thread is shut down.
277 thread->shutdown();
278 wasShutDown = true;
280 }
281 }
282
284 {
285 if constexpr (!std::is_const_v<Data>) {
286 // After we're done modifying the configuration, we need to restart the thread.
287 if (wasShutDown) {
288 Q_ASSERT(data->thread());
290 data->thread()->restart();
294
295 Data &operator*() const { return data->m_configuredData; }
296 Data *operator->() const { return &data->m_configuredData; }
297 operator Data *() const { return &data->m_configuredData; }
298
299private:
300 LockedData *data = nullptr;
301 bool wasShutDown = false;
302};
303
304using QQmlTypeLoaderConfiguredDataPtr
306using QQmlTypeLoaderConfiguredDataConstPtr
308
309#if QT_CONFIG(qml_network)
310class QQmlEnginePublicAPIToken;
311template<typename Data, typename LockedData>
312class QQmlNetworkAccessManagerFactoryPtrBase
313{
314 Q_DISABLE_COPY_MOVE(QQmlNetworkAccessManagerFactoryPtrBase)
315public:
316 Q_NODISCARD_CTOR QQmlNetworkAccessManagerFactoryPtrBase(LockedData *data) : data(data)
317 {
318 Q_ASSERT(data);
319 data->m_networkAccessManagerData.networkAccessManagerMutex.lock();
320 }
321
322 ~QQmlNetworkAccessManagerFactoryPtrBase()
323 {
324 Q_ASSERT(data);
325 data->m_networkAccessManagerData.networkAccessManagerMutex.unlock();
326 }
327
328 QQmlNetworkAccessManagerFactory &operator*() const
329 {
330 return *data->m_networkAccessManagerData.networkAccessManagerFactory;
331 }
332
333 QQmlNetworkAccessManagerFactory *operator->() const
334 {
335 return data->m_networkAccessManagerData.networkAccessManagerFactory;
336 }
337
338 operator bool() const
339 {
340 return data->m_networkAccessManagerData.networkAccessManagerFactory != nullptr;
341 }
342
343 // This is dangerous since it allows you to subvert the locking.
344 // You must only do this when serving public API that can't be changed for now.
345 QQmlNetworkAccessManagerFactory *get(const QQmlEnginePublicAPIToken &) const
346 {
347 return data->m_networkAccessManagerData.networkAccessManagerFactory;
348 }
349
350protected:
351 LockedData *data = nullptr;
352};
353
354// This is const in the sense that you cannot reset the pointer. Therefore the "Const" postfix.
355// That's in contrast to the other *Ptr classes here that are const in the way that the _data_
356// pointed to cannot be modified.
357using QQmlNetworkAccessManagerFactoryPtrConst
358 = QQmlNetworkAccessManagerFactoryPtrBase<const QQmlTypeLoaderNetworkAccessManagerData, const QQmlTypeLoaderLockedData>;
359
360class QQmlNetworkAccessManagerFactoryPtr
361 : public QQmlNetworkAccessManagerFactoryPtrBase<QQmlTypeLoaderNetworkAccessManagerData, QQmlTypeLoaderLockedData>
362{
363 Q_DISABLE_COPY(QQmlNetworkAccessManagerFactoryPtr)
364public:
365 Q_NODISCARD_CTOR QQmlNetworkAccessManagerFactoryPtr(QQmlTypeLoaderLockedData *lockedData)
366 : QQmlNetworkAccessManagerFactoryPtrBase<QQmlTypeLoaderNetworkAccessManagerData, QQmlTypeLoaderLockedData>(lockedData)
367 {
368 }
369
370 void reset(QQmlNetworkAccessManagerFactory *factory)
371 {
372 data->m_networkAccessManagerData.networkAccessManagerFactory = factory;
373 }
374};
375#endif // QT_CONFIG(qml_network)
376
377QT_END_NAMESPACE
378
379#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
QQmlTypeLoaderSharedData()=default
ImportQmlDirCache importQmlDirCache
QSet< QString > modulesForWhichPluginsHaveBeenProcessed
QQmlTypeLoaderThreadData()=default
QStringHash< QmldirInfo * > qmldirInfo
Combined button and popup list for selecting options.
QQmlTypeLoaderSharedDataPtrBase< QQmlTypeLoaderSharedData, QQmlTypeLoaderLockedData > QQmlTypeLoaderSharedDataPtr