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#include <QtCore/qpair.h>
38
39QT_BEGIN_NAMESPACE
40
41class QQmlVMEMetaObject;
42class QQmlVMEResolvedList
43{
44 Q_DISABLE_COPY_MOVE(QQmlVMEResolvedList)
45
46public:
47 QQmlVMEResolvedList(QQmlListProperty<QObject> *prop);
48 ~QQmlVMEResolvedList();
49
50 QQmlVMEMetaObject *metaObject() const { return m_metaObject; }
51 QVector<QQmlGuard<QObject>> *list() const { return m_list; }
52 quintptr id() const { return m_id; }
53
54 void activateSignal() const;
55
56private:
57 QQmlVMEMetaObject *m_metaObject = nullptr;
58 QVector<QQmlGuard<QObject>> *m_list = nullptr;
59 quintptr m_id = 0;
60};
61
62class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject>
63{
64public:
65 inline QQmlVMEVariantQObjectPtr();
66
67 inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index);
68
69 QQmlVMEMetaObject *m_target;
70 int m_index;
71
72private:
73 static void objectDestroyedImpl(QQmlGuardImpl *guard);
74};
75
76
77class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QDynamicMetaObjectData
78{
79public:
80 QQmlInterceptorMetaObject(QObject *obj, const QQmlPropertyCache::ConstPtr &cache);
81 ~QQmlInterceptorMetaObject() override;
82
83 void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor);
84
85 static QQmlInterceptorMetaObject *get(QObject *obj);
86
87 QMetaObject *toDynamicMetaObject(QObject *o) override;
88
89 // Used by auto-tests for inspection
90 QQmlPropertyCache::ConstPtr propertyCache() const { return cache; }
91
92 bool intercepts(QQmlPropertyIndex propertyIndex) const
93 {
94 for (auto it = interceptors; it; it = it->m_next) {
95 if (it->m_propertyIndex == propertyIndex)
96 return true;
97 }
98 if (auto parentInterceptor = ((parent.isT1() && parent.flag()) ? static_cast<QQmlInterceptorMetaObject *>(parent.asT1()) : nullptr))
99 return parentInterceptor->intercepts(propertyIndex);
100 return false;
101 }
102
103 void invalidate() { metaObject.setTag(MetaObjectInvalid); }
104
105 QObject *object = nullptr;
106 QQmlPropertyCache::ConstPtr cache;
107
108protected:
109 int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) override;
110 bool intercept(QMetaObject::Call c, int id, void **a)
111 {
112 if (!interceptors)
113 return false;
114
115 switch (c) {
116 case QMetaObject::WriteProperty:
117 if (*reinterpret_cast<int*>(a[3]) & QQmlPropertyData::BypassInterceptor)
118 return false;
119 break;
120 case QMetaObject::BindableProperty:
121 break;
122 default:
123 return false;
124 }
125
126 return doIntercept(c, id, a);
127 }
128
129 QBiPointer<QDynamicMetaObjectData, const QMetaObject> parent;
130
131 enum MetaObjectValidity { MetaObjectValid, MetaObjectInvalid };
132 QTaggedPointer<const QMetaObject, MetaObjectValidity> metaObject;
133
134private:
135 bool doIntercept(QMetaObject::Call c, int id, void **a);
136 QQmlPropertyValueInterceptor *interceptors = nullptr;
137};
138
139inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj)
140{
141 if (obj) {
142 if (QQmlData *data = QQmlData::get(object: obj)) {
143 if (data->hasInterceptorMetaObject)
144 return static_cast<QQmlInterceptorMetaObject *>(QObjectPrivate::get(o: obj)->metaObject);
145 }
146 }
147
148 return nullptr;
149}
150
151class QQmlVMEMetaObjectEndpoint;
152class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
153{
154public:
155 QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj,
156 const QQmlPropertyCache::ConstPtr &cache,
157 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit,
158 int qmlObjectId);
159 ~QQmlVMEMetaObject() override;
160
161 bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
162 QV4::ReturnedValue vmeMethod(int index) const;
163 void setVmeMethod(int index, const QV4::Value &function);
164 QV4::ReturnedValue vmeProperty(int index) const;
165 void setVMEProperty(int index, const QV4::Value &v);
166
167 void connectAliasSignal(int index, bool indexInSignalRange);
168
169 static inline QQmlVMEMetaObject *get(QObject *o);
170 static QQmlVMEMetaObject *getForProperty(QObject *o, int coreIndex);
171 static QQmlVMEMetaObject *getForMethod(QObject *o, int coreIndex);
172 static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex);
173
174 static void list_append(QQmlListProperty<QObject> *prop, QObject *o);
175 static void list_clear(QQmlListProperty<QObject> *prop);
176 static void list_append_nosignal(QQmlListProperty<QObject> *prop, QObject *o);
177 static void list_clear_nosignal(QQmlListProperty<QObject> *prop);
178
179protected:
180 int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override;
181
182public:
183 QV4::ExecutionEngine *engine;
184 QQmlGuardedContextData ctxt;
185
186 inline int propOffset() const;
187 inline int methodOffset() const;
188 inline int signalOffset() const;
189 inline int signalCount() const;
190
191 QQmlVMEMetaObjectEndpoint *aliasEndpoints;
192
193 QV4::WeakValue propertyAndMethodStorage;
194 QV4::MemberData *propertyAndMethodStorageAsMemberData() const;
195
196 int readPropertyAsInt(int id) const;
197 bool readPropertyAsBool(int id) const;
198 double readPropertyAsDouble(int id) const;
199 QString readPropertyAsString(int id) const;
200 QSizeF readPropertyAsSizeF(int id) const;
201 QPointF readPropertyAsPointF(int id) const;
202 QUrl readPropertyAsUrl(int id) const;
203 QDate readPropertyAsDate(int id) const;
204 QTime readPropertyAsTime(int id) const;
205 QDateTime readPropertyAsDateTime(int id) const;
206
207#if QT_CONFIG(regularexpression)
208 QRegularExpression readPropertyAsRegularExpression(int id) const;
209#endif
210
211 QRectF readPropertyAsRectF(int id) const;
212 QObject *readPropertyAsQObject(int id) const;
213 QVector<QQmlGuard<QObject> > *readPropertyAsList(int id) const;
214
215 void writeProperty(int id, int v);
216 void writeProperty(int id, bool v);
217 void writeProperty(int id, double v);
218 void writeProperty(int id, const QString& v);
219
220 template<typename VariantCompatible>
221 void writeProperty(int id, const VariantCompatible &v)
222 {
223 QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
224 if (md) {
225 QV4::Scope scope(engine);
226 QV4::Scoped<QV4::MemberData>(scope, md)->set(
227 engine, id, engine->newVariantObject(
228 type: QMetaType::fromType<VariantCompatible>(), data: &v));
229 }
230 }
231
232 void writeProperty(int id, QObject *v);
233
234 void ensureQObjectWrapper();
235
236 void mark(QV4::MarkStack *markStack);
237
238 void connectAlias(int aliasId);
239
240 QV4::ReturnedValue method(int) const;
241
242 QV4::ReturnedValue readVarProperty(int) const;
243 void writeVarProperty(int, const QV4::Value &);
244 QVariant readPropertyAsVariant(int) const;
245 void writeProperty(int, const QVariant &);
246
247 inline QQmlVMEMetaObject *parentVMEMetaObject() const;
248
249 void activate(QObject *, int, void **);
250
251 QList<QQmlVMEVariantQObjectPtr *> varObjectGuards;
252
253 QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
254
255
256 // keep a reference to the compilation unit in order to still
257 // do property access when the context has been invalidated.
258 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
259 const QV4::CompiledData::Object *compiledObject;
260};
261
262QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
263{
264 if (obj) {
265 if (QQmlData *data = QQmlData::get(object: obj)) {
266 if (data->hasVMEMetaObject)
267 return static_cast<QQmlVMEMetaObject *>(QObjectPrivate::get(o: obj)->metaObject);
268 }
269 }
270
271 return nullptr;
272}
273
274int QQmlVMEMetaObject::propOffset() const
275{
276 return cache->propertyOffset();
277}
278
279int QQmlVMEMetaObject::methodOffset() const
280{
281 return cache->methodOffset();
282}
283
284int QQmlVMEMetaObject::signalOffset() const
285{
286 return cache->signalOffset();
287}
288
289int QQmlVMEMetaObject::signalCount() const
290{
291 return cache->signalCount();
292}
293
294QQmlVMEMetaObject *QQmlVMEMetaObject::parentVMEMetaObject() const
295{
296 if (parent.isT1() && parent.flag())
297 return static_cast<QQmlVMEMetaObject *>(parent.asT1());
298
299 return nullptr;
300}
301
302QT_END_NAMESPACE
303
304#endif // QQMLVMEMETAOBJECT_P_H
305

source code of qtdeclarative/src/qml/qml/qqmlvmemetaobject_p.h