Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlobjectcreator_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#ifndef QQMLOBJECTCREATOR_P_H
4#define QQMLOBJECTCREATOR_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qqmlimport_p.h>
18#include <private/qqmltypenamecache_p.h>
19#include <private/qv4compileddata_p.h>
20#include <private/qfinitestack_p.h>
21#include <private/qrecursionwatcher_p.h>
22#include <private/qqmlprofiler_p.h>
23#include <private/qv4qmlcontext_p.h>
24#include <private/qqmlguardedcontextdata_p.h>
25#include <private/qqmlfinalizer_p.h>
26#include <private/qqmlvmemetaobject_p.h>
27
28#include <qpointer.h>
29
31
35
40
55
57{
60 : object(object)
61 , data(data)
62 {}
63
64 const QObject *object = nullptr;
65 const QQmlPropertyData *data = nullptr;
66
67private:
68 friend size_t qHash(const RequiredPropertyKey &key, size_t seed = 0)
69 {
70 return qHashMulti(seed, key.object, key.data);
71 }
72
74 {
75 return a.object == b.object && a.data == b.data;
76 }
77};
78
79class RequiredProperties : public QHash<RequiredPropertyKey, RequiredPropertyInfo> {};
80
86
88public:
89 // this is a non owning view, rule of zero applies
91 ObjectInCreationGCAnchorList(const QV4::Scope &scope, int totalObjectCount)
92 {
93 allJavaScriptObjects = scope.alloc(totalObjectCount);
94 }
96 bool canTrack() const { return allJavaScriptObjects; }
97private:
98 QV4::Value *allJavaScriptObjects = nullptr; // pointer to vector on JS stack to reference JS wrappers during creation phase.
99};
100
101struct QQmlObjectCreatorSharedState final : QQmlRefCounted<QQmlObjectCreatorSharedState>
102{
103 QQmlRefPointer<QQmlContextData> rootContext;
104 QQmlRefPointer<QQmlContextData> creationContext;
105 QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
106 QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
107 QFiniteStack<QQmlGuard<QObject> > allCreatedObjects;
108 ObjectInCreationGCAnchorList allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase.
110 QList<QQmlFinalizerHook *> finalizeHooks;
114 QList<DeferredQPropertyBinding> allQPropertyBindings;
116};
117
118class Q_QML_EXPORT QQmlObjectCreator
119{
121public:
122 QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
123 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
124 const QQmlRefPointer<QQmlContextData> &creationContext,
125 QQmlIncubatorPrivate *incubator = nullptr);
127
128 enum CreationFlags { NormalObject = 1, InlineComponent = 2 };
129 QObject *create(int subComponentIndex = -1, QObject *parent = nullptr,
130 QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject);
131
132 bool populateDeferredProperties(QObject *instance, const QQmlData::DeferredData *deferredData);
133
134 void beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &context);
135 void populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
136 const QV4::CompiledData::Binding *binding);
137 void populateDeferredInstance(QObject *outerObject, int deferredIndex,
138 int index, QObject *instance, QObject *bindingTarget,
139 const QQmlPropertyData *valueTypeProperty,
140 const QV4::CompiledData::Binding *binding = nullptr);
141 void finalizePopulateDeferred();
142
143 bool finalize(QQmlInstantiationInterrupt &interrupt);
144 void clear();
145
146 QQmlRefPointer<QQmlContextData> rootContext() const { return sharedState->rootContext; }
147 QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; }
148
149 QList<QQmlError> errors;
150
151 QQmlRefPointer<QQmlContextData> parentContextData() const
152 {
153 return parentContext.contextData();
154 }
155 QFiniteStack<QQmlGuard<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; }
156
157 RequiredProperties *requiredProperties() {return &sharedState->requiredProperties;}
158 bool componentHadTopLevelRequiredProperties() const {return sharedState->hadTopLevelRequiredProperties;}
159
160 static QQmlComponent *createComponent(QQmlEngine *engine,
161 QV4::ExecutableCompilationUnit *compilationUnit,
162 int index, QObject *parent,
163 const QQmlRefPointer<QQmlContextData> &context);
164
165 void removePendingBinding(QObject *target, int propertyIndex)
166 {
167 QList<DeferredQPropertyBinding> &pendingBindings = sharedState.data()->allQPropertyBindings;
168 pendingBindings.removeIf([&](const DeferredQPropertyBinding &deferred) {
169 return deferred.properyIndex == propertyIndex && deferred.target == target;
170 });
171 }
172
173private:
174 QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData,
175 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
176 QQmlObjectCreatorSharedState *inheritedSharedState,
177 bool isContextObject);
178
179 void init(QQmlRefPointer<QQmlContextData> parentContext);
180
181 QObject *createInstance(int index, QObject *parent = nullptr, bool isContextObject = false);
182
183 bool populateInstance(int index, QObject *instance, QObject *bindingTarget,
184 const QQmlPropertyData *valueTypeProperty,
185 const QV4::CompiledData::Binding *binding = nullptr);
186
187 // If qmlProperty and binding are null, populate all properties, otherwise only the given one.
188 void populateDeferred(QObject *instance, int deferredIndex);
189 void populateDeferred(QObject *instance, int deferredIndex,
190 const QQmlPropertyPrivate *qmlProperty,
191 const QV4::CompiledData::Binding *binding);
192
193 enum BindingMode {
194 ApplyNone = 0x0,
195 ApplyImmediate = 0x1,
196 ApplyDeferred = 0x2,
197 ApplyAll = ApplyImmediate | ApplyDeferred,
198 };
199 Q_DECLARE_FLAGS(BindingSetupFlags, BindingMode);
200
201 void setupBindings(BindingSetupFlags mode = BindingMode::ApplyImmediate);
202 bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
203 void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
204 void setupFunctions();
205
206 QString stringAt(int idx) const { return compilationUnit->stringAt(idx); }
207 void recordError(const QV4::CompiledData::Location &location, const QString &description);
208
209 void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
210
211 inline QV4::QmlContext *currentQmlContext();
212 QV4::ResolvedTypeReference *resolvedType(int id) const
213 {
214 return compilationUnit->resolvedType(id);
215 }
216
217 enum Phase {
218 Startup,
219 CreatingObjects,
220 CreatingObjectsPhase2,
221 ObjectsCreated,
222 Finalizing,
223 Done
224 } phase;
225
228 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
229 const QV4::CompiledData::Unit *qmlUnit;
230 QQmlGuardedContextData parentContext;
231 QQmlRefPointer<QQmlContextData> context;
232 const QQmlPropertyCacheVector *propertyCaches;
233 QQmlRefPointer<QQmlObjectCreatorSharedState> sharedState;
234 bool topLevelCreator;
235 bool isContextObject;
236 QQmlIncubatorPrivate *incubator;
237
238 QObject *_qobject;
239 QObject *_scopeObject;
240 QObject *_bindingTarget;
241
242 const QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache
243 int _compiledObjectIndex;
244 const QV4::CompiledData::Object *_compiledObject;
245 QQmlData *_ddata;
246 QQmlPropertyCache::ConstPtr _propertyCache;
247 QQmlVMEMetaObject *_vmeMetaObject;
248 QQmlListProperty<void> _currentList;
249 QV4::QmlContext *_qmlContext;
250
252
253 typedef std::function<bool(QQmlObjectCreatorSharedState *sharedState)> PendingAliasBinding;
254 std::vector<PendingAliasBinding> pendingAliasBindings;
255
256 template<typename Functor>
257 void doPopulateDeferred(QObject *instance, int deferredIndex, Functor f)
258 {
259 QQmlData *declarativeData = QQmlData::get(instance);
260
261 // We're in the process of creating the object. We sure hope it's still alive.
262 Q_ASSERT(declarativeData && declarativeData->propertyCache);
263
264 QObject *bindingTarget = instance;
265
267 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
268
269 QObject *scopeObject = instance;
270 qt_ptr_swap(_scopeObject, scopeObject);
271
272 QV4::Scope valueScope(v4);
273 QScopedValueRollback<ObjectInCreationGCAnchorList> jsObjectGuard(
274 sharedState->allJavaScriptObjects,
275 ObjectInCreationGCAnchorList(valueScope, compilationUnit->totalObjectCount()));
276
277 Q_ASSERT(topLevelCreator);
278 QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
279
280 qt_ptr_swap(_qmlContext, qmlContext);
281
282 _propertyCache.swap(cache);
283 qt_ptr_swap(_qobject, instance);
284
285 int objectIndex = deferredIndex;
286 std::swap(_compiledObjectIndex, objectIndex);
287
288 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
289 qt_ptr_swap(_compiledObject, obj);
290 qt_ptr_swap(_ddata, declarativeData);
291 qt_ptr_swap(_bindingTarget, bindingTarget);
292 qt_ptr_swap(_vmeMetaObject, vmeMetaObject);
293
294 f();
295
296 qt_ptr_swap(_vmeMetaObject, vmeMetaObject);
297 qt_ptr_swap(_bindingTarget, bindingTarget);
298 qt_ptr_swap(_ddata, declarativeData);
299 qt_ptr_swap(_compiledObject, obj);
300 std::swap(_compiledObjectIndex, objectIndex);
301 qt_ptr_swap(_qobject, instance);
302 _propertyCache.swap(cache);
303
304 qt_ptr_swap(_qmlContext, qmlContext);
305 qt_ptr_swap(_scopeObject, scopeObject);
306 }
307};
308
310{
312
313 bool hasRecursed() const { return watcher.hasRecursed(); }
314
315private:
316 QQmlRefPointer<QQmlObjectCreatorSharedState> sharedState;
317 QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher;
318};
319
320QV4::QmlContext *QQmlObjectCreator::currentQmlContext()
321{
322 if (!_qmlContext->isManaged())
323 _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
324
325 return _qmlContext;
326}
327
329
330#endif // QQMLOBJECTCREATOR_P_H
ObjectInCreationGCAnchorList(const QV4::Scope &scope, int totalObjectCount)
void trackObject(QV4::ExecutionEngine *engine, QObject *instance)
\inmodule QtCore
Definition qhash.h:820
\inmodule QtCore
Definition qobject.h:103
The QQmlComponent class encapsulates a QML component definition.
QQmlPropertyCache::ConstPtr propertyCache
Definition qqmldata_p.h:195
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QQmlComponentAttached ** componentAttachment()
QQmlObjectCreator(QQmlRefPointer< QQmlContextData > parentContext, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit, const QQmlRefPointer< QQmlContextData > &creationContext, QQmlIncubatorPrivate *incubator=nullptr)
bool componentHadTopLevelRequiredProperties() const
QQmlRefPointer< QQmlContextData > parentContextData() const
void removePendingBinding(QObject *target, int propertyIndex)
RequiredProperties * requiredProperties()
QList< QQmlError > errors
QFiniteStack< QQmlGuard< QObject > > & allCreatedObjects()
QQmlRefPointer< QQmlContextData > rootContext() const
The QQmlProperty class abstracts accessing properties on objects created from QML.
void swap(QQmlRefPointer &other) noexcept
static QQmlVMEMetaObject * get(QObject *o)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qurl.h:94
b clear()
QCache< int, Employee > cache
[0]
@ Startup
Definition qhooks_p.h:33
Combined button and popup list for selecting options.
static void * context
#define Q_DECLARE_TR_FUNCTIONS(context)
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
constexpr QtPrivate::QHashMultiReturnType< T... > qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v< QtPrivate::QNothrowHashable< T >... >)
GLint location
GLboolean GLboolean GLboolean b
GLenum mode
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum target
GLbitfield flags
GLhandleARB obj
[2]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
constexpr void qt_ptr_swap(T *&lhs, T *&rhs) noexcept
Definition qswap.h:29
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
const char property[13]
Definition qwizard.cpp:101
QItemEditorCreatorBase * creator
view create()
QJSEngine engine
[0]
QUntypedPropertyBinding binding
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)
QList< DeferredQPropertyBinding > allQPropertyBindings
QFiniteStack< QQmlAbstractBinding::Ptr > allCreatedBindings
QQmlRefPointer< QQmlContextData > rootContext
QQmlRefPointer< QQmlContextData > creationContext
QQmlComponentAttached * componentAttached
QFiniteStack< QQmlGuard< QObject > > allCreatedObjects
QFiniteStack< QQmlParserStatus * > allParserStatusCallbacks
QList< QQmlFinalizerHook * > finalizeHooks
ObjectInCreationGCAnchorList allJavaScriptObjects
ExecutionContext * rootContext() const
static Heap::QmlContext * create(QV4::ExecutionContext *parent, QQmlRefPointer< QQmlContextData > context, QObject *scopeObject)
Value * alloc(qint64 nValues) const =delete
bool isManaged() const
QVector< AliasToRequiredInfo > aliasesToRequired
QV4::CompiledData::Location location
friend bool operator==(const RequiredPropertyKey &a, const RequiredPropertyKey &b)
friend size_t qHash(const RequiredPropertyKey &key, size_t seed=0)
RequiredPropertyKey()=default
RequiredPropertyKey(const QObject *object, const QQmlPropertyData *data)