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
qqmlguard_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 QQMLGUARD_P_H
6#define QQMLGUARD_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 for the convenience
13// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
14// file may change from version to version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmldata_p.h>
20#include <private/qqmlglobal_p.h>
21
22QT_BEGIN_NAMESPACE
23
24class QQmlGuardImpl
25{
26public:
27 using ObjectDestroyedFn = void(*)(QQmlGuardImpl *);
28
29 inline QQmlGuardImpl();
30 inline QQmlGuardImpl(QObject *);
31 inline QQmlGuardImpl(const QQmlGuardImpl &);
32protected:
33 inline ~QQmlGuardImpl();
34
35public: // ### make so it can be private
36 QObject *o = nullptr;
37 QQmlGuardImpl *next = nullptr;
38 QQmlGuardImpl **prev = nullptr;
39 ObjectDestroyedFn objectDestroyed = nullptr;
40
41 inline void addGuard();
42 inline void remGuard();
43
44 inline void setObject(QObject *g);
45 bool isNull() const noexcept { return !o; }
46};
47
48class QObject;
49template<class T>
50class QQmlGuard : protected QQmlGuardImpl
51{
52 friend class QQmlData;
53public:
57 Q_NODISCARD_CTOR inline QQmlGuard(const QQmlGuard<T> &);
58
59 inline QQmlGuard<T> &operator=(const QQmlGuard<T> &o);
60 inline QQmlGuard<T> &operator=(T *);
61
62 T *object() const noexcept { return static_cast<T *>(o); }
63 void setObject(T *g) { QQmlGuardImpl::setObject(g); }
64
65 using QQmlGuardImpl::isNull;
66
67 T *operator->() const noexcept { return object(); }
68 T &operator*() const { return *object(); }
69 operator T *() const noexcept { return object(); }
70 T *data() const noexcept { return object(); }
71};
72
73/* used in QQmlStrongJSQObjectReference to indicate that the
74 * object has JS ownership
75 * We save it in objectDestroyFn to save space
76 * (implemented in qqmlengine.cpp)
77 */
78void Q_QML_EXPORT hasJsOwnershipIndicator(QQmlGuardImpl *);
79
80template <typename T>
81class QQmlStrongJSQObjectReference final : protected QQmlGuardImpl
82{
83public:
84 T *object() const noexcept { return static_cast<T *>(o); }
85
86 using QQmlGuardImpl::isNull;
87
88 T *operator->() const noexcept { return object(); }
89 T &operator*() const { return *object(); }
90 operator T *() const noexcept { return object(); }
91 T *data() const noexcept { return object(); }
92
93 void setObject(T *obj, QObject *parent) {
94 T *old = object();
95 if (obj == old)
96 return;
97
98 if (hasJsOwnership() && old && old->parent() == parent)
99 QQml_setParent_noEvent(old, nullptr);
100
101 QQmlGuardImpl::setObject(obj);
102
103 if (obj && !obj->parent() && !QQmlData::keepAliveDuringGarbageCollection(obj)) {
104 setJsOwnership(true);
105 QQml_setParent_noEvent(obj, parent);
106 } else {
107 setJsOwnership(false);
108 }
109 }
110
111private:
112 bool hasJsOwnership() {
113 return objectDestroyed == hasJsOwnershipIndicator;
114 }
115
116 void setJsOwnership(bool itHasOwnership) {
117 objectDestroyed = itHasOwnership ? hasJsOwnershipIndicator : nullptr;
118 }
119};
120
121QT_END_NAMESPACE
122
123Q_DECLARE_METATYPE(QQmlGuard<QObject>)
124
125QT_BEGIN_NAMESPACE
126
127QQmlGuardImpl::QQmlGuardImpl()
128{
129}
130
131QQmlGuardImpl::QQmlGuardImpl(QObject *g)
132: o(g)
133{
134 if (o) addGuard();
135}
136
137/*
138 \internal
139 Copying a QQmlGuardImpl leaves the old one in the intrinsic linked list of guards.
140 The fresh copy does not contain the list pointer of the existing guard; instead
141 only the object and objectDestroyed pointers are copied, and if there is an object
142 we add the new guard to the object's list of guards.
143 */
144QQmlGuardImpl::QQmlGuardImpl(const QQmlGuardImpl &g)
145: o(g.o), objectDestroyed(g.objectDestroyed)
146{
147 if (o) addGuard();
148}
149
150QQmlGuardImpl::~QQmlGuardImpl()
151{
152 if (prev) remGuard();
153 o = nullptr;
154}
155
156void QQmlGuardImpl::addGuard()
157{
158 Q_ASSERT(!prev);
159
160 if (QObjectPrivate::get(o)->wasDeleted)
161 return;
162
163 QQmlData *data = QQmlData::get(o, true);
164 next = data->guards;
165 if (next) next->prev = &next;
166 data->guards = this;
167 prev = &data->guards;
168}
169
170void QQmlGuardImpl::remGuard()
171{
172 Q_ASSERT(prev);
173
174 if (next) next->prev = prev;
175 *prev = next;
176 next = nullptr;
177 prev = nullptr;
178}
179
180template<class T>
181QQmlGuard<T>::QQmlGuard()
182{
183}
184
185template<class T>
186QQmlGuard<T>::QQmlGuard(ObjectDestroyedFn objDestroyed, T *obj)
187 : QQmlGuardImpl(obj)
188{
189 objectDestroyed = objDestroyed;
190}
191
192template<class T>
193QQmlGuard<T>::QQmlGuard(T *g)
194: QQmlGuardImpl(g)
195{
196}
197
198template<class T>
199QQmlGuard<T>::QQmlGuard(const QQmlGuard<T> &g)
200: QQmlGuardImpl(g)
201{
202}
203
204template<class T>
205QQmlGuard<T> &QQmlGuard<T>::operator=(const QQmlGuard<T> &g)
206{
207 objectDestroyed = g.objectDestroyed;
208 setObject(g.object());
209 return *this;
210}
211
212template<class T>
213QQmlGuard<T> &QQmlGuard<T>::operator=(T *g)
214{
215 /* this does not touch objectDestroyed, as operator= is only a convenience
216 * for setObject. All logic involving objectDestroyed is (sub-)class specific
217 * and remains unaffected.
218 */
219 setObject(g);
220 return *this;
221}
222
223void QQmlGuardImpl::setObject(QObject *g)
224{
225 if (g != o) {
226 if (prev) remGuard();
227 o = g;
228 if (o) addGuard();
229 }
230}
231
232QT_END_NAMESPACE
233
234#endif // QQMLGUARD_P_H
T & operator*() const
Definition qqmlguard_p.h:68
QQmlGuard< T > & operator=(T *)
operator T*() const noexcept
Definition qqmlguard_p.h:69
T * operator->() const noexcept
Definition qqmlguard_p.h:67
void setObject(T *g)
Definition qqmlguard_p.h:63
T * object() const noexcept
Definition qqmlguard_p.h:62
QQmlGuard< T > & operator=(const QQmlGuard< T > &o)
T * data() const noexcept
Definition qqmlguard_p.h:70
T * object() const noexcept
Definition qqmlguard_p.h:84
operator T*() const noexcept
Definition qqmlguard_p.h:90
T * operator->() const noexcept
Definition qqmlguard_p.h:88
void setObject(T *obj, QObject *parent)
Definition qqmlguard_p.h:93
T * data() const noexcept
Definition qqmlguard_p.h:91
QDebug Q_QML_EXPORT operator<<(QDebug debug, const QQmlError &error)