7#include <private/qjsvalue_p.h>
8#include <private/qqmlanybinding_p.h>
9#include <private/qqmlbinding_p.h>
10#include <private/qqmlboundsignal_p.h>
11#include <private/qqmlcomponent_p.h>
12#include <private/qqmlcomponentattached_p.h>
13#include <private/qqmlcustomparser_p.h>
14#include <private/qqmldebugconnector_p.h>
15#include <private/qqmldebugserviceinterfaces_p.h>
16#include <private/qqmlengine_p.h>
17#include <private/qqmlpropertybinding_p.h>
18#include <private/qqmlpropertyvalueinterceptor_p.h>
19#include <private/qqmlscriptdata_p.h>
20#include <private/qqmlscriptstring_p.h>
21#include <private/qqmlsourcecoordinate_p.h>
22#include <private/qqmlstringconverters_p.h>
23#include <private/qqmlvaluetypeproxybinding_p.h>
24#include <private/qqmlvme_p.h>
25#include <private/qqmlvmemetaobject_p.h>
26#include <private/qv4function_p.h>
27#include <private/qv4functionobject_p.h>
28#include <private/qv4generatorobject_p.h>
29#include <private/qv4qobjectwrapper_p.h>
30#include <private/qv4referenceobject_p.h>
31#include <private/qv4resolvedtypereference_p.h>
33#include <qtqml_tracepoints_p.h>
35#include <QtCore/qscopedvaluerollback.h>
36#include <QtCore/qloggingcategory.h>
44"struct ExecutionEngine;"\
45"class ExecutableCompilationUnit;"\
46"namespace CompiledData {"\
47"struct Object;"\
48"}}"\
49"class QQmlEngine;"
52Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_entry,
const QV4::ExecutableCompilationUnit *compilationUnit,
const QV4::CompiledData::Object *object,
const QUrl &url)
53Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_exit,
const QString &typeName)
55QQmlObjectCreator::QQmlObjectCreator(
56 const QQmlRefPointer<QQmlContextData> &parentContext,
57 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
58 const QQmlRefPointer<QQmlContextData> &creationContext,
59 const QString &inlineComponentName,
60 QQmlIncubatorPrivate *incubator)
62 , m_inlineComponentName(inlineComponentName)
63 , compilationUnit(compilationUnit)
64 , propertyCaches(compilationUnit->propertyCachesPtr())
65 , sharedState(
new QQmlObjectCreatorSharedState, QQmlRefPointer<QQmlObjectCreatorSharedState>::Adopt)
66 , topLevelCreator(
true)
67 , isContextObject(
true)
68 , incubator(incubator)
72 sharedState->componentAttached =
nullptr;
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));
86QQmlObjectCreator::QQmlObjectCreator(
const QQmlRefPointer<QQmlContextData> &parentContext,
87 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
const QString inlineComponentName,
88 QQmlObjectCreatorSharedState *inheritedSharedState,
bool isContextObject)
90 , m_inlineComponentName(inlineComponentName)
91 , compilationUnit(compilationUnit)
92 , propertyCaches(compilationUnit->propertyCachesPtr())
93 , sharedState(inheritedSharedState)
94 , topLevelCreator(
false)
95 , isContextObject(isContextObject)
101void QQmlObjectCreator::init(
const QQmlRefPointer<QQmlContextData> &providedParentContext)
103 parentContext = providedParentContext;
104 engine = parentContext->engine();
105 v4 = engine->handle();
107 Q_ASSERT(compilationUnit);
108 Q_ASSERT(compilationUnit->engine == v4);
109 if (!compilationUnit->runtimeStrings)
110 compilationUnit->populate();
112 qmlUnit = compilationUnit->unitData();
114 _scopeObject =
nullptr;
115 _bindingTarget =
nullptr;
116 _valueTypeProperty =
nullptr;
117 _compiledObject =
nullptr;
118 _compiledObjectIndex = -1;
120 _vmeMetaObject =
nullptr;
121 _qmlContext =
nullptr;
124QQmlObjectCreator::~QQmlObjectCreator()
126 if (topLevelCreator) {
130 QQmlObjectCreatorRecursionWatcher watcher(
this);
132 while (sharedState->componentAttached) {
133 QQmlComponentAttached *a = sharedState->componentAttached;
139QObject *QQmlObjectCreator::create(
int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt,
int flags)
141 if (phase == CreatingObjectsPhase2) {
142 phase = ObjectsCreated;
143 return context->contextObject();
145 Q_ASSERT(phase == Startup);
146 phase = CreatingObjects;
149 bool isComponentRoot =
false;
151 if (subComponentIndex == -1) {
153 isComponentRoot =
true;
155 Q_ASSERT(subComponentIndex >= 0);
156 if (flags & CreationFlags::InlineComponent) {
157 if (compilationUnit->componentsAreBound()
158 && compilationUnit != parentContext->typeCompilationUnit()) {
159 recordError({}, tr(
"Cannot instantiate bound inline component in different file"));
160 phase = ObjectsCreated;
163 objectToCreate = subComponentIndex;
164 isComponentRoot =
true;
166 Q_ASSERT(flags & CreationFlags::NormalObject);
167 if (compilationUnit->componentsAreBound()
168 && sharedState->creationContext != parentContext) {
169 recordError({}, tr(
"Cannot instantiate bound component "
170 "outside its creation context"));
171 phase = ObjectsCreated;
174 if (subComponentIndex < compilationUnit->objectCount()) {
175 const QV4::CompiledData::Object *compObj
176 = compilationUnit->objectAt(subComponentIndex);
177 objectToCreate = compObj->bindingTable()->value.objectIndex;
181 objectToCreate = compilationUnit->resolvedIndex(subComponentIndex);
186 QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
187 context = isComponentRoot
188 ? enginePriv->createComponentRootContext(compilationUnit, parentContext,
190 : enginePriv->createBareContext(compilationUnit, parentContext, subComponentIndex);
192 if (!sharedState->rootContext) {
193 sharedState->rootContext = context;
194 sharedState->rootContext->setIncubator(incubator);
195 sharedState->rootContext->setRootObjectInCreation(
true);
198 QV4::Scope scope(v4);
200 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack() || topLevelCreator);
202 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
204 if (!isComponentRoot && sharedState->creationContext) {
206 QV4::ScopedValue scripts(scope, sharedState->creationContext->importedScripts());
207 context->setImportedScripts(v4, scripts);
210 QObject *instance = createInstance(objectToCreate, parent,
true);
212 QQmlData *ddata = QQmlData::get(instance);
214 ddata->compilationUnit = compilationUnit;
218 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
220 phase = CreatingObjectsPhase2;
222 if (interrupt && interrupt->shouldInterrupt())
225 phase = ObjectsCreated;
228 if (QQmlEngineDebugService *service
229 = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
230 if (!parentContext->isInternal())
231 parentContext->asQQmlContextPrivate()->appendInstance(instance);
232 service->objectCreated(engine, instance);
233 }
else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
234 parentContext->asQQmlContextPrivate()->appendInstance(instance);
241void QQmlObjectCreator::beginPopulateDeferred(
const QQmlRefPointer<QQmlContextData> &newContext)
243 context = newContext;
244 sharedState->rootContext = newContext;
246 Q_ASSERT(topLevelCreator);
247 Q_ASSERT(!sharedState->allJavaScriptObjects.canTrack());
250 QV4::Scope valueScope(v4);
251 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(valueScope);
254void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex,
255 const QQmlPropertyPrivate *qmlProperty,
256 const QV4::CompiledData::Binding *binding)
258 doPopulateDeferred(instance, deferredIndex, [
this, qmlProperty, binding]() {
259 Q_ASSERT(qmlProperty);
261 QQmlListProperty<QObject> savedList;
262 qSwap(_currentList, savedList);
264 const QQmlPropertyData &property = qmlProperty->core;
266 if (property.propType().flags().testFlag(QMetaType::IsQmlList)) {
267 void *argv[1] = { (
void*)&_currentList };
268 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
269 }
else if (_currentList.object) {
270 _currentList = QQmlListProperty<QObject>();
273 setPropertyBinding(&property, binding);
275 qSwap(_currentList, savedList);
279void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex)
281 doPopulateDeferred(instance, deferredIndex, [
this]() { setupBindings(ApplyDeferred); });
284bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
285 const QQmlData::DeferredData *deferredData)
287 beginPopulateDeferred(deferredData->context);
288 populateDeferred(instance, deferredData->deferredIdx);
289 finalizePopulateDeferred();
290 return errors.isEmpty();
293void QQmlObjectCreator::populateDeferredBinding(
const QQmlProperty &qmlProperty,
int deferredIndex,
294 const QV4::CompiledData::Binding *binding)
297 populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
300 populateDeferred(qmlProperty.object(), deferredIndex);
304void QQmlObjectCreator::populateDeferredInstance(
305 QObject *outerObject,
int deferredIndex,
int index, QObject *instance,
306 QObject *bindingTarget,
const QQmlPropertyData *valueTypeProperty,
307 const QV4::CompiledData::Binding *binding)
309 doPopulateDeferred(outerObject, deferredIndex, [&]() {
310 populateInstance(index, instance, bindingTarget, valueTypeProperty, binding);
314void QQmlObjectCreator::finalizePopulateDeferred()
316 phase = ObjectsCreated;
319void QQmlObjectCreator::setPropertyValue(
const QQmlPropertyData *property,
const QV4::CompiledData::Binding *binding,
320 std::optional<
int> foldedNumber)
322 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
323 QV4::Scope scope(v4);
325 QMetaType propertyType = property->propType();
327 const QV4::CompiledData::Binding::Type effectiveType
328 = foldedNumber ? QV4::CompiledData::Binding::Type_Number : binding->type();
329 const auto effectiveNumber = [&]() ->
double {
330 return foldedNumber ?
double(*foldedNumber) : compilationUnit->bindingValueAsNumber(binding);
333 if (property->isEnum()) {
334 if (foldedNumber.has_value() ||
337 (property->isAlias() && binding->isNumberBinding())) {
338 propertyType = property->propType().underlyingType();
341 QVariant value = compilationUnit->bindingValueAsString(binding);
342 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
349 auto assertOrNull = [&](
bool ok)
351 Q_ASSERT(ok || effectiveType == QV4::CompiledData::Binding::Type_Null);
355 auto assertType = [&](QV4::CompiledData::Binding::Type type)
357 Q_ASSERT(effectiveType == type || effectiveType == QV4::CompiledData::Binding::Type_Null);
361 if (property->isQObject()) {
362 if (effectiveType == QV4::CompiledData::Binding::Type_Null) {
363 QObject *value =
nullptr;
364 const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags);
371 switch (propertyType.id()) {
372 case QMetaType::QVariant: {
373 if (effectiveType == QV4::CompiledData::Binding::Type_Number) {
374 double n = effectiveNumber();
375 if (
double(
int(n)) == n) {
376 if (property->isVarProperty()) {
377 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(
int(n)));
381 property->writeProperty(_qobject, &value, propertyWriteFlags);
384 if (property->isVarProperty()) {
385 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromDouble(n));
388 property->writeProperty(_qobject, &value, propertyWriteFlags);
391 }
else if (effectiveType == QV4::CompiledData::Binding::Type_Boolean) {
392 if (property->isVarProperty()) {
393 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean()));
395 QVariant value(binding->valueAsBoolean());
396 property->writeProperty(_qobject, &value, propertyWriteFlags);
398 }
else if (effectiveType == QV4::CompiledData::Binding::Type_Null) {
399 if (property->isVarProperty()) {
400 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue());
402 QVariant nullValue = QVariant::fromValue(
nullptr);
403 property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
406 QString stringValue = compilationUnit->bindingValueAsString(binding);
407 if (property->isVarProperty()) {
408 QV4::ScopedString s(scope, v4->newString(stringValue));
409 _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
411 QVariant value = stringValue;
412 property->writeProperty(_qobject, &value, propertyWriteFlags);
417 case QMetaType::QString: {
418 assertOrNull(binding->evaluatesToString());
419 QString value = compilationUnit->bindingValueAsString(binding);
420 property->writeProperty(_qobject, &value, propertyWriteFlags);
423 case QMetaType::QStringList: {
424 assertOrNull(binding->evaluatesToString());
425 QStringList value(compilationUnit->bindingValueAsString(binding));
426 property->writeProperty(_qobject, &value, propertyWriteFlags);
429 case QMetaType::QByteArray: {
430 assertType(QV4::CompiledData::Binding::Type_String);
431 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
432 property->writeProperty(_qobject, &value, propertyWriteFlags);
435 case QMetaType::QUrl: {
436 assertType(QV4::CompiledData::Binding::Type_String);
437 const QString string = compilationUnit->bindingValueAsString(binding);
438 QUrl value = (!string.isEmpty() && QQmlPropertyPrivate::resolveUrlsOnAssignment())
439 ? compilationUnit->finalUrl().resolved(QUrl(string))
441 property->writeProperty(_qobject, &value, propertyWriteFlags);
444 case QMetaType::UInt: {
445 assertType(QV4::CompiledData::Binding::Type_Number);
446 double d = effectiveNumber();
447 uint value = uint(d);
448 property->writeProperty(_qobject, &value, propertyWriteFlags);
452 case QMetaType::Int: {
453 assertType(QV4::CompiledData::Binding::Type_Number);
454 double d = effectiveNumber();
456 property->writeProperty(_qobject, &value, propertyWriteFlags);
460 case QMetaType::SChar: {
461 assertType(QV4::CompiledData::Binding::Type_Number);
462 double d = effectiveNumber();
463 qint8 value = qint8(d);
464 property->writeProperty(_qobject, &value, propertyWriteFlags);
467 case QMetaType::UChar: {
468 assertType(QV4::CompiledData::Binding::Type_Number);
469 double d = effectiveNumber();
470 quint8 value = quint8(d);
471 property->writeProperty(_qobject, &value, propertyWriteFlags);
474 case QMetaType::Short: {
475 assertType(QV4::CompiledData::Binding::Type_Number);
476 double d = effectiveNumber();
477 qint16 value = qint16(d);
478 property->writeProperty(_qobject, &value, propertyWriteFlags);
481 case QMetaType::UShort: {
482 assertType(QV4::CompiledData::Binding::Type_Number);
483 double d = effectiveNumber();
484 quint16 value = quint16(d);
485 property->writeProperty(_qobject, &value, propertyWriteFlags);
488 case QMetaType::LongLong: {
489 assertType(QV4::CompiledData::Binding::Type_Number);
490 double d = effectiveNumber();
491 qint64 value = qint64(d);
492 property->writeProperty(_qobject, &value, propertyWriteFlags);
495 case QMetaType::ULongLong: {
496 assertType(QV4::CompiledData::Binding::Type_Number);
497 double d = effectiveNumber();
498 quint64 value = quint64(d);
499 property->writeProperty(_qobject, &value, propertyWriteFlags);
503 case QMetaType::Float: {
504 assertType(QV4::CompiledData::Binding::Type_Number);
505 float value =
float(effectiveNumber());
506 property->writeProperty(_qobject, &value, propertyWriteFlags);
509 case QMetaType::Double: {
510 assertType(QV4::CompiledData::Binding::Type_Number);
511 double value = effectiveNumber();
512 property->writeProperty(_qobject, &value, propertyWriteFlags);
515 case QMetaType::QColor: {
517 QVariant data = QQmlStringConverters::colorFromString(
518 compilationUnit->bindingValueAsString(binding), &ok);
520 property->writeProperty(_qobject, data.data(), propertyWriteFlags);
523#if QT_CONFIG(datestring)
524 case QMetaType::QDate: {
526 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
528 property->writeProperty(_qobject, &value, propertyWriteFlags);
531 case QMetaType::QTime: {
533 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
535 property->writeProperty(_qobject, &value, propertyWriteFlags);
538 case QMetaType::QDateTime: {
540 QDateTime value = QQmlStringConverters::dateTimeFromString(
541 compilationUnit->bindingValueAsString(binding), &ok);
543 property->writeProperty(_qobject, &value, propertyWriteFlags);
547 case QMetaType::QPoint: {
549 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
551 property->writeProperty(_qobject, &value, propertyWriteFlags);
554 case QMetaType::QPointF: {
556 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
558 property->writeProperty(_qobject, &value, propertyWriteFlags);
561 case QMetaType::QSize: {
563 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
565 property->writeProperty(_qobject, &value, propertyWriteFlags);
568 case QMetaType::QSizeF: {
570 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
572 property->writeProperty(_qobject, &value, propertyWriteFlags);
575 case QMetaType::QRect: {
577 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
579 property->writeProperty(_qobject, &value, propertyWriteFlags);
582 case QMetaType::QRectF: {
584 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
586 property->writeProperty(_qobject, &value, propertyWriteFlags);
589 case QMetaType::Bool: {
590 assertType(QV4::CompiledData::Binding::Type_Boolean);
591 bool value = binding->valueAsBoolean();
592 property->writeProperty(_qobject, &value, propertyWriteFlags);
595 case QMetaType::QVector2D:
596 case QMetaType::QVector3D:
597 case QMetaType::QVector4D:
598 case QMetaType::QQuaternion: {
599 QVariant result = QQmlValueTypeProvider::createValueType(
600 compilationUnit->bindingValueAsString(binding), propertyType);
601 assertOrNull(result.isValid());
602 property->writeProperty(_qobject, result.data(), propertyWriteFlags);
607 if (propertyType == QMetaType::fromType<QList<qreal>>()) {
608 assertType(QV4::CompiledData::Binding::Type_Number);
610 value.append(compilationUnit->bindingValueAsNumber(binding));
611 property->writeProperty(_qobject, &value, propertyWriteFlags);
613 }
else if (propertyType == QMetaType::fromType<QList<
int>>()) {
614 assertType(QV4::CompiledData::Binding::Type_Number);
615 double n = compilationUnit->bindingValueAsNumber(binding);
617 value.append(
int(n));
618 property->writeProperty(_qobject, &value, propertyWriteFlags);
620 }
else if (propertyType == QMetaType::fromType<QList<
bool>>()) {
621 assertType(QV4::CompiledData::Binding::Type_Boolean);
623 value.append(binding->valueAsBoolean());
624 property->writeProperty(_qobject, &value, propertyWriteFlags);
626 }
else if (propertyType == QMetaType::fromType<QList<QUrl>>()) {
627 assertType(QV4::CompiledData::Binding::Type_String);
628 const QUrl url(compilationUnit->bindingValueAsString(binding));
630 QQmlPropertyPrivate::resolveUrlsOnAssignment()
631 ? compilationUnit->finalUrl().resolved(url)
634 property->writeProperty(_qobject, &value, propertyWriteFlags);
636 }
else if (propertyType == QMetaType::fromType<QList<QString>>()) {
637 assertOrNull(binding->evaluatesToString());
638 QList<QString> value;
639 value.append(compilationUnit->bindingValueAsString(binding));
640 property->writeProperty(_qobject, &value, propertyWriteFlags);
642 }
else if (propertyType == QMetaType::fromType<QJSValue>()) {
644 switch (binding->type()) {
645 case QV4::CompiledData::Binding::Type_Boolean:
646 value = QJSValue(binding->valueAsBoolean());
648 case QV4::CompiledData::Binding::Type_Number: {
649 const double n = compilationUnit->bindingValueAsNumber(binding);
650 if (
double(
int(n)) == n)
651 value = QJSValue(
int(n));
656 case QV4::CompiledData::Binding::Type_Null:
657 value = QJSValue::NullValue;
660 value = QJSValue(compilationUnit->bindingValueAsString(binding));
663 property->writeProperty(_qobject, &value, propertyWriteFlags);
667 switch (binding->type()) {
668 case QV4::CompiledData::Binding::Type_Boolean:
669 source = binding->valueAsBoolean();
671 case QV4::CompiledData::Binding::Type_Number: {
672 const double n = compilationUnit->bindingValueAsNumber(binding);
673 if (
double(
int(n)) == n)
679 case QV4::CompiledData::Binding::Type_Null:
680 source = QVariant::fromValue<std::nullptr_t>(
nullptr);
682 case QV4::CompiledData::Binding::Type_Invalid:
685 source = compilationUnit->bindingValueAsString(binding);
689 QVariant target = QQmlValueTypeProvider::createValueType(
690 source, propertyType, engine->handle());
691 if (target.isValid()) {
692 property->writeProperty(_qobject, target.data(), propertyWriteFlags);
698 QString stringValue = compilationUnit->bindingValueAsString(binding);
699 QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
700 recordError(binding->location, tr(
"Cannot assign value %1 to property"
701" %2").arg(stringValue, QString::fromUtf8(metaProperty.name())));
710 const QMetaObject *mo = object->metaObject();
711 while (mo && !type.isValid()) {
712 type = QQmlMetaType::qmlType(mo);
713 mo = mo->superClass();
718void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
720 QQmlListProperty<QObject> savedList;
721 qSwap(_currentList, savedList);
723 const QV4::CompiledData::BindingPropertyData *propertyData
724 = compilationUnit->bindingPropertyDataPerObjectAt(_compiledObjectIndex);
726 if (_compiledObject->idNameIndex) {
727 const QQmlPropertyData *idProperty = propertyData->last();
728 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String(
"id"));
729 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) {
730 QV4::CompiledData::Binding idBinding;
731 idBinding.propertyNameIndex = 0;
732 idBinding.clearFlags();
733 idBinding.setType(QV4::CompiledData::Binding::Type_String);
734 idBinding.stringIndex = _compiledObject->idNameIndex;
735 idBinding.location = _compiledObject->location;
736 idBinding.value.nullMarker = 0;
737 setPropertyValue(idProperty, &idBinding);
742 if (_valueTypeProperty) {
743 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
745 if (binding && binding->kind() != QQmlAbstractBinding::ValueTypeProxy) {
746 QQmlPropertyPrivate::removeBinding(
747 _bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()),
748 QQmlPropertyPrivate::OverrideSticky);
749 }
else if (binding) {
750 QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
752 if (qmlTypeForObject(_bindingTarget).isValid()) {
753 quint32 bindingSkipList = 0;
755 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
757 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
758 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
759 const QQmlPropertyData *property = binding->propertyNameIndex != 0
760 ? _propertyCache->property(stringAt(binding->propertyNameIndex),
764 bindingSkipList |= (1 << property->coreIndex());
767 proxy->removeBindings(bindingSkipList);
772 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1
773 ? _propertyCache->parent()->defaultProperty()
774 : _propertyCache->defaultProperty();
776 int currentListPropertyIndex = -1;
779 const auto applyBinding = [&](
const QQmlPropertyData *property,
780 const QV4::CompiledData::Binding *binding) ->
bool {
781 if (property && property->propType().flags().testFlag(QMetaType::IsQmlList)) {
782 if (property->coreIndex() != currentListPropertyIndex) {
783 void *argv[1] = { (
void*)&_currentList };
784 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
785 currentListPropertyIndex = property->coreIndex();
788 const QMetaObject *
const metaobject = _qobject->metaObject();
789 const int qmlListBehavorClassInfoIndex = metaobject->indexOfClassInfo(
"QML.ListPropertyAssignBehavior");
790 if (qmlListBehavorClassInfoIndex != -1) {
791 const char *overrideBehavior =
792 metaobject->classInfo(qmlListBehavorClassInfoIndex).value();
793 if (!strcmp(overrideBehavior,
795 if (_currentList.clear) {
796 _currentList.clear(&_currentList);
799 bool isDefaultProperty =
800 (property->name(_qobject)
801 == QString::fromUtf8(
803 ->classInfo(metaobject->indexOfClassInfo(
806 if (!isDefaultProperty
807 && (!strcmp(overrideBehavior,
808 "ReplaceIfNotDefault"))) {
809 if (_currentList.clear) {
810 _currentList.clear(&_currentList);
816 }
else if (_currentList.object) {
817 _currentList = QQmlListProperty<QObject>();
818 currentListPropertyIndex = -1;
821 return setPropertyBinding(property, binding);
827 QVarLengthArray<
const QV4::CompiledData::Binding *, 8> explicitDefaultPropertyBindings;
829 const auto applyExplicitDefaultPropertyBindings = [&]() ->
bool {
830 for (
const QV4::CompiledData::Binding *b : std::as_const(explicitDefaultPropertyBindings)) {
831 if (!applyBinding(defaultProperty, b))
834 explicitDefaultPropertyBindings.clear();
838 const QV4::CompiledData::RuntimeBindingIndex *bindingOrder =
839 compilationUnit->bindingApplicationOrder(_compiledObjectIndex);
840 for (quint32 k = 0; k < _compiledObject->nBindings; ++k) {
841 const quint32 i = bindingOrder[k];
842 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable() + i;
843 const QQmlPropertyData *
const property = propertyData->at(i);
845 const QQmlPropertyData *targetProperty = property;
846 if (targetProperty->isAlias()) {
848 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(),
849 _valueTypeProperty ? _valueTypeProperty->coreIndex()
851 auto [targetObject, targetIndex] =
852 QQmlPropertyPrivate::findAliasTarget(_bindingTarget, originalIndex);
853 QQmlData *data = QQmlData::get(targetObject);
854 Q_ASSERT(data && data->propertyCache);
855 targetProperty = data->propertyCache->property(targetIndex.coreIndex());
856 sharedState->requiredProperties.remove({ targetObject, targetProperty });
858 sharedState->requiredProperties.remove({ _bindingTarget, property });
861 if (compilationUnit->bindingIsCustomParser(_compiledObjectIndex, i))
864 if (compilationUnit->bindingIsDeferred(_compiledObjectIndex, i)) {
865 if (!(mode & ApplyDeferred))
867 }
else if (!(mode & ApplyImmediate)) {
873 if (binding->propertyNameIndex != quint32(0)
875 && property == defaultProperty) {
876 explicitDefaultPropertyBindings.append(binding);
882 if (binding->propertyNameIndex == quint32(0)
883 && !explicitDefaultPropertyBindings.isEmpty()
884 && !(binding->location < explicitDefaultPropertyBindings.first()->location)) {
885 if (!applyExplicitDefaultPropertyBindings())
889 if (!applyBinding(property, binding))
894 if (!applyExplicitDefaultPropertyBindings())
896 qSwap(_currentList, savedList);
899bool QQmlObjectCreator::setPropertyBinding(
const QQmlPropertyData *bindingProperty,
const QV4::CompiledData::Binding *binding)
901 const int bindingIndex =
int(binding - _compiledObject->bindingTable());
902 const std::optional<
int> foldedNumber
903 = compilationUnit->bindingFoldedEnum(_compiledObjectIndex, bindingIndex);
904 const QV4::CompiledData::Binding::Type bindingType = binding->type();
905 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
906 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
907 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
909 Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
910 QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
912 QQmlType attachedType = tr->type();
913 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
914 if (!attachedType.isValid()) {
915 QQmlTypeNameCache::Result res
916 = context->imports()->query(stringAt(binding->propertyNameIndex), typeLoader);
918 attachedType = res.type;
924 sharedState->profiler,
925 profiler.update(compilationUnit.data(), obj, attachedType.qmlTypeName(),
928 QObject *qmlObject = qmlAttachedPropertiesObject(
929 _qobject, attachedType.attachedPropertiesFunction(typeLoader));
931 recordError(binding->location,
932 QStringLiteral(
"Could not create attached properties object '%1'")
933 .arg(QString::fromUtf8(attachedType.typeName())));
937 const size_t objectIndex = sharedState->allCreatedObjects.size();
938 sharedState->allCreatedObjects.push_back(qmlObject);
939 const QQmlType attachedObjectType
940 = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(typeLoader));
941 const int parserStatusCast = attachedObjectType.parserStatusCast();
942 QQmlParserStatus *parserStatus =
nullptr;
943 if (parserStatusCast != -1)
944 parserStatus =
reinterpret_cast<QQmlParserStatus*>(
reinterpret_cast<
char *>(qmlObject) + parserStatusCast);
946 parserStatus->classBegin();
948 sharedState->allParserStatusCallbacks.push_back({objectIndex, parserStatusCast});
951 if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject,
958 if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) {
959 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
960 context->asQQmlContext(), _scopeObject);
961 ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
962 ss.d.data()->lineNumber = binding->location.line();
963 ss.d.data()->columnNumber = binding->location.column();
964 ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String;
965 ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number;
966 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
968 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
969 QQmlPropertyData::RemoveBindingOnAliasWrite;
970 int propertyWriteStatus = -1;
971 void *argv[] = { &ss,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
972 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
976 QObject *createdSubObject =
nullptr;
977 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
980 QScopedValueRollback topLevelRequired(sharedState->hadTopLevelRequiredProperties);
981 int objectIndex = binding->value.objectIndex;
982 if (
const int wrapperIdx = compilationUnit->implicitComponentForObject(objectIndex);
985 objectIndex = wrapperIdx;
987 createdSubObject = createInstance(objectIndex, _bindingTarget);
988 if (!createdSubObject)
992 if (bindingType == QV4::CompiledData::Binding::Type_GroupedProperty) {
993 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
994 if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
996 QObject *groupObject =
nullptr;
997 QQmlGadgetPtrWrapper *valueType =
nullptr;
998 const QQmlPropertyData *valueTypeProperty =
nullptr;
999 QObject *bindingTarget = _bindingTarget;
1000 int groupObjectIndex = binding->value.objectIndex;
1002 if (!bindingProperty) {
1003 for (
int i = 0, end = compilationUnit->objectCount(); i != end; ++i) {
1004 const QV4::CompiledData::Object *external = compilationUnit->objectAt(i);
1005 if (external->idNameIndex == binding->propertyNameIndex) {
1006 bindingTarget = groupObject = context->idValue(compilationUnit->objectId(i));
1012 }
else if (QQmlMetaType::isValueType(bindingProperty->propType())) {
1013 valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
1015 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
1019 valueType->read(_qobject, bindingProperty->coreIndex());
1021 groupObject = valueType;
1022 valueTypeProperty = bindingProperty;
1023 }
else if (bindingProperty->propType().flags() & QMetaType::PointerToQObject) {
1024 void *argv[1] = { &groupObject };
1025 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
1027 QQmlPropertyIndex index(bindingProperty->coreIndex());
1028 auto anyBinding = QQmlAnyBinding::ofProperty(_qobject, index);
1032 anyBinding.refresh();
1033 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
1036 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
1041 bindingTarget = groupObject;
1045 tr(
"Using grouped property syntax on %1 which has no properties")
1046 .arg(stringAt(binding->propertyNameIndex)));
1050 if (!populateInstance(groupObjectIndex, groupObject, bindingTarget, valueTypeProperty,
1057 _qobject, bindingProperty->coreIndex(),
1058 QQmlPropertyData::BypassInterceptor,
1059 QV4::ReferenceObject::AllProperties);
1066 if (!bindingProperty)
1069 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
1070 const bool allowedToRemoveBinding
1071 = !compilationUnit->bindingIsSignalHandlerExpression(_compiledObjectIndex, bindingIndex)
1072 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
1073 && !compilationUnit->bindingIsPropertyObserver(_compiledObjectIndex, bindingIndex)
1074 && !_valueTypeProperty;
1076 if (allowedToRemoveBinding) {
1077 if (bindingProperty->acceptsQBinding()) {
1078 removePendingBinding(_bindingTarget, bindingProperty->coreIndex());
1080 QQmlPropertyPrivate::removeBinding(
1081 _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()),
1082 QQmlPropertyPrivate::OverrideSticky);
1087 && (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding())) {
1088 if (compilationUnit->bindingIsSignalHandlerExpression(_compiledObjectIndex, bindingIndex)
1089 || compilationUnit->bindingIsPropertyObserver(_compiledObjectIndex, bindingIndex)) {
1090 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1091 int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
1092 QQmlBoundSignalExpression *expr =
new QQmlBoundSignalExpression(
1093 _bindingTarget, signalIndex, context,
1094 _scopeObject, runtimeFunction, currentQmlContext());
1096 if (bindingProperty->notifiesViaBindable()) {
1097 auto target = _bindingTarget;
1098 if (bindingProperty->isAlias()) {
1103 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1104 auto [aliasTargetObject, aliasTargetIndex] = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1105 target = aliasTargetObject;
1106 QQmlData *data = QQmlData::get(target);
1107 Q_ASSERT(data && data->propertyCache);
1108 bindingProperty = data->propertyCache->property(aliasTargetIndex.coreIndex());
1110 auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
1111 QUntypedBindable bindable;
1112 void *argv[] = { &bindable };
1113 target->qt_metacall(QMetaObject::BindableProperty, bindingProperty->coreIndex(), argv);
1114 Q_ASSERT(bindable.isValid());
1115 bindable.observe(&observer);
1117 QQmlBoundSignal *bs =
new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
1118 bs->takeExpression(expr);
1120 }
else if (bindingProperty->acceptsQBinding()) {
1121 QUntypedPropertyBinding qmlBinding;
1122 if (binding->isTranslationBinding()) {
1123 qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
1125 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1126 QQmlPropertyIndex index(bindingProperty->coreIndex(), -1);
1127 qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index);
1129 sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding });
1131 QQmlData *data = QQmlData::get(_bindingTarget,
true);
1132 data->setBindingBit(_bindingTarget, bindingProperty->coreIndex());
1139 QQmlBinding::Ptr qmlBinding;
1140 const QQmlPropertyData *targetProperty = bindingProperty;
1141 const QQmlPropertyData *subprop =
nullptr;
1142 if (_valueTypeProperty) {
1143 targetProperty = _valueTypeProperty;
1144 subprop = bindingProperty;
1146 if (binding->isTranslationBinding()) {
1147 qmlBinding = QQmlBinding::createTranslationBinding(
1148 compilationUnit, binding, _scopeObject, context);
1150 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1151 qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
1152 context, currentQmlContext());
1155 auto bindingTarget = _bindingTarget;
1156 auto valueTypeProperty = _valueTypeProperty;
1157 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState)
mutable ->
bool {
1158 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, subprop) && targetProperty->isAlias())
1161 sharedState->allCreatedBindings.push_back(qmlBinding);
1163 if (bindingProperty->isAlias()) {
1164 QQmlPropertyPrivate::setBinding(qmlBinding.data(), QQmlPropertyPrivate::DontEnable);
1166 qmlBinding->addToObject();
1168 if (!valueTypeProperty) {
1169 QQmlData *targetDeclarativeData = QQmlData::get(bindingTarget);
1170 Q_ASSERT(targetDeclarativeData);
1171 targetDeclarativeData->setPendingBindingBit(bindingTarget, bindingProperty->coreIndex());
1177 if (!assignBinding(sharedState.data()))
1178 pendingAliasBindings.push_back(assignBinding);
1183 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
1184 if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) {
1186 QQmlType type = qmlTypeForObject(createdSubObject);
1187 Q_ASSERT(type.isValid());
1189 int valueSourceCast = type.propertyValueSourceCast();
1190 if (valueSourceCast != -1) {
1191 QQmlPropertyValueSource *vs =
reinterpret_cast<QQmlPropertyValueSource *>(
reinterpret_cast<
char *>(createdSubObject) + valueSourceCast);
1192 QObject *target = createdSubObject->parent();
1194 if (_valueTypeProperty) {
1195 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
1196 bindingProperty, context);
1198 prop = QQmlPropertyPrivate::restore(target, *bindingProperty,
nullptr, context);
1200 vs->setTarget(prop);
1203 int valueInterceptorCast = type.propertyValueInterceptorCast();
1204 if (valueInterceptorCast != -1) {
1205 QQmlPropertyValueInterceptor *vi =
reinterpret_cast<QQmlPropertyValueInterceptor *>(
reinterpret_cast<
char *>(createdSubObject) + valueInterceptorCast);
1206 QObject *target = createdSubObject->parent();
1208 QQmlPropertyIndex propertyIndex;
1209 if (bindingProperty->isAlias()) {
1210 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1211 auto aliasTarget = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1212 target = aliasTarget.targetObject;
1213 QQmlData *data = QQmlData::get(target);
1214 if (!data || !data->propertyCache) {
1215 qWarning() <<
"can't resolve property alias for 'on' assignment";
1220 QQmlPropertyData targetPropertyData = *data->propertyCache->property(aliasTarget.targetIndex.coreIndex());
1221 auto prop = QQmlPropertyPrivate::restore(
1222 target, targetPropertyData,
nullptr, context);
1223 vi->setTarget(prop);
1224 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1227 if (_valueTypeProperty) {
1228 prop = QQmlPropertyPrivate::restore(
1229 target, *_valueTypeProperty, bindingProperty, context);
1231 prop = QQmlPropertyPrivate::restore(
1232 target, *bindingProperty,
nullptr, context);
1234 vi->setTarget(prop);
1235 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1238 QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
1240 mo =
new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
1241 mo->registerInterceptor(propertyIndex, vi);
1248 if (compilationUnit->bindingIsSignalHandlerObject(_compiledObjectIndex, bindingIndex)) {
1249 if (!bindingProperty->isFunction()) {
1250 recordError(binding->valueLocation, tr(
"Cannot assign an object to signal property %1").arg(bindingProperty->name(_qobject)));
1253 QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
1254 if (!method.isValid()) {
1255 recordError(binding->valueLocation, tr(
"Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
1258 qCWarning(lcQmlDefaultMethod) <<
"Assigning an object to a signal handler is deprecated. "
1259 "Instead, create the object, give it an id, and call the desired slot "
1260 "from the signal handler. The object is:" << createdSubObject;
1262 QMetaMethod signalMethod = _qobject->metaObject()->method(bindingProperty->coreIndex());
1263 if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
1264 recordError(binding->valueLocation,
1265 tr(
"Cannot connect mismatched signal/slot %1 vs %2")
1266 .arg(QString::fromUtf8(method.methodSignature()),
1267 QString::fromUtf8(signalMethod.methodSignature())));
1271 QQmlPropertyPrivate::connect(_qobject, bindingProperty->coreIndex(), createdSubObject, method.methodIndex());
1275 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
1276 QQmlPropertyData::RemoveBindingOnAliasWrite;
1277 int propertyWriteStatus = -1;
1278 void *argv[] = {
nullptr,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
1280 if (
const char *iid = QQmlMetaType::interfaceIId(bindingProperty->propType())) {
1281 void *ptr = createdSubObject->qt_metacast(iid);
1284 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1286 recordError(binding->location, tr(
"Cannot assign object to interface property"));
1289 }
else if (bindingProperty->propType() == QMetaType::fromType<QVariant>()) {
1290 if (bindingProperty->isVarProperty()) {
1291 QV4::Scope scope(v4);
1292 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1293 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1295 QVariant value = QVariant::fromValue(createdSubObject);
1297 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1299 }
else if (bindingProperty->propType() == QMetaType::fromType<QJSValue>()) {
1300 QV4::Scope scope(v4);
1301 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1302 if (bindingProperty->isVarProperty()) {
1303 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1306 QJSValuePrivate::setValue(&value, wrappedObject);
1308 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1310 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::IsQmlList)) {
1311 Q_ASSERT(_currentList.object);
1313 QObject *itemToAdd = createdSubObject;
1315 QMetaType listItemType = QQmlMetaType::listValueType(bindingProperty->propType());
1316 if (listItemType.isValid()) {
1317 const char *iid = QQmlMetaType::interfaceIId(listItemType);
1319 itemToAdd =
static_cast<QObject *>(createdSubObject->qt_metacast(iid));
1322 if (_currentList.append)
1323 _currentList.append(&_currentList, itemToAdd);
1325 recordError(binding->location, tr(
"Cannot assign object to read only list"));
1328 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::PointerToQObject)) {
1330 argv[0] = &createdSubObject;
1331 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1333 QVariant target = QQmlValueTypeProvider::createValueType(
1334 QVariant::fromValue(createdSubObject), bindingProperty->propType(), v4);
1335 if (target.isValid())
1336 bindingProperty->writeProperty(_qobject, target.data(), propertyWriteFlags);
1338 recordError(binding->location, tr(
"Cannot construct value type from given object"));
1343 if (bindingProperty->isQList()) {
1344 recordError(binding->location, tr(
"Cannot assign primitives to lists"));
1348 setPropertyValue(bindingProperty, binding, foldedNumber);
1352void QQmlObjectCreator::setupFunctions()
1354 QV4::Scope scope(v4);
1355 QV4::ScopedValue function(scope);
1356 QV4::ScopedContext qmlContext(scope, currentQmlContext());
1358 const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
1359 for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1360 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
1361 const QString name = runtimeFunction->name()->toQString();
1363 const QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
1364 if (!property->isVMEFunction())
1367 if (runtimeFunction->isGenerator())
1368 function = QV4::GeneratorFunction::create(qmlContext, runtimeFunction);
1370 function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
1371 _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
1375void QQmlObjectCreator::recordError(
const QV4::CompiledData::Location &location,
const QString &description)
1378 error.setUrl(compilationUnit->url());
1379 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(location.line()));
1380 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(location.column()));
1381 error.setDescription(description);
1385void QQmlObjectCreator::registerObjectWithContextById(
int objectIndex, QObject *instance)
const
1387 if (
const int id = compilationUnit->objectId(objectIndex); id >= 0)
1388 context->setIdValue(id, instance);
1391QObject *QQmlObjectCreator::createInstance(
int index, QObject *parent,
bool isContextObject)
1393 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1394 Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
1395 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
1397 const bool isImplicitComponent = index >= compilationUnit->objectCount();
1398 const InitFlags flags = (isContextObject ? InitFlag::IsContextObject : InitFlag::None)
1399 | (index == 0 ? InitFlag::IsDocumentRoot : InitFlag::None)
1400 | (isImplicitComponent ? InitFlag::IsImplicitComponent : InitFlag::None);
1402 if (compilationUnit->objectIsComponent(index) || isImplicitComponent) {
1403 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, QStringLiteral(
"<component>"));
1405 sharedState->profiler,
1407 compilationUnit.data(), obj, QStringLiteral(
"<component>"),
1409 return initializeComponent(
1411 createComponent(engine, compilationUnit.data(), index, parent, context), flags);
1414 const QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
1416 const QQmlType type = typeRef->type();
1417 Q_ASSERT(type.isValid());
1419 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, type.qmlTypeName());
1421 sharedState->profiler,
1422 profiler.update(compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
1424 if (type.isCompositeSingleton()) {
1427 tr(
"Composite Singleton Type %1 is not creatable")
1428 .arg(stringAt(obj->inheritedTypeNameIndex)));
1432 if (!type.isComposite()) {
1433 if (QObject *instance = type.createWithQQmlData())
1434 return initializeNonComposite(index, obj, typeRef, instance, parent, flags);
1437 tr(
"Unable to create object of type %1").arg(
1438 stringAt(obj->inheritedTypeNameIndex)));
1442 QQmlRefPointer<QV4::ExecutableCompilationUnit> executableCu = typeRef->isSelfReference()
1444 : engine->handle()->executableCompilationUnit(typeRef->compilationUnit());
1445 Q_ASSERT(executableCu);
1447 const bool isInlineComponent = type.isInlineComponent();
1448 const QString inlineComponentName = isInlineComponent ? type.elementName() : QString();
1449 QQmlObjectCreator subCreator(
1450 context, executableCu, inlineComponentName, sharedState.data(),
1453 if (QObject *instance = isInlineComponent
1454 ? subCreator.create(
1455 executableCu->inlineComponentId(inlineComponentName),
nullptr,
nullptr,
1456 CreationFlags::InlineComponent)
1457 : subCreator.create()) {
1458 return initializeComposite(index, obj, typeRef, instance, parent, flags);
1461 errors += subCreator.errors;
1465void QQmlObjectCreator::initializeDData(
1466 const QV4::CompiledData::Object *obj, QObject *instance, QQmlData *ddata, InitFlags flags)
1468 ddata->lineNumber = obj->location.line();
1469 ddata->columnNumber = obj->location.column();
1470 ddata->setImplicitDestructible();
1474 const bool documentRoot = (flags & InitFlag::IsDocumentRoot)
1475 || ddata->rootObjectInCreation
1476 || obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot);
1478 context->installContext(
1479 ddata, documentRoot ? QQmlContextData::DocumentRoot : QQmlContextData::OrdinaryObject);
1483 if ((flags & (InitFlag::IsContextObject | InitFlag::IsImplicitComponent))
1484 == InitFlag::IsContextObject) {
1485 context->setContextObject(instance);
1489void QQmlObjectCreator::initializePropertyCache(
1490 int index, QQmlData *ddata,
const QV4::ResolvedTypeReference *typeRef)
1492 if (!typeRef->isFullyDynamicType()) {
1493 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(index);
1494 Q_ASSERT(!cache.isNull());
1495 ddata->propertyCache = std::move(cache);
1499void QQmlObjectCreator::initializeParent(QObject *instance, QObject *parent)
1501 if (instance->isWidgetType()) {
1502 if (parent && parent->isWidgetType()) {
1503 QAbstractDeclarativeData::setWidgetParent(instance, parent);
1508 }
else if (parent) {
1509 QQml_setParent_noEvent(instance, parent);
1513QObject *QQmlObjectCreator::populateInstanceAndAliasBindings(
1514 int index, QObject *instance, InitFlags flags)
1516 const auto doPopulate = [&]() {
1517 if (!populateInstance(
1518 index, instance, instance,
nullptr)) {
1520 pendingAliasBindings.clear();
1524 if (!flags.testFlag(InitFlag::IsContextObject))
1527 while (!pendingAliasBindings.empty()) {
1528 for (std::vector<PendingAliasBinding>::iterator it = pendingAliasBindings.begin();
1529 it != pendingAliasBindings.end(); ) {
1530 if ((*it)(sharedState.data()))
1531 it = pendingAliasBindings.erase(it);
1540 QObject *scopeObject = instance;
1541 qSwap(_scopeObject, scopeObject);
1543 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
1544 sharedState->allJavaScriptObjects.trackObject(v4, instance);
1546 QV4::Scope valueScope(v4);
1547 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(valueScope.constructUndefined(1));
1549 qSwap(_qmlContext, qmlContext);
1551 const bool ok = doPopulate();
1553 qSwap(_qmlContext, qmlContext);
1554 qSwap(_scopeObject, scopeObject);
1556 return ok ? instance :
nullptr;
1559QObject *QQmlObjectCreator::initializeComponent(
1560 int index,
const QV4::CompiledData::Object *obj, QObject *instance, InitFlags flags)
1565 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1566 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1569 initializeDData(obj, instance, QQmlData::get(instance), flags);
1571 if (!flags.testFlag(InitFlag::IsImplicitComponent))
1572 registerObjectWithContextById(index, instance);
1576QObject *QQmlObjectCreator::initializeComposite(
1577 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1578 QObject *instance, QObject *parent, InitFlags flags)
1583 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1584 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1586 initializeParent(instance, parent);
1587 QQmlData *ddata = QQmlData::get(instance,
true);
1588 initializeDData(obj, instance, ddata, flags);
1590 initializePropertyCache(index, ddata, typeRef);
1592 return populateInstanceAndAliasBindings(index, instance, flags);
1595QObject *QQmlObjectCreator::initializeNonComposite(
1596 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1597 QObject *instance, QObject *parent, InitFlags flags)
1601 Q_ASSERT(!compilationUnit->objectIsComponent(index));
1604 const QQmlType type = typeRef->type();
1605 Q_ASSERT(type.isValid());
1606 Q_ASSERT(!type.isComposite());
1608 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1610 if (
const int finalizerCast = type.finalizerCast(); finalizerCast != -1) {
1611 const auto hook =
reinterpret_cast<QQmlFinalizerHook *>(
1612 reinterpret_cast<
char *>(instance) + finalizerCast);
1613 sharedState->finalizeHooks.push_back(hook);
1616 QQmlData *ddata = QQmlData::get(instance,
true);
1617 if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
1618 ddata->rootObjectInCreation =
true;
1619 sharedState->rootContext->setRootObjectInCreation(
false);
1622 const size_t instanceIndex = sharedState->allCreatedObjects.size();
1623 sharedState->allCreatedObjects.push_back(instance);
1625 initializeParent(instance, parent);
1626 initializeDData(obj, instance, ddata, flags);
1628 if (
const int parserStatusCast = type.parserStatusCast(); parserStatusCast != -1) {
1629 if (QQmlParserStatus *parserStatus =
reinterpret_cast<QQmlParserStatus*>(
1630 reinterpret_cast<
char *>(instance) + parserStatusCast)) {
1631 parserStatus->classBegin();
1634 Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
1635 sharedState->allParserStatusCallbacks.push_back({ instanceIndex, parserStatusCast });
1639 if (QQmlCustomParser *customParser = type.customParser();
1640 customParser && compilationUnit->objectHasCustomParserBindings(index)) {
1641 customParser->engine = QQmlEnginePrivate::get(engine);
1642 customParser->imports = compilationUnit->typeNameCache().data();
1644 QList<
const QV4::CompiledData::Binding *> bindings;
1645 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1646 const QV4::CompiledData::RuntimeBindingIndex *bindingOrder =
1647 compilationUnit->bindingApplicationOrder(index);
1648 for (quint32 k = 0; k < obj->nBindings; ++k) {
1649 const quint32 i = bindingOrder[k];
1650 if (compilationUnit->bindingIsCustomParser(index, i))
1651 bindings << obj->bindingTable() + i;
1653 customParser->applyBindings(instance, compilationUnit, bindings);
1655 customParser->engine =
nullptr;
1656 customParser->imports = (QQmlTypeNameCache*)
nullptr;
1659 initializePropertyCache(index, ddata, typeRef);
1660 return populateInstanceAndAliasBindings(index, instance, flags);
1664
1665
1666
1667
1668
1669QObject *QQmlObjectCreator::createObjectInContext(
1670 int objectIndex, QObject *parent,
1671 const QQmlRefPointer<QQmlContextData> &existingContext)
1673 Q_ASSERT(phase == Startup);
1674 phase = CreatingObjects;
1676 context = existingContext;
1677 if (!sharedState->rootContext)
1678 sharedState->rootContext = context;
1680 QV4::Scope scope(v4);
1681 if (topLevelCreator)
1682 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
1684 QObject *rv = createInstance(objectIndex, parent,
false);
1685 phase = ObjectsCreated;
1689bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1691 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1694 QQmlObjectCreatorRecursionWatcher watcher(
this);
1695 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710 const bool removeConstantBindings = !QV4::ExecutionEngine::isPreviewing();
1712 while (!sharedState->allCreatedBindings.empty()) {
1713 QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.back();
1714 sharedState->allCreatedBindings.pop_back();
1717 if (!b->isAddedToObject())
1719 QQmlData *data = QQmlData::get(b->targetObject());
1721 data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
1722 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
1723 QQmlPropertyData::DontRemoveBinding);
1724 if (removeConstantBindings && b->kind() == QQmlAbstractBinding::QmlBinding) {
1725 QQmlBinding *binding =
static_cast<QQmlBinding*>(b.data());
1726 if (!binding->hasError() && !binding->hasDependencies()
1727 && !binding->hasUnresolvedNames()) {
1728 b->removeFromObject();
1732 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1736 while (!sharedState->allQPropertyBindings.isEmpty()) {
1737 auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first();
1739 QQmlData *data = QQmlData::get(target);
1740 if (!data || !data->hasBindingBit(index)) {
1742 sharedState->allQPropertyBindings.pop_front();
1746 QUntypedBindable bindable;
1747 void *argv[] = { &bindable };
1749 target->metaObject()->metacall(target, QMetaObject::BindableProperty, index, argv);
1750 const bool success = bindable.setBinding(qmlBinding);
1752 const auto bindingPrivateRefCount = QPropertyBindingPrivate::get(qmlBinding)->refCount();
1755 sharedState->allQPropertyBindings.pop_front();
1758 if (removeConstantBindings && success && bindingPrivateRefCount > 1) {
1759 if (
auto priv = QPropertyBindingPrivate::get(qmlBinding); priv->isQmlBinding()) {
1760 const auto qmlBindingBase =
static_cast<
const QQmlPropertyBindingBase *>(priv);
1761 if (qmlBindingBase->bindingKind()
1762 == QQmlPropertyBindingBase::BindingKind::JavaScript) {
1763 const auto qmlBindingPriv =
1764 static_cast<
const QQmlPropertyBinding *>(qmlBindingBase);
1765 const auto jsExpression = qmlBindingPriv->jsExpression();
1766 const bool canRemove = !qmlBinding.error().hasError()
1767 && !qmlBindingPriv->hasDependencies()
1768 && !jsExpression->hasUnresolvedNames();
1770 bindable.takeBinding();
1775 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1779 if (QQmlVME::componentCompleteEnabled()) {
1780 while (!sharedState->allParserStatusCallbacks.empty()) {
1781 QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
1782 const ParserStatus status = sharedState->allParserStatusCallbacks.back();
1783 sharedState->allParserStatusCallbacks.pop_back();
1785 const QQmlGuard<QObject> &instance = sharedState->allCreatedObjects[status.objectIndex];
1789 QQmlParserStatus *parserStatus
1790 =
reinterpret_cast<QQmlParserStatus *>(
1791 reinterpret_cast<
char *>(instance.data()) + status.parserStatusCast);
1792 parserStatus->componentComplete();
1794 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1799 for (QQmlFinalizerHook *hook: std::as_const(sharedState->finalizeHooks)) {
1800 hook->componentFinalized();
1801 if (watcher.hasRecursed())
1804 sharedState->finalizeHooks.clear();
1806 while (sharedState->componentAttached) {
1807 QQmlComponentAttached *a = sharedState->componentAttached;
1808 a->removeFromList();
1809 QQmlData *d = QQmlData::get(a->parent());
1811 Q_ASSERT(d->context);
1812 d->context->addComponentAttached(a);
1813 if (QQmlVME::componentCompleteEnabled())
1814 emit a->completed();
1816 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1825void QQmlObjectCreator::clear()
1827 if (phase == Done || phase == Finalizing || phase == Startup)
1829 Q_ASSERT(phase != Startup);
1831 while (!sharedState->allCreatedObjects.empty()) {
1832 auto object = sharedState->allCreatedObjects.back();
1833 sharedState->allCreatedObjects.pop_back();
1834 if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
1839 while (sharedState->componentAttached) {
1840 QQmlComponentAttached *a = sharedState->componentAttached;
1841 a->removeFromList();
1847void QQmlObjectCreator::registerPostHocRequiredProperties(
const QV4::CompiledData::Binding *binding)
1849 const qsizetype oldRequiredPropertiesCount = sharedState->requiredProperties.size();
1850 QSet<QString> postHocRequired;
1851 for (
auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
1852 postHocRequired.insert(stringAt(it->nameIndex));
1853 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1855 for (
int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
1856 const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
1857 const QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
1859 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex()));
1860 if (!property->isRequired() && postHocRequired.end() == postHocIt)
1862 if (postHocIt != postHocRequired.end())
1863 postHocRequired.erase(postHocIt);
1864 if (isContextObject)
1865 sharedState->hadTopLevelRequiredProperties =
true;
1866 sharedState->requiredProperties.insert({_qobject, propertyData},
1867 RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex()), compilationUnit->finalUrl(), property->location, {}});
1871 const auto getPropertyCacheRange = [&]() -> std::pair<
int,
int> {
1889 QV4::ResolvedTypeReference *typeRef = resolvedType(_compiledObject->inheritedTypeNameIndex);
1892 if (binding->isAttachedProperty())
1893 return { 0, _propertyCache->propertyCount() };
1894 Q_ASSERT(binding->isGroupedProperty());
1895 return { 0, _propertyCache->propertyOffset() + 1 };
1897 Q_ASSERT(!compilationUnit->objectIsComponent(_compiledObjectIndex));
1898 QQmlType type = typeRef->type();
1899 if (type.isComposite())
1900 return { _propertyCache->propertyOffset(), _propertyCache->propertyCount() };
1901 return { 0, _propertyCache->propertyCount() };
1903 const auto [offset, count] = getPropertyCacheRange();
1904 for (
int i = offset; i < count; ++i) {
1905 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1911 if (!propertyData->isRequired() && postHocRequired.isEmpty())
1913 QString name = propertyData->name(_qobject);
1914 const auto postHocIt = postHocRequired.constFind(name);
1915 if (postHocIt == postHocRequired.constEnd()) {
1916 if (!propertyData->isRequired())
1919 postHocRequired.erase(postHocIt);
1922 if (isContextObject)
1923 sharedState->hadTopLevelRequiredProperties =
true;
1924 sharedState->requiredProperties.insert(
1925 {_qobject, propertyData},
1926 RequiredPropertyInfo {
1927 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1931 if (binding && binding->isAttachedProperty()
1932 && sharedState->requiredProperties.size() != oldRequiredPropertiesCount) {
1935 QLatin1String(
"Attached property has required properties. This is not supported"));
1942 if (!postHocRequired.isEmpty()) {
1944 for (
int i = 0; i < offset; ++i) {
1945 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1948 QString name = propertyData->name(_qobject);
1949 const auto postHocIt = postHocRequired.constFind(name);
1950 if (postHocIt == postHocRequired.constEnd())
1952 postHocRequired.erase(postHocIt);
1954 if (isContextObject)
1955 sharedState->hadTopLevelRequiredProperties =
true;
1956 sharedState->requiredProperties.insert(
1957 {_qobject, propertyData},
1958 RequiredPropertyInfo {
1959 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1964 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1965 recordError({}, QLatin1String(
"Property %1 was marked as required but does not exist").arg(*postHocRequired.begin()));
1968bool QQmlObjectCreator::populateInstance(
int index, QObject *instance, QObject *bindingTarget,
1969 const QQmlPropertyData *valueTypeProperty,
1970 const QV4::CompiledData::Binding *binding)
1973 QQmlData *declarativeData = QQmlData::get(instance,
true);
1975 qSwap(_qobject, instance);
1976 qSwap(_valueTypeProperty, valueTypeProperty);
1977 qSwap(_compiledObjectIndex, index);
1978 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
1979 qSwap(_compiledObject, obj);
1980 qSwap(_ddata, declarativeData);
1981 qSwap(_bindingTarget, bindingTarget);
1983 QV4::Scope valueScope(v4);
1984 QV4::ScopedValue scopeObjectProtector(valueScope);
1986 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
1988 QQmlVMEMetaObject *vmeMetaObject =
nullptr;
1989 if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) {
1990 Q_ASSERT(!cache.isNull());
1992 vmeMetaObject =
new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
1993 _ddata->propertyCache = cache;
1994 scopeObjectProtector = _ddata->jsWrapper.value();
1996 vmeMetaObject = QQmlVMEMetaObject::get(_qobject, v4);
1999 registerObjectWithContextById(_compiledObjectIndex, _qobject);
2001 qSwap(_propertyCache, cache);
2002 qSwap(_vmeMetaObject, vmeMetaObject);
2007 if (!stringAt(_compiledObject->inheritedTypeNameIndex).isEmpty()) {
2008 _ddata->compilationUnit = compilationUnit;
2009 _ddata->cuObjectIndex =
int(_compiledObjectIndex);
2015 const bool applyingDeferred =
2016 compilationUnit->objectIsPopulatedByDeferredBinding(_compiledObjectIndex);
2017 if (!applyingDeferred
2018 && compilationUnit->objectHasDeferredBindings(_compiledObjectIndex)) {
2019 _ddata->deferData(_compiledObjectIndex, compilationUnit, context, m_inlineComponentName);
2022 registerPostHocRequiredProperties(binding);
2024 if (_compiledObject->nFunctions > 0)
2026 setupBindings(applyingDeferred ? BindingMode::ApplyAll : BindingMode::ApplyImmediate);
2028 for (
int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
2033 _vmeMetaObject->connectAlias(_compiledObject, aliasIndex);
2034 if (!context->isIdValueSet(0))
2036 const QQmlPropertyData *aliasProperty =
2037 _propertyCache->property(_vmeMetaObject->aliasOffset() + aliasIndex);
2040 QObject *target = context->idValue(aliasProperty->aliasTargetObjectId());
2043 QQmlData *targetDData = QQmlData::get(target,
false);
2044 if (targetDData ==
nullptr || targetDData->propertyCache.isNull())
2047 const int targetPropertyIndex = aliasProperty->aliasTarget();
2048 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
2050 const QQmlPropertyData *
const targetProperty = targetDData->propertyCache->property(coreIndex);
2051 if (!targetProperty)
2053 auto it = sharedState->requiredProperties.find({target, targetProperty});
2054 if (it != sharedState->requiredProperties.end()) {
2055 const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
2056 it->aliasesToRequired.push_back(
2057 AliasToRequiredInfo {
2058 compilationUnit->stringAt(alias->nameIndex()),
2059 compilationUnit->finalUrl()
2064 qSwap(_vmeMetaObject, vmeMetaObject);
2065 qSwap(_bindingTarget, bindingTarget);
2066 qSwap(_ddata, declarativeData);
2067 qSwap(_compiledObject, obj);
2068 qSwap(_compiledObjectIndex, index);
2069 qSwap(_valueTypeProperty, valueTypeProperty);
2070 qSwap(_qobject, instance);
2071 qSwap(_propertyCache, cache);
2073 return errors.isEmpty();
2077
2078
2079QQmlComponent *QQmlObjectCreator::createComponent(
2080 QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit,
int index,
2081 QObject *parent,
const QQmlRefPointer<QQmlContextData> &context)
2083 QQmlComponent *component =
new QQmlComponent(engine, compilationUnit, index, parent);
2084 QQmlComponentPrivate::get(component)->setCreationContext(context);
2085 QQmlData *ddata = QQmlData::get(component,
true);
2087 ddata->compilationUnit = compilationUnit;
2088 ddata->cuObjectIndex = index;
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105void QQmlObjectCreator::repopulateBindings(
2106 int index, QObject *instance,
2107 const QQmlRefPointer<QQmlContextData> &instanceContext, InitFlags flags)
2109 phase = QQmlObjectCreator::ObjectsCreated;
2112 if (compilationUnit->objectCount() <= index)
2115 const auto oldContext = std::exchange(context, instanceContext);
2116 const auto contextGuard = qScopeGuard([&]() {
2117 context = oldContext;
2120 auto rootContextGuard = qScopeGuard([&]() {
2121 sharedState->rootContext.reset();
2123 if (!sharedState->rootContext)
2124 sharedState->rootContext = context;
2126 rootContextGuard.dismiss();
2128 QV4::Scope scope(engine->handle());
2129 auto jsObjectsGuard = qScopeGuard([&]() {
2130 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
2132 if (!sharedState->allJavaScriptObjects.canTrack())
2133 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
2135 jsObjectsGuard.dismiss();
2137 QQmlData *ddata = QQmlData::get(instance,
true);
2140 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance, v4);
2142 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
2145 qSwap(_qobject, instance);
2146 qSwap(_compiledObjectIndex, index);
2147 qSwap(_compiledObject, obj);
2148 qSwap(_ddata, ddata);
2149 QObject *bindingTarget = _qobject;
2150 qSwap(_bindingTarget, bindingTarget);
2151 QObject *scopeObject = _qobject;
2152 qSwap(_scopeObject, scopeObject);
2153 const QQmlPropertyData *valueTypeProperty =
nullptr;
2154 qSwap(_valueTypeProperty, valueTypeProperty);
2156 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
2157 sharedState->allJavaScriptObjects.trackObject(v4, _qobject);
2159 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(scope.constructUndefined(1));
2160 qSwap(_qmlContext, qmlContext);
2162 QV4::ScopedValue scopeObjectProtector(scope);
2164 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
2165 _ddata->propertyCache = cache;
2166 qSwap(_propertyCache, cache);
2167 qSwap(_vmeMetaObject, vmeMetaObject);
2169 if (compilationUnit->objectId(_compiledObjectIndex) < context->numIdValues())
2170 registerObjectWithContextById(_compiledObjectIndex, _qobject);
2172 _ddata->compilationUnit = compilationUnit;
2173 _ddata->cuObjectIndex =
int(_compiledObjectIndex);
2175 if (_compiledObject->nFunctions > 0)
2177 setupBindings(BindingMode::ApplyImmediate);
2179 if (flags.testFlag(InitFlag::IsContextObject)) {
2180 while (!pendingAliasBindings.empty()) {
2181 for (
auto it = pendingAliasBindings.begin(); it != pendingAliasBindings.end();) {
2182 if ((*it)(sharedState.data()))
2183 it = pendingAliasBindings.erase(it);
2191 qSwap(_vmeMetaObject, vmeMetaObject);
2192 qSwap(_propertyCache, cache);
2193 qSwap(_qmlContext, qmlContext);
2194 qSwap(_scopeObject, scopeObject);
2195 qSwap(_valueTypeProperty, valueTypeProperty);
2196 qSwap(_bindingTarget, bindingTarget);
2197 qSwap(_ddata, ddata);
2198 qSwap(_compiledObject, obj);
2199 qSwap(_compiledObjectIndex, index);
2200 qSwap(_qobject, instance);
2209void ObjectInCreationGCAnchorList::trackObject(QV4::ExecutionEngine *engine, QObject *instance)
2211 QV4::Value *wrapper = allocationScope->construct(1, QV4::QObjectWrapper::wrap(engine, instance));
2215 QV4::WriteBarrier::markCustom(engine, [wrapper](QV4::MarkStack *ms) {
2216 wrapper->heapObject()->mark(ms);
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static QQmlType qmlTypeForObject(QObject *object)
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)