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
qv4qobjectwrapper_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 QV4QOBJECTWRAPPER_P_H
6#define QV4QOBJECTWRAPPER_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/qintrusivelist_p.h>
21#include <private/qqmldata_p.h>
22#include <private/qv4functionobject_p.h>
23#include <private/qv4lookup_p.h>
24#include <private/qv4value_p.h>
25
26#include <QtCore/qglobal.h>
27#include <QtCore/qmetatype.h>
28#include <QtCore/qhash.h>
29
30#include <utility>
31
33
35
36class QObject;
37class QQmlData;
38class QQmlPropertyCache;
40class QQmlObjectOrGadget;
41
42namespace QV4 {
44
45namespace Heap {
46
47struct QQmlValueTypeWrapper;
48
51 {
52 Object::init();
54 }
55
56 void destroy() {
57 qObj.destroy();
58 Object::destroy();
59 }
60
61 QObject *object() const { return qObj.data(); }
63
64private:
66};
67
68#define QObjectMethodMembers(class, Member)
69 Member(class, Pointer, Object *, wrapper)
70
71DECLARE_EXPORTED_HEAP_OBJECT(QObjectMethod, FunctionObject) {
72 DECLARE_MARKOBJECTS(QObjectMethod)
73
74 QQmlPropertyData *methods;
75 alignas(alignof(QQmlPropertyData)) std::byte _singleMethod[sizeof(QQmlPropertyData)];
76 int methodCount;
77 int index;
78
79 void init(QV4::ExecutionEngine *engine, Object *wrapper, int index);
80 void destroy()
81 {
82 if (methods != reinterpret_cast<const QQmlPropertyData *>(&_singleMethod))
83 delete[] methods;
84 FunctionObject::destroy();
85 }
86
87 void ensureMethodsCache(const QMetaObject *thisMeta);
88 QString name() const;
89
90 const QMetaObject *metaObject() const;
91 QObject *object() const;
92
93 bool isDetached() const;
94 bool isAttachedTo(QObject *o) const;
95
96 enum ThisObjectMode {
97 Invalid,
98 Included,
99 Explicit,
100 };
101
102 QV4::Heap::QObjectMethod::ThisObjectMode checkThisObject(const QMetaObject *thisMeta) const;
103};
104
106 void init(QObject *object, int signalIndex);
107 void destroy() {
108 qObj.destroy();
109 Object::destroy();
110 }
112
113 QObject *object() const { return qObj.data(); }
114 void setObject(QObject *o) { qObj = o; }
115
116private:
117 QV4QPointer<QObject> qObj;
118};
119
120}
121
122struct Q_QML_EXPORT QObjectWrapper : public Object
123{
127
135
137
139
140 const QMetaObject *metaObject() const
141 {
142 if (QObject *o = object())
143 return o->metaObject();
144 return nullptr;
145 }
146
147 QObject *object() const { return d()->object(); }
148
151 Flags flags, bool *hasProperty = nullptr) const;
152
156 bool *hasProperty = nullptr, const QQmlPropertyData **property = nullptr);
157
158 static bool setQmlProperty(
161
162 Q_NODISCARD_X("Use ensureWrapper if you don't need the return value")
164 Q_NODISCARD_X("Throwing the const wrapper away can cause it to be garbage collected")
168
169 using Object::get;
170
173 static void setProperty(
175 const QQmlPropertyData *property, const Value &value);
176
177 void destroyObject(bool lastCall);
178
182
186
188
195 static bool virtualResolveLookupSetter(
198
199 static int virtualMetacall(Object *object, QMetaObject::Call call, int index, void **a);
200
201 static QString objectToString(
203
204protected:
205 static bool virtualIsEqualTo(Managed *that, Managed *o);
207
208 static const QQmlPropertyData *findProperty(
211
215
217 const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
218 static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
220
222 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
224 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
225
226private:
229};
230
232
233// We generally musn't pass ReturnedValue as arguments to other functions.
234// In this case, we do it solely for marking purposes so it's fine.
245
247{
249 return QV4::Encode::null();
250
251 auto ddata = QQmlData::get(object);
253 // We own the JS object
254 return ddata->jsWrapper.value();
255 }
256
257 const auto rv = wrap_slowPath(engine, object);
259 return rv;
260}
261
262// Unfortunately we still need a non-const QObject* here because QQmlData needs to register itself in QObjectPrivate.
272
273inline bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
274{
275 while (fromMo) {
276 if (fromMo == toMo)
277 return true;
278 fromMo = fromMo->parent().data();
279 }
280 return false;
281}
282
283template <typename ReversalFunctor>
287{
288 // we can safely cast to a QV4::Object here. If object is something else,
289 // the internal class won't match
290 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
291 if (!o || o->internalClass != lookup->qobjectLookup.ic)
292 return revertLookup();
293
294 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
295 QObject *qobj = This->object();
297 return QV4::Encode::undefined();
298
299 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
300 if (!ddata)
301 return revertLookup();
302
305 // If the property is overridden and the lookup allows overrides to be considered,
306 // we have to revert here and redo the lookup from scratch.
308 && ((flags & AllowOverride)
309 || property->isFunction()
310 || property->isSignalHandler())) {
311 return revertLookup();
312 }
313
315 return revertLookup();
316 }
317
319}
320
321template <typename ReversalFunctor>
325{
326 // we can safely cast to a QV4::Object here. If object is something else,
327 // the internal class won't match
328 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
330 return revertLookup();
331
332 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
333 QObject *qobj = This->object();
335 return QV4::Encode::undefined();
336
337 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
338 if (!ddata)
339 return revertLookup();
340
344 return revertLookup();
345
347 return revertLookup();
348 }
349
351 if (method->isDetached())
352 return method->asReturnedValue();
353 }
354
355 if (!property) // was toString() or destroy()
356 return revertLookup();
357
360 if (!v->as<QObjectMethod>())
361 return revertLookup();
362
364 return v->asReturnedValue();
365}
366
367struct QQmlValueTypeWrapper;
368
369struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
370{
373
374 enum { DestroyMethod = -1, ToStringMethod = -2 };
375
377 static ReturnedValue create(
379 static ReturnedValue create(
382
383 int methodIndex() const { return d()->index; }
384 QObject *object() const { return d()->object(); }
385
388 QV4::ExecutionEngine *ctx, QObject *o, const Value *args, int argc) const;
389 bool method_destroy(
390 QV4::ExecutionEngine *engine, QObject *o, int delay) const;
391
393 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
394 static void virtualCallWithMetaTypes(
396 void **argv, const QMetaType *types, int argc);
397
399 const Value *thisObject, const Value *argv, int argc) const;
401 QObject *thisObject, void **argv, const QMetaType *types, int argc) const;
402
403 static std::pair<QObject *, int> extractQtMethod(const QV4::FunctionObject *function);
404
405 static bool isExactMatch(
406 const QMetaMethod &method, void **argv, int argc, const QMetaType *types);
407
408private:
409 friend struct QMetaObjectWrapper;
410
414
417 void **argv, int argc, const QMetaType *types);
418
423};
424
425struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object
426{
430
431 int signalIndex() const { return d()->signalIndex; }
432 QObject *object() const { return d()->object(); }
433
434 ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const;
435
436 static void initProto(ExecutionEngine *v4);
437};
438
440
443{
445public:
448
450
451 ConstIterator begin() const { return QHash<QObjectBiPointer, QV4::WeakValue>::constBegin(); }
452 Iterator begin() { return QHash<QObjectBiPointer, QV4::WeakValue>::begin(); }
453 ConstIterator end() const { return QHash<QObjectBiPointer, QV4::WeakValue>::constEnd(); }
454 Iterator end() { return QHash<QObjectBiPointer, QV4::WeakValue>::end(); }
455
456 template<typename Pointer>
457 void insert(Pointer key, Heap::Object *value)
458 {
459 QHash<QObjectBiPointer, WeakValue>::operator[](key).set(value->internalClass->engine, value);
460 connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
461 }
462
463 template<typename Pointer>
464 ReturnedValue value(Pointer key) const
465 {
466 ConstIterator it = find(key);
467 return it == end()
468 ? QV4::WeakValue().value()
469 : it->value();
470 }
471
473
474 template<typename Pointer>
475 void remove(Pointer key)
476 {
477 Iterator it = find(key);
478 if (it == end())
479 return;
480 erase(it);
481 }
482
483 template<typename Pointer>
484 void mark(Pointer key, MarkStack *markStack)
485 {
486 Iterator it = find(key);
487 if (it == end())
488 return;
489 it->markOnce(markStack);
490 }
491
492private Q_SLOTS:
494};
495
496}
497
498QT_END_NAMESPACE
499
500#endif // QV4QOBJECTWRAPPER_P_H
void insert(Pointer key, Heap::Object *value)
void mark(Pointer key, MarkStack *markStack)
QHash< QObjectBiPointer, QV4::WeakValue >::Iterator Iterator
ReturnedValue value(Pointer key) const
DECLARE_EXPORTED_HEAP_OBJECT(QObjectMethod, FunctionObject)
Definition qjsvalue.h:23
bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher)
#define V4_NEEDS_DESTROY
#define Q_MANAGED_TYPE(type)
void init(QObject *object, int signalIndex)