1// Copyright (C) 2022 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 QV4REFERENCEOBJECT_P_H
5#define QV4REFERENCEOBJECT_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/qv4object_p.h>
19#include <private/qv4stackframe_p.h>
20
21QT_BEGIN_NAMESPACE
22
23namespace QV4 {
24namespace Heap {
25
26
27#define ReferenceObjectMembers(class, Member) \
28 Member(class, Pointer, Object *, m_object)
29
30DECLARE_HEAP_OBJECT(ReferenceObject, Object) {
31 DECLARE_MARKOBJECTS(ReferenceObject);
32
33 enum Flag : quint8 {
34 NoFlag = 0,
35 CanWriteBack = 1 << 0,
36 IsVariant = 1 << 1,
37 EnforcesLocation = 1 << 2,
38 };
39 Q_DECLARE_FLAGS(Flags, Flag);
40
41 void init(Object *object, int property, Flags flags)
42 {
43 setObject(object);
44 m_property = property;
45 m_flags = flags;
46 Object::init();
47 }
48
49 Flags flags() const { return Flags(m_flags); }
50
51 Object *object() const { return m_object.get(); }
52 void setObject(Object *object) { m_object.set(e: internalClass->engine, newVal: object); }
53
54 int property() const { return m_property; }
55
56 bool canWriteBack() const { return hasFlag(flag: CanWriteBack); }
57 bool isVariant() const { return hasFlag(flag: IsVariant); }
58 bool enforcesLocation() const { return hasFlag(flag: EnforcesLocation); }
59
60 void setLocation(const Function *function, quint16 statement)
61 {
62 m_function = function;
63 m_statementIndex = statement;
64 }
65
66 const Function *function() const { return m_function; }
67 quint16 statementIndex() const { return m_statementIndex; }
68
69 bool isAttachedToProperty() const
70 {
71 if (enforcesLocation()) {
72 if (CppStackFrame *frame = internalClass->engine->currentStackFrame) {
73 if (frame->v4Function != function() || frame->statementNumber() != statementIndex())
74 return false;
75 } else {
76 return false;
77 }
78 }
79
80 return true;
81 }
82
83 bool isReference() const { return m_object; }
84
85private:
86
87 bool hasFlag(Flag flag) const
88 {
89 return m_flags & quint8(flag);
90 }
91
92 void setFlag(Flag flag, bool set)
93 {
94 m_flags = set ? (m_flags | quint8(flag)) : (m_flags & ~quint8(flag));
95 }
96
97 const Function *m_function;
98 int m_property;
99 quint16 m_statementIndex;
100 quint8 m_flags;
101};
102
103Q_DECLARE_OPERATORS_FOR_FLAGS(ReferenceObject::Flags)
104
105} // namespace Heap
106
107
108struct ReferenceObject : public Object
109{
110 V4_OBJECT2(ReferenceObject, Object)
111 V4_NEEDS_DESTROY
112
113public:
114 static constexpr const int AllProperties = -1;
115
116 template<typename HeapObject>
117 static bool readReference(HeapObject *ref)
118 {
119 if (!ref->object())
120 return false;
121
122 QV4::Scope scope(ref->internalClass->engine);
123 QV4::ScopedObject object(scope, ref->object());
124
125 if (ref->isVariant()) {
126 QVariant variant;
127 void *a[] = { &variant };
128 return object->metacall(call: QMetaObject::ReadProperty, index: ref->property(), a)
129 && ref->setVariant(variant);
130 }
131
132 void *a[] = { ref->storagePointer() };
133 return object->metacall(call: QMetaObject::ReadProperty, index: ref->property(), a);
134 }
135
136 template<typename HeapObject>
137 static bool writeBack(HeapObject *ref, int internalIndex = AllProperties)
138 {
139 if (!ref->object() || !ref->canWriteBack())
140 return false;
141
142 QV4::Scope scope(ref->internalClass->engine);
143 QV4::ScopedObject object(scope, ref->object());
144
145 int flags = QQmlPropertyData::HasInternalIndex;
146 int status = -1;
147 if (ref->isVariant()) {
148 QVariant variant = ref->toVariant();
149 void *a[] = { &variant, nullptr, &status, &flags, &internalIndex };
150 return object->metacall(call: QMetaObject::WriteProperty, index: ref->property(), a);
151 }
152
153 void *a[] = { ref->storagePointer(), nullptr, &status, &flags, &internalIndex };
154 return object->metacall(call: QMetaObject::WriteProperty, index: ref->property(), a);
155 }
156
157 template<typename HeapObject>
158 static HeapObject *detached(HeapObject *ref)
159 {
160 if (ref->object() && !ref->enforcesLocation() && !readReference(ref))
161 return ref; // It's dead. No point in detaching it anymore
162
163 return ref->detached();
164 }
165};
166
167} // namespace QV4
168
169QT_END_NAMESPACE
170
171#endif // QV4REFERENCEOBJECT_P_H
172

source code of qtdeclarative/src/qml/jsruntime/qv4referenceobject_p.h