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