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
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
32Q_DECLARE_LOGGING_CATEGORY(lcBuiltinsBindingRemoval)
33
34class QObject;
35class QQmlData;
36class QQmlPropertyCache;
38class QQmlObjectOrGadget;
39
40namespace QV4 {
42
43namespace Heap {
44
45struct QQmlValueTypeWrapper;
46
49 {
50 Object::init();
52 }
53
54 void destroy() {
55 qObj.destroy();
56 Object::destroy();
57 }
58
59 QObject *object() const { return qObj.data(); }
61
62private:
64};
65
66#define QObjectMethodMembers(class, Member)
67 Member(class, Pointer, Object *, wrapper)
68
69DECLARE_EXPORTED_HEAP_OBJECT(QObjectMethod, FunctionObject) {
70 DECLARE_MARKOBJECTS(QObjectMethod)
71
72 QQmlPropertyData *methods;
73 alignas(alignof(QQmlPropertyData)) std::byte _singleMethod[sizeof(QQmlPropertyData)];
74 int methodCount;
75 int index;
76
77 void init(QV4::ExecutionEngine *engine, Object *wrapper, int index);
78 void destroy()
79 {
80 if (methods != reinterpret_cast<const QQmlPropertyData *>(&_singleMethod))
81 delete[] methods;
82 FunctionObject::destroy();
83 }
84
85 void ensureMethodsCache(const QMetaObject *thisMeta);
86 QString name() const;
87
88 const QMetaObject *metaObject() const;
89 QObject *object() const;
90
91 bool isDetached() const;
92 bool isAttachedTo(QObject *o) const;
93
94 enum ThisObjectMode {
95 Invalid,
96 Included,
97 Explicit,
98 };
99
100 QV4::Heap::QObjectMethod::ThisObjectMode checkThisObject(const QMetaObject *thisMeta) const;
101};
102
104 void init(QObject *object, int signalIndex);
105 void destroy() {
106 qObj.destroy();
107 Object::destroy();
108 }
110
111 QObject *object() const { return qObj.data(); }
112 void setObject(QObject *o) { qObj = o; }
113
114private:
115 QV4QPointer<QObject> qObj;
116};
117
118}
119
120struct Q_QML_EXPORT QObjectWrapper : public Object
121{
125
133
135
137
138 const QMetaObject *metaObject() const
139 {
140 if (QObject *o = object())
141 return o->metaObject();
142 return nullptr;
143 }
144
145 QObject *object() const { return d()->object(); }
146
149 Flags flags, bool *hasProperty = nullptr) const;
150
154 bool *hasProperty = nullptr, const QQmlPropertyData **property = nullptr);
155
156 static bool setQmlProperty(
159
160 Q_NODISCARD_X("Use ensureWrapper if you don't need the return value")
162 Q_NODISCARD_X("Throwing the const wrapper away can cause it to be garbage collected")
166
167 using Object::get;
168
171 static void setProperty(
173 const QQmlPropertyData *property, const Value &value);
174
175 void destroyObject(bool lastCall);
176
180
184
186
193 static bool virtualResolveLookupSetter(
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
213
215 const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
216 static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
218
220 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
222 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
223
224private:
227};
228
230
231// We generally musn't pass ReturnedValue as arguments to other functions.
232// In this case, we do it solely for marking purposes so it's fine.
243
245{
247 return QV4::Encode::null();
248
249 auto ddata = QQmlData::get(object);
251 // We own the JS object
252 return ddata->jsWrapper.value();
253 }
254
255 const auto rv = wrap_slowPath(engine, object);
257 return rv;
258}
259
260// Unfortunately we still need a non-const QObject* here because QQmlData needs to register itself in QObjectPrivate.
270
271inline bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
272{
273 while (fromMo) {
274 if (fromMo == toMo)
275 return true;
276 fromMo = fromMo->parent().data();
277 }
278 return false;
279}
280
281template <typename ReversalFunctor>
285{
286 // we can safely cast to a QV4::Object here. If object is something else,
287 // the internal class won't match
288 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
289 if (!o || o->internalClass != lookup->qobjectLookup.ic)
290 return revertLookup();
291
292 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
293 QObject *qobj = This->object();
295 return QV4::Encode::undefined();
296
297 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
298 if (!ddata)
299 return revertLookup();
300
303 // If the property is overridden and the lookup allows overrides to be considered,
304 // we have to revert here and redo the lookup from scratch.
306 && ((flags & AllowOverride)
307 || property->isFunction()
308 || property->isSignalHandler())) {
309 return revertLookup();
310 }
311
313 return revertLookup();
314 }
315
317}
318
319template <typename ReversalFunctor>
323{
324 // we can safely cast to a QV4::Object here. If object is something else,
325 // the internal class won't match
326 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
328 return revertLookup();
329
330 Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper *>(o);
331 QObject *qobj = This->object();
333 return QV4::Encode::undefined();
334
335 QQmlData *ddata = QQmlData::get(qobj, /*create*/false);
336 if (!ddata)
337 return revertLookup();
338
342 return revertLookup();
343
345 return revertLookup();
346 }
347
349 if (method->isDetached())
350 return method->asReturnedValue();
351 }
352
353 if (!property) // was toString() or destroy()
354 return revertLookup();
355
358 if (!v->as<QObjectMethod>())
359 return revertLookup();
360
362 return v->asReturnedValue();
363}
364
365struct QQmlValueTypeWrapper;
366
367struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
368{
371
372 enum { DestroyMethod = -1, ToStringMethod = -2 };
373
375 static ReturnedValue create(
377 static ReturnedValue create(
380
381 int methodIndex() const { return d()->index; }
382 QObject *object() const { return d()->object(); }
383
386 QV4::ExecutionEngine *ctx, QObject *o, const Value *args, int argc) const;
387 bool method_destroy(
388 QV4::ExecutionEngine *engine, QObject *o, int delay) const;
389
391 const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
392 static void virtualCallWithMetaTypes(
394 void **argv, const QMetaType *types, int argc);
395
397 const Value *thisObject, const Value *argv, int argc) const;
399 QObject *thisObject, void **argv, const QMetaType *types, int argc) const;
400
401 static QPair<QObject *, int> extractQtMethod(const QV4::FunctionObject *function);
402
403 static bool isExactMatch(
404 const QMetaMethod &method, void **argv, int argc, const QMetaType *types);
405
406private:
407 friend struct QMetaObjectWrapper;
408
412
415 void **argv, int argc, const QMetaType *types);
416
421};
422
423struct Q_QML_EXPORT QmlSignalHandler : public QV4::Object
424{
428
429 int signalIndex() const { return d()->signalIndex; }
430 QObject *object() const { return d()->object(); }
431
432 ReturnedValue call(const Value *thisObject, const Value *argv, int argc) const;
433
434 static void initProto(ExecutionEngine *v4);
435};
436
438
441{
443public:
446
448
449 ConstIterator begin() const { return QHash<QObjectBiPointer, QV4::WeakValue>::constBegin(); }
450 Iterator begin() { return QHash<QObjectBiPointer, QV4::WeakValue>::begin(); }
451 ConstIterator end() const { return QHash<QObjectBiPointer, QV4::WeakValue>::constEnd(); }
452 Iterator end() { return QHash<QObjectBiPointer, QV4::WeakValue>::end(); }
453
454 template<typename Pointer>
455 void insert(Pointer key, Heap::Object *value)
456 {
457 QHash<QObjectBiPointer, WeakValue>::operator[](key).set(value->internalClass->engine, value);
458 connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*)));
459 }
460
461 template<typename Pointer>
462 ReturnedValue value(Pointer key) const
463 {
464 ConstIterator it = find(key);
465 return it == end()
466 ? QV4::WeakValue().value()
467 : it->value();
468 }
469
471
472 template<typename Pointer>
473 void remove(Pointer key)
474 {
475 Iterator it = find(key);
476 if (it == end())
477 return;
478 erase(it);
479 }
480
481 template<typename Pointer>
482 void mark(Pointer key, MarkStack *markStack)
483 {
484 Iterator it = find(key);
485 if (it == end())
486 return;
487 it->markOnce(markStack);
488 }
489
490private Q_SLOTS:
492};
493
494}
495
496QT_END_NAMESPACE
497
498#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
Combined button and popup list for selecting options.
DECLARE_EXPORTED_HEAP_OBJECT(QObjectMethod, FunctionObject)
Definition qjsvalue.h:23
bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
#define V4_NEEDS_DESTROY
#define Q_MANAGED_TYPE(type)
void init(QObject *object, int signalIndex)