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 | |
39 | QT_BEGIN_NAMESPACE |
40 | |
41 | class QQmlVMEMetaObject; |
42 | class QQmlVMEResolvedList |
43 | { |
44 | Q_DISABLE_COPY_MOVE(QQmlVMEResolvedList) |
45 | |
46 | public: |
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 | |
56 | private: |
57 | QQmlVMEMetaObject *m_metaObject = nullptr; |
58 | QVector<QQmlGuard<QObject>> *m_list = nullptr; |
59 | quintptr m_id = 0; |
60 | }; |
61 | |
62 | class QQmlVMEVariantQObjectPtr : public QQmlGuard<QObject> |
63 | { |
64 | public: |
65 | inline QQmlVMEVariantQObjectPtr(); |
66 | |
67 | inline void setGuardedValue(QObject *obj, QQmlVMEMetaObject *target, int index); |
68 | |
69 | QQmlVMEMetaObject *m_target; |
70 | int m_index; |
71 | |
72 | private: |
73 | static void objectDestroyedImpl(QQmlGuardImpl *guard); |
74 | }; |
75 | |
76 | |
77 | class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QDynamicMetaObjectData |
78 | { |
79 | public: |
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 | |
108 | protected: |
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 | |
134 | private: |
135 | bool doIntercept(QMetaObject::Call c, int id, void **a); |
136 | QQmlPropertyValueInterceptor *interceptors = nullptr; |
137 | }; |
138 | |
139 | inline 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 | |
151 | class QQmlVMEMetaObjectEndpoint; |
152 | class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject |
153 | { |
154 | public: |
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 | |
179 | protected: |
180 | int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override; |
181 | |
182 | public: |
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 | |
262 | QQmlVMEMetaObject *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 | |
274 | int QQmlVMEMetaObject::propOffset() const |
275 | { |
276 | return cache->propertyOffset(); |
277 | } |
278 | |
279 | int QQmlVMEMetaObject::methodOffset() const |
280 | { |
281 | return cache->methodOffset(); |
282 | } |
283 | |
284 | int QQmlVMEMetaObject::signalOffset() const |
285 | { |
286 | return cache->signalOffset(); |
287 | } |
288 | |
289 | int QQmlVMEMetaObject::signalCount() const |
290 | { |
291 | return cache->signalCount(); |
292 | } |
293 | |
294 | QQmlVMEMetaObject *QQmlVMEMetaObject::parentVMEMetaObject() const |
295 | { |
296 | if (parent.isT1() && parent.flag()) |
297 | return static_cast<QQmlVMEMetaObject *>(parent.asT1()); |
298 | |
299 | return nullptr; |
300 | } |
301 | |
302 | QT_END_NAMESPACE |
303 | |
304 | #endif // QQMLVMEMETAOBJECT_P_H |
305 | |