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
qqmlvmemetaobject_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 BasysKom GmbH.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant
5
6#ifndef QQMLVMEMETAOBJECT_P_H
7#define QQMLVMEMETAOBJECT_P_H
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists purely as an
14// implementation detail. This header file may change from version to
15// version without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include <private/qbipointer_p.h>
21#include <private/qqmlguard_p.h>
22#include <private/qqmlguardedcontextdata_p.h>
23#include <private/qqmlpropertyvalueinterceptor_p.h>
24#include <private/qv4object_p.h>
25#include <private/qv4value_p.h>
26
27#include <QtCore/private/qobject_p.h>
28
29#if QT_CONFIG(regularexpression)
30#include <QtCore/qregularexpression.h>
31#endif
32
33#include <QtCore/qbitarray.h>
34#include <QtCore/qdatetime.h>
35#include <QtCore/qdebug.h>
36#include <QtCore/qlist.h>
37#include <QtCore/qmetaobject.h>
38
39QT_BEGIN_NAMESPACE
40
41class QQmlVMEMetaObject;
43{
45
46public:
49
50 QQmlVMEMetaObject *metaObject() const { return m_metaObject; }
51 QV4::Heap::Object *list() const { return m_list; }
52 quintptr id() const { return m_id; }
53
54 void append(QObject *o) const;
55 void replace(qsizetype i, QObject *o) const;
56 QObject *at(qsizetype i) const;
57
58 qsizetype size() const { return m_list->arrayData->length(); }
59
60 void clear() const
61 {
62 QV4::Scope scope(m_list->internalClass->engine);
63 QV4::ScopedObject object(scope, m_list);
64 m_list->arrayData->vtable()->truncate(object, 0);
65 }
66
67 void removeLast() const
68 {
69 const uint length = m_list->arrayData->length();
70 if (length == 0)
71 return;
72
73 QV4::Scope scope(m_list->internalClass->engine);
74 QV4::ScopedObject object(scope, m_list);
75 m_list->arrayData->vtable()->truncate(object, length - 1);
76 }
77
78 void activateSignal() const;
79
80private:
81 QQmlVMEMetaObject *m_metaObject = nullptr;
82 QV4::Heap::Object *m_list = nullptr;
83 quintptr m_id = 0;
84};
85
87{
88public:
90
91 inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index);
92
93 QQmlVMEMetaObject *m_target;
95
96private:
97 static void objectDestroyedImpl(QQmlGuardImpl *guard);
98};
99
100
101class Q_QML_EXPORT QQmlInterceptorMetaObject : public QDynamicMetaObjectData
102{
103public:
104 QQmlInterceptorMetaObject(QObject *obj, const QQmlPropertyCache::ConstPtr &cache);
105 ~QQmlInterceptorMetaObject() override;
106
107 void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor);
108
109 static QQmlInterceptorMetaObject *get(QObject *obj);
110
111#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
112 const QMetaObject *toDynamicMetaObject(QObject *o) const override;
113#else
114 QMetaObject *toDynamicMetaObject(QObject *o) override;
115#endif
116
117 // Used by auto-tests for inspection
118 QQmlPropertyCache::ConstPtr propertyCache() const { return cache; }
119
120 bool intercepts(QQmlPropertyIndex propertyIndex) const
121 {
122 for (auto it = interceptors; it; it = it->m_next) {
123 if (it->m_propertyIndex == propertyIndex)
124 return true;
125 }
126 if (auto parentInterceptor = ((parent.isT1() && parent.flag()) ? static_cast<QQmlInterceptorMetaObject *>(parent.asT1()) : nullptr))
127 return parentInterceptor->intercepts(propertyIndex);
128 return false;
129 }
130
131 void invalidate() { metaObject.setTag(MetaObjectInvalid); }
132
133 QObject *object = nullptr;
134 QQmlPropertyCache::ConstPtr cache;
135
136protected:
137 int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) override;
138 bool intercept(QMetaObject::Call c, int id, void **a)
139 {
140 if (!interceptors)
141 return false;
142
143 switch (c) {
144 case QMetaObject::WriteProperty:
145 if (*reinterpret_cast<int*>(a[3]) & QQmlPropertyData::BypassInterceptor)
146 return false;
147 break;
148 case QMetaObject::BindableProperty:
149 break;
150 default:
151 return false;
152 }
153
154 return doIntercept(c, id, a);
155 }
156
157 QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
158
159 enum MetaObjectValidity { MetaObjectValid, MetaObjectInvalid };
160 QTaggedPointer<const QMetaObject, MetaObjectValidity> metaObject;
161
162private:
163 bool doIntercept(QMetaObject::Call c, int id, void **a);
164 QQmlPropertyValueInterceptor *interceptors = nullptr;
165};
166
167inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj)
168{
169 if (obj) {
170 if (QQmlData *data = QQmlData::get(obj)) {
171 if (data->hasInterceptorMetaObject)
172 return static_cast<QQmlInterceptorMetaObject *>(QObjectPrivate::get(obj)->metaObject);
173 }
174 }
175
176 return nullptr;
177}
178
180class Q_QML_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
181{
182public:
183 QQmlVMEMetaObject(
184 QV4::ExecutionEngine *engine, QObject *obj, const QQmlPropertyCache::ConstPtr &cache,
185 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit,
186 int qmlObjectId);
187 ~QQmlVMEMetaObject() override;
188
189 bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
190 QV4::ReturnedValue vmeMethod(int index) const;
191 void setVmeMethod(int index, const QV4::Value &function);
192 QV4::ReturnedValue vmeProperty(int index) const;
193 void setVMEProperty(int index, const QV4::Value &v);
194
195 void connectAliasSignal(int index, bool indexInSignalRange);
196
197 static inline QQmlVMEMetaObject *get(QObject *o);
198 static QQmlVMEMetaObject *getForProperty(QObject *o, int coreIndex);
199 static QQmlVMEMetaObject *getForMethod(QObject *o, int coreIndex);
200 static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
201
202 static void list_append(QQmlListProperty<QObject> *prop, QObject *o);
203 static void list_clear(QQmlListProperty<QObject> *prop);
204 static void list_append_nosignal(QQmlListProperty<QObject> *prop, QObject *o);
205 static void list_clear_nosignal(QQmlListProperty<QObject> *prop);
206
207 inline int propOffset() const;
208 inline int propCount() const;
209 inline int aliasOffset() const;
210 inline int aliasCount() const;
211 inline int signalOffset() const;
212 inline int signalCount() const;
213 inline int methodOffset() const;
214 inline int methodCount() const;
215
216 QV4::MemberData *propertyAndMethodStorageAsMemberData() const;
217
218 int readPropertyAsInt(int id) const;
219 bool readPropertyAsBool(int id) const;
220 double readPropertyAsDouble(int id) const;
221 QString readPropertyAsString(int id) const;
222 QSizeF readPropertyAsSizeF(int id) const;
223 QPointF readPropertyAsPointF(int id) const;
224 QUrl readPropertyAsUrl(int id) const;
225 QDate readPropertyAsDate(int id) const;
226 QTime readPropertyAsTime(int id) const;
227 QDateTime readPropertyAsDateTime(int id) const;
228
229#if QT_CONFIG(regularexpression)
230 QRegularExpression readPropertyAsRegularExpression(int id) const;
231#endif
232
233 QRectF readPropertyAsRectF(int id) const;
234 QObject *readPropertyAsQObject(int id) const;
235 void initPropertyAsList(int id) const;
236
237 void writeProperty(int id, int v);
238 void writeProperty(int id, bool v);
239 void writeProperty(int id, double v);
240 void writeProperty(int id, const QString& v);
241
242 template<typename VariantCompatible>
243 void writeProperty(int id, const VariantCompatible &v)
244 {
245 QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
246 if (md) {
247 QV4::Scope scope(m_engine);
248 QV4::Scoped<QV4::MemberData>(scope, md)->set(
249 m_engine, id, m_engine->newVariantObject(
250 QMetaType::fromType<VariantCompatible>(), &v));
251 }
252 }
253
254 void writeProperty(int id, QObject *v);
255
256 void ensureQObjectWrapper();
257
258 void mark(QV4::MarkStack *markStack);
259
260 void connectAlias(const QV4::CompiledData::Object *compiledObject, int aliasId);
261
262 QV4::ReturnedValue method(int) const;
263
264 QV4::ReturnedValue readVarProperty(int) const;
265 void writeVarProperty(int, const QV4::Value &);
266 QVariant readPropertyAsVariant(int) const;
267
268 inline QQmlVMEMetaObject *parentVMEMetaObject() const;
269
270 void activate(QObject *, int, void **);
271
272 QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
273
274 QQmlRefPointer<QQmlContextData> contextData() const { return m_ctxt.contextData(); }
275 QV4::ExecutionEngine *engine() const { return m_engine; }
276 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() const
277 {
278 return m_compilationUnit;
279 }
280
281protected:
282 int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override;
283 bool getListProperty(int id, QQmlListProperty<QObject> *target);
284
285private:
286 friend class QQmlVMEMetaObjectEndpoint;
287 friend class QQmlVMEResolvedList;
288 friend class QQmlVMEVariantQObjectPtr;
289
290 const QV4::CompiledData::Object *findCompiledObject() const {
291 // If the executable CU has been stripped of its engine, it has an empty base CU
292 if (!m_compilationUnit || !m_compilationUnit->engine)
293 return nullptr;
294
295 Q_ASSERT(m_qmlObjectId >= 0 && m_qmlObjectId < m_compilationUnit->objectCount());
296 return m_compilationUnit->objectAt(m_qmlObjectId);
297 }
298
299 void writeKnownVarProperty(int id, const QVariant &value);
300
301 QV4::ExecutionEngine *m_engine;
302 QQmlGuardedContextData m_ctxt;
303
304 QQmlVMEMetaObjectEndpoint *m_aliasEndpoints;
305 QV4::WeakValue m_propertyAndMethodStorage;
306
307 QList<QQmlVMEVariantQObjectPtr *> m_varObjectGuards;
308
309 // keep a reference to the compilation unit in order to still
310 // do property access when the context has been invalidated.
311 QQmlRefPointer<QV4::ExecutableCompilationUnit> m_compilationUnit;
312 int m_qmlObjectId = -1;
313 int m_numAliases = 0;
314};
315
316QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
317{
318 if (obj) {
319 if (QQmlData *data = QQmlData::get(obj)) {
320 if (data->hasVMEMetaObject)
321 return static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(obj)->metaObject);
322 }
323 }
324
325 return nullptr;
326}
327
328int QQmlVMEMetaObject::propOffset() const
329{
330 // Regular properties are before aliases
331 return cache->propertyOffset();
332}
333
334int QQmlVMEMetaObject::propCount() const
335{
336 // Properties excluding aliases
337 return cache->ownPropertyCount() - m_numAliases;
338}
339
340int QQmlVMEMetaObject::aliasOffset() const
341{
342 // Aliases are after regular properties
343 return propOffset() + propCount();
344}
345
346int QQmlVMEMetaObject::aliasCount() const
347{
348 // We need to cache this since we don't want to count over and over.
349 return m_numAliases;
350}
351
352int QQmlVMEMetaObject::signalOffset() const
353{
354 // Signals are before regular methods
355 return cache->methodOffset();
356}
357
358int QQmlVMEMetaObject::signalCount() const
359{
360 // Signals including signals for properties and aliases
361 return cache->ownSignalCount();
362}
363
364int QQmlVMEMetaObject::methodOffset() const
365{
366 // Regular methods are after signals
367 return signalOffset() + signalCount();
368}
369
370int QQmlVMEMetaObject::methodCount() const
371{
372 // Methods excluding signals
373 return cache->ownMethodCount() - signalCount();
374}
375
376QQmlVMEMetaObject *QQmlVMEMetaObject::parentVMEMetaObject() const
377{
378 if (parent.isT1() && parent.flag())
379 return static_cast<QQmlVMEMetaObject *>(parent.asT1());
380
381 return nullptr;
382}
383
384QT_END_NAMESPACE
385
386#endif // QQMLVMEMETAOBJECT_P_H
QTaggedPointer< QQmlVMEMetaObject, Tag > metaObject
QQmlVMEMetaObject * metaObject() const
void replace(qsizetype i, QObject *o) const
qsizetype size() const
QV4::Heap::Object * list() const
void append(QObject *o) const
QObject * at(qsizetype i) const
QQmlVMEMetaObject * m_target
void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index)
static const QMetaObject * stringCastMetaObject(QObject *o, const QMetaObject *top)
static void list_removeLast(QQmlListProperty< QObject > *prop)
static QObject * list_at(QQmlListProperty< QObject > *prop, qsizetype index)
static qsizetype list_count(QQmlListProperty< QObject > *prop)
static void list_replace(QQmlListProperty< QObject > *prop, qsizetype index, QObject *o)
void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
static bool propertyIndicesConflict(QQmlPropertyIndex a, QQmlPropertyIndex b)