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
40#include "qqmlobjectcreator_p.h"
41
42#include <private/qqmlengine_p.h>
43#include <private/qqmlvmemetaobject_p.h>
44#include <private/qv4function_p.h>
45#include <private/qv4functionobject_p.h>
46#include <private/qv4qobjectwrapper_p.h>
47#include <private/qqmlbinding_p.h>
48#include <private/qqmlstringconverters_p.h>
49#include <private/qqmlboundsignal_p.h>
50#include <private/qqmlcomponentattached_p.h>
51#include <private/qqmlcomponent_p.h>
52#include <private/qqmlcustomparser_p.h>
53#include <private/qqmlscriptstring_p.h>
54#include <private/qqmlpropertyvalueinterceptor_p.h>
55#include <private/qqmlvaluetypeproxybinding_p.h>
56#include <private/qqmldebugconnector_p.h>
57#include <private/qqmldebugserviceinterfaces_p.h>
58#include <private/qqmlscriptdata_p.h>
59#include <private/qqmlsourcecoordinate_p.h>
60#include <private/qjsvalue_p.h>
61#include <private/qv4generatorobject_p.h>
62
63#include <QScopedValueRollback>
64
65#include <qtqml_tracepoints_p.h>
66#include <QScopedValueRollback>
67
68QT_USE_NAMESPACE
69
70QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext,
71 QQmlIncubatorPrivate *incubator)
72 : phase(Startup)
73 , compilationUnit(compilationUnit)
74 , propertyCaches(&compilationUnit->propertyCaches)
75 , sharedState(new QQmlObjectCreatorSharedState)
76 , topLevelCreator(true)
77 , incubator(incubator)
78{
79 init(parentContext);
80
81 sharedState->componentAttached = nullptr;
82 sharedState->allCreatedBindings.allocate(size: compilationUnit->totalBindingsCount());
83 sharedState->allParserStatusCallbacks.allocate(size: compilationUnit->totalParserStatusCount());
84 sharedState->allCreatedObjects.allocate(size: compilationUnit->totalObjectCount());
85 sharedState->allJavaScriptObjects = nullptr;
86 sharedState->creationContext = creationContext;
87 sharedState->rootContext = nullptr;
88 sharedState->hadRequiredProperties = false;
89
90 if (auto profiler = QQmlEnginePrivate::get(e: engine)->profiler) {
91 Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
92 sharedState->profiler.init(profiler, compilationUnit->totalParserStatusCount()));
93 } else {
94 Q_UNUSED(profiler);
95 }
96}
97
98QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
99 : phase(Startup)
100 , compilationUnit(compilationUnit)
101 , propertyCaches(&compilationUnit->propertyCaches)
102 , sharedState(inheritedSharedState)
103 , topLevelCreator(false)
104 , incubator(nullptr)
105{
106 init(parentContext);
107}
108
109void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
110{
111 parentContext = providedParentContext;
112 engine = parentContext->engine;
113 v4 = engine->handle();
114
115 if (compilationUnit && !compilationUnit->engine)
116 compilationUnit->linkToEngine(engine: v4);
117
118 qmlUnit = compilationUnit->unitData();
119 context = nullptr;
120 _qobject = nullptr;
121 _scopeObject = nullptr;
122 _bindingTarget = nullptr;
123 _valueTypeProperty = nullptr;
124 _compiledObject = nullptr;
125 _compiledObjectIndex = -1;
126 _ddata = nullptr;
127 _propertyCache = nullptr;
128 _vmeMetaObject = nullptr;
129 _qmlContext = nullptr;
130}
131
132QQmlObjectCreator::~QQmlObjectCreator()
133{
134 if (topLevelCreator) {
135 {
136 QQmlObjectCreatorRecursionWatcher watcher(this);
137 }
138 for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
139 QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(index: i);
140 if (ps)
141 ps->d = nullptr;
142 }
143 while (sharedState->componentAttached) {
144 QQmlComponentAttached *a = sharedState->componentAttached;
145 a->rem();
146 }
147 }
148}
149
150QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt, int flags)
151{
152 if (phase == CreatingObjectsPhase2) {
153 phase = ObjectsCreated;
154 return context->contextObject;
155 }
156 Q_ASSERT(phase == Startup);
157 phase = CreatingObjects;
158
159 int objectToCreate;
160
161 if (subComponentIndex == -1) {
162 objectToCreate = /*root object*/0;
163 } else {
164 Q_ASSERT(subComponentIndex >= 0);
165 if (flags & CreationFlags::InlineComponent) {
166 objectToCreate = subComponentIndex;
167 } else {
168 Q_ASSERT(flags & CreationFlags::NormalObject);
169 const QV4::CompiledData::Object *compObj = compilationUnit->objectAt(index: subComponentIndex);
170 objectToCreate = compObj->bindingTable()->value.objectIndex;
171 }
172 }
173
174 context = new QQmlContextData;
175 context->isInternal = true;
176 context->imports = compilationUnit->typeNameCache;
177 context->initFromTypeCompilationUnit(unit: compilationUnit, subComponentIndex);
178 context->setParent(parentContext);
179
180 if (!sharedState->rootContext) {
181 sharedState->rootContext = context;
182 sharedState->rootContext->incubator = incubator;
183 sharedState->rootContext->isRootObjectInCreation = true;
184 }
185
186 QV4::Scope scope(v4);
187
188 Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
189 if (topLevelCreator)
190 sharedState->allJavaScriptObjects = scope.alloc(nValues: compilationUnit->totalObjectCount());
191
192 if (subComponentIndex == -1 && compilationUnit->dependentScripts.count()) {
193 QV4::ScopedObject scripts(scope, v4->newArrayObject(count: compilationUnit->dependentScripts.count()));
194 context->importedScripts.set(engine: v4, value: scripts);
195 QV4::ScopedValue v(scope);
196 for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
197 QQmlRefPointer<QQmlScriptData> s = compilationUnit->dependentScripts.at(i);
198 scripts->put(idx: i, v: (v = s->scriptValueForContext(parentCtxt: context)));
199 }
200 } else if (sharedState->creationContext) {
201 context->importedScripts = sharedState->creationContext->importedScripts;
202 }
203
204 QObject *instance = createInstance(index: objectToCreate, parent, /*isContextObject*/true);
205 if (instance) {
206 QQmlData *ddata = QQmlData::get(object: instance);
207 Q_ASSERT(ddata);
208 ddata->compilationUnit = compilationUnit;
209 }
210
211 if (topLevelCreator)
212 sharedState->allJavaScriptObjects = nullptr;
213
214 phase = CreatingObjectsPhase2;
215
216 if (interrupt && interrupt->shouldInterrupt())
217 return nullptr;
218
219 phase = ObjectsCreated;
220
221 if (instance) {
222 if (QQmlEngineDebugService *service
223 = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
224 if (!parentContext->isInternal)
225 parentContext->asQQmlContextPrivate()->instances.append(t: instance);
226 service->objectCreated(engine, object: instance);
227 } else if (!parentContext->isInternal && QQmlDebugConnector::service<QV4DebugService>()) {
228 parentContext->asQQmlContextPrivate()->instances.append(t: instance);
229 }
230 }
231
232 return instance;
233}
234
235void QQmlObjectCreator::beginPopulateDeferred(QQmlContextData *newContext)
236{
237 context = newContext;
238 sharedState->rootContext = newContext;
239
240 Q_ASSERT(topLevelCreator);
241 Q_ASSERT(!sharedState->allJavaScriptObjects);
242
243 QV4::Scope valueScope(v4);
244 sharedState->allJavaScriptObjects = valueScope.alloc(nValues: compilationUnit->totalObjectCount());
245}
246
247void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex,
248 const QQmlPropertyPrivate *qmlProperty,
249 const QV4::CompiledData::Binding *binding)
250{
251 QQmlData *declarativeData = QQmlData::get(object: instance);
252 QObject *bindingTarget = instance;
253
254 QQmlRefPointer<QQmlPropertyCache> cache = declarativeData->propertyCache;
255 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(obj: instance);
256
257 QObject *scopeObject = instance;
258 qSwap(value1&: _scopeObject, value2&: scopeObject);
259
260 QV4::Scope valueScope(v4);
261 QScopedValueRollback<QV4::Value*> jsObjectGuard(sharedState->allJavaScriptObjects,
262 valueScope.alloc(nValues: compilationUnit->totalObjectCount()));
263
264 Q_ASSERT(topLevelCreator);
265 QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
266
267 qSwap(value1&: _qmlContext, value2&: qmlContext);
268
269 qSwap(value1&: _propertyCache, value2&: cache);
270 qSwap(value1&: _qobject, value2&: instance);
271
272 int objectIndex = deferredIndex;
273 qSwap(value1&: _compiledObjectIndex, value2&: objectIndex);
274
275 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index: _compiledObjectIndex);
276 qSwap(value1&: _compiledObject, value2&: obj);
277 qSwap(value1&: _ddata, value2&: declarativeData);
278 qSwap(value1&: _bindingTarget, value2&: bindingTarget);
279 qSwap(value1&: _vmeMetaObject, value2&: vmeMetaObject);
280
281 if (binding) {
282 Q_ASSERT(qmlProperty);
283 Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding);
284
285 QQmlListProperty<void> savedList;
286 qSwap(value1&: _currentList, value2&: savedList);
287
288 const QQmlPropertyData &property = qmlProperty->core;
289
290 if (property.isQList()) {
291 void *argv[1] = { (void*)&_currentList };
292 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
293 } else if (_currentList.object) {
294 _currentList = QQmlListProperty<void>();
295 }
296
297 setPropertyBinding(property: &property, binding);
298
299 qSwap(value1&: _currentList, value2&: savedList);
300 } else {
301 setupBindings(/*applyDeferredBindings=*/true);
302 }
303
304 qSwap(value1&: _vmeMetaObject, value2&: vmeMetaObject);
305 qSwap(value1&: _bindingTarget, value2&: bindingTarget);
306 qSwap(value1&: _ddata, value2&: declarativeData);
307 qSwap(value1&: _compiledObject, value2&: obj);
308 qSwap(value1&: _compiledObjectIndex, value2&: objectIndex);
309 qSwap(value1&: _qobject, value2&: instance);
310 qSwap(value1&: _propertyCache, value2&: cache);
311
312 qSwap(value1&: _qmlContext, value2&: qmlContext);
313 qSwap(value1&: _scopeObject, value2&: scopeObject);
314}
315
316bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
317 const QQmlData::DeferredData *deferredData)
318{
319 beginPopulateDeferred(newContext: deferredData->context);
320 populateDeferred(instance, deferredIndex: deferredData->deferredIdx);
321 finalizePopulateDeferred();
322 return errors.isEmpty();
323}
324
325void QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
326 const QV4::CompiledData::Binding *binding)
327{
328 populateDeferred(instance: qmlProperty.object(), deferredIndex, qmlProperty: QQmlPropertyPrivate::get(p: qmlProperty),
329 binding);
330}
331
332void QQmlObjectCreator::finalizePopulateDeferred()
333{
334 phase = ObjectsCreated;
335}
336
337void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
338{
339 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
340 QV4::Scope scope(v4);
341
342 int propertyType = property->propType();
343
344 if (property->isEnum()) {
345 if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) {
346 propertyType = QMetaType::Int;
347 } else {
348 // ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
349 QVariant value = compilationUnit->bindingValueAsString(binding);
350 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
351 Q_ASSERT(ok);
352 Q_UNUSED(ok);
353 return;
354 }
355 }
356
357 auto assertOrNull = [&](bool ok)
358 {
359 Q_ASSERT(ok || binding->type == QV4::CompiledData::Binding::Type_Null);
360 Q_UNUSED(ok);
361 };
362
363 auto assertType = [&](QV4::CompiledData::Binding::ValueType type)
364 {
365 Q_ASSERT(binding->type == type || binding->type == QV4::CompiledData::Binding::Type_Null);
366 Q_UNUSED(type);
367 };
368
369 if (property->isQObject()) {
370 if (binding->type == QV4::CompiledData::Binding::Type_Null) {
371 QObject *value = nullptr;
372 const bool ok = property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
373 Q_ASSERT(ok);
374 Q_UNUSED(ok);
375 return;
376 }
377 }
378
379 switch (propertyType) {
380 case QMetaType::QVariant: {
381 if (binding->type == QV4::CompiledData::Binding::Type_Number) {
382 double n = compilationUnit->bindingValueAsNumber(binding);
383 if (double(int(n)) == n) {
384 if (property->isVarProperty()) {
385 _vmeMetaObject->setVMEProperty(index: property->coreIndex(), v: QV4::Value::fromInt32(i: int(n)));
386 } else {
387 int i = int(n);
388 QVariant value(i);
389 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
390 }
391 } else {
392 if (property->isVarProperty()) {
393 _vmeMetaObject->setVMEProperty(index: property->coreIndex(), v: QV4::Value::fromDouble(d: n));
394 } else {
395 QVariant value(n);
396 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
397 }
398 }
399 } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
400 if (property->isVarProperty()) {
401 _vmeMetaObject->setVMEProperty(index: property->coreIndex(), v: QV4::Value::fromBoolean(b: binding->valueAsBoolean()));
402 } else {
403 QVariant value(binding->valueAsBoolean());
404 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
405 }
406 } else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
407 if (property->isVarProperty()) {
408 _vmeMetaObject->setVMEProperty(index: property->coreIndex(), v: QV4::Value::nullValue());
409 } else {
410 QVariant nullValue = QVariant::fromValue(value: nullptr);
411 property->writeProperty(target: _qobject, value: &nullValue, flags: propertyWriteFlags);
412 }
413 } else {
414 QString stringValue = compilationUnit->bindingValueAsString(binding);
415 if (property->isVarProperty()) {
416 QV4::ScopedString s(scope, v4->newString(s: stringValue));
417 _vmeMetaObject->setVMEProperty(index: property->coreIndex(), v: s);
418 } else {
419 // ### Qt 6: Doing the conversion here where we don't know the eventual target type is rather strange
420 // and caused for instance QTBUG-78943
421 QVariant value = QQmlStringConverters::variantFromString(stringValue);
422 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
423 }
424 }
425 }
426 break;
427 case QMetaType::QString: {
428 assertOrNull(binding->evaluatesToString());
429 QString value = compilationUnit->bindingValueAsString(binding);
430 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
431 }
432 break;
433 case QMetaType::QStringList: {
434 assertOrNull(binding->evaluatesToString());
435 QStringList value(compilationUnit->bindingValueAsString(binding));
436 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
437 }
438 break;
439 case QMetaType::QByteArray: {
440 assertType(QV4::CompiledData::Binding::Type_String);
441 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
442 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
443 }
444 break;
445 case QMetaType::QUrl: {
446 assertType(QV4::CompiledData::Binding::Type_String);
447 QString string = compilationUnit->bindingValueAsString(binding);
448 // Encoded dir-separators defeat QUrl processing - decode them first
449 string.replace(before: QLatin1String("%2f"), after: QLatin1String("/"), cs: Qt::CaseInsensitive);
450 QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(relative: QUrl(string));
451 // Apply URL interceptor
452 if (engine->urlInterceptor())
453 value = engine->urlInterceptor()->intercept(path: value, type: QQmlAbstractUrlInterceptor::UrlString);
454 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
455 }
456 break;
457 case QMetaType::UInt: {
458 assertType(QV4::CompiledData::Binding::Type_Number);
459 double d = compilationUnit->bindingValueAsNumber(binding);
460 uint value = uint(d);
461 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
462 break;
463 }
464 break;
465 case QMetaType::Int: {
466 assertType(QV4::CompiledData::Binding::Type_Number);
467 double d = compilationUnit->bindingValueAsNumber(binding);
468 int value = int(d);
469 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
470 break;
471 }
472 break;
473 case QMetaType::Float: {
474 assertType(QV4::CompiledData::Binding::Type_Number);
475 float value = float(compilationUnit->bindingValueAsNumber(binding));
476 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
477 }
478 break;
479 case QMetaType::Double: {
480 assertType(QV4::CompiledData::Binding::Type_Number);
481 double value = compilationUnit->bindingValueAsNumber(binding);
482 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
483 }
484 break;
485 case QMetaType::QColor: {
486 bool ok = false;
487 uint colorValue = QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
488 assertOrNull(ok);
489 struct { void *data[4]; } buffer;
490 if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) {
491 property->writeProperty(target: _qobject, value: &buffer, flags: propertyWriteFlags);
492 }
493 }
494 break;
495#if QT_CONFIG(datestring)
496 case QMetaType::QDate: {
497 bool ok = false;
498 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
499 assertOrNull(ok);
500 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
501 }
502 break;
503 case QMetaType::QTime: {
504 bool ok = false;
505 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
506 assertOrNull(ok);
507 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
508 }
509 break;
510 case QMetaType::QDateTime: {
511 bool ok = false;
512 QDateTime value = QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
513 // ### VME compatibility :(
514 {
515 const qint64 date = value.date().toJulianDay();
516 const int msecsSinceStartOfDay = value.time().msecsSinceStartOfDay();
517 value = QDateTime(QDate::fromJulianDay(jd_: date), QTime::fromMSecsSinceStartOfDay(msecs: msecsSinceStartOfDay));
518 }
519 assertOrNull(ok);
520 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
521 }
522 break;
523#endif // datestring
524 case QMetaType::QPoint: {
525 bool ok = false;
526 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok).toPoint();
527 assertOrNull(ok);
528 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
529 }
530 break;
531 case QMetaType::QPointF: {
532 bool ok = false;
533 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
534 assertOrNull(ok);
535 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
536 }
537 break;
538 case QMetaType::QSize: {
539 bool ok = false;
540 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok).toSize();
541 assertOrNull(ok);
542 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
543 }
544 break;
545 case QMetaType::QSizeF: {
546 bool ok = false;
547 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
548 assertOrNull(ok);
549 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
550 }
551 break;
552 case QMetaType::QRect: {
553 bool ok = false;
554 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok).toRect();
555 assertOrNull(ok);
556 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
557 }
558 break;
559 case QMetaType::QRectF: {
560 bool ok = false;
561 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), ok: &ok);
562 assertOrNull(ok);
563 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
564 }
565 break;
566 case QMetaType::Bool: {
567 assertType(QV4::CompiledData::Binding::Type_Boolean);
568 bool value = binding->valueAsBoolean();
569 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
570 }
571 break;
572 case QMetaType::QVector2D: {
573 struct {
574 float xp;
575 float yp;
576 } vec;
577 bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
578 assertOrNull(ok);
579 Q_UNUSED(ok);
580 property->writeProperty(target: _qobject, value: &vec, flags: propertyWriteFlags);
581 }
582 break;
583 case QMetaType::QVector3D: {
584 struct {
585 float xp;
586 float yp;
587 float zy;
588 } vec;
589 bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
590 assertOrNull(ok);
591 Q_UNUSED(ok);
592 property->writeProperty(target: _qobject, value: &vec, flags: propertyWriteFlags);
593 }
594 break;
595 case QMetaType::QVector4D: {
596 struct {
597 float xp;
598 float yp;
599 float zy;
600 float wp;
601 } vec;
602 bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
603 assertOrNull(ok);
604 Q_UNUSED(ok);
605 property->writeProperty(target: _qobject, value: &vec, flags: propertyWriteFlags);
606 }
607 break;
608 case QMetaType::QQuaternion: {
609 struct {
610 float wp;
611 float xp;
612 float yp;
613 float zp;
614 } vec;
615 bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec));
616 assertOrNull(ok);
617 Q_UNUSED(ok);
618 property->writeProperty(target: _qobject, value: &vec, flags: propertyWriteFlags);
619 }
620 break;
621 case QMetaType::QRegExp:
622 assertOrNull(!"not possible");
623 break;
624 default: {
625 // generate single literal value assignment to a list property if required
626 if (property->propType() == qMetaTypeId<QList<qreal> >()) {
627 assertType(QV4::CompiledData::Binding::Type_Number);
628 QList<qreal> value;
629 value.append(t: compilationUnit->bindingValueAsNumber(binding));
630 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
631 break;
632 } else if (property->propType() == qMetaTypeId<QList<int> >()) {
633 assertType(QV4::CompiledData::Binding::Type_Number);
634 double n = compilationUnit->bindingValueAsNumber(binding);
635 QList<int> value;
636 value.append(t: int(n));
637 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
638 break;
639 } else if (property->propType() == qMetaTypeId<QList<bool> >()) {
640 assertType(QV4::CompiledData::Binding::Type_Boolean);
641 QList<bool> value;
642 value.append(t: binding->valueAsBoolean());
643 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
644 break;
645 } else if (property->propType() == qMetaTypeId<QList<QUrl> >()) {
646 assertType(QV4::CompiledData::Binding::Type_String);
647 QString urlString = compilationUnit->bindingValueAsString(binding);
648 QUrl u = urlString.isEmpty() ? QUrl()
649 : compilationUnit->finalUrl().resolved(relative: QUrl(urlString));
650 QList<QUrl> value;
651 value.append(t: u);
652 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
653 break;
654 } else if (property->propType() == qMetaTypeId<QList<QString> >()) {
655 assertOrNull(binding->evaluatesToString());
656 QList<QString> value;
657 value.append(t: compilationUnit->bindingValueAsString(binding));
658 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
659 break;
660 } else if (property->propType() == qMetaTypeId<QJSValue>()) {
661 QJSValue value;
662 if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
663 value = QJSValue(binding->valueAsBoolean());
664 } else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
665 double n = compilationUnit->bindingValueAsNumber(binding);
666 if (double(int(n)) == n) {
667 value = QJSValue(int(n));
668 } else
669 value = QJSValue(n);
670 } else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
671 value = QJSValue::NullValue;
672 } else {
673 value = QJSValue(compilationUnit->bindingValueAsString(binding));
674 }
675 property->writeProperty(target: _qobject, value: &value, flags: propertyWriteFlags);
676 break;
677 }
678
679 // otherwise, try a custom type assignment
680 QString stringValue = compilationUnit->bindingValueAsString(binding);
681 QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType());
682 QVariant value = converter ? (*converter)(stringValue) : QVariant();
683
684 QMetaProperty metaProperty = _qobject->metaObject()->property(index: property->coreIndex());
685 if (value.isNull() || metaProperty.userType() != property->propType()) {
686 recordError(location: binding->location, description: tr(sourceText: "Cannot assign value %1 to property %2").arg(a: stringValue).arg(a: QString::fromUtf8(str: metaProperty.name())));
687 break;
688 }
689
690 property->writeProperty(target: _qobject, value: value.data(), flags: propertyWriteFlags);
691 }
692 break;
693 }
694}
695
696static QQmlType qmlTypeForObject(QObject *object)
697{
698 QQmlType type;
699 const QMetaObject *mo = object->metaObject();
700 while (mo && !type.isValid()) {
701 type = QQmlMetaType::qmlType(mo);
702 mo = mo->superClass();
703 }
704 return type;
705}
706
707void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
708{
709 QQmlListProperty<void> savedList;
710 qSwap(value1&: _currentList, value2&: savedList);
711
712 const QV4::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(i: _compiledObjectIndex);
713
714 if (_compiledObject->idNameIndex) {
715 const QQmlPropertyData *idProperty = propertyData.last();
716 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
717 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType() == QMetaType::QString) {
718 QV4::CompiledData::Binding idBinding;
719 idBinding.propertyNameIndex = 0; // Not used
720 idBinding.flags = 0;
721 idBinding.type = QV4::CompiledData::Binding::Type_String;
722 idBinding.stringIndex = _compiledObject->idNameIndex;
723 idBinding.location = _compiledObject->location; // ###
724 setPropertyValue(property: idProperty, binding: &idBinding);
725 }
726 }
727
728 // ### this is best done through type-compile-time binding skip lists.
729 if (_valueTypeProperty) {
730 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, index: QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
731
732 if (binding && !binding->isValueTypeProxy()) {
733 QQmlPropertyPrivate::removeBinding(o: _bindingTarget, index: QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
734 } else if (binding) {
735 QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
736
737 if (qmlTypeForObject(object: _bindingTarget).isValid()) {
738 quint32 bindingSkipList = 0;
739
740 QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
741
742 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
743 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
744 QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(key: stringAt(idx: binding->propertyNameIndex), object: _qobject, context) : defaultProperty;
745 if (property)
746 bindingSkipList |= (1 << property->coreIndex());
747 }
748
749 proxy->removeBindings(mask: bindingSkipList);
750 }
751 }
752 }
753
754 int currentListPropertyIndex = -1;
755
756 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
757 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
758 QQmlPropertyData *const property = propertyData.at(i);
759 if (property) {
760 QQmlPropertyData* targetProperty = property;
761 if (targetProperty->isAlias()) {
762 // follow alias
763 auto target = _bindingTarget;
764 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
765 QQmlPropertyIndex propIndex;
766 QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
767 QQmlData *data = QQmlData::get(object: target);
768 Q_ASSERT(data && data->propertyCache);
769 targetProperty = data->propertyCache->property(index: propIndex.coreIndex());
770 }
771 sharedState->requiredProperties.remove(akey: targetProperty);
772 }
773
774
775 if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding)
776 continue;
777
778 if (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding) {
779 if (!applyDeferredBindings)
780 continue;
781 } else {
782 if (applyDeferredBindings)
783 continue;
784 }
785
786 if (property && property->isQList()) {
787 if (property->coreIndex() != currentListPropertyIndex) {
788 void *argv[1] = { (void*)&_currentList };
789 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
790 currentListPropertyIndex = property->coreIndex();
791 }
792 } else if (_currentList.object) {
793 _currentList = QQmlListProperty<void>();
794 currentListPropertyIndex = -1;
795 }
796
797 if (!setPropertyBinding(property, binding))
798 return;
799 }
800
801 qSwap(value1&: _currentList, value2&: savedList);
802}
803
804bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProperty, const QV4::CompiledData::Binding *binding)
805{
806 if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
807 Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
808 QV4::ResolvedTypeReference *tr = resolvedType(id: binding->propertyNameIndex);
809 Q_ASSERT(tr);
810 QQmlType attachedType = tr->type;
811 if (!attachedType.isValid()) {
812 QQmlTypeNameCache::Result res = context->imports->query(stringAt(idx: binding->propertyNameIndex));
813 if (res.isValid())
814 attachedType = res.type;
815 else
816 return false;
817 }
818 QObject *qmlObject = qmlAttachedPropertiesObject(
819 _qobject, func: attachedType.attachedPropertiesFunction(engine: QQmlEnginePrivate::get(e: engine)));
820 if (!populateInstance(index: binding->value.objectIndex, instance: qmlObject, bindingTarget: qmlObject, /*value type property*/valueTypeProperty: nullptr))
821 return false;
822 return true;
823 }
824
825 // ### resolve this at compile time
826 if (bindingProperty && bindingProperty->propType() == qMetaTypeId<QQmlScriptString>()) {
827 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
828 context->asQQmlContext(), _scopeObject);
829 ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
830 ss.d.data()->lineNumber = binding->location.line;
831 ss.d.data()->columnNumber = binding->location.column;
832 ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String;
833 ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number;
834 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
835
836 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
837 QQmlPropertyData::RemoveBindingOnAliasWrite;
838 int propertyWriteStatus = -1;
839 void *argv[] = { &ss, nullptr, &propertyWriteStatus, &propertyWriteFlags };
840 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
841 return true;
842 }
843
844 QObject *createdSubObject = nullptr;
845 if (binding->type == QV4::CompiledData::Binding::Type_Object) {
846 createdSubObject = createInstance(index: binding->value.objectIndex, parent: _bindingTarget);
847 if (!createdSubObject)
848 return false;
849 }
850
851 if (!bindingProperty) // ### error
852 return true;
853
854 if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
855 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index: binding->value.objectIndex);
856 if (stringAt(idx: obj->inheritedTypeNameIndex).isEmpty()) {
857
858 QObject *groupObject = nullptr;
859 QQmlGadgetPtrWrapper *valueType = nullptr;
860 const QQmlPropertyData *valueTypeProperty = nullptr;
861 QObject *bindingTarget = _bindingTarget;
862
863 if (QQmlValueTypeFactory::isValueType(idx: bindingProperty->propType())) {
864 valueType = QQmlGadgetPtrWrapper::instance(engine, index: bindingProperty->propType());
865 if (!valueType) {
866 recordError(location: binding->location, description: tr(sourceText: "Cannot set properties on %1 as it is null").arg(a: stringAt(idx: binding->propertyNameIndex)));
867 return false;
868 }
869
870 valueType->read(obj: _qobject, idx: bindingProperty->coreIndex());
871
872 groupObject = valueType;
873 valueTypeProperty = bindingProperty;
874 } else {
875 void *argv[1] = { &groupObject };
876 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
877 if (!groupObject) {
878 recordError(location: binding->location, description: tr(sourceText: "Cannot set properties on %1 as it is null").arg(a: stringAt(idx: binding->propertyNameIndex)));
879 return false;
880 }
881
882 bindingTarget = groupObject;
883 }
884
885 if (!populateInstance(index: binding->value.objectIndex, instance: groupObject, bindingTarget, valueTypeProperty))
886 return false;
887
888 if (valueType)
889 valueType->write(obj: _qobject, idx: bindingProperty->coreIndex(), flags: QQmlPropertyData::BypassInterceptor);
890
891 return true;
892 }
893 }
894
895 if (_ddata->hasBindingBit(coreIndex: bindingProperty->coreIndex()) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
896 && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
897 && !_valueTypeProperty)
898 QQmlPropertyPrivate::removeBinding(o: _bindingTarget, index: QQmlPropertyIndex(bindingProperty->coreIndex()));
899
900 if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
901 if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
902 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
903 int signalIndex = _propertyCache->methodIndexToSignalIndex(index: bindingProperty->coreIndex());
904 QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
905 QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
906 context, _scopeObject, runtimeFunction, currentQmlContext());
907
908 bs->takeExpression(expr);
909 } else {
910 // When writing bindings to grouped properties implemented as value types,
911 // such as point.x: { someExpression; }, then the binding is installed on
912 // the point property (_qobjectForBindings) and after evaluating the expression,
913 // the result is written to a value type virtual property, that contains the sub-index
914 // of the "x" property.
915 QQmlBinding::Ptr qmlBinding;
916 const QQmlPropertyData *targetProperty = bindingProperty;
917 const QQmlPropertyData *subprop = nullptr;
918 if (_valueTypeProperty) {
919 targetProperty = _valueTypeProperty;
920 subprop = bindingProperty;
921 }
922 if (binding->isTranslationBinding()) {
923 qmlBinding = QQmlBinding::createTranslationBinding(unit: compilationUnit, binding, obj: _scopeObject, ctxt: context);
924 } else {
925 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
926 qmlBinding = QQmlBinding::create(property: targetProperty, function: runtimeFunction, obj: _scopeObject, ctxt: context, scope: currentQmlContext());
927 }
928
929 auto bindingTarget = _bindingTarget;
930 auto valueTypeProperty = _valueTypeProperty;
931 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState) mutable -> bool {
932 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, valueType: subprop) && targetProperty->isAlias())
933 return false;
934
935 sharedState->allCreatedBindings.push(o: qmlBinding);
936
937 if (bindingProperty->isAlias()) {
938 QQmlPropertyPrivate::setBinding(binding: qmlBinding.data(), flags: QQmlPropertyPrivate::DontEnable);
939 } else {
940 qmlBinding->addToObject();
941
942 if (!valueTypeProperty) {
943 QQmlData *targetDeclarativeData = QQmlData::get(object: bindingTarget);
944 Q_ASSERT(targetDeclarativeData);
945 targetDeclarativeData->setPendingBindingBit(obj: bindingTarget, coreIndex: bindingProperty->coreIndex());
946 }
947 }
948
949 return true;
950 };
951 if (!assignBinding(sharedState.data()))
952 pendingAliasBindings.push_back(x: assignBinding);
953 }
954 return true;
955 }
956
957 if (binding->type == QV4::CompiledData::Binding::Type_Object) {
958 if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) {
959 // ### determine value source and interceptor casts ahead of time.
960 QQmlType type = qmlTypeForObject(object: createdSubObject);
961 Q_ASSERT(type.isValid());
962
963 int valueSourceCast = type.propertyValueSourceCast();
964 if (valueSourceCast != -1) {
965 QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
966 QObject *target = createdSubObject->parent();
967 QQmlProperty prop;
968 if (_valueTypeProperty)
969 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
970 else
971 prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
972 vs->setTarget(prop);
973 return true;
974 }
975 int valueInterceptorCast = type.propertyValueInterceptorCast();
976 if (valueInterceptorCast != -1) {
977 QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
978 QObject *target = createdSubObject->parent();
979
980 QQmlPropertyIndex propertyIndex;
981 if (bindingProperty->isAlias()) {
982 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
983 QQmlPropertyIndex propIndex;
984 QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
985 QQmlData *data = QQmlData::get(object: target);
986 if (!data || !data->propertyCache) {
987 qWarning() << "can't resolve property alias for 'on' assignment";
988 return false;
989 }
990
991 // we can't have aliasses on subproperties of value types, so:
992 QQmlPropertyData targetPropertyData = *data->propertyCache->property(index: propIndex.coreIndex());
993 auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
994 vi->setTarget(prop);
995 propertyIndex = QQmlPropertyPrivate::propertyIndex(that: prop);
996 } else {
997 QQmlProperty prop;
998 if (_valueTypeProperty)
999 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
1000 else
1001 prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
1002 vi->setTarget(prop);
1003 propertyIndex = QQmlPropertyPrivate::propertyIndex(that: prop);
1004 }
1005
1006 QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(obj: target);
1007 if (!mo)
1008 mo = new QQmlInterceptorMetaObject(target, QQmlData::get(object: target)->propertyCache);
1009 mo->registerInterceptor(index: propertyIndex, interceptor: vi);
1010 return true;
1011 }
1012 return false;
1013 }
1014
1015 // Assigning object to signal property?
1016 if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
1017 if (!bindingProperty->isFunction()) {
1018 recordError(location: binding->valueLocation, description: tr(sourceText: "Cannot assign an object to signal property %1").arg(a: bindingProperty->name(_qobject)));
1019 return false;
1020 }
1021 QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
1022 if (!method.isValid()) {
1023 recordError(location: binding->valueLocation, description: tr(sourceText: "Cannot assign object type %1 with no default method").arg(a: QString::fromLatin1(str: createdSubObject->metaObject()->className())));
1024 return false;
1025 }
1026
1027 QMetaMethod signalMethod = _qobject->metaObject()->method(index: bindingProperty->coreIndex());
1028 if (!QMetaObject::checkConnectArgs(signal: signalMethod, method)) {
1029 recordError(location: binding->valueLocation,
1030 description: tr(sourceText: "Cannot connect mismatched signal/slot %1 vs %2")
1031 .arg(a: QString::fromUtf8(str: method.methodSignature()))
1032 .arg(a: QString::fromUtf8(str: signalMethod.methodSignature())));
1033 return false;
1034 }
1035
1036 QQmlPropertyPrivate::connect(sender: _qobject, signal_index: bindingProperty->coreIndex(), receiver: createdSubObject, method_index: method.methodIndex());
1037 return true;
1038 }
1039
1040 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
1041 QQmlPropertyData::RemoveBindingOnAliasWrite;
1042 int propertyWriteStatus = -1;
1043 void *argv[] = { nullptr, nullptr, &propertyWriteStatus, &propertyWriteFlags };
1044
1045 if (const char *iid = QQmlMetaType::interfaceIId(bindingProperty->propType())) {
1046 void *ptr = createdSubObject->qt_metacast(iid);
1047 if (ptr) {
1048 argv[0] = &ptr;
1049 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1050 } else {
1051 recordError(location: binding->location, description: tr(sourceText: "Cannot assign object to interface property"));
1052 return false;
1053 }
1054 } else if (bindingProperty->propType() == QMetaType::QVariant) {
1055 if (bindingProperty->isVarProperty()) {
1056 QV4::Scope scope(v4);
1057 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine: engine->handle(), object: createdSubObject));
1058 _vmeMetaObject->setVMEProperty(index: bindingProperty->coreIndex(), v: wrappedObject);
1059 } else {
1060 QVariant value = QVariant::fromValue(value: createdSubObject);
1061 argv[0] = &value;
1062 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1063 }
1064 } else if (bindingProperty->propType() == qMetaTypeId<QJSValue>()) {
1065 QV4::Scope scope(v4);
1066 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine: engine->handle(), object: createdSubObject));
1067 if (bindingProperty->isVarProperty()) {
1068 _vmeMetaObject->setVMEProperty(index: bindingProperty->coreIndex(), v: wrappedObject);
1069 } else {
1070 QJSValue value;
1071 QJSValuePrivate::setValue(jsval: &value, engine: v4, v: wrappedObject);
1072 argv[0] = &value;
1073 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1074 }
1075 } else if (bindingProperty->isQList()) {
1076 Q_ASSERT(_currentList.object);
1077
1078 void *itemToAdd = createdSubObject;
1079
1080 const char *iid = nullptr;
1081 int listItemType = QQmlEnginePrivate::get(e: engine)->listType(bindingProperty->propType());
1082 if (listItemType != -1)
1083 iid = QQmlMetaType::interfaceIId(listItemType);
1084 if (iid)
1085 itemToAdd = createdSubObject->qt_metacast(iid);
1086
1087 if (_currentList.append)
1088 _currentList.append(&_currentList, itemToAdd);
1089 else {
1090 recordError(location: binding->location, description: tr(sourceText: "Cannot assign object to read only list"));
1091 return false;
1092 }
1093
1094 } else {
1095 // pointer compatibility was tested in QQmlPropertyValidator at type compile time
1096 argv[0] = &createdSubObject;
1097 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1098 }
1099 return true;
1100 }
1101
1102 if (bindingProperty->isQList()) {
1103 recordError(location: binding->location, description: tr(sourceText: "Cannot assign primitives to lists"));
1104 return false;
1105 }
1106
1107 setPropertyValue(property: bindingProperty, binding);
1108 return true;
1109}
1110
1111void QQmlObjectCreator::setupFunctions()
1112{
1113 QV4::Scope scope(v4);
1114 QV4::ScopedValue function(scope);
1115 QV4::ScopedContext qmlContext(scope, currentQmlContext());
1116
1117 const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
1118 for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1119 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
1120 const QString name = runtimeFunction->name()->toQString();
1121
1122 QQmlPropertyData *property = _propertyCache->property(key: name, object: _qobject, context);
1123 if (!property->isVMEFunction())
1124 continue;
1125
1126 if (runtimeFunction->isGenerator())
1127 function = QV4::GeneratorFunction::create(scope: qmlContext, function: runtimeFunction);
1128 else
1129 function = QV4::FunctionObject::createScriptFunction(scope: qmlContext, function: runtimeFunction);
1130 _vmeMetaObject->setVmeMethod(index: property->coreIndex(), function);
1131 }
1132}
1133
1134void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
1135{
1136 QQmlError error;
1137 error.setUrl(compilationUnit->url());
1138 error.setLine(qmlConvertSourceCoordinate<quint32, int>(n: location.line));
1139 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(n: location.column));
1140 error.setDescription(description);
1141 errors << error;
1142}
1143
1144void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
1145{
1146 if (object->id >= 0)
1147 context->setIdProperty(object->id, instance);
1148}
1149
1150void QQmlObjectCreator::createQmlContext()
1151{
1152 _qmlContext->setM(QV4::QmlContext::create(parent: v4->rootContext(), context, scopeObject: _scopeObject));
1153}
1154
1155QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
1156{
1157 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1158 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
1159 Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
1160 QString typeName;
1161 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, typeName);
1162
1163 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(e: engine)->activeObjectCreator, this);
1164
1165 bool isComponent = false;
1166 QObject *instance = nullptr;
1167 QQmlData *ddata = nullptr;
1168 QQmlCustomParser *customParser = nullptr;
1169 QQmlParserStatus *parserStatus = nullptr;
1170 bool installPropertyCache = true;
1171
1172 if (obj->flags & QV4::CompiledData::Object::IsComponent) {
1173 isComponent = true;
1174 QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent);
1175 typeName = QStringLiteral("<component>");
1176 QQmlComponentPrivate::get(c: component)->creationContext = context;
1177 instance = component;
1178 ddata = QQmlData::get(object: instance, /*create*/true);
1179 } else {
1180 QV4::ResolvedTypeReference *typeRef = resolvedType(id: obj->inheritedTypeNameIndex);
1181 Q_ASSERT(typeRef);
1182 installPropertyCache = !typeRef->isFullyDynamicType;
1183 QQmlType type = typeRef->type;
1184 if (type.isValid() && !type.isInlineComponentType()) {
1185 typeName = type.qmlTypeName();
1186
1187 void *ddataMemory = nullptr;
1188 type.create(&instance, &ddataMemory, sizeof(QQmlData));
1189 if (!instance) {
1190 recordError(location: obj->location, description: tr(sourceText: "Unable to create object of type %1").arg(a: stringAt(idx: obj->inheritedTypeNameIndex)));
1191 return nullptr;
1192 }
1193
1194 {
1195 QQmlData *ddata = new (ddataMemory) QQmlData;
1196 ddata->ownMemory = false;
1197 QObjectPrivate* p = QObjectPrivate::get(o: instance);
1198 Q_ASSERT(!p->isDeletingChildren);
1199 p->declarativeData = ddata;
1200 }
1201
1202 const int parserStatusCast = type.parserStatusCast();
1203 if (parserStatusCast != -1)
1204 parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(instance) + parserStatusCast);
1205
1206 customParser = type.customParser();
1207
1208 if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
1209 QQmlData *ddata = QQmlData::get(object: instance, /*create*/true);
1210 ddata->rootObjectInCreation = true;
1211 sharedState->rootContext->isRootObjectInCreation = false;
1212 }
1213
1214 sharedState->allCreatedObjects.push(o: instance);
1215 } else {
1216 const auto compilationUnit = typeRef->compilationUnit();
1217 Q_ASSERT(compilationUnit);
1218 typeName = compilationUnit->fileName();
1219 // compilation unit is shared between root type and its inline component types
1220 // so isSingleton errorneously returns true for inline components
1221 if (compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType())
1222 {
1223 recordError(location: obj->location, description: tr(sourceText: "Composite Singleton Type %1 is not creatable").arg(a: stringAt(idx: obj->inheritedTypeNameIndex)));
1224 return nullptr;
1225 }
1226
1227
1228 if (!type.isInlineComponentType()) {
1229 QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
1230 instance = subCreator.create();
1231 if (!instance) {
1232 errors += subCreator.errors;
1233 return nullptr;
1234 }
1235 } else {
1236 int subObjectId = type.inlineComponendId();
1237 QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId};
1238 QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
1239 instance = subCreator.create(subComponentIndex: subObjectId, parent: nullptr, interrupt: nullptr, flags: CreationFlags::InlineComponent);
1240 if (!instance) {
1241 errors += subCreator.errors;
1242 return nullptr;
1243 }
1244 }
1245 }
1246 if (instance->isWidgetType()) {
1247 if (parent && parent->isWidgetType()) {
1248 QAbstractDeclarativeData::setWidgetParent(instance, parent);
1249 } else {
1250 // No parent! Layouts need to handle this through a default property that
1251 // reparents accordingly. Otherwise the garbage collector will collect.
1252 }
1253 } else if (parent) {
1254 QQml_setParent_noEvent(object: instance, parent);
1255 }
1256
1257 ddata = QQmlData::get(object: instance, /*create*/true);
1258 }
1259
1260 Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
1261 compilationUnit.data(), obj, typeName, context->url()));
1262 Q_UNUSED(typeName); // only relevant for tracing
1263
1264 ddata->lineNumber = obj->location.line;
1265 ddata->columnNumber = obj->location.column;
1266
1267 ddata->setImplicitDestructible();
1268 // inline components are root objects, but their index is != 0, so we need
1269 // an additional check
1270 const bool isInlineComponent = obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot;
1271 if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation || isInlineComponent) {
1272 if (ddata->context) {
1273 Q_ASSERT(ddata->context != context);
1274 Q_ASSERT(ddata->outerContext);
1275 Q_ASSERT(ddata->outerContext != context);
1276 QQmlContextData *c = ddata->context;
1277 while (c->linkedContext) c = c->linkedContext;
1278 c->linkedContext = context;
1279 } else {
1280 ddata->context = context;
1281 }
1282 ddata->ownContext = ddata->context;
1283 } else if (!ddata->context) {
1284 ddata->context = context;
1285 }
1286
1287 context->addObject(data: ddata);
1288
1289 if (parserStatus) {
1290 parserStatus->classBegin();
1291 // push() the profiler state here, together with the parserStatus, as we'll pop() them
1292 // together, too.
1293 Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
1294 sharedState->allParserStatusCallbacks.push(o: parserStatus);
1295 parserStatus->d = &sharedState->allParserStatusCallbacks.top();
1296 }
1297
1298 // Register the context object in the context early on in order for pending binding
1299 // initialization to find it available.
1300 if (isContextObject)
1301 context->contextObject = instance;
1302
1303 if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
1304 customParser->engine = QQmlEnginePrivate::get(e: engine);
1305 customParser->imports = compilationUnit->typeNameCache.data();
1306
1307 QList<const QV4::CompiledData::Binding *> bindings;
1308 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1309 const QV4::CompiledData::Binding *binding = obj->bindingTable();
1310 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1311 if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding) {
1312 bindings << binding;
1313 }
1314 }
1315 customParser->applyBindings(instance, compilationUnit.data(), bindings);
1316
1317 customParser->engine = nullptr;
1318 customParser->imports = (QQmlTypeNameCache*)nullptr;
1319 }
1320
1321 if (isComponent) {
1322 registerObjectWithContextById(object: obj, instance);
1323 return instance;
1324 }
1325
1326 QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches->at(index);
1327 Q_ASSERT(!cache.isNull());
1328 if (installPropertyCache) {
1329 if (ddata->propertyCache)
1330 ddata->propertyCache->release();;
1331 ddata->propertyCache = cache.data();
1332 ddata->propertyCache->addref();
1333 }
1334
1335 QObject *scopeObject = instance;
1336 qSwap(value1&: _scopeObject, value2&: scopeObject);
1337
1338 Q_ASSERT(sharedState->allJavaScriptObjects);
1339 *sharedState->allJavaScriptObjects = QV4::QObjectWrapper::wrap(engine: v4, object: instance);
1340 ++sharedState->allJavaScriptObjects;
1341
1342 QV4::Scope valueScope(v4);
1343 QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
1344
1345 qSwap(value1&: _qmlContext, value2&: qmlContext);
1346
1347 bool ok = populateInstance(index, instance, /*binding target*/bindingTarget: instance, /*value type property*/valueTypeProperty: nullptr);
1348 if (ok) {
1349 if (isContextObject && !pendingAliasBindings.empty()) {
1350 bool processedAtLeastOneBinding = false;
1351 do {
1352 processedAtLeastOneBinding = false;
1353 for (std::vector<PendingAliasBinding>::iterator it = pendingAliasBindings.begin();
1354 it != pendingAliasBindings.end(); ) {
1355 if ((*it)(sharedState.data())) {
1356 it = pendingAliasBindings.erase(position: it);
1357 processedAtLeastOneBinding = true;
1358 } else {
1359 ++it;
1360 }
1361 }
1362 } while (processedAtLeastOneBinding && pendingAliasBindings.empty());
1363 Q_ASSERT(pendingAliasBindings.empty());
1364 }
1365 } else {
1366 // an error occurred, so we can't setup the pending alias bindings
1367 pendingAliasBindings.clear();
1368 }
1369
1370 qSwap(value1&: _qmlContext, value2&: qmlContext);
1371 qSwap(value1&: _scopeObject, value2&: scopeObject);
1372
1373 return ok ? instance : nullptr;
1374}
1375
1376QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1377{
1378 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1379 phase = Finalizing;
1380
1381 QQmlObjectCreatorRecursionWatcher watcher(this);
1382 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(e: engine)->activeObjectCreator, this);
1383
1384 while (!sharedState->allCreatedBindings.isEmpty()) {
1385 QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.pop();
1386 Q_ASSERT(b);
1387 // skip, if b is not added to an object
1388 if (!b->isAddedToObject())
1389 continue;
1390 QQmlData *data = QQmlData::get(object: b->targetObject());
1391 Q_ASSERT(data);
1392 data->clearPendingBindingBit(coreIndex: b->targetPropertyIndex().coreIndex());
1393 b->setEnabled(e: true, f: QQmlPropertyData::BypassInterceptor |
1394 QQmlPropertyData::DontRemoveBinding);
1395 if (!b->isValueTypeProxy()) {
1396 QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
1397 if (!binding->hasError() && !binding->hasDependencies()
1398 && binding->context() && !binding->context()->unresolvedNames)
1399 b->removeFromObject();
1400 }
1401
1402 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1403 return nullptr;
1404 }
1405
1406 if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
1407 while (!sharedState->allParserStatusCallbacks.isEmpty()) {
1408 QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
1409 QQmlParserStatus *status = sharedState->allParserStatusCallbacks.pop();
1410
1411 if (status && status->d) {
1412 status->d = nullptr;
1413 status->componentComplete();
1414 }
1415
1416 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1417 return nullptr;
1418 }
1419 }
1420
1421 for (int ii = 0; ii < sharedState->finalizeCallbacks.count(); ++ii) {
1422 QQmlEnginePrivate::FinalizeCallback callback = sharedState->finalizeCallbacks.at(i: ii);
1423 QObject *obj = callback.first;
1424 if (obj) {
1425 void *args[] = { nullptr };
1426 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
1427 }
1428 if (watcher.hasRecursed())
1429 return nullptr;
1430 }
1431 sharedState->finalizeCallbacks.clear();
1432
1433 while (sharedState->componentAttached) {
1434 QQmlComponentAttached *a = sharedState->componentAttached;
1435 a->rem();
1436 QQmlData *d = QQmlData::get(object: a->parent());
1437 Q_ASSERT(d);
1438 Q_ASSERT(d->context);
1439 a->add(a: &d->context->componentAttached);
1440 if (QQmlVME::componentCompleteEnabled())
1441 emit a->completed();
1442
1443 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1444 return nullptr;
1445 }
1446
1447 phase = Done;
1448
1449 return sharedState->rootContext;
1450}
1451
1452void QQmlObjectCreator::clear()
1453{
1454 if (phase == Done || phase == Finalizing || phase == Startup)
1455 return;
1456 Q_ASSERT(phase != Startup);
1457
1458 while (!sharedState->allCreatedObjects.isEmpty()) {
1459 auto object = sharedState->allCreatedObjects.pop();
1460 if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
1461 delete object;
1462 }
1463 }
1464
1465 while (sharedState->componentAttached) {
1466 QQmlComponentAttached *a = sharedState->componentAttached;
1467 a->rem();
1468 }
1469
1470 phase = Done;
1471}
1472
1473bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty)
1474{
1475 QQmlData *declarativeData = QQmlData::get(object: instance, /*create*/true);
1476
1477 qSwap(value1&: _qobject, value2&: instance);
1478 qSwap(value1&: _valueTypeProperty, value2&: valueTypeProperty);
1479 qSwap(value1&: _compiledObjectIndex, value2&: index);
1480 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index: _compiledObjectIndex);
1481 qSwap(value1&: _compiledObject, value2&: obj);
1482 qSwap(value1&: _ddata, value2&: declarativeData);
1483 qSwap(value1&: _bindingTarget, value2&: bindingTarget);
1484
1485 QV4::Scope valueScope(v4);
1486 QV4::ScopedValue scopeObjectProtector(valueScope);
1487
1488 QQmlRefPointer<QQmlPropertyCache> cache = propertyCaches->at(index: _compiledObjectIndex);
1489
1490 QQmlVMEMetaObject *vmeMetaObject = nullptr;
1491 if (propertyCaches->needsVMEMetaObject(index: _compiledObjectIndex)) {
1492 Q_ASSERT(!cache.isNull());
1493 // install on _object
1494 vmeMetaObject = new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
1495 if (_ddata->propertyCache)
1496 _ddata->propertyCache->release();
1497 _ddata->propertyCache = cache.data();
1498 _ddata->propertyCache->addref();
1499 scopeObjectProtector = _ddata->jsWrapper.value();
1500 } else {
1501 vmeMetaObject = QQmlVMEMetaObject::get(obj: _qobject);
1502 }
1503
1504 registerObjectWithContextById(object: _compiledObject, instance: _qobject);
1505
1506 qSwap(value1&: _propertyCache, value2&: cache);
1507 qSwap(value1&: _vmeMetaObject, value2&: vmeMetaObject);
1508
1509 if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings)
1510 _ddata->deferData(objectIndex: _compiledObjectIndex, compilationUnit, context);
1511
1512 QSet<QString> postHocRequired;
1513 for (auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
1514 postHocRequired.insert(value: stringAt(idx: it->nameIndex));
1515 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1516
1517 for (int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
1518 const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
1519 QQmlPropertyData *propertyData = _propertyCache->property(index: _propertyCache->propertyOffset() + propertyIndex);
1520 // only compute stringAt if there's a chance for the lookup to succeed
1521 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(value: stringAt(idx: property->nameIndex));
1522 if (!property->isRequired && postHocRequired.end() == postHocIt)
1523 continue;
1524 if (postHocIt != postHocRequired.end())
1525 postHocRequired.erase(i: postHocIt);
1526 sharedState->hadRequiredProperties = true;
1527 sharedState->requiredProperties.insert(akey: propertyData,
1528 avalue: RequiredPropertyInfo {.propertyName: compilationUnit->stringAt(index: property->nameIndex), .fileUrl: compilationUnit->finalUrl(), .location: property->location, .aliasesToRequired: {}});
1529
1530 }
1531
1532 for (int i = 0; i <= _propertyCache->propertyOffset(); ++i) {
1533 QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1534 if (!propertyData)
1535 continue;
1536 if (!propertyData->isRequired() && postHocRequired.isEmpty())
1537 continue;
1538 QString name = propertyData->name(_qobject);
1539 auto postHocIt = postHocRequired.find(value: name);
1540 if (!propertyData->isRequired() && postHocRequired.end() == postHocIt )
1541 continue;
1542
1543 if (postHocIt != postHocRequired.end())
1544 postHocRequired.erase(i: postHocIt);
1545
1546 sharedState->hadRequiredProperties = true;
1547 sharedState->requiredProperties.insert(akey: propertyData, avalue: RequiredPropertyInfo {.propertyName: name, .fileUrl: compilationUnit->finalUrl(), .location: _compiledObject->location, .aliasesToRequired: {}});
1548 }
1549 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1550 recordError(location: {}, description: QLatin1String("Property %1 was marked as required but does not exist").arg(args: *postHocRequired.begin()));
1551
1552 if (_compiledObject->nFunctions > 0)
1553 setupFunctions();
1554 setupBindings();
1555
1556 for (int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
1557 const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
1558 const auto originalAlias = alias;
1559 while (alias->aliasToLocalAlias)
1560 alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
1561 Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
1562 if (!context->idValues->wasSet())
1563 continue;
1564 QObject *target = context->idValues[alias->targetObjectId].data();
1565 if (!target)
1566 continue;
1567 QQmlData *targetDData = QQmlData::get(object: target, /*create*/false);
1568 if (targetDData == nullptr || targetDData->propertyCache == nullptr)
1569 continue;
1570 int coreIndex = QQmlPropertyIndex::fromEncoded(encodedIndex: alias->encodedMetaPropertyIndex).coreIndex();
1571 QQmlPropertyData *const targetProperty = targetDData->propertyCache->property(index: coreIndex);
1572 if (!targetProperty)
1573 continue;
1574 auto it = sharedState->requiredProperties.find(akey: targetProperty);
1575 if (it != sharedState->requiredProperties.end())
1576 it->aliasesToRequired.push_back(t: AliasToRequiredInfo {.propertyName: compilationUnit->stringAt(index: originalAlias->nameIndex), .fileUrl: compilationUnit->finalUrl()});
1577 }
1578
1579 qSwap(value1&: _vmeMetaObject, value2&: vmeMetaObject);
1580 qSwap(value1&: _bindingTarget, value2&: bindingTarget);
1581 qSwap(value1&: _ddata, value2&: declarativeData);
1582 qSwap(value1&: _compiledObject, value2&: obj);
1583 qSwap(value1&: _compiledObjectIndex, value2&: index);
1584 qSwap(value1&: _valueTypeProperty, value2&: valueTypeProperty);
1585 qSwap(value1&: _qobject, value2&: instance);
1586 qSwap(value1&: _propertyCache, value2&: cache);
1587
1588 return errors.isEmpty();
1589}
1590
1591
1592
1593
1594QQmlObjectCreatorRecursionWatcher::QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)
1595 : sharedState(creator->sharedState)
1596 , watcher(creator->sharedState.data())
1597{
1598}
1599

source code of qtdeclarative/src/qml/qml/qqmlobjectcreator.cpp