6#include <private/qqmlengine_p.h>
7#include <private/qqmlvmemetaobject_p.h>
8#include <private/qv4function_p.h>
9#include <private/qv4functionobject_p.h>
10#include <private/qv4qobjectwrapper_p.h>
11#include <private/qqmlbinding_p.h>
12#include <private/qqmlstringconverters_p.h>
13#include <private/qqmlboundsignal_p.h>
14#include <private/qqmlcomponentattached_p.h>
15#include <private/qqmlcomponent_p.h>
16#include <private/qqmlcustomparser_p.h>
17#include <private/qqmlscriptstring_p.h>
18#include <private/qqmlpropertyvalueinterceptor_p.h>
19#include <private/qqmlvaluetypeproxybinding_p.h>
20#include <private/qqmldebugconnector_p.h>
21#include <private/qqmldebugserviceinterfaces_p.h>
22#include <private/qqmlscriptdata_p.h>
23#include <private/qqmlsourcecoordinate_p.h>
24#include <private/qjsvalue_p.h>
25#include <private/qv4generatorobject_p.h>
26#include <private/qv4resolvedtypereference_p.h>
27#include <private/qqmlpropertybinding_p.h>
28#include <private/qqmlanybinding_p.h>
29#include <QtQml/private/qqmlvme_p.h>
31#include <QScopedValueRollback>
33#include <qtqml_tracepoints_p.h>
34#include <QScopedValueRollback>
35#include <QLoggingCategory>
43"struct ExecutionEngine;
" \
44"class ExecutableCompilationUnit;
" \
45"namespace CompiledData {
" \
51Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_entry, const QV4::ExecutableCompilationUnit *compilationUnit, const QV4::CompiledData::Object *object, const QUrl &url)
52Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_exit, const QString &typeName)
54QQmlObjectCreator::QQmlObjectCreator(
55 QQmlRefPointer<QQmlContextData> parentContext,
56 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
57 const QQmlRefPointer<QQmlContextData> &creationContext,
58 QQmlIncubatorPrivate *incubator)
60 , compilationUnit(compilationUnit)
61 , propertyCaches(compilationUnit->propertyCachesPtr())
62 , sharedState(new QQmlObjectCreatorSharedState, QQmlRefPointer<QQmlObjectCreatorSharedState>::Adopt)
63 , topLevelCreator(true)
64 , isContextObject(true)
65 , incubator(incubator)
67 init(std::move(parentContext));
69 sharedState->componentAttached = nullptr;
70 sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount());
71 sharedState->allParserStatusCallbacks.allocate(compilationUnit->totalParserStatusCount());
72 sharedState->allCreatedObjects.allocate(compilationUnit->totalObjectCount());
73 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
74 sharedState->creationContext = creationContext;
75 sharedState->rootContext.reset();
76 sharedState->hadTopLevelRequiredProperties = false;
78 if (auto profiler = QQmlEnginePrivate::get(engine)->profiler) {
79 Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
80 sharedState->profiler.init(profiler, compilationUnit->totalParserStatusCount()));
86QQmlObjectCreator::QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
87 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
88 QQmlObjectCreatorSharedState *inheritedSharedState, bool isContextObject)
90 , compilationUnit(compilationUnit)
91 , propertyCaches(compilationUnit->propertyCachesPtr())
92 , sharedState(inheritedSharedState)
93 , topLevelCreator(false)
94 , isContextObject(isContextObject)
97 init(std::move(parentContext));
100void QQmlObjectCreator::init(QQmlRefPointer<QQmlContextData> providedParentContext)
102 parentContext = std::move(providedParentContext);
103 engine = parentContext->engine();
104 v4 = engine->handle();
106 Q_ASSERT(compilationUnit);
107 Q_ASSERT(compilationUnit->engine == v4);
108 if (!compilationUnit->runtimeStrings)
109 compilationUnit->populate();
111 qmlUnit = compilationUnit->unitData();
113 _scopeObject = nullptr;
114 _bindingTarget = nullptr;
115 _valueTypeProperty = nullptr;
116 _compiledObject = nullptr;
117 _compiledObjectIndex = -1;
119 _vmeMetaObject = nullptr;
120 _qmlContext = nullptr;
123QQmlObjectCreator::~QQmlObjectCreator()
125 if (topLevelCreator) {
127 QQmlObjectCreatorRecursionWatcher watcher(this);
129 for (int i = 0; i < sharedState->allParserStatusCallbacks.count(); ++i) {
130 QQmlParserStatus *ps = sharedState->allParserStatusCallbacks.at(i);
134 while (sharedState->componentAttached) {
135 QQmlComponentAttached *a = sharedState->componentAttached;
141QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt, int flags)
143 if (phase == CreatingObjectsPhase2) {
144 phase = ObjectsCreated;
145 return context->contextObject();
147 Q_ASSERT(phase == Startup);
148 phase = CreatingObjects;
151 bool isComponentRoot = false; // either a "real
" component of or an inline component
153 if (subComponentIndex == -1) {
154 objectToCreate = /*root object*/0;
155 isComponentRoot = true;
157 Q_ASSERT(subComponentIndex >= 0);
158 if (flags & CreationFlags::InlineComponent) {
159 if (compilationUnit->componentsAreBound()
160 && compilationUnit != parentContext->typeCompilationUnit()) {
161 recordError({}, tr("Cannot instantiate bound
inline component in different
file"));
162 phase = ObjectsCreated;
165 objectToCreate = subComponentIndex;
166 isComponentRoot = true;
168 Q_ASSERT(flags & CreationFlags::NormalObject);
169 if (compilationUnit->componentsAreBound()
170 && sharedState->creationContext != parentContext) {
171 recordError({}, tr("Cannot instantiate bound
component "
172 "outside its creation
context"));
173 phase = ObjectsCreated;
176 const QV4::CompiledData::Object *compObj = compilationUnit->objectAt(subComponentIndex);
177 objectToCreate = compObj->bindingTable()->value.objectIndex;
181 context = QQmlEnginePrivate::get(engine)->createInternalContext(
182 compilationUnit, parentContext, subComponentIndex, isComponentRoot);
184 if (!sharedState->rootContext) {
185 sharedState->rootContext = context;
186 sharedState->rootContext->setIncubator(incubator);
187 sharedState->rootContext->setRootObjectInCreation(true);
190 QV4::Scope scope(v4);
192 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack() || topLevelCreator);
194 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope, compilationUnit->totalObjectCount());
196 if (!isComponentRoot && sharedState->creationContext) {
197 // otherwise QQmlEnginePrivate::createInternalContext() handles it
198 context->setImportedScripts(sharedState->creationContext->importedScripts());
201 QObject *instance = createInstance(objectToCreate, parent, /*isContextObject*/true);
203 QQmlData *ddata = QQmlData::get(instance);
205 ddata->compilationUnit = compilationUnit;
209 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
211 phase = CreatingObjectsPhase2;
213 if (interrupt && interrupt->shouldInterrupt())
216 phase = ObjectsCreated;
219 if (QQmlEngineDebugService *service
220 = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
221 if (!parentContext->isInternal())
222 parentContext->asQQmlContextPrivate()->appendInstance(instance);
223 service->objectCreated(engine, instance);
224 } else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
225 parentContext->asQQmlContextPrivate()->appendInstance(instance);
232void QQmlObjectCreator::beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &newContext)
234 context = newContext;
235 sharedState->rootContext = newContext;
237 Q_ASSERT(topLevelCreator);
238 Q_ASSERT(!sharedState->allJavaScriptObjects.canTrack());
240 // FIXME (QTBUG-122956): allocating from the short lived scope does not make any sense
241 QV4::Scope valueScope(v4);
242 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(valueScope, compilationUnit->totalObjectCount());
245void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex,
246 const QQmlPropertyPrivate *qmlProperty,
247 const QV4::CompiledData::Binding *binding)
249 doPopulateDeferred(instance, deferredIndex, [this, qmlProperty, binding]() {
250 Q_ASSERT(qmlProperty);
251 Q_ASSERT(binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding));
253 QQmlListProperty<void> savedList;
254 qSwap(_currentList, savedList);
256 const QQmlPropertyData &property = qmlProperty->core;
258 if (property.propType().flags().testFlag(QMetaType::IsQmlList)) {
259 void *argv[1] = { (void*)&_currentList };
260 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
261 } else if (_currentList.object) {
262 _currentList = QQmlListProperty<void>();
265 setPropertyBinding(&property, binding);
267 qSwap(_currentList, savedList);
271void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex)
273 doPopulateDeferred(instance, deferredIndex, [this]() { setupBindings(ApplyDeferred); });
276bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
277 const QQmlData::DeferredData *deferredData)
279 beginPopulateDeferred(deferredData->context);
280 populateDeferred(instance, deferredData->deferredIdx);
281 finalizePopulateDeferred();
282 return errors.isEmpty();
285void QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
286 const QV4::CompiledData::Binding *binding)
289 populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
292 populateDeferred(qmlProperty.object(), deferredIndex);
296void QQmlObjectCreator::populateDeferredInstance(
297 QObject *outerObject, int deferredIndex, int index, QObject *instance,
298 QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty,
299 const QV4::CompiledData::Binding *binding)
301 doPopulateDeferred(outerObject, deferredIndex, [&]() {
302 populateInstance(index, instance, bindingTarget, valueTypeProperty, binding);
306void QQmlObjectCreator::finalizePopulateDeferred()
308 phase = ObjectsCreated;
311void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding)
313 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
314 QV4::Scope scope(v4);
316 QMetaType propertyType = property->propType();
318 if (property->isEnum()) {
319 if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum) ||
320 // TODO: For historical reasons you can assign any number to an enum property alias
321 // This can be fixed with an opt-out mechanism, for example a pragma.
322 (property->isAlias() && binding->isNumberBinding())) {
323 propertyType = property->propType().underlyingType();
325 // ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
326 QVariant value = compilationUnit->bindingValueAsString(binding);
327 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
334 auto assertOrNull = [&](bool ok)
336 Q_ASSERT(ok || binding->type() == QV4::CompiledData::Binding::Type_Null);
340 auto assertType = [&](QV4::CompiledData::Binding::Type type)
342 Q_ASSERT(binding->type()== type || binding->type() == QV4::CompiledData::Binding::Type_Null);
346 if (property->isQObject()) {
347 if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
348 QObject *value = nullptr;
349 const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags);
356 switch (propertyType.id()) {
357 case QMetaType::QVariant: {
358 if (binding->type() == QV4::CompiledData::Binding::Type_Number) {
359 double n = compilationUnit->bindingValueAsNumber(binding);
360 if (double(int(n)) == n) {
361 if (property->isVarProperty()) {
362 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(int(n)));
366 property->writeProperty(_qobject, &value, propertyWriteFlags);
369 if (property->isVarProperty()) {
370 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromDouble(n));
373 property->writeProperty(_qobject, &value, propertyWriteFlags);
376 } else if (binding->type() == QV4::CompiledData::Binding::Type_Boolean) {
377 if (property->isVarProperty()) {
378 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean()));
380 QVariant value(binding->valueAsBoolean());
381 property->writeProperty(_qobject, &value, propertyWriteFlags);
383 } else if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
384 if (property->isVarProperty()) {
385 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue());
387 QVariant nullValue = QVariant::fromValue(nullptr);
388 property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
391 QString stringValue = compilationUnit->bindingValueAsString(binding);
392 if (property->isVarProperty()) {
393 QV4::ScopedString s(scope, v4->newString(stringValue));
394 _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
396 QVariant value = stringValue;
397 property->writeProperty(_qobject, &value, propertyWriteFlags);
402 case QMetaType::QString: {
403 assertOrNull(binding->evaluatesToString());
404 QString value = compilationUnit->bindingValueAsString(binding);
405 property->writeProperty(_qobject, &value, propertyWriteFlags);
408 case QMetaType::QStringList: {
409 assertOrNull(binding->evaluatesToString());
410 QStringList value(compilationUnit->bindingValueAsString(binding));
411 property->writeProperty(_qobject, &value, propertyWriteFlags);
414 case QMetaType::QByteArray: {
415 assertType(QV4::CompiledData::Binding::Type_String);
416 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
417 property->writeProperty(_qobject, &value, propertyWriteFlags);
420 case QMetaType::QUrl: {
421 assertType(QV4::CompiledData::Binding::Type_String);
422 const QString string = compilationUnit->bindingValueAsString(binding);
423 QUrl value = (!string.isEmpty() && QQmlPropertyPrivate::resolveUrlsOnAssignment())
424 ? compilationUnit->finalUrl().resolved(QUrl(string))
426 property->writeProperty(_qobject, &value, propertyWriteFlags);
429 case QMetaType::UInt: {
430 assertType(QV4::CompiledData::Binding::Type_Number);
431 double d = compilationUnit->bindingValueAsNumber(binding);
432 uint value = uint(d);
433 property->writeProperty(_qobject, &value, propertyWriteFlags);
437 case QMetaType::Int: {
438 assertType(QV4::CompiledData::Binding::Type_Number);
439 double d = compilationUnit->bindingValueAsNumber(binding);
441 property->writeProperty(_qobject, &value, propertyWriteFlags);
445 case QMetaType::SChar: {
446 assertType(QV4::CompiledData::Binding::Type_Number);
447 double d = compilationUnit->bindingValueAsNumber(binding);
448 qint8 value = qint8(d);
449 property->writeProperty(_qobject, &value, propertyWriteFlags);
452 case QMetaType::UChar: {
453 assertType(QV4::CompiledData::Binding::Type_Number);
454 double d = compilationUnit->bindingValueAsNumber(binding);
455 quint8 value = quint8(d);
456 property->writeProperty(_qobject, &value, propertyWriteFlags);
459 case QMetaType::Short: {
460 assertType(QV4::CompiledData::Binding::Type_Number);
461 double d = compilationUnit->bindingValueAsNumber(binding);
462 qint16 value = qint16(d);
463 property->writeProperty(_qobject, &value, propertyWriteFlags);
466 case QMetaType::UShort: {
467 assertType(QV4::CompiledData::Binding::Type_Number);
468 double d = compilationUnit->bindingValueAsNumber(binding);
469 quint16 value = quint16(d);
470 property->writeProperty(_qobject, &value, propertyWriteFlags);
473 case QMetaType::LongLong: {
474 assertType(QV4::CompiledData::Binding::Type_Number);
475 double d = compilationUnit->bindingValueAsNumber(binding);
476 qint64 value = qint64(d);
477 property->writeProperty(_qobject, &value, propertyWriteFlags);
480 case QMetaType::ULongLong: {
481 assertType(QV4::CompiledData::Binding::Type_Number);
482 double d = compilationUnit->bindingValueAsNumber(binding);
483 quint64 value = quint64(d);
484 property->writeProperty(_qobject, &value, propertyWriteFlags);
488 case QMetaType::Float: {
489 assertType(QV4::CompiledData::Binding::Type_Number);
490 float value = float(compilationUnit->bindingValueAsNumber(binding));
491 property->writeProperty(_qobject, &value, propertyWriteFlags);
494 case QMetaType::Double: {
495 assertType(QV4::CompiledData::Binding::Type_Number);
496 double value = compilationUnit->bindingValueAsNumber(binding);
497 property->writeProperty(_qobject, &value, propertyWriteFlags);
500 case QMetaType::QColor: {
501 QVariant data = QQmlValueTypeProvider::createValueType(
502 compilationUnit->bindingValueAsString(binding), propertyType);
503 if (data.isValid()) {
504 property->writeProperty(_qobject, data.data(), propertyWriteFlags);
508#if QT_CONFIG(datestring)
509 case QMetaType::QDate: {
511 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
513 property->writeProperty(_qobject, &value, propertyWriteFlags);
516 case QMetaType::QTime: {
518 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
520 property->writeProperty(_qobject, &value, propertyWriteFlags);
523 case QMetaType::QDateTime: {
525 QDateTime value = QQmlStringConverters::dateTimeFromString(
526 compilationUnit->bindingValueAsString(binding), &ok);
528 property->writeProperty(_qobject, &value, propertyWriteFlags);
532 case QMetaType::QPoint: {
534 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
536 property->writeProperty(_qobject, &value, propertyWriteFlags);
539 case QMetaType::QPointF: {
541 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
543 property->writeProperty(_qobject, &value, propertyWriteFlags);
546 case QMetaType::QSize: {
548 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
550 property->writeProperty(_qobject, &value, propertyWriteFlags);
553 case QMetaType::QSizeF: {
555 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
557 property->writeProperty(_qobject, &value, propertyWriteFlags);
560 case QMetaType::QRect: {
562 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
564 property->writeProperty(_qobject, &value, propertyWriteFlags);
567 case QMetaType::QRectF: {
569 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
571 property->writeProperty(_qobject, &value, propertyWriteFlags);
574 case QMetaType::Bool: {
575 assertType(QV4::CompiledData::Binding::Type_Boolean);
576 bool value = binding->valueAsBoolean();
577 property->writeProperty(_qobject, &value, propertyWriteFlags);
580 case QMetaType::QVector2D:
581 case QMetaType::QVector3D:
582 case QMetaType::QVector4D:
583 case QMetaType::QQuaternion: {
584 QVariant result = QQmlValueTypeProvider::createValueType(
585 compilationUnit->bindingValueAsString(binding), propertyType);
586 assertOrNull(result.isValid());
587 property->writeProperty(_qobject, result.data(), propertyWriteFlags);
591 // generate single literal value assignment to a list property if required
592 if (propertyType == QMetaType::fromType<QList<qreal>>()) {
593 assertType(QV4::CompiledData::Binding::Type_Number);
595 value.append(compilationUnit->bindingValueAsNumber(binding));
596 property->writeProperty(_qobject, &value, propertyWriteFlags);
598 } else if (propertyType == QMetaType::fromType<QList<int>>()) {
599 assertType(QV4::CompiledData::Binding::Type_Number);
600 double n = compilationUnit->bindingValueAsNumber(binding);
602 value.append(int(n));
603 property->writeProperty(_qobject, &value, propertyWriteFlags);
605 } else if (propertyType == QMetaType::fromType<QList<bool>>()) {
606 assertType(QV4::CompiledData::Binding::Type_Boolean);
608 value.append(binding->valueAsBoolean());
609 property->writeProperty(_qobject, &value, propertyWriteFlags);
611 } else if (propertyType == QMetaType::fromType<QList<QUrl>>()) {
612 assertType(QV4::CompiledData::Binding::Type_String);
613 const QUrl url(compilationUnit->bindingValueAsString(binding));
615 QQmlPropertyPrivate::resolveUrlsOnAssignment()
616 ? compilationUnit->finalUrl().resolved(url)
619 property->writeProperty(_qobject, &value, propertyWriteFlags);
621 } else if (propertyType == QMetaType::fromType<QList<QString>>()) {
622 assertOrNull(binding->evaluatesToString());
623 QList<QString> value;
624 value.append(compilationUnit->bindingValueAsString(binding));
625 property->writeProperty(_qobject, &value, propertyWriteFlags);
627 } else if (propertyType == QMetaType::fromType<QJSValue>()) {
629 switch (binding->type()) {
630 case QV4::CompiledData::Binding::Type_Boolean:
631 value = QJSValue(binding->valueAsBoolean());
633 case QV4::CompiledData::Binding::Type_Number: {
634 const double n = compilationUnit->bindingValueAsNumber(binding);
635 if (double(int(n)) == n)
636 value = QJSValue(int(n));
641 case QV4::CompiledData::Binding::Type_Null:
642 value = QJSValue::NullValue;
645 value = QJSValue(compilationUnit->bindingValueAsString(binding));
648 property->writeProperty(_qobject, &value, propertyWriteFlags);
652 switch (binding->type()) {
653 case QV4::CompiledData::Binding::Type_Boolean:
654 source = binding->valueAsBoolean();
656 case QV4::CompiledData::Binding::Type_Number: {
657 const double n = compilationUnit->bindingValueAsNumber(binding);
658 if (double(int(n)) == n)
664 case QV4::CompiledData::Binding::Type_Null:
665 source = QVariant::fromValue<std::nullptr_t>(nullptr);
667 case QV4::CompiledData::Binding::Type_Invalid:
670 source = compilationUnit->bindingValueAsString(binding);
674 QVariant target = QQmlValueTypeProvider::createValueType(source, propertyType);
675 if (target.isValid()) {
676 property->writeProperty(_qobject, target.data(), propertyWriteFlags);
681 // string converters are not exposed, so ending up here indicates an error
682 QString stringValue = compilationUnit->bindingValueAsString(binding);
683 QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
684 recordError(binding->location, tr("Cannot assign
value %1 to
property"
685" %2
").arg(stringValue, QString::fromUtf8(metaProperty.name())));
691static QQmlType qmlTypeForObject(QObject *object)
694 const QMetaObject *mo = object->metaObject();
695 while (mo && !type.isValid()) {
696 type = QQmlMetaType::qmlType(mo);
697 mo = mo->superClass();
702void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
704 QQmlListProperty<void> savedList;
705 qSwap(_currentList, savedList);
707 const QV4::CompiledData::BindingPropertyData *propertyData
708 = compilationUnit->bindingPropertyDataPerObjectAt(_compiledObjectIndex);
710 if (_compiledObject->idNameIndex) {
711 const QQmlPropertyData *idProperty = propertyData->last();
712 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
713 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) {
714 QV4::CompiledData::Binding idBinding;
715 idBinding.propertyNameIndex = 0; // Not used
716 idBinding.clearFlags();
717 idBinding.setType(QV4::CompiledData::Binding::Type_String);
718 idBinding.stringIndex = _compiledObject->idNameIndex;
719 idBinding.location = _compiledObject->location; // ###
720 idBinding.value.nullMarker = 0; // zero the value field to make codechecker happy
721 setPropertyValue(idProperty, &idBinding);
725 // ### this is best done through type-compile-time binding skip lists.
726 if (_valueTypeProperty) {
727 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
729 if (binding && binding->kind() != QQmlAbstractBinding::ValueTypeProxy) {
730 QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
731 } else if (binding) {
732 QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
734 if (qmlTypeForObject(_bindingTarget).isValid()) {
735 quint32 bindingSkipList = 0;
737 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
739 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
740 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
741 const QQmlPropertyData *property = binding->propertyNameIndex != 0
742 ? _propertyCache->property(stringAt(binding->propertyNameIndex),
746 bindingSkipList |= (1 << property->coreIndex());
749 proxy->removeBindings(bindingSkipList);
754 int currentListPropertyIndex = -1;
756 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
757 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
758 const QQmlPropertyData *const property = propertyData->at(i);
760 const QQmlPropertyData *targetProperty = property;
761 if (targetProperty->isAlias()) {
763 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
764 auto [targetObject, targetIndex] = QQmlPropertyPrivate::findAliasTarget(_bindingTarget, originalIndex);
765 QQmlData *data = QQmlData::get(targetObject);
766 Q_ASSERT(data && data->propertyCache);
767 targetProperty = data->propertyCache->property(targetIndex.coreIndex());
768 sharedState->requiredProperties.remove({targetObject, targetProperty});
770 sharedState->requiredProperties.remove({_bindingTarget, property});
774 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
777 if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
778 if (!(mode & ApplyDeferred))
780 } else if (!(mode & ApplyImmediate)) {
784 if (property && property->propType().flags().testFlag(QMetaType::IsQmlList)) {
785 if (property->coreIndex() != currentListPropertyIndex) {
786 void *argv[1] = { (void*)&_currentList };
787 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
788 currentListPropertyIndex = property->coreIndex();
790 // manage override behavior
791 const QMetaObject *const metaobject = _qobject->metaObject();
792 const int qmlListBehavorClassInfoIndex = metaobject->indexOfClassInfo("QML.ListPropertyAssignBehavior
");
793 if (qmlListBehavorClassInfoIndex != -1) { // QML.ListPropertyAssignBehavior class info is set
794 const char *overrideBehavior =
795 metaobject->classInfo(qmlListBehavorClassInfoIndex).value();
796 if (!strcmp(overrideBehavior,
798 if (_currentList.clear) {
799 _currentList.clear(&_currentList);
802 bool isDefaultProperty =
803 (property->name(_qobject)
804 == QString::fromUtf8(
806 ->classInfo(metaobject->indexOfClassInfo(
809 if (!isDefaultProperty
810 && (!strcmp(overrideBehavior,
811 "ReplaceIfNotDefault
"))) {
812 if (_currentList.clear) {
813 _currentList.clear(&_currentList);
819 } else if (_currentList.object) {
820 _currentList = QQmlListProperty<void>();
821 currentListPropertyIndex = -1;
824 if (!setPropertyBinding(property, binding))
828 qSwap(_currentList, savedList);
831bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProperty, const QV4::CompiledData::Binding *binding)
833 const QV4::CompiledData::Binding::Type bindingType = binding->type();
834 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
835 Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
836 QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
838 QQmlType attachedType = tr->type();
839 QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
840 if (!attachedType.isValid()) {
841 QQmlTypeNameCache::Result res = context->imports()->query(
842 stringAt(binding->propertyNameIndex), QQmlTypeLoader::get(enginePrivate));
844 attachedType = res.type;
848 QObject *qmlObject = qmlAttachedPropertiesObject(
849 _qobject, attachedType.attachedPropertiesFunction(enginePrivate));
851 recordError(binding->location,
853 .arg(QString::fromUtf8(attachedType.typeName())));
857 if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject,
858 /*value type property*/ nullptr, binding))
863 // ### resolve this at compile time
864 if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) {
865 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
866 context->asQQmlContext(), _scopeObject);
867 ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
868 ss.d.data()->lineNumber = binding->location.line();
869 ss.d.data()->columnNumber = binding->location.column();
870 ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String;
871 ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number;
872 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
874 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
875 QQmlPropertyData::RemoveBindingOnAliasWrite;
876 int propertyWriteStatus = -1;
877 void *argv[] = { &ss, nullptr, &propertyWriteStatus, &propertyWriteFlags };
878 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
882 QObject *createdSubObject = nullptr;
883 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
884 createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
885 if (!createdSubObject)
889 if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) {
890 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
891 if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
893 QObject *groupObject = nullptr;
894 QQmlGadgetPtrWrapper *valueType = nullptr;
895 const QQmlPropertyData *valueTypeProperty = nullptr;
896 QObject *bindingTarget = _bindingTarget;
897 int groupObjectIndex = binding->value.objectIndex;
899 if (!bindingProperty) {
900 for (int i = 0, end = compilationUnit->objectCount(); i != end; ++i) {
901 const QV4::CompiledData::Object *external = compilationUnit->objectAt(i);
902 if (external->idNameIndex == binding->propertyNameIndex) {
903 bindingTarget = groupObject = context->idValue(external->objectId());
909 } else if (QQmlMetaType::isValueType(bindingProperty->propType())) {
910 valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
912 recordError(binding->location, tr("Cannot
set properties on %1 as
it is null
").arg(stringAt(binding->propertyNameIndex)));
916 valueType->read(_qobject, bindingProperty->coreIndex());
918 groupObject = valueType;
919 valueTypeProperty = bindingProperty;
921 void *argv[1] = { &groupObject };
922 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
924 QQmlPropertyIndex index(bindingProperty->coreIndex());
925 auto anyBinding = QQmlAnyBinding::ofProperty(_qobject, index);
927 // if there is a binding, try to force-evaluate it now
928 // this might instantiate a necessary part of a grouped property
929 anyBinding.refresh();
930 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
933 recordError(binding->location, tr("Cannot
set properties on %1 as
it is null
").arg(stringAt(binding->propertyNameIndex)));
938 bindingTarget = groupObject;
941 if (!populateInstance(groupObjectIndex, groupObject, bindingTarget, valueTypeProperty,
947 valueType->write(_qobject, bindingProperty->coreIndex(), QQmlPropertyData::BypassInterceptor);
953 if (!bindingProperty) // ### error
956 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
957 const bool allowedToRemoveBinding
958 = !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
959 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
960 && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver)
961 && !_valueTypeProperty;
963 if (allowedToRemoveBinding) {
964 if (bindingProperty->isBindable()) {
965 removePendingBinding(_bindingTarget, bindingProperty->coreIndex());
967 QQmlPropertyPrivate::removeBinding(
968 _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()));
972 if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
973 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
974 || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) {
975 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
976 int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
977 QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(
978 _bindingTarget, signalIndex, context,
979 _scopeObject, runtimeFunction, currentQmlContext());
981 if (bindingProperty->isBindable()) {
982 auto target = _bindingTarget;
983 if (bindingProperty->isAlias()) {
984 // If the property is an alias, we cannot obtain the bindable interface directly with qt_metacall
985 // so instead, we resolve the alias to obtain the actual target
986 // This should be faster than doing a detour through the metaobject of the target, and relying on
987 // QMetaObject::metacall doing the correct resolution
988 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
989 auto [aliasTargetObject, aliasTargetIndex] = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
990 target = aliasTargetObject;
991 QQmlData *data = QQmlData::get(target);
992 Q_ASSERT(data && data->propertyCache);
993 bindingProperty = data->propertyCache->property(aliasTargetIndex.coreIndex());
995 auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
996 QUntypedBindable bindable;
997 void *argv[] = { &bindable };
998 target->qt_metacall(QMetaObject::BindableProperty, bindingProperty->coreIndex(), argv);
999 Q_ASSERT(bindable.isValid());
1000 bindable.observe(&observer);
1002 QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
1003 bs->takeExpression(expr);
1005 } else if (bindingProperty->isBindable()) {
1006 QUntypedPropertyBinding qmlBinding;
1007 if (binding->isTranslationBinding()) {
1008 qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
1010 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1011 QQmlPropertyIndex index(bindingProperty->coreIndex(), -1);
1012 qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index);
1014 sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding });
1016 QQmlData *data = QQmlData::get(_bindingTarget, true);
1017 data->setBindingBit(_bindingTarget, bindingProperty->coreIndex());
1019 // When writing bindings to grouped properties implemented as value types,
1020 // such as point.x: { someExpression; }, then the binding is installed on
1021 // the point property (_qobjectForBindings) and after evaluating the expression,
1022 // the result is written to a value type virtual property, that contains the sub-index
1023 // of the "x" property.
1024 QQmlBinding::Ptr qmlBinding;
1025 const QQmlPropertyData *targetProperty = bindingProperty;
1026 const QQmlPropertyData *subprop = nullptr;
1027 if (_valueTypeProperty) {
1028 targetProperty = _valueTypeProperty;
1029 subprop = bindingProperty;
1031 if (binding->isTranslationBinding()) {
1032 qmlBinding = QQmlBinding::createTranslationBinding(
1033 compilationUnit, binding, _scopeObject, context);
1035 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1036 qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
1037 context, currentQmlContext());
1040 auto bindingTarget = _bindingTarget;
1041 auto valueTypeProperty = _valueTypeProperty;
1042 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState) mutable -> bool {
1043 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, subprop) && targetProperty->isAlias())
1046 sharedState->allCreatedBindings.push(qmlBinding);
1048 if (bindingProperty->isAlias()) {
1049 QQmlPropertyPrivate::setBinding(qmlBinding.data(), QQmlPropertyPrivate::DontEnable);
1051 qmlBinding->addToObject();
1053 if (!valueTypeProperty) {
1054 QQmlData *targetDeclarativeData = QQmlData::get(bindingTarget);
1055 Q_ASSERT(targetDeclarativeData);
1056 targetDeclarativeData->setPendingBindingBit(bindingTarget, bindingProperty->coreIndex());
1062 if (!assignBinding(sharedState.data()))
1063 pendingAliasBindings.push_back(assignBinding);
1068 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
1069 if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) {
1070 // ### determine value source and interceptor casts ahead of time.
1071 QQmlType type = qmlTypeForObject(createdSubObject);
1072 Q_ASSERT(type.isValid());
1074 int valueSourceCast = type.propertyValueSourceCast();
1075 if (valueSourceCast != -1) {
1076 QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
1077 QObject *target = createdSubObject->parent();
1079 if (_valueTypeProperty) {
1080 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
1081 bindingProperty, context);
1083 prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
1085 vs->setTarget(prop);
1088 int valueInterceptorCast = type.propertyValueInterceptorCast();
1089 if (valueInterceptorCast != -1) {
1090 QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
1091 QObject *target = createdSubObject->parent();
1093 QQmlPropertyIndex propertyIndex;
1094 if (bindingProperty->isAlias()) {
1095 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1096 auto aliasTarget = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1097 target = aliasTarget.targetObject;
1098 QQmlData *data = QQmlData::get(target);
1099 if (!data || !data->propertyCache) {
1100 qWarning() << "can
't resolve property alias for 'on
' assignment";
1104 // we can't have aliasses on subproperties of
value types, so:
1105 QQmlPropertyData targetPropertyData = *
data->propertyCache->property(aliasTarget.targetIndex.coreIndex());
1108 vi->setTarget(prop);
1112 if (_valueTypeProperty) {
1119 vi->setTarget(prop);
1126 mo->registerInterceptor(propertyIndex, vi);
1134 if (!bindingProperty->isFunction()) {
1135 recordError(binding->valueLocation,
tr(
"Cannot assign an object to signal property %1").
arg(bindingProperty->name(_qobject)));
1140 recordError(binding->valueLocation,
tr(
"Cannot assign object type %1 with no default method").
arg(
QString::fromLatin1(createdSubObject->metaObject()->className())));
1143 qCWarning(lcQmlDefaultMethod) <<
"Assigning an object to a signal handler is deprecated. "
1144 "Instead, create the object, give it an id, and call the desired slot "
1145 "from the signal handler. The object is:" << createdSubObject;
1147 QMetaMethod signalMethod = _qobject->metaObject()->method(bindingProperty->coreIndex());
1149 recordError(binding->valueLocation,
1150 tr(
"Cannot connect mismatched signal/slot %1 vs %2")
1162 int propertyWriteStatus = -1;
1163 void *argv[] = {
nullptr,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
1166 void *
ptr = createdSubObject->qt_metacast(iid);
1171 recordError(binding->location,
tr(
"Cannot assign object to interface property"));
1174 }
else if (bindingProperty->propType() == QMetaType::fromType<QVariant>()) {
1175 if (bindingProperty->isVarProperty()) {
1178 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1184 }
else if (bindingProperty->propType() == QMetaType::fromType<QJSValue>()) {
1187 if (bindingProperty->isVarProperty()) {
1188 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1198 void *itemToAdd = createdSubObject;
1201 if (listItemType.isValid()) {
1204 itemToAdd = createdSubObject->qt_metacast(iid);
1207 if (_currentList.append)
1208 _currentList.append(&_currentList, itemToAdd);
1210 recordError(binding->location,
tr(
"Cannot assign object to read only list"));
1216 argv[0] = &createdSubObject;
1222 if (bindingProperty->isQList()) {
1223 recordError(binding->location,
tr(
"Cannot assign primitives to lists"));
1227 setPropertyValue(bindingProperty, binding);
1231void QQmlObjectCreator::setupFunctions()
1240 const QString name = runtimeFunction->name()->toQString();
1246 if (runtimeFunction->isGenerator())
1257 error.setUrl(compilationUnit->
url());
1258 error.setLine(qmlConvertSourceCoordinate<quint32, int>(
location.line()));
1259 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(
location.column()));
1260 error.setDescription(description);
1266 if (
object->objectId() >= 0)
1280 bool isComponent =
false;
1285 bool installPropertyCache =
true;
1296 installPropertyCache = !typeRef->isFullyDynamicType();
1298 if (
type.isValid() && !
type.isInlineComponentType()) {
1301 instance =
type.createWithQQmlData();
1303 recordError(
obj->location,
tr(
"Unable to create object of type %1").
arg(stringAt(
obj->inheritedTypeNameIndex)));
1307 const int finalizerCast =
type.finalizerCast();
1308 if (finalizerCast != -1) {
1309 auto hook =
reinterpret_cast<QQmlFinalizerHook *
>(
reinterpret_cast<char *
>(instance) + finalizerCast);
1312 const int parserStatusCast =
type.parserStatusCast();
1313 if (parserStatusCast != -1)
1314 parserStatus =
reinterpret_cast<QQmlParserStatus*
>(
reinterpret_cast<char *
>(instance) + parserStatusCast);
1316 customParser =
type.customParser();
1320 ddata->rootObjectInCreation =
true;
1326 auto compilationUnit = typeRef->compilationUnit();
1332 recordError(
obj->location,
tr(
"Composite Singleton Type %1 is not creatable").
arg(stringAt(
obj->inheritedTypeNameIndex)));
1336 if (!
type.isInlineComponentType()) {
1339 std::move(compilationUnit)),
1340 sharedState.
data(), isContextObject);
1341 instance = subCreator.create();
1343 errors += subCreator.errors;
1348 if (
QString *icRootName = compilationUnit->icRootName.get()) {
1349 subObjectName =
type.elementName();
1350 std::swap(*icRootName, subObjectName);
1352 compilationUnit->icRootName = std::make_unique<QString>(
type.elementName());
1356 if (subObjectName.isEmpty())
1357 compilationUnit->icRootName.reset();
1359 std::swap(*compilationUnit->icRootName, subObjectName);
1362 const int inlineComponentId
1367 QQmlRefPointer<QV4::CompiledData::CompilationUnit>(
1371 instance = subCreator.create(
1374 errors += subCreator.errors;
1386 }
else if (parent) {
1397 ddata->lineNumber =
obj->location.line();
1398 ddata->columnNumber =
obj->location.column();
1400 ddata->setImplicitDestructible();
1403 const bool documentRoot =
static_cast<quint32>(
index) == 0
1404 || ddata->rootObjectInCreation
1410 parserStatus->classBegin();
1420 if (isContextObject)
1421 context->setContextObject(instance);
1427 QList<const QV4::CompiledData::Binding *> bindings;
1432 bindings << binding;
1434 customParser->
applyBindings(instance, compilationUnit, bindings);
1436 customParser->engine =
nullptr;
1441 registerObjectWithContextById(
obj, instance);
1447 if (installPropertyCache)
1448 ddata->propertyCache =
cache;
1450 QObject *scopeObject = instance;
1451 qSwap(_scopeObject, scopeObject);
1461 bool ok = populateInstance(
index, instance, instance,
nullptr);
1463 if (isContextObject && !pendingAliasBindings.empty()) {
1464 bool processedAtLeastOneBinding =
false;
1466 processedAtLeastOneBinding =
false;
1467 for (std::vector<PendingAliasBinding>::iterator
it = pendingAliasBindings.begin();
1468 it != pendingAliasBindings.end(); ) {
1469 if ((*
it)(sharedState.
data())) {
1470 it = pendingAliasBindings.erase(
it);
1471 processedAtLeastOneBinding =
true;
1476 }
while (processedAtLeastOneBinding && pendingAliasBindings.empty());
1477 Q_ASSERT(pendingAliasBindings.empty());
1481 pendingAliasBindings.clear();
1485 qSwap(_scopeObject, scopeObject);
1487 return ok ? instance :
nullptr;
1492 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1515 if (!
b->isAddedToObject())
1519 data->clearPendingBindingBit(
b->targetPropertyIndex().coreIndex());
1545 void *argv[] = { &bindable };
1548 const bool success = bindable.
setBinding(qmlBinding);
1556 if (success && bindingPrivateRefCount > 1) {
1560 const bool canRemove = !qmlBinding.
error().hasError()
1561 && !qmlBindingPriv->hasDependencies()
1562 && !jsExpression->hasUnresolvedNames();
1577 if (status && status->d) {
1578 status->d =
nullptr;
1588 hook->componentFinalized();
1600 d->context->addComponentAttached(
a);
1602 emit a->completed();
1615 if (phase == Done || phase == Finalizing || phase == Startup)
1634bool QQmlObjectCreator::populateInstance(
int index,
QObject *instance,
QObject *bindingTarget,
1641 qSwap(_qobject, instance);
1642 qSwap(_valueTypeProperty, valueTypeProperty);
1646 qSwap(_ddata, declarativeData);
1647 qSwap(_bindingTarget, bindingTarget);
1665 registerObjectWithContextById(_compiledObject, _qobject);
1668 qSwap(_vmeMetaObject, vmeMetaObject);
1675 QSet<QString> postHocRequired;
1677 postHocRequired.insert(stringAt(
it->nameIndex));
1678 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1680 for (
int propertyIndex = 0; propertyIndex != _compiledObject->
propertyCount(); ++propertyIndex) {
1682 const QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
1684 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(
property->nameIndex));
1685 if (!
property->isRequired() && postHocRequired.end() == postHocIt)
1687 if (postHocIt != postHocRequired.end())
1688 postHocRequired.erase(postHocIt);
1689 if (isContextObject)
1696 const auto getPropertyCacheRange = [&]() -> std::pair<int, int> {
1718 return { 0, _propertyCache->propertyCount() };
1720 return { 0, _propertyCache->propertyOffset() + 1 };
1724 if (
type.isValid() && !
type.isInlineComponentType()) {
1725 return { 0, _propertyCache->propertyCount() };
1728 return { _propertyCache->propertyOffset(), _propertyCache->propertyCount() };
1730 const auto [
offset,
count] = getPropertyCacheRange();
1732 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(
i);
1738 if (!propertyData->
isRequired() && postHocRequired.isEmpty())
1741 auto postHocIt = postHocRequired.find(
name);
1742 if (!propertyData->
isRequired() && postHocRequired.end() == postHocIt )
1745 if (postHocIt != postHocRequired.end())
1746 postHocRequired.
erase(postHocIt);
1748 if (isContextObject)
1751 {_qobject, propertyData},
1760 QLatin1String(
"Attached property has required properties. This is not supported"));
1767 if (!postHocRequired.isEmpty()) {
1770 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(
i);
1774 auto postHocIt = postHocRequired.find(
name);
1775 if (postHocRequired.end() == postHocIt)
1777 postHocRequired.
erase(postHocIt);
1779 if (isContextObject)
1782 {_qobject, propertyData},
1788 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1789 recordError({},
QLatin1String(
"Property %1 was marked as required but does not exist").
arg(*postHocRequired.begin()));
1794 ? BindingMode::ApplyAll
1795 : BindingMode::ApplyImmediate);
1797 for (
int aliasIndex = 0; aliasIndex != _compiledObject->
aliasCount(); ++aliasIndex) {
1799 const auto originalAlias = alias;
1803 if (!
context->isIdValueSet(0))
1809 if (targetDData ==
nullptr || targetDData->propertyCache.isNull())
1812 const QQmlPropertyData *
const targetProperty = targetDData->propertyCache->property(coreIndex);
1813 if (!targetProperty)
1817 it->aliasesToRequired.push_back(
1819 compilationUnit->
stringAt(originalAlias->nameIndex()),
1824 qSwap(_vmeMetaObject, vmeMetaObject);
1825 qSwap(_bindingTarget, bindingTarget);
1826 qSwap(_ddata, declarativeData);
1829 qSwap(_valueTypeProperty, valueTypeProperty);
1830 qSwap(_qobject, instance);
1842 const QQmlRefPointer<QQmlContextData> &
context)
1851 : sharedState(
creator->sharedState)
1863 allJavaScriptObjects->
heapObject()->mark(ms);
1865 ++allJavaScriptObjects;
void trackObject(QV4::ExecutionEngine *engine, QObject *instance)
static void(* setWidgetParent)(QObject *, QObject *)
qsizetype size() const noexcept
Returns the number of items in the hash.
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
QV4::ExecutionEngine * handle() const
static ObjectOwnership objectOwnership(QObject *)
Returns the ownership of object.
static void setValue(QJSValue *jsval, const QV4::Value &v)
The QJSValue class acts as a container for Qt/JavaScript data types.
QString arg(Args &&...args) const
bool isEmpty() const noexcept
void push_back(parameter_type t)
void pop_front() noexcept
QObject * parent() const
Returns a pointer to the parent object.
bool isWidgetType() const
Returns true if the object is a widget; otherwise returns false.
static QPropertyBindingPrivate * get(const QUntypedPropertyBinding &binding)
void removeFromObject()
Remove the binding from the object.
virtual bool hasDependencies() const
static QQmlComponentPrivate * get(QQmlComponent *c)
The QQmlComponent class encapsulates a QML component definition.
void setRootObjectInCreation(bool rootInCreation)
bool isRootObjectInCreation() const
The QQmlCustomParser class allows you to add new arbitrary types to QML.
virtual void applyBindings(QObject *, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &, const QList< const QV4::CompiledData::Binding * > &)=0
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
QQmlPropertyCache::ConstPtr propertyCache
static QQmlData * get(QObjectPrivate *priv, bool create)
void deferData(int objectIndex, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &, const QQmlRefPointer< QQmlContextData > &)
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlEngine class provides an environment for instantiating QML components.
The QQmlError class encapsulates a QML error.
bool shouldInterrupt() const
bool hasUnresolvedNames() const
QQmlError error(QQmlEngine *) const
bool finalize(QQmlInstantiationInterrupt &interrupt)
static QQmlComponent * createComponent(QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit, int index, QObject *parent, const QQmlRefPointer< QQmlContextData > &context)
QList< QQmlError > errors
The QQmlParserStatus class provides updates on the QML parser state.
virtual void componentComplete()=0
Invoked after the root component that caused this instantiation has completed construction.
QQmlPropertyBindingJS * jsExpression()
bool needsVMEMetaObject(int index) const
QQmlPropertyCache::ConstPtr at(int index) const
@ RemoveBindingOnAliasWrite
QString name(QObject *) const
static QQmlPropertyIndex fromEncoded(qint32 encodedIndex)
static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *, const QQmlRefPointer< QQmlContextData > &)
static QQmlPropertyIndex propertyIndex(const QQmlProperty &that)
static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Connect sender signal_index to receiver method_index with the specified type and types.
The QQmlProperty class abstracts accessing properties on objects created from QML.
static bool componentCompleteEnabled()
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
iterator erase(const_iterator first, const_iterator last)
QUntypedPropertyBinding takeBinding()
Removes the currently set binding from the property and returns it.
bool setBinding(const QUntypedPropertyBinding &binding)
Sets the underlying property's binding to binding.
const CompiledObject * objectAt(int index) const
const CompiledData::Unit * unitData() const
int inlineComponentId(const QString &inlineComponentName) const
QString stringAt(uint index) const
QQmlRefPointer< QQmlTypeNameCache > typeNameCache() const
ReturnedValue value() const
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Scoped< ExecutionContext > ScopedContext
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
static ControlElement< T > * ptr(QWidget *widget)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
static qreal component(const QPointF &point, unsigned int i)
QQmlContext * qmlContext(const QObject *obj)
void QQml_setParent_noEvent(QObject *object, QObject *parent)
Makes the object a child of parent.
#define Q_QML_OC_PROFILE(member, Code)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
QLatin1StringView QLatin1String
#define QStringLiteral(str)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
#define Q_TRACE_PREFIX(provider, prefix)
#define Q_TRACE_EXIT(x,...)
QFuture< QSet< QChar > > set
[10]
QFutureWatcher< int > watcher
QItemEditorCreatorBase * creator
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)
QList< DeferredQPropertyBinding > allQPropertyBindings
QFiniteStack< QQmlAbstractBinding::Ptr > allCreatedBindings
QQmlRefPointer< QQmlContextData > rootContext
QQmlComponentAttached * componentAttached
QFiniteStack< QQmlGuard< QObject > > allCreatedObjects
RequiredProperties requiredProperties
QFiniteStack< QQmlParserStatus * > allParserStatusCallbacks
QList< QQmlFinalizerHook * > finalizeHooks
bool hadTopLevelRequiredProperties
ObjectInCreationGCAnchorList allJavaScriptObjects
static const quintptr profiler
void push(const QV4::CompiledData::Object *)
QVector< QV4::Function * > runtimeFunctions
qint32_le encodedMetaPropertyIndex
quint32 targetObjectId() const
bool hasFlag(Flag flag) const
bool isAliasToLocalAlias() const
quint32_le localAliasIndex
bool isAttachedProperty() const
bool hasFlag(Flag flag) const
bool isGroupProperty() const
int propertyCount() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const
quint32_le inheritedTypeNameIndex
bool hasFlag(Flag flag) const
@ HasCustomParserBindings
const Property * propertiesBegin() const
const quint32_le * functionOffsetTable() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const
const Alias * aliasesBegin() const
QQmlRefPointer< ExecutableCompilationUnit > executableCompilationUnit(QQmlRefPointer< QV4::CompiledData::CompilationUnit > &&unit)
static Heap::FunctionObject * createScriptFunction(ExecutionContext *scope, Function *function)
static Heap::FunctionObject * create(ExecutionContext *scope, Function *function)
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object)
QML_NEARLY_ALWAYS_INLINE Value::HeapBasePtr heapObject() const
static void markCustom(Engine *engine, F &&markFunction)