Qt 6.x
The Qt SDK
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
4#ifndef QV4QOBJECTWRAPPER_P_H
5#define QV4QOBJECTWRAPPER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qbipointer_p.h>
19#include <private/qintrusivelist_p.h>
20#include <private/qqmldata_p.h>
21#include <private/qv4functionobject_p.h>
22#include <private/qv4lookup_p.h>
23#include <private/qv4value_p.h>
24
25#include <QtCore/qglobal.h>
26#include <QtCore/qmetatype.h>
27#include <QtCore/qpair.h>
28#include <QtCore/qhash.h>
29
31
32class QObject;
33class QQmlData;
36
37namespace QV4 {
38struct QObjectSlotDispatcher;
39
40namespace Heap {
41
42struct QQmlValueTypeWrapper;
43
44struct Q_QML_EXPORT QObjectWrapper : Object {
45 void init(QObject *object)
46 {
47 Object::init();
48 qObj.init(object);
49 }
50
51 void destroy() {
52 qObj.destroy();
53 Object::destroy();
54 }
55
56 QObject *object() const { return qObj.data(); }
57 static void markObjects(Heap::Base *that, MarkStack *markStack);
58
59private:
61};
62
63#define QObjectMethodMembers(class, Member) \
64 Member(class, Pointer, Object *, wrapper) \
65
68
70 alignas(alignof(QQmlPropertyData)) std::byte _singleMethod[sizeof(QQmlPropertyData)];
71 int methodCount;
72 int index;
73
74 void init(QV4::ExecutionContext *scope, Object *wrapper, int index);
75 void destroy()
76 {
77 if (methods != reinterpret_cast<const QQmlPropertyData *>(&_singleMethod))
78 delete[] methods;
79 FunctionObject::destroy();
80 }
81
82 void ensureMethodsCache(const QMetaObject *thisMeta);
83 QString name() const;
84
85 const QMetaObject *metaObject() const;
86 QObject *object() const;
87
88 bool isDetached() const;
89 bool isAttachedTo(QObject *o) const;
90
91 enum ThisObjectMode {
92 Invalid,
93 Included,
94 Explicit,
95 };
96
97 QV4::Heap::QObjectMethod::ThisObjectMode checkThisObject(const QMetaObject *thisMeta) const;
98};
99
104
105 void init(const QMetaObject* metaObject);
106 void destroy();
108};
109
111 void init(QObject *object, int signalIndex);
112 void destroy() {
113 qObj.destroy();
114 Object::destroy();
115 }
117
118 QObject *object() const { return qObj.data(); }
119 void setObject(QObject *o) { qObj = o; }
120
121private:
123};
124
125}
126
127struct Q_QML_EXPORT QObjectWrapper : public Object
128{
131
132 enum Flag {
133 NoFlag = 0x0,
134 CheckRevision = 0x1,
135 AttachMethods = 0x2,
136 AllowOverride = 0x4,
137 IncludeImports = 0x8,
138 };
139
141
142 static void initializeBindings(ExecutionEngine *engine);
143
144 const QMetaObject *metaObject() const
145 {
146 if (QObject *o = object())
147 return o->metaObject();
148 return nullptr;
149 }
150
151 QObject *object() const { return d()->object(); }
152
155 Flags flags, bool *hasProperty = nullptr) const;
156
159 Heap::Object *wrapper, QObject *object, String *name, Flags flags,
160 bool *hasProperty = nullptr, const QQmlPropertyData **property = nullptr);
161
162 static bool setQmlProperty(
164 QObject *object, String *name, Flags flags, const Value &value);
165
167 static ReturnedValue wrapConst(ExecutionEngine *engine, QObject *object);
168 static void markWrapper(QObject *object, MarkStack *markStack);
169
170 using Object::get;
171
172 static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
173 void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
174 static void setProperty(
176 const QQmlPropertyData *property, const Value &value);
177
178 void destroyObject(bool lastCall);
179
180 static ReturnedValue getProperty(
181 ExecutionEngine *engine, Heap::Object *wrapper, QObject *object,
183
184 static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
185 static ReturnedValue lookupAttached(Lookup *l, ExecutionEngine *engine, const Value &object);
186
187 template <typename ReversalFunctor> static ReturnedValue lookupPropertyGetterImpl(
188 Lookup *l, ExecutionEngine *engine, const Value &object,
189 Flags flags, ReversalFunctor revert);
190 template <typename ReversalFunctor> static ReturnedValue lookupMethodGetterImpl(
191 Lookup *l, ExecutionEngine *engine, const Value &object,
192 Flags flags, ReversalFunctor revert);
193 static bool virtualResolveLookupSetter(
194 Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value);
195 static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
196
197 static int virtualMetacall(Object *object, QMetaObject::Call call, int index, void **a);
198
199 static QString objectToString(
201
202protected:
203 static bool virtualIsEqualTo(Managed *that, Managed *o);
205
206 static const QQmlPropertyData *findProperty(
209
210 const QQmlPropertyData *findProperty(
212 String *name, Flags flags, QQmlPropertyData *local) const;
213
214 static ReturnedValue virtualGet(
215 const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
216 static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
217 static PropertyAttributes virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p);
218
219 static ReturnedValue method_connect(
220 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
221 static ReturnedValue method_disconnect(
222 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
223
224private:
225 Q_NEVER_INLINE static ReturnedValue wrap_slowPath(ExecutionEngine *engine, QObject *object);
226 Q_NEVER_INLINE static ReturnedValue wrapConst_slowPath(ExecutionEngine *engine, QObject *object);
227};
228
229Q_DECLARE_OPERATORS_FOR_FLAGS(QObjectWrapper::Flags)
230
232{
233 if (Q_UNLIKELY(QQmlData::wasDeleted(object)))
234 return QV4::Encode::null();
235
236 auto ddata = QQmlData::get(object);
237 if (Q_LIKELY(ddata && ddata->jsEngineId == engine->m_engineId && !ddata->jsWrapper.isUndefined())) {
238 // We own the JS object
239 return ddata->jsWrapper.value();
240 }
241
242 return wrap_slowPath(engine, object);
243}
244
245// Unfortunately we still need a non-const QObject* here because QQmlData needs to register itself in QObjectPrivate.
247{
248 if (Q_UNLIKELY(QQmlData::wasDeleted(object)))
249 return QV4::Encode::null();
250
251 return wrapConst_slowPath(engine, object);
252}
253
254inline bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
255{
256 while (fromMo) {
257 if (fromMo == toMo)
258 return true;
259 fromMo = fromMo->parent().data();
260 }
261 return false;
262}
263
264template <typename ReversalFunctor>
266 Lookup *lookup, ExecutionEngine *engine, const Value &object,
267 QObjectWrapper::Flags flags, ReversalFunctor revertLookup)
268{
269 // we can safely cast to a QV4::Object here. If object is something else,
270 // the internal class won't match
271 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
272 if (!o || o->internalClass != lookup->qobjectLookup.ic)
273 return revertLookup();
274
275 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
276 QObject *qobj = This->object();
277 if (QQmlData::wasDeleted(qobj))
278 return QV4::Encode::undefined();
279
280 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
281 if (!ddata)
282 return revertLookup();
283
284 const QQmlPropertyData *property = lookup->qobjectLookup.propertyData;
285 if (ddata->propertyCache.data() != lookup->qobjectLookup.propertyCache) {
286 // If the property is overridden and the lookup allows overrides to be considered,
287 // we have to revert here and redo the lookup from scratch.
288 if (property->isOverridden()
289 && ((flags & AllowOverride)
290 || property->isFunction()
291 || property->isSignalHandler())) {
292 return revertLookup();
293 }
294
296 return revertLookup();
297 }
298
299 return getProperty(engine, This, qobj, property, flags);
300}
301
302template <typename ReversalFunctor>
304 Lookup *lookup, ExecutionEngine *engine, const Value &object,
305 QObjectWrapper::Flags flags, ReversalFunctor revertLookup)
306{
307 // we can safely cast to a QV4::Object here. If object is something else,
308 // the internal class won't match
309 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
310 if (!o || o->internalClass != lookup->qobjectMethodLookup.ic)
311 return revertLookup();
312
313 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
314 QObject *qobj = This->object();
315 if (QQmlData::wasDeleted(qobj))
316 return QV4::Encode::undefined();
317
318 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
319 if (!ddata)
320 return revertLookup();
321
322 const QQmlPropertyData *property = lookup->qobjectMethodLookup.propertyData;
323 if (ddata->propertyCache.data() != lookup->qobjectMethodLookup.propertyCache) {
324 if (property && property->isOverridden())
325 return revertLookup();
326
328 return revertLookup();
329 }
330
331 if (Heap::QObjectMethod *method = lookup->qobjectMethodLookup.method) {
332 if (method->isDetached())
333 return method->asReturnedValue();
334 }
335
336 if (!property) // was toString() or destroy()
337 return revertLookup();
338
339 QV4::Scope scope(engine);
340 QV4::ScopedValue v(scope, getProperty(engine, This, qobj, property, flags));
341 if (!v->as<QObjectMethod>())
342 return revertLookup();
343
344 lookup->qobjectMethodLookup.method = static_cast<Heap::QObjectMethod *>(v->heapObject());
345 return v->asReturnedValue();
346}
347
349
350struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
351{
354
355 enum { DestroyMethod = -1, ToStringMethod = -2 };
356
357 static ReturnedValue create(QV4::ExecutionContext *scope, Heap::Object *wrapper, int index);
358 static ReturnedValue create(
359 QV4::ExecutionContext *scope, Heap::QQmlValueTypeWrapper *valueType, int index);
360 static ReturnedValue create(QV4::ExecutionEngine *engine, Heap::QObjectMethod *cloneFrom,
361 Heap::Object *wrapper, Heap::Object *object);
362
363 int methodIndex() const { return d()->index; }
364 QObject *object() const { return d()->object(); }
365
366 QV4::ReturnedValue method_toString(QV4::ExecutionEngine *engine, QObject *o) const;
367 QV4::ReturnedValue method_destroy(
368 QV4::ExecutionEngine *ctx, QObject *o, const Value *args, int argc) const;
369
370 static ReturnedValue virtualCall(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
371
372 ReturnedValue callInternal(const Value *thisObject, const Value *argv, int argc) const;
373
374 static QPair<QObject *, int> extractQtMethod(const QV4::FunctionObject *function);
375};
376
377
378struct Q_QML_EXPORT QMetaObjectWrapper : public QV4::FunctionObject
379{
382
384 const QMetaObject *metaObject() const { return d()->metaObject; }
385
386protected:
387 static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *);
388 static bool virtualIsEqualTo(Managed *a, Managed *b);
389
390private:
392 ReturnedValue constructInternal(const Value *argv, int argc) const;
393};
394
395struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object
396{
398 V4_PROTOTYPE(signalHandlerPrototype)
400
401 int signalIndex() const { return d()->signalIndex; }
402 QObject *object() const { return d()->object(); }
403
404 static void initProto(ExecutionEngine *v4);
405};
406
408
410 private QHash<QObjectBiPointer, QV4::WeakValue>
411{
413public:
416
418
423
424 template<typename Pointer>
425 void insert(Pointer key, Heap::Object *value)
426 {
428 connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
429 }
430
431 template<typename Pointer>
432 ReturnedValue value(Pointer key) const
433 {
435 return it == end()
437 : it->value();
438 }
439
441
442 template<typename Pointer>
443 void remove(Pointer key)
444 {
445 Iterator it = find(key);
446 if (it == end())
447 return;
448 erase(it);
449 }
450
451 template<typename Pointer>
452 void mark(Pointer key, MarkStack *markStack)
453 {
454 Iterator it = find(key);
455 if (it == end())
456 return;
457 it->markOnce(markStack);
458 }
459
460private Q_SLOTS:
461 void removeDestroyedObject(QObject*);
462};
463
464}
465
467
468#endif // QV4QOBJECTWRAPPER_P_H
469
470
static JNINativeMethod methods[]
\inmodule QtCore
Definition qhash.h:1135
\inmodule QtCore
Definition qhash.h:1093
\inmodule QtCore
Definition qhash.h:818
T value_type
Definition qhash.h:830
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
T & operator[](const Key &key)
Returns the value associated with the key as a modifiable reference.
Definition qhash.h:1060
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1209
iterator find(const QObjectBiPointer &key)
Returns an iterator pointing to the item with the key in the hash.
Definition qhash.h:1258
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1205
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
QQmlPropertyCache::ConstPtr propertyCache
Definition qqmldata_p.h:195
static bool wasDeleted(const QObject *)
Definition qqmldata_p.h:312
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
const QQmlPropertyCache::ConstPtr & parent() const
T * data() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void insert(Pointer key, Heap::Object *value)
QHash< QObjectBiPointer, QV4::WeakValue >::ConstIterator ConstIterator
void mark(Pointer key, MarkStack *markStack)
QHash< QObjectBiPointer, QV4::WeakValue >::Iterator Iterator
ReturnedValue value(Pointer key) const
QHash< QObjectBiPointer, QV4::WeakValue >::value_type value_type
ReturnedValue value() const
EGLContext ctx
object setProperty("down", true)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
#define Q_UNLIKELY(x)
#define Q_NEVER_INLINE
#define Q_LIKELY(x)
std::pair< T1, T2 > QPair
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
Flags
@ Invalid
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLuint object
[3]
GLenum target
GLbitfield flags
GLuint name
GLfloat GLfloat p
[1]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_OBJECT
#define Q_SLOTS
#define V4_NEEDS_DESTROY
#define DECLARE_HEAP_OBJECT(name, base)
#define DECLARE_MARKOBJECTS(class)
#define V4_PROTOTYPE(p)
#define V4_OBJECT2(DataClass, superClass)
const char property[13]
Definition qwizard.cpp:101
obj metaObject() -> className()
view create()
QJSValueList args
QJSEngine engine
[0]
\inmodule QtCore
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
void init(const QMetaObject *metaObject)
void init(QObject *object)
void init(QObject *object, int signalIndex)
Heap::QObjectMethod * method
const QQmlPropertyData * propertyData
Definition qv4lookup_p.h:96
struct QV4::Lookup::@576::@601 qobjectLookup
Heap::InternalClass * ic
Definition qv4lookup_p.h:51
struct QV4::Lookup::@576::@602 qobjectMethodLookup
const QQmlPropertyCache * propertyCache
Definition qv4lookup_p.h:95
ExecutionEngine * engine() const
const QMetaObject * metaObject() const
QObject * object() const
ReturnedValue getQmlProperty(const QQmlRefPointer< QQmlContextData > &qmlContext, String *name, Flags flags, bool *hasProperty=nullptr) const
static ReturnedValue getProperty(ExecutionEngine *engine, Heap::Object *wrapper, QObject *object, const QQmlPropertyData *property, Flags flags)
static ReturnedValue lookupPropertyGetterImpl(Lookup *l, ExecutionEngine *engine, const Value &object, Flags flags, ReversalFunctor revert)
Q_DECLARE_FLAGS(Flags, Flag)
static ReturnedValue getQmlProperty(ExecutionEngine *engine, const QQmlRefPointer< QQmlContextData > &qmlContext, Heap::Object *wrapper, QObject *object, String *name, Flags flags, bool *hasProperty=nullptr, const QQmlPropertyData **property=nullptr)
const QMetaObject * metaObject() const
QObject * object() const
static ReturnedValue wrapConst(ExecutionEngine *engine, QObject *object)
static ReturnedValue lookupMethodGetterImpl(Lookup *l, ExecutionEngine *engine, const Value &object, Flags flags, ReversalFunctor revert)
T * data() const
Definition qv4heap_p.h:193
V4_NEEDS_DESTROY int signalIndex() const
void wrapper()