1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the tools applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | #ifndef QQMLOBJECTCREATOR_P_H |
40 | #define QQMLOBJECTCREATOR_P_H |
41 | |
42 | // |
43 | // W A R N I N G |
44 | // ------------- |
45 | // |
46 | // This file is not part of the Qt API. It exists purely as an |
47 | // implementation detail. This header file may change from version to |
48 | // version without notice, or even be removed. |
49 | // |
50 | // We mean it. |
51 | // |
52 | |
53 | #include <private/qqmlimport_p.h> |
54 | #include <private/qqmltypenamecache_p.h> |
55 | #include <private/qv4compileddata_p.h> |
56 | #include <private/qfinitestack_p.h> |
57 | #include <private/qrecursionwatcher_p.h> |
58 | #include <private/qqmlprofiler_p.h> |
59 | #include <private/qv4qmlcontext_p.h> |
60 | |
61 | #include <qpointer.h> |
62 | |
63 | QT_BEGIN_NAMESPACE |
64 | |
65 | class QQmlAbstractBinding; |
66 | class QQmlInstantiationInterrupt; |
67 | class QQmlIncubatorPrivate; |
68 | |
69 | struct AliasToRequiredInfo { |
70 | QString propertyName; |
71 | QUrl fileUrl; |
72 | }; |
73 | |
74 | /*! |
75 | \internal |
76 | This struct contains information solely used for displaying error messages |
77 | \variable aliasesToRequired allows us to give the user a way to know which (aliasing) properties |
78 | can be set to set the required property |
79 | \sa QQmlComponentPrivate::unsetRequiredPropertyToQQmlError |
80 | */ |
81 | struct RequiredPropertyInfo |
82 | { |
83 | QString propertyName; |
84 | QUrl fileUrl; |
85 | QV4::CompiledData::Location location; |
86 | QVector<AliasToRequiredInfo> aliasesToRequired; |
87 | }; |
88 | |
89 | class RequiredProperties : public QHash<QQmlPropertyData*, RequiredPropertyInfo> {}; |
90 | |
91 | struct QQmlObjectCreatorSharedState : public QSharedData |
92 | { |
93 | QQmlContextData *rootContext; |
94 | QQmlContextData *creationContext; |
95 | QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings; |
96 | QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks; |
97 | QFiniteStack<QPointer<QObject> > allCreatedObjects; |
98 | QV4::Value *allJavaScriptObjects; // pointer to vector on JS stack to reference JS wrappers during creation phase. |
99 | QQmlComponentAttached *componentAttached; |
100 | QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks; |
101 | QQmlVmeProfiler profiler; |
102 | QRecursionNode recursionNode; |
103 | RequiredProperties requiredProperties; |
104 | bool hadRequiredProperties; |
105 | }; |
106 | |
107 | class Q_QML_PRIVATE_EXPORT QQmlObjectCreator |
108 | { |
109 | Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator) |
110 | public: |
111 | QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr); |
112 | ~QQmlObjectCreator(); |
113 | |
114 | enum CreationFlags { NormalObject = 1, InlineComponent = 2 }; |
115 | QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject); |
116 | |
117 | bool populateDeferredProperties(QObject *instance, const QQmlData::DeferredData *deferredData); |
118 | |
119 | void beginPopulateDeferred(QQmlContextData *context); |
120 | void populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex, |
121 | const QV4::CompiledData::Binding *binding); |
122 | void finalizePopulateDeferred(); |
123 | |
124 | QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt); |
125 | void clear(); |
126 | |
127 | QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; } |
128 | |
129 | QList<QQmlEnginePrivate::FinalizeCallback> *finalizeCallbacks() { return &sharedState->finalizeCallbacks; } |
130 | |
131 | QList<QQmlError> errors; |
132 | |
133 | QQmlContextData *parentContextData() const { return parentContext.contextData(); } |
134 | QFiniteStack<QPointer<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; } |
135 | |
136 | RequiredProperties &requiredProperties() {return sharedState->requiredProperties;} |
137 | bool componentHadRequiredProperties() const {return sharedState->hadRequiredProperties;} |
138 | |
139 | private: |
140 | QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState); |
141 | |
142 | void init(QQmlContextData *parentContext); |
143 | |
144 | QObject *createInstance(int index, QObject *parent = nullptr, bool isContextObject = false); |
145 | |
146 | bool populateInstance(int index, QObject *instance, |
147 | QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty); |
148 | |
149 | // If qmlProperty and binding are null, populate all properties, otherwise only the given one. |
150 | void populateDeferred(QObject *instance, int deferredIndex, |
151 | const QQmlPropertyPrivate *qmlProperty = nullptr, |
152 | const QV4::CompiledData::Binding *binding = nullptr); |
153 | |
154 | void setupBindings(bool applyDeferredBindings = false); |
155 | bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); |
156 | void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding); |
157 | void setupFunctions(); |
158 | |
159 | QString stringAt(int idx) const { return compilationUnit->stringAt(index: idx); } |
160 | void recordError(const QV4::CompiledData::Location &location, const QString &description); |
161 | |
162 | void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const; |
163 | |
164 | inline QV4::QmlContext *currentQmlContext(); |
165 | Q_NEVER_INLINE void createQmlContext(); |
166 | QV4::ResolvedTypeReference *resolvedType(int id) const |
167 | { |
168 | return compilationUnit->resolvedType(id); |
169 | } |
170 | |
171 | enum Phase { |
172 | Startup, |
173 | CreatingObjects, |
174 | CreatingObjectsPhase2, |
175 | ObjectsCreated, |
176 | Finalizing, |
177 | Done |
178 | } phase; |
179 | |
180 | QQmlEngine *engine; |
181 | QV4::ExecutionEngine *v4; |
182 | QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; |
183 | const QV4::CompiledData::Unit *qmlUnit; |
184 | QQmlGuardedContextData parentContext; |
185 | QQmlContextData *context; |
186 | const QQmlPropertyCacheVector *propertyCaches; |
187 | QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; |
188 | bool topLevelCreator; |
189 | QQmlIncubatorPrivate *incubator; |
190 | |
191 | QObject *_qobject; |
192 | QObject *_scopeObject; |
193 | QObject *_bindingTarget; |
194 | |
195 | const QQmlPropertyData *_valueTypeProperty; // belongs to _qobjectForBindings's property cache |
196 | int _compiledObjectIndex; |
197 | const QV4::CompiledData::Object *_compiledObject; |
198 | QQmlData *_ddata; |
199 | QQmlRefPointer<QQmlPropertyCache> _propertyCache; |
200 | QQmlVMEMetaObject *_vmeMetaObject; |
201 | QQmlListProperty<void> _currentList; |
202 | QV4::QmlContext *_qmlContext; |
203 | |
204 | friend struct QQmlObjectCreatorRecursionWatcher; |
205 | |
206 | typedef std::function<bool(QQmlObjectCreatorSharedState *sharedState)> PendingAliasBinding; |
207 | std::vector<PendingAliasBinding> pendingAliasBindings; |
208 | }; |
209 | |
210 | struct QQmlObjectCreatorRecursionWatcher |
211 | { |
212 | QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator); |
213 | |
214 | bool hasRecursed() const { return watcher.hasRecursed(); } |
215 | |
216 | private: |
217 | QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; |
218 | QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher; |
219 | }; |
220 | |
221 | QV4::QmlContext *QQmlObjectCreator::currentQmlContext() |
222 | { |
223 | if (!_qmlContext->isManaged()) |
224 | _qmlContext->setM(QV4::QmlContext::create(parent: v4->rootContext(), context, scopeObject: _scopeObject)); |
225 | |
226 | return _qmlContext; |
227 | } |
228 | |
229 | QT_END_NAMESPACE |
230 | |
231 | #endif // QQMLOBJECTCREATOR_P_H |
232 | |