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);
260 Q_ASSERT(binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding));
262 QQmlListProperty<QObject> savedList;
263 qSwap(_currentList, savedList);
265 const QQmlPropertyData &property = qmlProperty->core;
267 if (property.propType().flags().testFlag(QMetaType::IsQmlList)) {
268 void *argv[1] = { (
void*)&_currentList };
269 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
270 }
else if (_currentList.object) {
271 _currentList = QQmlListProperty<QObject>();
274 setPropertyBinding(&property, binding);
276 qSwap(_currentList, savedList);
280void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex)
282 doPopulateDeferred(instance, deferredIndex, [
this]() { setupBindings(ApplyDeferred); });
285bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
286 const QQmlData::DeferredData *deferredData)
288 beginPopulateDeferred(deferredData->context);
289 populateDeferred(instance, deferredData->deferredIdx);
290 finalizePopulateDeferred();
291 return errors.isEmpty();
294void QQmlObjectCreator::populateDeferredBinding(
const QQmlProperty &qmlProperty,
int deferredIndex,
295 const QV4::CompiledData::Binding *binding)
298 populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
301 populateDeferred(qmlProperty.object(), deferredIndex);
305void QQmlObjectCreator::populateDeferredInstance(
306 QObject *outerObject,
int deferredIndex,
int index, QObject *instance,
307 QObject *bindingTarget,
const QQmlPropertyData *valueTypeProperty,
308 const QV4::CompiledData::Binding *binding)
310 doPopulateDeferred(outerObject, deferredIndex, [&]() {
311 populateInstance(index, instance, bindingTarget, valueTypeProperty, binding);
315void QQmlObjectCreator::finalizePopulateDeferred()
317 phase = ObjectsCreated;
320void QQmlObjectCreator::setPropertyValue(
const QQmlPropertyData *property,
const QV4::CompiledData::Binding *binding)
322 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
323 QV4::Scope scope(v4);
325 QMetaType propertyType = property->propType();
327 if (property->isEnum()) {
328 if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum) ||
331 (property->isAlias() && binding->isNumberBinding())) {
332 propertyType = property->propType().underlyingType();
335 QVariant value = compilationUnit->bindingValueAsString(binding);
336 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
343 auto assertOrNull = [&](
bool ok)
345 Q_ASSERT(ok || binding->type() == QV4::CompiledData::Binding::Type_Null);
349 auto assertType = [&](QV4::CompiledData::Binding::Type type)
351 Q_ASSERT(binding->type()== type || binding->type() == QV4::CompiledData::Binding::Type_Null);
355 if (property->isQObject()) {
356 if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
357 QObject *value =
nullptr;
358 const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags);
365 switch (propertyType.id()) {
366 case QMetaType::QVariant: {
367 if (binding->type() == QV4::CompiledData::Binding::Type_Number) {
368 double n = compilationUnit->bindingValueAsNumber(binding);
369 if (
double(
int(n)) == n) {
370 if (property->isVarProperty()) {
371 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(
int(n)));
375 property->writeProperty(_qobject, &value, propertyWriteFlags);
378 if (property->isVarProperty()) {
379 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromDouble(n));
382 property->writeProperty(_qobject, &value, propertyWriteFlags);
385 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Boolean) {
386 if (property->isVarProperty()) {
387 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean()));
389 QVariant value(binding->valueAsBoolean());
390 property->writeProperty(_qobject, &value, propertyWriteFlags);
392 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
393 if (property->isVarProperty()) {
394 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue());
396 QVariant nullValue = QVariant::fromValue(
nullptr);
397 property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
400 QString stringValue = compilationUnit->bindingValueAsString(binding);
401 if (property->isVarProperty()) {
402 QV4::ScopedString s(scope, v4->newString(stringValue));
403 _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
405 QVariant value = stringValue;
406 property->writeProperty(_qobject, &value, propertyWriteFlags);
411 case QMetaType::QString: {
412 assertOrNull(binding->evaluatesToString());
413 QString value = compilationUnit->bindingValueAsString(binding);
414 property->writeProperty(_qobject, &value, propertyWriteFlags);
417 case QMetaType::QStringList: {
418 assertOrNull(binding->evaluatesToString());
419 QStringList value(compilationUnit->bindingValueAsString(binding));
420 property->writeProperty(_qobject, &value, propertyWriteFlags);
423 case QMetaType::QByteArray: {
424 assertType(QV4::CompiledData::Binding::Type_String);
425 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
426 property->writeProperty(_qobject, &value, propertyWriteFlags);
429 case QMetaType::QUrl: {
430 assertType(QV4::CompiledData::Binding::Type_String);
431 const QString string = compilationUnit->bindingValueAsString(binding);
432 QUrl value = (!string.isEmpty() && QQmlPropertyPrivate::resolveUrlsOnAssignment())
433 ? compilationUnit->finalUrl().resolved(QUrl(string))
435 property->writeProperty(_qobject, &value, propertyWriteFlags);
438 case QMetaType::UInt: {
439 assertType(QV4::CompiledData::Binding::Type_Number);
440 double d = compilationUnit->bindingValueAsNumber(binding);
441 uint value = uint(d);
442 property->writeProperty(_qobject, &value, propertyWriteFlags);
446 case QMetaType::Int: {
447 assertType(QV4::CompiledData::Binding::Type_Number);
448 double d = compilationUnit->bindingValueAsNumber(binding);
450 property->writeProperty(_qobject, &value, propertyWriteFlags);
454 case QMetaType::SChar: {
455 assertType(QV4::CompiledData::Binding::Type_Number);
456 double d = compilationUnit->bindingValueAsNumber(binding);
457 qint8 value = qint8(d);
458 property->writeProperty(_qobject, &value, propertyWriteFlags);
461 case QMetaType::UChar: {
462 assertType(QV4::CompiledData::Binding::Type_Number);
463 double d = compilationUnit->bindingValueAsNumber(binding);
464 quint8 value = quint8(d);
465 property->writeProperty(_qobject, &value, propertyWriteFlags);
468 case QMetaType::Short: {
469 assertType(QV4::CompiledData::Binding::Type_Number);
470 double d = compilationUnit->bindingValueAsNumber(binding);
471 qint16 value = qint16(d);
472 property->writeProperty(_qobject, &value, propertyWriteFlags);
475 case QMetaType::UShort: {
476 assertType(QV4::CompiledData::Binding::Type_Number);
477 double d = compilationUnit->bindingValueAsNumber(binding);
478 quint16 value = quint16(d);
479 property->writeProperty(_qobject, &value, propertyWriteFlags);
482 case QMetaType::LongLong: {
483 assertType(QV4::CompiledData::Binding::Type_Number);
484 double d = compilationUnit->bindingValueAsNumber(binding);
485 qint64 value = qint64(d);
486 property->writeProperty(_qobject, &value, propertyWriteFlags);
489 case QMetaType::ULongLong: {
490 assertType(QV4::CompiledData::Binding::Type_Number);
491 double d = compilationUnit->bindingValueAsNumber(binding);
492 quint64 value = quint64(d);
493 property->writeProperty(_qobject, &value, propertyWriteFlags);
497 case QMetaType::Float: {
498 assertType(QV4::CompiledData::Binding::Type_Number);
499 float value =
float(compilationUnit->bindingValueAsNumber(binding));
500 property->writeProperty(_qobject, &value, propertyWriteFlags);
503 case QMetaType::Double: {
504 assertType(QV4::CompiledData::Binding::Type_Number);
505 double value = compilationUnit->bindingValueAsNumber(binding);
506 property->writeProperty(_qobject, &value, propertyWriteFlags);
509 case QMetaType::QColor: {
511 QVariant data = QQmlStringConverters::colorFromString(
512 compilationUnit->bindingValueAsString(binding), &ok);
514 property->writeProperty(_qobject, data.data(), propertyWriteFlags);
517#if QT_CONFIG(datestring)
518 case QMetaType::QDate: {
520 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
522 property->writeProperty(_qobject, &value, propertyWriteFlags);
525 case QMetaType::QTime: {
527 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
529 property->writeProperty(_qobject, &value, propertyWriteFlags);
532 case QMetaType::QDateTime: {
534 QDateTime value = QQmlStringConverters::dateTimeFromString(
535 compilationUnit->bindingValueAsString(binding), &ok);
537 property->writeProperty(_qobject, &value, propertyWriteFlags);
541 case QMetaType::QPoint: {
543 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
545 property->writeProperty(_qobject, &value, propertyWriteFlags);
548 case QMetaType::QPointF: {
550 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
552 property->writeProperty(_qobject, &value, propertyWriteFlags);
555 case QMetaType::QSize: {
557 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
559 property->writeProperty(_qobject, &value, propertyWriteFlags);
562 case QMetaType::QSizeF: {
564 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
566 property->writeProperty(_qobject, &value, propertyWriteFlags);
569 case QMetaType::QRect: {
571 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
573 property->writeProperty(_qobject, &value, propertyWriteFlags);
576 case QMetaType::QRectF: {
578 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
580 property->writeProperty(_qobject, &value, propertyWriteFlags);
583 case QMetaType::Bool: {
584 assertType(QV4::CompiledData::Binding::Type_Boolean);
585 bool value = binding->valueAsBoolean();
586 property->writeProperty(_qobject, &value, propertyWriteFlags);
589 case QMetaType::QVector2D:
590 case QMetaType::QVector3D:
591 case QMetaType::QVector4D:
592 case QMetaType::QQuaternion: {
593 QVariant result = QQmlValueTypeProvider::createValueType(
594 compilationUnit->bindingValueAsString(binding), propertyType);
595 assertOrNull(result.isValid());
596 property->writeProperty(_qobject, result.data(), propertyWriteFlags);
601 if (propertyType == QMetaType::fromType<QList<qreal>>()) {
602 assertType(QV4::CompiledData::Binding::Type_Number);
604 value.append(compilationUnit->bindingValueAsNumber(binding));
605 property->writeProperty(_qobject, &value, propertyWriteFlags);
607 }
else if (propertyType == QMetaType::fromType<QList<
int>>()) {
608 assertType(QV4::CompiledData::Binding::Type_Number);
609 double n = compilationUnit->bindingValueAsNumber(binding);
611 value.append(
int(n));
612 property->writeProperty(_qobject, &value, propertyWriteFlags);
614 }
else if (propertyType == QMetaType::fromType<QList<
bool>>()) {
615 assertType(QV4::CompiledData::Binding::Type_Boolean);
617 value.append(binding->valueAsBoolean());
618 property->writeProperty(_qobject, &value, propertyWriteFlags);
620 }
else if (propertyType == QMetaType::fromType<QList<QUrl>>()) {
621 assertType(QV4::CompiledData::Binding::Type_String);
622 const QUrl url(compilationUnit->bindingValueAsString(binding));
624 QQmlPropertyPrivate::resolveUrlsOnAssignment()
625 ? compilationUnit->finalUrl().resolved(url)
628 property->writeProperty(_qobject, &value, propertyWriteFlags);
630 }
else if (propertyType == QMetaType::fromType<QList<QString>>()) {
631 assertOrNull(binding->evaluatesToString());
632 QList<QString> value;
633 value.append(compilationUnit->bindingValueAsString(binding));
634 property->writeProperty(_qobject, &value, propertyWriteFlags);
636 }
else if (propertyType == QMetaType::fromType<QJSValue>()) {
638 switch (binding->type()) {
639 case QV4::CompiledData::Binding::Type_Boolean:
640 value = QJSValue(binding->valueAsBoolean());
642 case QV4::CompiledData::Binding::Type_Number: {
643 const double n = compilationUnit->bindingValueAsNumber(binding);
644 if (
double(
int(n)) == n)
645 value = QJSValue(
int(n));
650 case QV4::CompiledData::Binding::Type_Null:
651 value = QJSValue::NullValue;
654 value = QJSValue(compilationUnit->bindingValueAsString(binding));
657 property->writeProperty(_qobject, &value, propertyWriteFlags);
661 switch (binding->type()) {
662 case QV4::CompiledData::Binding::Type_Boolean:
663 source = binding->valueAsBoolean();
665 case QV4::CompiledData::Binding::Type_Number: {
666 const double n = compilationUnit->bindingValueAsNumber(binding);
667 if (
double(
int(n)) == n)
673 case QV4::CompiledData::Binding::Type_Null:
674 source = QVariant::fromValue<std::nullptr_t>(
nullptr);
676 case QV4::CompiledData::Binding::Type_Invalid:
679 source = compilationUnit->bindingValueAsString(binding);
683 QVariant target = QQmlValueTypeProvider::createValueType(
684 source, propertyType, engine->handle());
685 if (target.isValid()) {
686 property->writeProperty(_qobject, target.data(), propertyWriteFlags);
692 QString stringValue = compilationUnit->bindingValueAsString(binding);
693 QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
694 recordError(binding->location, tr(
"Cannot assign value %1 to property"
695" %2").arg(stringValue, QString::fromUtf8(metaProperty.name())));
704 const QMetaObject *mo = object->metaObject();
705 while (mo && !type.isValid()) {
706 type = QQmlMetaType::qmlType(mo);
707 mo = mo->superClass();
712void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
714 QQmlListProperty<QObject> savedList;
715 qSwap(_currentList, savedList);
717 const QV4::CompiledData::BindingPropertyData *propertyData
718 = compilationUnit->bindingPropertyDataPerObjectAt(_compiledObjectIndex);
720 if (_compiledObject->idNameIndex) {
721 const QQmlPropertyData *idProperty = propertyData->last();
722 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String(
"id"));
723 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) {
724 QV4::CompiledData::Binding idBinding;
725 idBinding.propertyNameIndex = 0;
726 idBinding.clearFlags();
727 idBinding.setType(QV4::CompiledData::Binding::Type_String);
728 idBinding.stringIndex = _compiledObject->idNameIndex;
729 idBinding.location = _compiledObject->location;
730 idBinding.value.nullMarker = 0;
731 setPropertyValue(idProperty, &idBinding);
736 if (_valueTypeProperty) {
737 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
739 if (binding && binding->kind() != QQmlAbstractBinding::ValueTypeProxy) {
740 QQmlPropertyPrivate::removeBinding(
741 _bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()),
742 QQmlPropertyPrivate::OverrideSticky);
743 }
else if (binding) {
744 QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
746 if (qmlTypeForObject(_bindingTarget).isValid()) {
747 quint32 bindingSkipList = 0;
749 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
751 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
752 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
753 const QQmlPropertyData *property = binding->propertyNameIndex != 0
754 ? _propertyCache->property(stringAt(binding->propertyNameIndex),
758 bindingSkipList |= (1 << property->coreIndex());
761 proxy->removeBindings(bindingSkipList);
766 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1
767 ? _propertyCache->parent()->defaultProperty()
768 : _propertyCache->defaultProperty();
770 int currentListPropertyIndex = -1;
773 const auto applyBinding = [&](
const QQmlPropertyData *property,
774 const QV4::CompiledData::Binding *binding) ->
bool {
775 if (property && property->propType().flags().testFlag(QMetaType::IsQmlList)) {
776 if (property->coreIndex() != currentListPropertyIndex) {
777 void *argv[1] = { (
void*)&_currentList };
778 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
779 currentListPropertyIndex = property->coreIndex();
782 const QMetaObject *
const metaobject = _qobject->metaObject();
783 const int qmlListBehavorClassInfoIndex = metaobject->indexOfClassInfo(
"QML.ListPropertyAssignBehavior");
784 if (qmlListBehavorClassInfoIndex != -1) {
785 const char *overrideBehavior =
786 metaobject->classInfo(qmlListBehavorClassInfoIndex).value();
787 if (!strcmp(overrideBehavior,
789 if (_currentList.clear) {
790 _currentList.clear(&_currentList);
793 bool isDefaultProperty =
794 (property->name(_qobject)
795 == QString::fromUtf8(
797 ->classInfo(metaobject->indexOfClassInfo(
800 if (!isDefaultProperty
801 && (!strcmp(overrideBehavior,
802 "ReplaceIfNotDefault"))) {
803 if (_currentList.clear) {
804 _currentList.clear(&_currentList);
810 }
else if (_currentList.object) {
811 _currentList = QQmlListProperty<QObject>();
812 currentListPropertyIndex = -1;
815 return setPropertyBinding(property, binding);
823 const QV4::CompiledData::Binding *explicitDefaultPropertyBindings =
nullptr;
824 quint32 numExplicitDefaultPropertyBindings = 0;
826 const auto applyExplicitDefaultPropertyBindings = [&]() ->
bool {
827 for (; numExplicitDefaultPropertyBindings > 0; --numExplicitDefaultPropertyBindings) {
828 if (!applyBinding(defaultProperty, explicitDefaultPropertyBindings++))
834 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
835 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
836 const QQmlPropertyData *
const property = propertyData->at(i);
838 const QQmlPropertyData *targetProperty = property;
839 if (targetProperty->isAlias()) {
841 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(),
842 _valueTypeProperty ? _valueTypeProperty->coreIndex()
844 auto [targetObject, targetIndex] =
845 QQmlPropertyPrivate::findAliasTarget(_bindingTarget, originalIndex);
846 QQmlData *data = QQmlData::get(targetObject);
847 Q_ASSERT(data && data->propertyCache);
848 targetProperty = data->propertyCache->property(targetIndex.coreIndex());
849 sharedState->requiredProperties.remove({ targetObject, targetProperty });
851 sharedState->requiredProperties.remove({ _bindingTarget, property });
854 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
857 if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
858 if (!(mode & ApplyDeferred))
860 }
else if (!(mode & ApplyImmediate)) {
866 if (binding->propertyNameIndex != quint32(0)
868 && property == defaultProperty) {
869 if (++numExplicitDefaultPropertyBindings == 1)
870 explicitDefaultPropertyBindings = binding;
876 if (binding->propertyNameIndex == quint32(0)
877 && numExplicitDefaultPropertyBindings > 0
878 && !(binding->location < explicitDefaultPropertyBindings->location)) {
879 if (!applyExplicitDefaultPropertyBindings())
883 if (!applyBinding(property, binding))
888 if (!applyExplicitDefaultPropertyBindings())
890 qSwap(_currentList, savedList);
893bool QQmlObjectCreator::setPropertyBinding(
const QQmlPropertyData *bindingProperty,
const QV4::CompiledData::Binding *binding)
895 const QV4::CompiledData::Binding::Type bindingType = binding->type();
896 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
897 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
898 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
900 Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
901 QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
903 QQmlType attachedType = tr->type();
904 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
905 if (!attachedType.isValid()) {
906 QQmlTypeNameCache::Result res
907 = context->imports()->query(stringAt(binding->propertyNameIndex), typeLoader);
909 attachedType = res.type;
915 sharedState->profiler,
916 profiler.update(compilationUnit.data(), obj, attachedType.qmlTypeName(),
919 QObject *qmlObject = qmlAttachedPropertiesObject(
920 _qobject, attachedType.attachedPropertiesFunction(typeLoader));
922 recordError(binding->location,
923 QStringLiteral(
"Could not create attached properties object '%1'")
924 .arg(QString::fromUtf8(attachedType.typeName())));
928 const size_t objectIndex = sharedState->allCreatedObjects.size();
929 sharedState->allCreatedObjects.push_back(qmlObject);
930 const QQmlType attachedObjectType
931 = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(typeLoader));
932 const int parserStatusCast = attachedObjectType.parserStatusCast();
933 QQmlParserStatus *parserStatus =
nullptr;
934 if (parserStatusCast != -1)
935 parserStatus =
reinterpret_cast<QQmlParserStatus*>(
reinterpret_cast<
char *>(qmlObject) + parserStatusCast);
937 parserStatus->classBegin();
939 sharedState->allParserStatusCallbacks.push_back({objectIndex, parserStatusCast});
942 if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject,
949 if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) {
950 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
951 context->asQQmlContext(), _scopeObject);
952 ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
953 ss.d.data()->lineNumber = binding->location.line();
954 ss.d.data()->columnNumber = binding->location.column();
955 ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String;
956 ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number;
957 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
959 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
960 QQmlPropertyData::RemoveBindingOnAliasWrite;
961 int propertyWriteStatus = -1;
962 void *argv[] = { &ss,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
963 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
967 QObject *createdSubObject =
nullptr;
968 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
971 QScopedValueRollback topLevelRequired(sharedState->hadTopLevelRequiredProperties);
972 int objectIndex = binding->value.objectIndex;
973 if (
const int wrapperIdx = compilationUnit->implicitComponentForObject(objectIndex);
976 objectIndex = wrapperIdx;
978 createdSubObject = createInstance(objectIndex, _bindingTarget);
979 if (!createdSubObject)
983 if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) {
984 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
985 if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
987 QObject *groupObject =
nullptr;
988 QQmlGadgetPtrWrapper *valueType =
nullptr;
989 const QQmlPropertyData *valueTypeProperty =
nullptr;
990 QObject *bindingTarget = _bindingTarget;
991 int groupObjectIndex = binding->value.objectIndex;
993 if (!bindingProperty) {
994 for (
int i = 0, end = compilationUnit->objectCount(); i != end; ++i) {
995 const QV4::CompiledData::Object *external = compilationUnit->objectAt(i);
996 if (external->idNameIndex == binding->propertyNameIndex) {
997 bindingTarget = groupObject = context->idValue(external->objectId());
1003 }
else if (QQmlMetaType::isValueType(bindingProperty->propType())) {
1004 valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
1006 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
1010 valueType->read(_qobject, bindingProperty->coreIndex());
1012 groupObject = valueType;
1013 valueTypeProperty = bindingProperty;
1014 }
else if (bindingProperty->propType().flags() & QMetaType::PointerToQObject) {
1015 void *argv[1] = { &groupObject };
1016 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
1018 QQmlPropertyIndex index(bindingProperty->coreIndex());
1019 auto anyBinding = QQmlAnyBinding::ofProperty(_qobject, index);
1023 anyBinding.refresh();
1024 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
1027 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
1032 bindingTarget = groupObject;
1036 tr(
"Using grouped property syntax on %1 which has no properties")
1037 .arg(stringAt(binding->propertyNameIndex)));
1041 if (!populateInstance(groupObjectIndex, groupObject, bindingTarget, valueTypeProperty,
1048 _qobject, bindingProperty->coreIndex(),
1049 QQmlPropertyData::BypassInterceptor,
1050 QV4::ReferenceObject::AllProperties);
1057 if (!bindingProperty)
1060 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
1061 const bool allowedToRemoveBinding
1062 = !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
1063 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
1064 && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver)
1065 && !_valueTypeProperty;
1067 if (allowedToRemoveBinding) {
1068 if (bindingProperty->acceptsQBinding()) {
1069 removePendingBinding(_bindingTarget, bindingProperty->coreIndex());
1071 QQmlPropertyPrivate::removeBinding(
1072 _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()),
1073 QQmlPropertyPrivate::OverrideSticky);
1077 if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
1078 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
1079 || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) {
1080 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1081 int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
1082 QQmlBoundSignalExpression *expr =
new QQmlBoundSignalExpression(
1083 _bindingTarget, signalIndex, context,
1084 _scopeObject, runtimeFunction, currentQmlContext());
1086 if (bindingProperty->notifiesViaBindable()) {
1087 auto target = _bindingTarget;
1088 if (bindingProperty->isAlias()) {
1093 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1094 auto [aliasTargetObject, aliasTargetIndex] = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1095 target = aliasTargetObject;
1096 QQmlData *data = QQmlData::get(target);
1097 Q_ASSERT(data && data->propertyCache);
1098 bindingProperty = data->propertyCache->property(aliasTargetIndex.coreIndex());
1100 auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
1101 QUntypedBindable bindable;
1102 void *argv[] = { &bindable };
1103 target->qt_metacall(QMetaObject::BindableProperty, bindingProperty->coreIndex(), argv);
1104 Q_ASSERT(bindable.isValid());
1105 bindable.observe(&observer);
1107 QQmlBoundSignal *bs =
new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
1108 bs->takeExpression(expr);
1110 }
else if (bindingProperty->acceptsQBinding()) {
1111 QUntypedPropertyBinding qmlBinding;
1112 if (binding->isTranslationBinding()) {
1113 qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
1115 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1116 QQmlPropertyIndex index(bindingProperty->coreIndex(), -1);
1117 qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index);
1119 sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding });
1121 QQmlData *data = QQmlData::get(_bindingTarget,
true);
1122 data->setBindingBit(_bindingTarget, bindingProperty->coreIndex());
1129 QQmlBinding::Ptr qmlBinding;
1130 const QQmlPropertyData *targetProperty = bindingProperty;
1131 const QQmlPropertyData *subprop =
nullptr;
1132 if (_valueTypeProperty) {
1133 targetProperty = _valueTypeProperty;
1134 subprop = bindingProperty;
1136 if (binding->isTranslationBinding()) {
1137 qmlBinding = QQmlBinding::createTranslationBinding(
1138 compilationUnit, binding, _scopeObject, context);
1140 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1141 qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
1142 context, currentQmlContext());
1145 auto bindingTarget = _bindingTarget;
1146 auto valueTypeProperty = _valueTypeProperty;
1147 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState)
mutable ->
bool {
1148 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, subprop) && targetProperty->isAlias())
1151 sharedState->allCreatedBindings.push_back(qmlBinding);
1153 if (bindingProperty->isAlias()) {
1154 QQmlPropertyPrivate::setBinding(qmlBinding.data(), QQmlPropertyPrivate::DontEnable);
1156 qmlBinding->addToObject();
1158 if (!valueTypeProperty) {
1159 QQmlData *targetDeclarativeData = QQmlData::get(bindingTarget);
1160 Q_ASSERT(targetDeclarativeData);
1161 targetDeclarativeData->setPendingBindingBit(bindingTarget, bindingProperty->coreIndex());
1167 if (!assignBinding(sharedState.data()))
1168 pendingAliasBindings.push_back(assignBinding);
1173 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
1174 if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) {
1176 QQmlType type = qmlTypeForObject(createdSubObject);
1177 Q_ASSERT(type.isValid());
1179 int valueSourceCast = type.propertyValueSourceCast();
1180 if (valueSourceCast != -1) {
1181 QQmlPropertyValueSource *vs =
reinterpret_cast<QQmlPropertyValueSource *>(
reinterpret_cast<
char *>(createdSubObject) + valueSourceCast);
1182 QObject *target = createdSubObject->parent();
1184 if (_valueTypeProperty) {
1185 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
1186 bindingProperty, context);
1188 prop = QQmlPropertyPrivate::restore(target, *bindingProperty,
nullptr, context);
1190 vs->setTarget(prop);
1193 int valueInterceptorCast = type.propertyValueInterceptorCast();
1194 if (valueInterceptorCast != -1) {
1195 QQmlPropertyValueInterceptor *vi =
reinterpret_cast<QQmlPropertyValueInterceptor *>(
reinterpret_cast<
char *>(createdSubObject) + valueInterceptorCast);
1196 QObject *target = createdSubObject->parent();
1198 QQmlPropertyIndex propertyIndex;
1199 if (bindingProperty->isAlias()) {
1200 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1201 auto aliasTarget = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1202 target = aliasTarget.targetObject;
1203 QQmlData *data = QQmlData::get(target);
1204 if (!data || !data->propertyCache) {
1205 qWarning() <<
"can't resolve property alias for 'on' assignment";
1210 QQmlPropertyData targetPropertyData = *data->propertyCache->property(aliasTarget.targetIndex.coreIndex());
1211 auto prop = QQmlPropertyPrivate::restore(
1212 target, targetPropertyData,
nullptr, context);
1213 vi->setTarget(prop);
1214 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1217 if (_valueTypeProperty) {
1218 prop = QQmlPropertyPrivate::restore(
1219 target, *_valueTypeProperty, bindingProperty, context);
1221 prop = QQmlPropertyPrivate::restore(
1222 target, *bindingProperty,
nullptr, context);
1224 vi->setTarget(prop);
1225 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1228 QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
1230 mo =
new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
1231 mo->registerInterceptor(propertyIndex, vi);
1238 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
1239 if (!bindingProperty->isFunction()) {
1240 recordError(binding->valueLocation, tr(
"Cannot assign an object to signal property %1").arg(bindingProperty->name(_qobject)));
1243 QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
1244 if (!method.isValid()) {
1245 recordError(binding->valueLocation, tr(
"Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
1248 qCWarning(lcQmlDefaultMethod) <<
"Assigning an object to a signal handler is deprecated. "
1249 "Instead, create the object, give it an id, and call the desired slot "
1250 "from the signal handler. The object is:" << createdSubObject;
1252 QMetaMethod signalMethod = _qobject->metaObject()->method(bindingProperty->coreIndex());
1253 if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
1254 recordError(binding->valueLocation,
1255 tr(
"Cannot connect mismatched signal/slot %1 vs %2")
1256 .arg(QString::fromUtf8(method.methodSignature()),
1257 QString::fromUtf8(signalMethod.methodSignature())));
1261 QQmlPropertyPrivate::connect(_qobject, bindingProperty->coreIndex(), createdSubObject, method.methodIndex());
1265 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
1266 QQmlPropertyData::RemoveBindingOnAliasWrite;
1267 int propertyWriteStatus = -1;
1268 void *argv[] = {
nullptr,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
1270 if (
const char *iid = QQmlMetaType::interfaceIId(bindingProperty->propType())) {
1271 void *ptr = createdSubObject->qt_metacast(iid);
1274 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1276 recordError(binding->location, tr(
"Cannot assign object to interface property"));
1279 }
else if (bindingProperty->propType() == QMetaType::fromType<QVariant>()) {
1280 if (bindingProperty->isVarProperty()) {
1281 QV4::Scope scope(v4);
1282 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1283 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1285 QVariant value = QVariant::fromValue(createdSubObject);
1287 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1289 }
else if (bindingProperty->propType() == QMetaType::fromType<QJSValue>()) {
1290 QV4::Scope scope(v4);
1291 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1292 if (bindingProperty->isVarProperty()) {
1293 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1296 QJSValuePrivate::setValue(&value, wrappedObject);
1298 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1300 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::IsQmlList)) {
1301 Q_ASSERT(_currentList.object);
1303 QObject *itemToAdd = createdSubObject;
1305 QMetaType listItemType = QQmlMetaType::listValueType(bindingProperty->propType());
1306 if (listItemType.isValid()) {
1307 const char *iid = QQmlMetaType::interfaceIId(listItemType);
1309 itemToAdd =
static_cast<QObject *>(createdSubObject->qt_metacast(iid));
1312 if (_currentList.append)
1313 _currentList.append(&_currentList, itemToAdd);
1315 recordError(binding->location, tr(
"Cannot assign object to read only list"));
1318 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::PointerToQObject)) {
1320 argv[0] = &createdSubObject;
1321 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1323 QVariant target = QQmlValueTypeProvider::createValueType(
1324 QVariant::fromValue(createdSubObject), bindingProperty->propType(), v4);
1325 if (target.isValid())
1326 bindingProperty->writeProperty(_qobject, target.data(), propertyWriteFlags);
1328 recordError(binding->location, tr(
"Cannot construct value type from given object"));
1333 if (bindingProperty->isQList()) {
1334 recordError(binding->location, tr(
"Cannot assign primitives to lists"));
1338 setPropertyValue(bindingProperty, binding);
1342void QQmlObjectCreator::setupFunctions()
1344 QV4::Scope scope(v4);
1345 QV4::ScopedValue function(scope);
1346 QV4::ScopedContext qmlContext(scope, currentQmlContext());
1348 const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
1349 for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1350 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
1351 const QString name = runtimeFunction->name()->toQString();
1353 const QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
1354 if (!property->isVMEFunction())
1357 if (runtimeFunction->isGenerator())
1358 function = QV4::GeneratorFunction::create(qmlContext, runtimeFunction);
1360 function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
1361 _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
1365void QQmlObjectCreator::recordError(
const QV4::CompiledData::Location &location,
const QString &description)
1368 error.setUrl(compilationUnit->url());
1369 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(location.line()));
1370 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(location.column()));
1371 error.setDescription(description);
1375void QQmlObjectCreator::registerObjectWithContextById(
const QV4::CompiledData::Object *object, QObject *instance)
const
1377 if (object->objectId() >= 0)
1378 context->setIdValue(object->objectId(), instance);
1381QObject *QQmlObjectCreator::createInstance(
int index, QObject *parent,
bool isContextObject)
1383 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1384 Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
1385 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
1387 const bool isImplicitComponent = index >= compilationUnit->objectCount();
1388 const InitFlags flags = (isContextObject ? InitFlag::IsContextObject : InitFlag::None)
1389 | (index == 0 ? InitFlag::IsDocumentRoot : InitFlag::None)
1390 | (isImplicitComponent ? InitFlag::IsImplicitComponent : InitFlag::None);
1392 if (obj->hasFlag(QV4::CompiledData::Object::IsComponent) || isImplicitComponent) {
1393 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, QStringLiteral(
"<component>"));
1395 sharedState->profiler,
1397 compilationUnit.data(), obj, QStringLiteral(
"<component>"),
1399 return initializeComponent(
1400 obj, createComponent(engine, compilationUnit.data(), index, parent, context),
1404 const QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
1406 const QQmlType type = typeRef->type();
1407 Q_ASSERT(type.isValid());
1409 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, type.qmlTypeName());
1411 sharedState->profiler,
1412 profiler.update(compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
1414 if (type.isCompositeSingleton()) {
1417 tr(
"Composite Singleton Type %1 is not creatable")
1418 .arg(stringAt(obj->inheritedTypeNameIndex)));
1422 if (!type.isComposite() && !type.isInlineComponentType()) {
1423 if (QObject *instance = type.createWithQQmlData())
1424 return initializeNonComposite(index, obj, typeRef, instance, parent, flags);
1427 tr(
"Unable to create object of type %1").arg(
1428 stringAt(obj->inheritedTypeNameIndex)));
1432 QQmlRefPointer<QV4::ExecutableCompilationUnit> executableCu = typeRef->isSelfReference()
1434 : engine->handle()->executableCompilationUnit(typeRef->compilationUnit());
1435 Q_ASSERT(executableCu);
1437 const bool isInlineComponent = type.isInlineComponentType();
1438 const QString inlineComponentName = isInlineComponent ? type.elementName() : QString();
1439 QQmlObjectCreator subCreator(
1440 context, executableCu, inlineComponentName, sharedState.data(),
1443 if (QObject *instance = isInlineComponent
1444 ? subCreator.create(
1445 executableCu->inlineComponentId(inlineComponentName),
nullptr,
nullptr,
1446 CreationFlags::InlineComponent)
1447 : subCreator.create()) {
1448 return initializeComposite(index, obj, typeRef, instance, parent, flags);
1451 errors += subCreator.errors;
1455void QQmlObjectCreator::initializeDData(
1456 const QV4::CompiledData::Object *obj, QObject *instance, QQmlData *ddata, InitFlags flags)
1458 ddata->lineNumber = obj->location.line();
1459 ddata->columnNumber = obj->location.column();
1460 ddata->setImplicitDestructible();
1464 const bool documentRoot = (flags & InitFlag::IsDocumentRoot)
1465 || ddata->rootObjectInCreation
1466 || obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot);
1468 context->installContext(
1469 ddata, documentRoot ? QQmlContextData::DocumentRoot : QQmlContextData::OrdinaryObject);
1473 if ((flags & (InitFlag::IsContextObject | InitFlag::IsImplicitComponent))
1474 == InitFlag::IsContextObject) {
1475 context->setContextObject(instance);
1479void QQmlObjectCreator::initializePropertyCache(
1480 int index, QQmlData *ddata,
const QV4::ResolvedTypeReference *typeRef)
1482 if (!typeRef->isFullyDynamicType()) {
1483 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(index);
1484 Q_ASSERT(!cache.isNull());
1485 ddata->propertyCache = std::move(cache);
1489void QQmlObjectCreator::initializeParent(QObject *instance, QObject *parent)
1491 if (instance->isWidgetType()) {
1492 if (parent && parent->isWidgetType()) {
1493 QAbstractDeclarativeData::setWidgetParent(instance, parent);
1498 }
else if (parent) {
1499 QQml_setParent_noEvent(instance, parent);
1503QObject *QQmlObjectCreator::populateInstanceAndAliasBindings(
1504 int index, QObject *instance, InitFlags flags)
1506 const auto doPopulate = [&]() {
1507 if (!populateInstance(
1508 index, instance, instance,
nullptr)) {
1510 pendingAliasBindings.clear();
1514 if (!flags.testFlag(InitFlag::IsContextObject))
1517 while (!pendingAliasBindings.empty()) {
1518 for (std::vector<PendingAliasBinding>::iterator it = pendingAliasBindings.begin();
1519 it != pendingAliasBindings.end(); ) {
1520 if ((*it)(sharedState.data()))
1521 it = pendingAliasBindings.erase(it);
1530 QObject *scopeObject = instance;
1531 qSwap(_scopeObject, scopeObject);
1533 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
1534 sharedState->allJavaScriptObjects.trackObject(v4, instance);
1536 QV4::Scope valueScope(v4);
1537 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(valueScope.constructUndefined(1));
1539 qSwap(_qmlContext, qmlContext);
1541 const bool ok = doPopulate();
1543 qSwap(_qmlContext, qmlContext);
1544 qSwap(_scopeObject, scopeObject);
1546 return ok ? instance :
nullptr;
1549QObject *QQmlObjectCreator::initializeComponent(
1550 const QV4::CompiledData::Object *obj, QObject *instance, InitFlags flags)
1555 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1556 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1559 initializeDData(obj, instance, QQmlData::get(instance), flags);
1561 if (!flags.testFlag(InitFlag::IsImplicitComponent))
1562 registerObjectWithContextById(obj, instance);
1566QObject *QQmlObjectCreator::initializeComposite(
1567 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1568 QObject *instance, QObject *parent, InitFlags flags)
1573 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1574 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1576 initializeParent(instance, parent);
1577 QQmlData *ddata = QQmlData::get(instance,
true);
1578 initializeDData(obj, instance, ddata, flags);
1580 initializePropertyCache(index, ddata, typeRef);
1582 return populateInstanceAndAliasBindings(index, instance, flags);
1585QObject *QQmlObjectCreator::initializeNonComposite(
1586 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1587 QObject *instance, QObject *parent, InitFlags flags)
1591 Q_ASSERT(!obj->hasFlag(QV4::CompiledData::Object::IsComponent));
1594 const QQmlType type = typeRef->type();
1595 Q_ASSERT(type.isValid());
1596 Q_ASSERT(!type.isComposite() && !type.isInlineComponentType());
1598 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1600 if (
const int finalizerCast = type.finalizerCast(); finalizerCast != -1) {
1601 const auto hook =
reinterpret_cast<QQmlFinalizerHook *>(
1602 reinterpret_cast<
char *>(instance) + finalizerCast);
1603 sharedState->finalizeHooks.push_back(hook);
1606 QQmlData *ddata = QQmlData::get(instance,
true);
1607 if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
1608 ddata->rootObjectInCreation =
true;
1609 sharedState->rootContext->setRootObjectInCreation(
false);
1612 const size_t instanceIndex = sharedState->allCreatedObjects.size();
1613 sharedState->allCreatedObjects.push_back(instance);
1615 initializeParent(instance, parent);
1616 initializeDData(obj, instance, ddata, flags);
1618 if (
const int parserStatusCast = type.parserStatusCast(); parserStatusCast != -1) {
1619 if (QQmlParserStatus *parserStatus =
reinterpret_cast<QQmlParserStatus*>(
1620 reinterpret_cast<
char *>(instance) + parserStatusCast)) {
1621 parserStatus->classBegin();
1624 Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
1625 sharedState->allParserStatusCallbacks.push_back({ instanceIndex, parserStatusCast });
1629 if (QQmlCustomParser *customParser = type.customParser();
1630 customParser && obj->hasFlag(QV4::CompiledData::Object::HasCustomParserBindings)) {
1631 customParser->engine = QQmlEnginePrivate::get(engine);
1632 customParser->imports = compilationUnit->typeNameCache().data();
1634 QList<
const QV4::CompiledData::Binding *> bindings;
1635 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1636 const QV4::CompiledData::Binding *binding = obj->bindingTable();
1637 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1638 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
1639 bindings << binding;
1641 customParser->applyBindings(instance, compilationUnit, bindings);
1643 customParser->engine =
nullptr;
1644 customParser->imports = (QQmlTypeNameCache*)
nullptr;
1647 initializePropertyCache(index, ddata, typeRef);
1648 return populateInstanceAndAliasBindings(index, instance, flags);
1652
1653
1654
1655
1656
1657QObject *QQmlObjectCreator::createObjectInContext(
1658 int objectIndex, QObject *parent,
1659 const QQmlRefPointer<QQmlContextData> &existingContext)
1661 Q_ASSERT(phase == Startup);
1662 phase = CreatingObjects;
1664 context = existingContext;
1665 if (!sharedState->rootContext)
1666 sharedState->rootContext = context;
1668 QV4::Scope scope(v4);
1669 if (topLevelCreator)
1670 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
1672 QObject *rv = createInstance(objectIndex, parent,
false);
1673 phase = ObjectsCreated;
1677bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1679 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1682 QQmlObjectCreatorRecursionWatcher watcher(
this);
1683 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1698 while (!sharedState->allCreatedBindings.empty()) {
1699 QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.back();
1700 sharedState->allCreatedBindings.pop_back();
1703 if (!b->isAddedToObject())
1705 QQmlData *data = QQmlData::get(b->targetObject());
1707 data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
1708 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
1709 QQmlPropertyData::DontRemoveBinding);
1710 if (b->kind() == QQmlAbstractBinding::QmlBinding) {
1711 QQmlBinding *binding =
static_cast<QQmlBinding*>(b.data());
1712 if (!binding->hasError() && !binding->hasDependencies()
1713 && !binding->hasUnresolvedNames()) {
1714 b->removeFromObject();
1718 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1722 while (!sharedState->allQPropertyBindings.isEmpty()) {
1723 auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first();
1725 QQmlData *data = QQmlData::get(target);
1726 if (!data || !data->hasBindingBit(index)) {
1728 sharedState->allQPropertyBindings.pop_front();
1732 QUntypedBindable bindable;
1733 void *argv[] = { &bindable };
1735 target->metaObject()->metacall(target, QMetaObject::BindableProperty, index, argv);
1736 const bool success = bindable.setBinding(qmlBinding);
1738 const auto bindingPrivateRefCount = QPropertyBindingPrivate::get(qmlBinding)->refCount();
1741 sharedState->allQPropertyBindings.pop_front();
1744 if (success && bindingPrivateRefCount > 1) {
1745 if (
auto priv = QPropertyBindingPrivate::get(qmlBinding); priv->hasCustomVTable()) {
1746 auto qmlBindingPriv =
static_cast<QQmlPropertyBinding *>(priv);
1747 auto jsExpression = qmlBindingPriv->jsExpression();
1748 const bool canRemove = !qmlBinding.error().hasError()
1749 && !qmlBindingPriv->hasDependencies()
1750 && !jsExpression->hasUnresolvedNames();
1752 bindable.takeBinding();
1756 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1760 if (QQmlVME::componentCompleteEnabled()) {
1761 while (!sharedState->allParserStatusCallbacks.empty()) {
1762 QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
1763 const ParserStatus status = sharedState->allParserStatusCallbacks.back();
1764 sharedState->allParserStatusCallbacks.pop_back();
1766 const QQmlGuard<QObject> &instance = sharedState->allCreatedObjects[status.objectIndex];
1770 QQmlParserStatus *parserStatus
1771 =
reinterpret_cast<QQmlParserStatus *>(
1772 reinterpret_cast<
char *>(instance.data()) + status.parserStatusCast);
1773 parserStatus->componentComplete();
1775 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1780 for (QQmlFinalizerHook *hook: std::as_const(sharedState->finalizeHooks)) {
1781 hook->componentFinalized();
1782 if (watcher.hasRecursed())
1785 sharedState->finalizeHooks.clear();
1787 while (sharedState->componentAttached) {
1788 QQmlComponentAttached *a = sharedState->componentAttached;
1789 a->removeFromList();
1790 QQmlData *d = QQmlData::get(a->parent());
1792 Q_ASSERT(d->context);
1793 d->context->addComponentAttached(a);
1794 if (QQmlVME::componentCompleteEnabled())
1795 emit a->completed();
1797 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1806void QQmlObjectCreator::clear()
1808 if (phase == Done || phase == Finalizing || phase == Startup)
1810 Q_ASSERT(phase != Startup);
1812 while (!sharedState->allCreatedObjects.empty()) {
1813 auto object = sharedState->allCreatedObjects.back();
1814 sharedState->allCreatedObjects.pop_back();
1815 if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
1820 while (sharedState->componentAttached) {
1821 QQmlComponentAttached *a = sharedState->componentAttached;
1822 a->removeFromList();
1828void QQmlObjectCreator::registerPostHocRequiredProperties(
const QV4::CompiledData::Binding *binding)
1830 const qsizetype oldRequiredPropertiesCount = sharedState->requiredProperties.size();
1831 QSet<QString> postHocRequired;
1832 for (
auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
1833 postHocRequired.insert(stringAt(it->nameIndex));
1834 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1836 for (
int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
1837 const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
1838 const QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
1840 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex()));
1841 if (!property->isRequired() && postHocRequired.end() == postHocIt)
1843 if (postHocIt != postHocRequired.end())
1844 postHocRequired.erase(postHocIt);
1845 if (isContextObject)
1846 sharedState->hadTopLevelRequiredProperties =
true;
1847 sharedState->requiredProperties.insert({_qobject, propertyData},
1848 RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex()), compilationUnit->finalUrl(), property->location, {}});
1852 const auto getPropertyCacheRange = [&]() -> std::pair<
int,
int> {
1870 QV4::ResolvedTypeReference *typeRef = resolvedType(_compiledObject->inheritedTypeNameIndex);
1873 if (binding->isAttachedProperty())
1874 return { 0, _propertyCache->propertyCount() };
1875 Q_ASSERT(binding->isGroupProperty());
1876 return { 0, _propertyCache->propertyOffset() + 1 };
1878 Q_ASSERT(!_compiledObject->hasFlag(QV4::CompiledData::Object::IsComponent));
1879 QQmlType type = typeRef->type();
1880 if (type.isComposite() || type.isInlineComponentType())
1881 return { _propertyCache->propertyOffset(), _propertyCache->propertyCount() };
1882 return { 0, _propertyCache->propertyCount() };
1884 const auto [offset, count] = getPropertyCacheRange();
1885 for (
int i = offset; i < count; ++i) {
1886 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1892 if (!propertyData->isRequired() && postHocRequired.isEmpty())
1894 QString name = propertyData->name(_qobject);
1895 const auto postHocIt = postHocRequired.constFind(name);
1896 if (postHocIt == postHocRequired.constEnd()) {
1897 if (!propertyData->isRequired())
1900 postHocRequired.erase(postHocIt);
1903 if (isContextObject)
1904 sharedState->hadTopLevelRequiredProperties =
true;
1905 sharedState->requiredProperties.insert(
1906 {_qobject, propertyData},
1907 RequiredPropertyInfo {
1908 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1912 if (binding && binding->isAttachedProperty()
1913 && sharedState->requiredProperties.size() != oldRequiredPropertiesCount) {
1916 QLatin1String(
"Attached property has required properties. This is not supported"));
1923 if (!postHocRequired.isEmpty()) {
1925 for (
int i = 0; i < offset; ++i) {
1926 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1929 QString name = propertyData->name(_qobject);
1930 const auto postHocIt = postHocRequired.constFind(name);
1931 if (postHocIt == postHocRequired.constEnd())
1933 postHocRequired.erase(postHocIt);
1935 if (isContextObject)
1936 sharedState->hadTopLevelRequiredProperties =
true;
1937 sharedState->requiredProperties.insert(
1938 {_qobject, propertyData},
1939 RequiredPropertyInfo {
1940 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1945 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1946 recordError({}, QLatin1String(
"Property %1 was marked as required but does not exist").arg(*postHocRequired.begin()));
1949bool QQmlObjectCreator::populateInstance(
int index, QObject *instance, QObject *bindingTarget,
1950 const QQmlPropertyData *valueTypeProperty,
1951 const QV4::CompiledData::Binding *binding)
1954 QQmlData *declarativeData = QQmlData::get(instance,
true);
1956 qSwap(_qobject, instance);
1957 qSwap(_valueTypeProperty, valueTypeProperty);
1958 qSwap(_compiledObjectIndex, index);
1959 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
1960 qSwap(_compiledObject, obj);
1961 qSwap(_ddata, declarativeData);
1962 qSwap(_bindingTarget, bindingTarget);
1964 QV4::Scope valueScope(v4);
1965 QV4::ScopedValue scopeObjectProtector(valueScope);
1967 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
1969 QQmlVMEMetaObject *vmeMetaObject =
nullptr;
1970 if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) {
1971 Q_ASSERT(!cache.isNull());
1973 vmeMetaObject =
new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
1974 _ddata->propertyCache = cache;
1975 scopeObjectProtector = _ddata->jsWrapper.value();
1977 vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
1980 registerObjectWithContextById(_compiledObject, _qobject);
1982 qSwap(_propertyCache, cache);
1983 qSwap(_vmeMetaObject, vmeMetaObject);
1988 if (!stringAt(_compiledObject->inheritedTypeNameIndex).isEmpty()) {
1989 _ddata->compilationUnit = compilationUnit;
1990 _ddata->cuObjectIndex =
int(_compiledObjectIndex);
1993 if (_compiledObject->hasFlag(QV4::CompiledData::Object::HasDeferredBindings))
1994 _ddata->deferData(_compiledObjectIndex, compilationUnit, context, m_inlineComponentName);
1996 registerPostHocRequiredProperties(binding);
1998 if (_compiledObject->nFunctions > 0)
2000 setupBindings((binding && binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding))
2001 ? BindingMode::ApplyAll
2002 : BindingMode::ApplyImmediate);
2004 for (
int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
2009 _vmeMetaObject->connectAlias(_compiledObject, aliasIndex);
2010 if (!context->isIdValueSet(0))
2012 const QQmlPropertyData *aliasProperty =
2013 _propertyCache->property(_vmeMetaObject->aliasOffset() + aliasIndex);
2016 QObject *target = context->idValue(aliasProperty->aliasTargetObjectId());
2019 QQmlData *targetDData = QQmlData::get(target,
false);
2020 if (targetDData ==
nullptr || targetDData->propertyCache.isNull())
2023 const int targetPropertyIndex = aliasProperty->aliasTarget();
2024 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
2026 const QQmlPropertyData *
const targetProperty = targetDData->propertyCache->property(coreIndex);
2027 if (!targetProperty)
2029 auto it = sharedState->requiredProperties.find({target, targetProperty});
2030 if (it != sharedState->requiredProperties.end()) {
2031 const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
2032 it->aliasesToRequired.push_back(
2033 AliasToRequiredInfo {
2034 compilationUnit->stringAt(alias->nameIndex()),
2035 compilationUnit->finalUrl()
2040 qSwap(_vmeMetaObject, vmeMetaObject);
2041 qSwap(_bindingTarget, bindingTarget);
2042 qSwap(_ddata, declarativeData);
2043 qSwap(_compiledObject, obj);
2044 qSwap(_compiledObjectIndex, index);
2045 qSwap(_valueTypeProperty, valueTypeProperty);
2046 qSwap(_qobject, instance);
2047 qSwap(_propertyCache, cache);
2049 return errors.isEmpty();
2053
2054
2055QQmlComponent *QQmlObjectCreator::createComponent(
2056 QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit,
int index,
2057 QObject *parent,
const QQmlRefPointer<QQmlContextData> &context)
2059 QQmlComponent *component =
new QQmlComponent(engine, compilationUnit, index, parent);
2060 QQmlComponentPrivate::get(component)->setCreationContext(context);
2061 QQmlData *ddata = QQmlData::get(component,
true);
2063 ddata->compilationUnit = compilationUnit;
2064 ddata->cuObjectIndex = index;
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081void QQmlObjectCreator::repopulateBindings(
2082 int index, QObject *instance,
2083 const QQmlRefPointer<QQmlContextData> &instanceContext, InitFlags flags)
2085 phase = QQmlObjectCreator::ObjectsCreated;
2088 if (compilationUnit->objectCount() <= index)
2091 const auto oldContext = std::exchange(context, instanceContext);
2092 const auto contextGuard = qScopeGuard([&]() {
2093 context = oldContext;
2096 auto rootContextGuard = qScopeGuard([&]() {
2097 sharedState->rootContext.reset();
2099 if (!sharedState->rootContext)
2100 sharedState->rootContext = context;
2102 rootContextGuard.dismiss();
2104 QV4::Scope scope(engine->handle());
2105 auto jsObjectsGuard = qScopeGuard([&]() {
2106 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
2108 if (!sharedState->allJavaScriptObjects.canTrack())
2109 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
2111 jsObjectsGuard.dismiss();
2113 QQmlData *ddata = QQmlData::get(instance,
true);
2116 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(instance);
2118 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
2121 qSwap(_qobject, instance);
2122 qSwap(_compiledObjectIndex, index);
2123 qSwap(_compiledObject, obj);
2124 qSwap(_ddata, ddata);
2125 QObject *bindingTarget = _qobject;
2126 qSwap(_bindingTarget, bindingTarget);
2127 QObject *scopeObject = _qobject;
2128 qSwap(_scopeObject, scopeObject);
2129 const QQmlPropertyData *valueTypeProperty =
nullptr;
2130 qSwap(_valueTypeProperty, valueTypeProperty);
2132 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
2133 sharedState->allJavaScriptObjects.trackObject(v4, _qobject);
2135 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(scope.constructUndefined(1));
2136 qSwap(_qmlContext, qmlContext);
2138 QV4::ScopedValue scopeObjectProtector(scope);
2140 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
2141 _ddata->propertyCache = cache;
2142 qSwap(_propertyCache, cache);
2143 qSwap(_vmeMetaObject, vmeMetaObject);
2145 if (_compiledObject->objectId() < context->numIdValues())
2146 registerObjectWithContextById(_compiledObject, _qobject);
2148 _ddata->compilationUnit = compilationUnit;
2149 _ddata->cuObjectIndex =
int(_compiledObjectIndex);
2151 if (_compiledObject->nFunctions > 0)
2153 setupBindings(BindingMode::ApplyImmediate);
2155 if (flags.testFlag(InitFlag::IsContextObject)) {
2156 while (!pendingAliasBindings.empty()) {
2157 for (
auto it = pendingAliasBindings.begin(); it != pendingAliasBindings.end();) {
2158 if ((*it)(sharedState.data()))
2159 it = pendingAliasBindings.erase(it);
2167 qSwap(_vmeMetaObject, vmeMetaObject);
2168 qSwap(_propertyCache, cache);
2169 qSwap(_qmlContext, qmlContext);
2170 qSwap(_scopeObject, scopeObject);
2171 qSwap(_valueTypeProperty, valueTypeProperty);
2172 qSwap(_bindingTarget, bindingTarget);
2173 qSwap(_ddata, ddata);
2174 qSwap(_compiledObject, obj);
2175 qSwap(_compiledObjectIndex, index);
2176 qSwap(_qobject, instance);
2185void ObjectInCreationGCAnchorList::trackObject(QV4::ExecutionEngine *engine, QObject *instance)
2187 QV4::Value *wrapper = allocationScope->construct(1, QV4::QObjectWrapper::wrap(engine, instance));
2191 QV4::WriteBarrier::markCustom(engine, [wrapper](QV4::MarkStack *ms) {
2192 wrapper->heapObject()->mark(ms);
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static QQmlType qmlTypeForObject(QObject *object)
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)