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 const QV4::CompiledData::Object *compObj = compilationUnit->objectAt(subComponentIndex);
175 objectToCreate = compObj->bindingTable()->value.objectIndex;
179 context = QQmlEnginePrivate::get(engine)->createInternalContext(
180 compilationUnit, parentContext, subComponentIndex, isComponentRoot);
182 if (!sharedState->rootContext) {
183 sharedState->rootContext = context;
184 sharedState->rootContext->setIncubator(incubator);
185 sharedState->rootContext->setRootObjectInCreation(
true);
188 QV4::Scope scope(v4);
190 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack() || topLevelCreator);
192 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
194 if (!isComponentRoot && sharedState->creationContext) {
196 QV4::ScopedValue scripts(scope, sharedState->creationContext->importedScripts());
197 context->setImportedScripts(v4, scripts);
200 QObject *instance = createInstance(objectToCreate, parent,
true);
202 QQmlData *ddata = QQmlData::get(instance);
204 ddata->compilationUnit = compilationUnit;
208 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
210 phase = CreatingObjectsPhase2;
212 if (interrupt && interrupt->shouldInterrupt())
215 phase = ObjectsCreated;
218 if (QQmlEngineDebugService *service
219 = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
220 if (!parentContext->isInternal())
221 parentContext->asQQmlContextPrivate()->appendInstance(instance);
222 service->objectCreated(engine, instance);
223 }
else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
224 parentContext->asQQmlContextPrivate()->appendInstance(instance);
231void QQmlObjectCreator::beginPopulateDeferred(
const QQmlRefPointer<QQmlContextData> &newContext)
233 context = newContext;
234 sharedState->rootContext = newContext;
236 Q_ASSERT(topLevelCreator);
237 Q_ASSERT(!sharedState->allJavaScriptObjects.canTrack());
240 QV4::Scope valueScope(v4);
241 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(valueScope);
244void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex,
245 const QQmlPropertyPrivate *qmlProperty,
246 const QV4::CompiledData::Binding *binding)
248 doPopulateDeferred(instance, deferredIndex, [
this, qmlProperty, binding]() {
249 Q_ASSERT(qmlProperty);
250 Q_ASSERT(binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding));
252 QQmlListProperty<QObject> savedList;
253 qSwap(_currentList, savedList);
255 const QQmlPropertyData &property = qmlProperty->core;
257 if (property.propType().flags().testFlag(QMetaType::IsQmlList)) {
258 void *argv[1] = { (
void*)&_currentList };
259 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
260 }
else if (_currentList.object) {
261 _currentList = QQmlListProperty<QObject>();
264 setPropertyBinding(&property, binding);
266 qSwap(_currentList, savedList);
270void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex)
272 doPopulateDeferred(instance, deferredIndex, [
this]() { setupBindings(ApplyDeferred); });
275bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
276 const QQmlData::DeferredData *deferredData)
278 beginPopulateDeferred(deferredData->context);
279 populateDeferred(instance, deferredData->deferredIdx);
280 finalizePopulateDeferred();
281 return errors.isEmpty();
284void QQmlObjectCreator::populateDeferredBinding(
const QQmlProperty &qmlProperty,
int deferredIndex,
285 const QV4::CompiledData::Binding *binding)
288 populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
291 populateDeferred(qmlProperty.object(), deferredIndex);
295void QQmlObjectCreator::populateDeferredInstance(
296 QObject *outerObject,
int deferredIndex,
int index, QObject *instance,
297 QObject *bindingTarget,
const QQmlPropertyData *valueTypeProperty,
298 const QV4::CompiledData::Binding *binding)
300 doPopulateDeferred(outerObject, deferredIndex, [&]() {
301 populateInstance(index, instance, bindingTarget, valueTypeProperty, binding);
305void QQmlObjectCreator::finalizePopulateDeferred()
307 phase = ObjectsCreated;
310void QQmlObjectCreator::setPropertyValue(
const QQmlPropertyData *property,
const QV4::CompiledData::Binding *binding)
312 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
313 QV4::Scope scope(v4);
315 QMetaType propertyType = property->propType();
317 if (property->isEnum()) {
318 if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum) ||
321 (property->isAlias() && binding->isNumberBinding())) {
322 propertyType = property->propType().underlyingType();
325 QVariant value = compilationUnit->bindingValueAsString(binding);
326 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
333 auto assertOrNull = [&](
bool ok)
335 Q_ASSERT(ok || binding->type() == QV4::CompiledData::Binding::Type_Null);
339 auto assertType = [&](QV4::CompiledData::Binding::Type type)
341 Q_ASSERT(binding->type()== type || binding->type() == QV4::CompiledData::Binding::Type_Null);
345 if (property->isQObject()) {
346 if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
347 QObject *value =
nullptr;
348 const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags);
355 switch (propertyType.id()) {
356 case QMetaType::QVariant: {
357 if (binding->type() == QV4::CompiledData::Binding::Type_Number) {
358 double n = compilationUnit->bindingValueAsNumber(binding);
359 if (
double(
int(n)) == n) {
360 if (property->isVarProperty()) {
361 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(
int(n)));
365 property->writeProperty(_qobject, &value, propertyWriteFlags);
368 if (property->isVarProperty()) {
369 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromDouble(n));
372 property->writeProperty(_qobject, &value, propertyWriteFlags);
375 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Boolean) {
376 if (property->isVarProperty()) {
377 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean()));
379 QVariant value(binding->valueAsBoolean());
380 property->writeProperty(_qobject, &value, propertyWriteFlags);
382 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
383 if (property->isVarProperty()) {
384 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue());
386 QVariant nullValue = QVariant::fromValue(
nullptr);
387 property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
390 QString stringValue = compilationUnit->bindingValueAsString(binding);
391 if (property->isVarProperty()) {
392 QV4::ScopedString s(scope, v4->newString(stringValue));
393 _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
395 QVariant value = stringValue;
396 property->writeProperty(_qobject, &value, propertyWriteFlags);
401 case QMetaType::QString: {
402 assertOrNull(binding->evaluatesToString());
403 QString value = compilationUnit->bindingValueAsString(binding);
404 property->writeProperty(_qobject, &value, propertyWriteFlags);
407 case QMetaType::QStringList: {
408 assertOrNull(binding->evaluatesToString());
409 QStringList value(compilationUnit->bindingValueAsString(binding));
410 property->writeProperty(_qobject, &value, propertyWriteFlags);
413 case QMetaType::QByteArray: {
414 assertType(QV4::CompiledData::Binding::Type_String);
415 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
416 property->writeProperty(_qobject, &value, propertyWriteFlags);
419 case QMetaType::QUrl: {
420 assertType(QV4::CompiledData::Binding::Type_String);
421 const QString string = compilationUnit->bindingValueAsString(binding);
422 QUrl value = (!string.isEmpty() && QQmlPropertyPrivate::resolveUrlsOnAssignment())
423 ? compilationUnit->finalUrl().resolved(QUrl(string))
425 property->writeProperty(_qobject, &value, propertyWriteFlags);
428 case QMetaType::UInt: {
429 assertType(QV4::CompiledData::Binding::Type_Number);
430 double d = compilationUnit->bindingValueAsNumber(binding);
431 uint value = uint(d);
432 property->writeProperty(_qobject, &value, propertyWriteFlags);
436 case QMetaType::Int: {
437 assertType(QV4::CompiledData::Binding::Type_Number);
438 double d = compilationUnit->bindingValueAsNumber(binding);
440 property->writeProperty(_qobject, &value, propertyWriteFlags);
444 case QMetaType::SChar: {
445 assertType(QV4::CompiledData::Binding::Type_Number);
446 double d = compilationUnit->bindingValueAsNumber(binding);
447 qint8 value = qint8(d);
448 property->writeProperty(_qobject, &value, propertyWriteFlags);
451 case QMetaType::UChar: {
452 assertType(QV4::CompiledData::Binding::Type_Number);
453 double d = compilationUnit->bindingValueAsNumber(binding);
454 quint8 value = quint8(d);
455 property->writeProperty(_qobject, &value, propertyWriteFlags);
458 case QMetaType::Short: {
459 assertType(QV4::CompiledData::Binding::Type_Number);
460 double d = compilationUnit->bindingValueAsNumber(binding);
461 qint16 value = qint16(d);
462 property->writeProperty(_qobject, &value, propertyWriteFlags);
465 case QMetaType::UShort: {
466 assertType(QV4::CompiledData::Binding::Type_Number);
467 double d = compilationUnit->bindingValueAsNumber(binding);
468 quint16 value = quint16(d);
469 property->writeProperty(_qobject, &value, propertyWriteFlags);
472 case QMetaType::LongLong: {
473 assertType(QV4::CompiledData::Binding::Type_Number);
474 double d = compilationUnit->bindingValueAsNumber(binding);
475 qint64 value = qint64(d);
476 property->writeProperty(_qobject, &value, propertyWriteFlags);
479 case QMetaType::ULongLong: {
480 assertType(QV4::CompiledData::Binding::Type_Number);
481 double d = compilationUnit->bindingValueAsNumber(binding);
482 quint64 value = quint64(d);
483 property->writeProperty(_qobject, &value, propertyWriteFlags);
487 case QMetaType::Float: {
488 assertType(QV4::CompiledData::Binding::Type_Number);
489 float value =
float(compilationUnit->bindingValueAsNumber(binding));
490 property->writeProperty(_qobject, &value, propertyWriteFlags);
493 case QMetaType::Double: {
494 assertType(QV4::CompiledData::Binding::Type_Number);
495 double value = compilationUnit->bindingValueAsNumber(binding);
496 property->writeProperty(_qobject, &value, propertyWriteFlags);
499 case QMetaType::QColor: {
501 QVariant data = QQmlStringConverters::colorFromString(
502 compilationUnit->bindingValueAsString(binding), &ok);
504 property->writeProperty(_qobject, data.data(), propertyWriteFlags);
507#if QT_CONFIG(datestring)
508 case QMetaType::QDate: {
510 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
512 property->writeProperty(_qobject, &value, propertyWriteFlags);
515 case QMetaType::QTime: {
517 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
519 property->writeProperty(_qobject, &value, propertyWriteFlags);
522 case QMetaType::QDateTime: {
524 QDateTime value = QQmlStringConverters::dateTimeFromString(
525 compilationUnit->bindingValueAsString(binding), &ok);
527 property->writeProperty(_qobject, &value, propertyWriteFlags);
531 case QMetaType::QPoint: {
533 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
535 property->writeProperty(_qobject, &value, propertyWriteFlags);
538 case QMetaType::QPointF: {
540 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
542 property->writeProperty(_qobject, &value, propertyWriteFlags);
545 case QMetaType::QSize: {
547 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
549 property->writeProperty(_qobject, &value, propertyWriteFlags);
552 case QMetaType::QSizeF: {
554 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
556 property->writeProperty(_qobject, &value, propertyWriteFlags);
559 case QMetaType::QRect: {
561 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
563 property->writeProperty(_qobject, &value, propertyWriteFlags);
566 case QMetaType::QRectF: {
568 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
570 property->writeProperty(_qobject, &value, propertyWriteFlags);
573 case QMetaType::Bool: {
574 assertType(QV4::CompiledData::Binding::Type_Boolean);
575 bool value = binding->valueAsBoolean();
576 property->writeProperty(_qobject, &value, propertyWriteFlags);
579 case QMetaType::QVector2D:
580 case QMetaType::QVector3D:
581 case QMetaType::QVector4D:
582 case QMetaType::QQuaternion: {
583 QVariant result = QQmlValueTypeProvider::createValueType(
584 compilationUnit->bindingValueAsString(binding), propertyType);
585 assertOrNull(result.isValid());
586 property->writeProperty(_qobject, result.data(), propertyWriteFlags);
591 if (propertyType == QMetaType::fromType<QList<qreal>>()) {
592 assertType(QV4::CompiledData::Binding::Type_Number);
594 value.append(compilationUnit->bindingValueAsNumber(binding));
595 property->writeProperty(_qobject, &value, propertyWriteFlags);
597 }
else if (propertyType == QMetaType::fromType<QList<
int>>()) {
598 assertType(QV4::CompiledData::Binding::Type_Number);
599 double n = compilationUnit->bindingValueAsNumber(binding);
601 value.append(
int(n));
602 property->writeProperty(_qobject, &value, propertyWriteFlags);
604 }
else if (propertyType == QMetaType::fromType<QList<
bool>>()) {
605 assertType(QV4::CompiledData::Binding::Type_Boolean);
607 value.append(binding->valueAsBoolean());
608 property->writeProperty(_qobject, &value, propertyWriteFlags);
610 }
else if (propertyType == QMetaType::fromType<QList<QUrl>>()) {
611 assertType(QV4::CompiledData::Binding::Type_String);
612 const QUrl url(compilationUnit->bindingValueAsString(binding));
614 QQmlPropertyPrivate::resolveUrlsOnAssignment()
615 ? compilationUnit->finalUrl().resolved(url)
618 property->writeProperty(_qobject, &value, propertyWriteFlags);
620 }
else if (propertyType == QMetaType::fromType<QList<QString>>()) {
621 assertOrNull(binding->evaluatesToString());
622 QList<QString> value;
623 value.append(compilationUnit->bindingValueAsString(binding));
624 property->writeProperty(_qobject, &value, propertyWriteFlags);
626 }
else if (propertyType == QMetaType::fromType<QJSValue>()) {
628 switch (binding->type()) {
629 case QV4::CompiledData::Binding::Type_Boolean:
630 value = QJSValue(binding->valueAsBoolean());
632 case QV4::CompiledData::Binding::Type_Number: {
633 const double n = compilationUnit->bindingValueAsNumber(binding);
634 if (
double(
int(n)) == n)
635 value = QJSValue(
int(n));
640 case QV4::CompiledData::Binding::Type_Null:
641 value = QJSValue::NullValue;
644 value = QJSValue(compilationUnit->bindingValueAsString(binding));
647 property->writeProperty(_qobject, &value, propertyWriteFlags);
651 switch (binding->type()) {
652 case QV4::CompiledData::Binding::Type_Boolean:
653 source = binding->valueAsBoolean();
655 case QV4::CompiledData::Binding::Type_Number: {
656 const double n = compilationUnit->bindingValueAsNumber(binding);
657 if (
double(
int(n)) == n)
663 case QV4::CompiledData::Binding::Type_Null:
664 source = QVariant::fromValue<std::nullptr_t>(
nullptr);
666 case QV4::CompiledData::Binding::Type_Invalid:
669 source = compilationUnit->bindingValueAsString(binding);
673 QVariant target = QQmlValueTypeProvider::createValueType(
674 source, propertyType, engine->handle());
675 if (target.isValid()) {
676 property->writeProperty(_qobject, target.data(), propertyWriteFlags);
682 QString stringValue = compilationUnit->bindingValueAsString(binding);
683 QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
684 recordError(binding->location, tr(
"Cannot assign value %1 to property"
685" %2").arg(stringValue, QString::fromUtf8(metaProperty.name())));
694 const QMetaObject *mo = object->metaObject();
695 while (mo && !type.isValid()) {
696 type = QQmlMetaType::qmlType(mo);
697 mo = mo->superClass();
702void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
704 QQmlListProperty<QObject> savedList;
705 qSwap(_currentList, savedList);
707 const QV4::CompiledData::BindingPropertyData *propertyData
708 = compilationUnit->bindingPropertyDataPerObjectAt(_compiledObjectIndex);
710 if (_compiledObject->idNameIndex) {
711 const QQmlPropertyData *idProperty = propertyData->last();
712 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String(
"id"));
713 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) {
714 QV4::CompiledData::Binding idBinding;
715 idBinding.propertyNameIndex = 0;
716 idBinding.clearFlags();
717 idBinding.setType(QV4::CompiledData::Binding::Type_String);
718 idBinding.stringIndex = _compiledObject->idNameIndex;
719 idBinding.location = _compiledObject->location;
720 idBinding.value.nullMarker = 0;
721 setPropertyValue(idProperty, &idBinding);
726 if (_valueTypeProperty) {
727 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
729 if (binding && binding->kind() != QQmlAbstractBinding::ValueTypeProxy) {
730 QQmlPropertyPrivate::removeBinding(
731 _bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()),
732 QQmlPropertyPrivate::OverrideSticky);
733 }
else if (binding) {
734 QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
736 if (qmlTypeForObject(_bindingTarget).isValid()) {
737 quint32 bindingSkipList = 0;
739 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
741 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
742 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
743 const QQmlPropertyData *property = binding->propertyNameIndex != 0
744 ? _propertyCache->property(stringAt(binding->propertyNameIndex),
748 bindingSkipList |= (1 << property->coreIndex());
751 proxy->removeBindings(bindingSkipList);
756 int currentListPropertyIndex = -1;
758 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
759 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
760 const QQmlPropertyData *
const property = propertyData->at(i);
762 const QQmlPropertyData *targetProperty = property;
763 if (targetProperty->isAlias()) {
765 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
766 auto [targetObject, targetIndex] = QQmlPropertyPrivate::findAliasTarget(_bindingTarget, originalIndex);
767 QQmlData *data = QQmlData::get(targetObject);
768 Q_ASSERT(data && data->propertyCache);
769 targetProperty = data->propertyCache->property(targetIndex.coreIndex());
770 sharedState->requiredProperties.remove({targetObject, targetProperty});
772 sharedState->requiredProperties.remove({_bindingTarget, property});
776 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
779 if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
780 if (!(mode & ApplyDeferred))
782 }
else if (!(mode & ApplyImmediate)) {
786 if (property && property->propType().flags().testFlag(QMetaType::IsQmlList)) {
787 if (property->coreIndex() != currentListPropertyIndex) {
788 void *argv[1] = { (
void*)&_currentList };
789 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
790 currentListPropertyIndex = property->coreIndex();
793 const QMetaObject *
const metaobject = _qobject->metaObject();
794 const int qmlListBehavorClassInfoIndex = metaobject->indexOfClassInfo(
"QML.ListPropertyAssignBehavior");
795 if (qmlListBehavorClassInfoIndex != -1) {
796 const char *overrideBehavior =
797 metaobject->classInfo(qmlListBehavorClassInfoIndex).value();
798 if (!strcmp(overrideBehavior,
800 if (_currentList.clear) {
801 _currentList.clear(&_currentList);
804 bool isDefaultProperty =
805 (property->name(_qobject)
806 == QString::fromUtf8(
808 ->classInfo(metaobject->indexOfClassInfo(
811 if (!isDefaultProperty
812 && (!strcmp(overrideBehavior,
813 "ReplaceIfNotDefault"))) {
814 if (_currentList.clear) {
815 _currentList.clear(&_currentList);
821 }
else if (_currentList.object) {
822 _currentList = QQmlListProperty<QObject>();
823 currentListPropertyIndex = -1;
826 if (!setPropertyBinding(property, binding))
830 qSwap(_currentList, savedList);
833bool QQmlObjectCreator::setPropertyBinding(
const QQmlPropertyData *bindingProperty,
const QV4::CompiledData::Binding *binding)
835 const QV4::CompiledData::Binding::Type bindingType = binding->type();
836 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
837 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
838 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
840 Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
841 QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
843 QQmlType attachedType = tr->type();
844 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
845 if (!attachedType.isValid()) {
846 QQmlTypeNameCache::Result res
847 = context->imports()->query(stringAt(binding->propertyNameIndex), typeLoader);
849 attachedType = res.type;
855 sharedState->profiler,
856 profiler.update(compilationUnit.data(), obj, attachedType.qmlTypeName(),
859 QObject *qmlObject = qmlAttachedPropertiesObject(
860 _qobject, attachedType.attachedPropertiesFunction(typeLoader));
862 recordError(binding->location,
863 QStringLiteral(
"Could not create attached properties object '%1'")
864 .arg(QString::fromUtf8(attachedType.typeName())));
868 const size_t objectIndex = sharedState->allCreatedObjects.size();
869 sharedState->allCreatedObjects.push_back(qmlObject);
870 const QQmlType attachedObjectType
871 = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(typeLoader));
872 const int parserStatusCast = attachedObjectType.parserStatusCast();
873 QQmlParserStatus *parserStatus =
nullptr;
874 if (parserStatusCast != -1)
875 parserStatus =
reinterpret_cast<QQmlParserStatus*>(
reinterpret_cast<
char *>(qmlObject) + parserStatusCast);
877 parserStatus->classBegin();
879 sharedState->allParserStatusCallbacks.push_back({objectIndex, parserStatusCast});
882 if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject,
889 if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) {
890 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
891 context->asQQmlContext(), _scopeObject);
892 ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
893 ss.d.data()->lineNumber = binding->location.line();
894 ss.d.data()->columnNumber = binding->location.column();
895 ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String;
896 ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number;
897 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
899 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
900 QQmlPropertyData::RemoveBindingOnAliasWrite;
901 int propertyWriteStatus = -1;
902 void *argv[] = { &ss,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
903 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
907 QObject *createdSubObject =
nullptr;
908 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
911 QScopedValueRollback topLevelRequired(sharedState->hadTopLevelRequiredProperties);
912 createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
913 if (!createdSubObject)
917 if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) {
918 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
919 if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
921 QObject *groupObject =
nullptr;
922 QQmlGadgetPtrWrapper *valueType =
nullptr;
923 const QQmlPropertyData *valueTypeProperty =
nullptr;
924 QObject *bindingTarget = _bindingTarget;
925 int groupObjectIndex = binding->value.objectIndex;
927 if (!bindingProperty) {
928 for (
int i = 0, end = compilationUnit->objectCount(); i != end; ++i) {
929 const QV4::CompiledData::Object *external = compilationUnit->objectAt(i);
930 if (external->idNameIndex == binding->propertyNameIndex) {
931 bindingTarget = groupObject = context->idValue(external->objectId());
937 }
else if (QQmlMetaType::isValueType(bindingProperty->propType())) {
938 valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
940 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
944 valueType->read(_qobject, bindingProperty->coreIndex());
946 groupObject = valueType;
947 valueTypeProperty = bindingProperty;
948 }
else if (bindingProperty->propType().flags() & QMetaType::PointerToQObject) {
949 void *argv[1] = { &groupObject };
950 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
952 QQmlPropertyIndex index(bindingProperty->coreIndex());
953 auto anyBinding = QQmlAnyBinding::ofProperty(_qobject, index);
957 anyBinding.refresh();
958 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
961 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
966 bindingTarget = groupObject;
970 tr(
"Using grouped property syntax on %1 which has no properties")
971 .arg(stringAt(binding->propertyNameIndex)));
975 if (!populateInstance(groupObjectIndex, groupObject, bindingTarget, valueTypeProperty,
982 _qobject, bindingProperty->coreIndex(),
983 QQmlPropertyData::BypassInterceptor,
984 QV4::ReferenceObject::AllProperties);
991 if (!bindingProperty)
994 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
995 const bool allowedToRemoveBinding
996 = !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
997 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
998 && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver)
999 && !_valueTypeProperty;
1001 if (allowedToRemoveBinding) {
1002 if (bindingProperty->acceptsQBinding()) {
1003 removePendingBinding(_bindingTarget, bindingProperty->coreIndex());
1005 QQmlPropertyPrivate::removeBinding(
1006 _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()),
1007 QQmlPropertyPrivate::OverrideSticky);
1011 if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
1012 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
1013 || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) {
1014 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1015 int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
1016 QQmlBoundSignalExpression *expr =
new QQmlBoundSignalExpression(
1017 _bindingTarget, signalIndex, context,
1018 _scopeObject, runtimeFunction, currentQmlContext());
1020 if (bindingProperty->notifiesViaBindable()) {
1021 auto target = _bindingTarget;
1022 if (bindingProperty->isAlias()) {
1027 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1028 auto [aliasTargetObject, aliasTargetIndex] = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1029 target = aliasTargetObject;
1030 QQmlData *data = QQmlData::get(target);
1031 Q_ASSERT(data && data->propertyCache);
1032 bindingProperty = data->propertyCache->property(aliasTargetIndex.coreIndex());
1034 auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
1035 QUntypedBindable bindable;
1036 void *argv[] = { &bindable };
1037 target->qt_metacall(QMetaObject::BindableProperty, bindingProperty->coreIndex(), argv);
1038 Q_ASSERT(bindable.isValid());
1039 bindable.observe(&observer);
1041 QQmlBoundSignal *bs =
new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
1042 bs->takeExpression(expr);
1044 }
else if (bindingProperty->acceptsQBinding()) {
1045 QUntypedPropertyBinding qmlBinding;
1046 if (binding->isTranslationBinding()) {
1047 qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
1049 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1050 QQmlPropertyIndex index(bindingProperty->coreIndex(), -1);
1051 qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index);
1053 sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding });
1055 QQmlData *data = QQmlData::get(_bindingTarget,
true);
1056 data->setBindingBit(_bindingTarget, bindingProperty->coreIndex());
1063 QQmlBinding::Ptr qmlBinding;
1064 const QQmlPropertyData *targetProperty = bindingProperty;
1065 const QQmlPropertyData *subprop =
nullptr;
1066 if (_valueTypeProperty) {
1067 targetProperty = _valueTypeProperty;
1068 subprop = bindingProperty;
1070 if (binding->isTranslationBinding()) {
1071 qmlBinding = QQmlBinding::createTranslationBinding(
1072 compilationUnit, binding, _scopeObject, context);
1074 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1075 qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
1076 context, currentQmlContext());
1079 auto bindingTarget = _bindingTarget;
1080 auto valueTypeProperty = _valueTypeProperty;
1081 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState)
mutable ->
bool {
1082 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, subprop) && targetProperty->isAlias())
1085 sharedState->allCreatedBindings.push_back(qmlBinding);
1087 if (bindingProperty->isAlias()) {
1088 QQmlPropertyPrivate::setBinding(qmlBinding.data(), QQmlPropertyPrivate::DontEnable);
1090 qmlBinding->addToObject();
1092 if (!valueTypeProperty) {
1093 QQmlData *targetDeclarativeData = QQmlData::get(bindingTarget);
1094 Q_ASSERT(targetDeclarativeData);
1095 targetDeclarativeData->setPendingBindingBit(bindingTarget, bindingProperty->coreIndex());
1101 if (!assignBinding(sharedState.data()))
1102 pendingAliasBindings.push_back(assignBinding);
1107 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
1108 if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) {
1110 QQmlType type = qmlTypeForObject(createdSubObject);
1111 Q_ASSERT(type.isValid());
1113 int valueSourceCast = type.propertyValueSourceCast();
1114 if (valueSourceCast != -1) {
1115 QQmlPropertyValueSource *vs =
reinterpret_cast<QQmlPropertyValueSource *>(
reinterpret_cast<
char *>(createdSubObject) + valueSourceCast);
1116 QObject *target = createdSubObject->parent();
1118 if (_valueTypeProperty) {
1119 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
1120 bindingProperty, context);
1122 prop = QQmlPropertyPrivate::restore(target, *bindingProperty,
nullptr, context);
1124 vs->setTarget(prop);
1127 int valueInterceptorCast = type.propertyValueInterceptorCast();
1128 if (valueInterceptorCast != -1) {
1129 QQmlPropertyValueInterceptor *vi =
reinterpret_cast<QQmlPropertyValueInterceptor *>(
reinterpret_cast<
char *>(createdSubObject) + valueInterceptorCast);
1130 QObject *target = createdSubObject->parent();
1132 QQmlPropertyIndex propertyIndex;
1133 if (bindingProperty->isAlias()) {
1134 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1135 auto aliasTarget = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1136 target = aliasTarget.targetObject;
1137 QQmlData *data = QQmlData::get(target);
1138 if (!data || !data->propertyCache) {
1139 qWarning() <<
"can't resolve property alias for 'on' assignment";
1144 QQmlPropertyData targetPropertyData = *data->propertyCache->property(aliasTarget.targetIndex.coreIndex());
1145 auto prop = QQmlPropertyPrivate::restore(
1146 target, targetPropertyData,
nullptr, context);
1147 vi->setTarget(prop);
1148 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1151 if (_valueTypeProperty) {
1152 prop = QQmlPropertyPrivate::restore(
1153 target, *_valueTypeProperty, bindingProperty, context);
1155 prop = QQmlPropertyPrivate::restore(
1156 target, *bindingProperty,
nullptr, context);
1158 vi->setTarget(prop);
1159 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1162 QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
1164 mo =
new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
1165 mo->registerInterceptor(propertyIndex, vi);
1172 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
1173 if (!bindingProperty->isFunction()) {
1174 recordError(binding->valueLocation, tr(
"Cannot assign an object to signal property %1").arg(bindingProperty->name(_qobject)));
1177 QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
1178 if (!method.isValid()) {
1179 recordError(binding->valueLocation, tr(
"Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
1182 qCWarning(lcQmlDefaultMethod) <<
"Assigning an object to a signal handler is deprecated. "
1183 "Instead, create the object, give it an id, and call the desired slot "
1184 "from the signal handler. The object is:" << createdSubObject;
1186 QMetaMethod signalMethod = _qobject->metaObject()->method(bindingProperty->coreIndex());
1187 if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
1188 recordError(binding->valueLocation,
1189 tr(
"Cannot connect mismatched signal/slot %1 vs %2")
1190 .arg(QString::fromUtf8(method.methodSignature()))
1191 .arg(QString::fromUtf8(signalMethod.methodSignature())));
1195 QQmlPropertyPrivate::connect(_qobject, bindingProperty->coreIndex(), createdSubObject, method.methodIndex());
1199 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
1200 QQmlPropertyData::RemoveBindingOnAliasWrite;
1201 int propertyWriteStatus = -1;
1202 void *argv[] = {
nullptr,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
1204 if (
const char *iid = QQmlMetaType::interfaceIId(bindingProperty->propType())) {
1205 void *ptr = createdSubObject->qt_metacast(iid);
1208 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1210 recordError(binding->location, tr(
"Cannot assign object to interface property"));
1213 }
else if (bindingProperty->propType() == QMetaType::fromType<QVariant>()) {
1214 if (bindingProperty->isVarProperty()) {
1215 QV4::Scope scope(v4);
1216 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1217 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1219 QVariant value = QVariant::fromValue(createdSubObject);
1221 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1223 }
else if (bindingProperty->propType() == QMetaType::fromType<QJSValue>()) {
1224 QV4::Scope scope(v4);
1225 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1226 if (bindingProperty->isVarProperty()) {
1227 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1230 QJSValuePrivate::setValue(&value, wrappedObject);
1232 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1234 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::IsQmlList)) {
1235 Q_ASSERT(_currentList.object);
1237 QObject *itemToAdd = createdSubObject;
1239 QMetaType listItemType = QQmlMetaType::listValueType(bindingProperty->propType());
1240 if (listItemType.isValid()) {
1241 const char *iid = QQmlMetaType::interfaceIId(listItemType);
1243 itemToAdd =
static_cast<QObject *>(createdSubObject->qt_metacast(iid));
1246 if (_currentList.append)
1247 _currentList.append(&_currentList, itemToAdd);
1249 recordError(binding->location, tr(
"Cannot assign object to read only list"));
1252 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::PointerToQObject)) {
1254 argv[0] = &createdSubObject;
1255 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1257 QVariant target = QQmlValueTypeProvider::createValueType(
1258 QVariant::fromValue(createdSubObject), bindingProperty->propType(), v4);
1259 if (target.isValid())
1260 bindingProperty->writeProperty(_qobject, target.data(), propertyWriteFlags);
1262 recordError(binding->location, tr(
"Cannot construct value type from given object"));
1267 if (bindingProperty->isQList()) {
1268 recordError(binding->location, tr(
"Cannot assign primitives to lists"));
1272 setPropertyValue(bindingProperty, binding);
1276void QQmlObjectCreator::setupFunctions()
1278 QV4::Scope scope(v4);
1279 QV4::ScopedValue function(scope);
1280 QV4::ScopedContext qmlContext(scope, currentQmlContext());
1282 const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
1283 for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1284 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
1285 const QString name = runtimeFunction->name()->toQString();
1287 const QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
1288 if (!property->isVMEFunction())
1291 if (runtimeFunction->isGenerator())
1292 function = QV4::GeneratorFunction::create(qmlContext, runtimeFunction);
1294 function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
1295 _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
1299void QQmlObjectCreator::recordError(
const QV4::CompiledData::Location &location,
const QString &description)
1302 error.setUrl(compilationUnit->url());
1303 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(location.line()));
1304 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(location.column()));
1305 error.setDescription(description);
1309void QQmlObjectCreator::registerObjectWithContextById(
const QV4::CompiledData::Object *object, QObject *instance)
const
1311 if (object->objectId() >= 0)
1312 context->setIdValue(object->objectId(), instance);
1315QObject *QQmlObjectCreator::createInstance(
int index, QObject *parent,
bool isContextObject)
1317 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1318 Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
1319 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
1322 const InitFlags flags = (isContextObject ? InitFlag::IsContextObject : InitFlag::None)
1323 | (index == 0 ? InitFlag::IsDocumentRoot : InitFlag::None);
1325 if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)) {
1326 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, QStringLiteral(
"<component>"));
1328 sharedState->profiler,
1330 compilationUnit.data(), obj, QStringLiteral(
"<component>"),
1332 return initializeComponent(
1333 obj, createComponent(engine, compilationUnit.data(), index, parent, context),
1337 const QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
1339 const QQmlType type = typeRef->type();
1340 Q_ASSERT(type.isValid());
1342 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, type.qmlTypeName());
1344 sharedState->profiler,
1345 profiler.update(compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
1347 if (type.isCompositeSingleton()) {
1350 tr(
"Composite Singleton Type %1 is not creatable")
1351 .arg(stringAt(obj->inheritedTypeNameIndex)));
1355 if (!type.isComposite() && !type.isInlineComponentType()) {
1356 if (QObject *instance = type.createWithQQmlData())
1357 return initializeNonComposite(index, obj, typeRef, instance, parent, flags);
1360 tr(
"Unable to create object of type %1").arg(
1361 stringAt(obj->inheritedTypeNameIndex)));
1365 QQmlRefPointer<QV4::ExecutableCompilationUnit> executableCu = typeRef->isSelfReference()
1367 : engine->handle()->executableCompilationUnit(typeRef->compilationUnit());
1368 Q_ASSERT(executableCu);
1370 const bool isInlineComponent = type.isInlineComponentType();
1371 const QString inlineComponentName = isInlineComponent ? type.elementName() : QString();
1372 QQmlObjectCreator subCreator(
1373 context, executableCu, inlineComponentName, sharedState.data(),
1376 if (QObject *instance = isInlineComponent
1377 ? subCreator.create(
1378 executableCu->inlineComponentId(inlineComponentName),
nullptr,
nullptr,
1379 CreationFlags::InlineComponent)
1380 : subCreator.create()) {
1381 return initializeComposite(index, obj, typeRef, instance, parent, flags);
1384 errors += subCreator.errors;
1388void QQmlObjectCreator::initializeDData(
1389 const QV4::CompiledData::Object *obj, QObject *instance, QQmlData *ddata, InitFlags flags)
1391 ddata->lineNumber = obj->location.line();
1392 ddata->columnNumber = obj->location.column();
1393 ddata->setImplicitDestructible();
1397 const bool documentRoot = (flags & InitFlag::IsDocumentRoot)
1398 || ddata->rootObjectInCreation
1399 || obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot);
1401 context->installContext(
1402 ddata, documentRoot ? QQmlContextData::DocumentRoot : QQmlContextData::OrdinaryObject);
1406 if (flags & InitFlag::IsContextObject)
1407 context->setContextObject(instance);
1410void QQmlObjectCreator::initializePropertyCache(
1411 int index, QQmlData *ddata,
const QV4::ResolvedTypeReference *typeRef)
1413 if (!typeRef->isFullyDynamicType()) {
1414 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(index);
1415 Q_ASSERT(!cache.isNull());
1416 ddata->propertyCache = std::move(cache);
1420void QQmlObjectCreator::initializeParent(QObject *instance, QObject *parent)
1422 if (instance->isWidgetType()) {
1423 if (parent && parent->isWidgetType()) {
1424 QAbstractDeclarativeData::setWidgetParent(instance, parent);
1429 }
else if (parent) {
1430 QQml_setParent_noEvent(instance, parent);
1434QObject *QQmlObjectCreator::populateInstanceAndAliasBindings(
1435 int index, QObject *instance, InitFlags flags)
1437 const auto doPopulate = [&]() {
1438 if (!populateInstance(
1439 index, instance, instance,
nullptr)) {
1441 pendingAliasBindings.clear();
1445 if (!flags.testFlag(InitFlag::IsContextObject))
1448 while (!pendingAliasBindings.empty()) {
1449 for (std::vector<PendingAliasBinding>::iterator it = pendingAliasBindings.begin();
1450 it != pendingAliasBindings.end(); ) {
1451 if ((*it)(sharedState.data()))
1452 it = pendingAliasBindings.erase(it);
1461 QObject *scopeObject = instance;
1462 qSwap(_scopeObject, scopeObject);
1464 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
1465 sharedState->allJavaScriptObjects.trackObject(v4, instance);
1467 QV4::Scope valueScope(v4);
1468 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(valueScope.constructUndefined(1));
1470 qSwap(_qmlContext, qmlContext);
1472 const bool ok = doPopulate();
1474 qSwap(_qmlContext, qmlContext);
1475 qSwap(_scopeObject, scopeObject);
1477 return ok ? instance :
nullptr;
1480QObject *QQmlObjectCreator::initializeComponent(
1481 const QV4::CompiledData::Object *obj, QObject *instance, InitFlags flags)
1485 Q_ASSERT(obj->hasFlag(QV4::CompiledData::Object::IsComponent));
1487 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1488 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1491 initializeDData(obj, instance, QQmlData::get(instance), flags);
1493 registerObjectWithContextById(obj, instance);
1497QObject *QQmlObjectCreator::initializeComposite(
1498 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1499 QObject *instance, QObject *parent, InitFlags flags)
1504 QScopedValueRollback<QQmlObjectCreator*> ocRestore(
1505 QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1507 initializeParent(instance, parent);
1508 QQmlData *ddata = QQmlData::get(instance,
true);
1509 initializeDData(obj, instance, ddata, flags);
1511 initializePropertyCache(index, ddata, typeRef);
1513 return populateInstanceAndAliasBindings(index, instance, flags);
1516QObject *QQmlObjectCreator::initializeNonComposite(
1517 int index,
const QV4::CompiledData::Object *obj,
const QV4::ResolvedTypeReference *typeRef,
1518 QObject *instance, QObject *parent, InitFlags flags)
1522 Q_ASSERT(!obj->hasFlag(QV4::CompiledData::Object::IsComponent));
1525 const QQmlType type = typeRef->type();
1526 Q_ASSERT(type.isValid());
1527 Q_ASSERT(!type.isComposite() && !type.isInlineComponentType());
1529 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1531 if (
const int finalizerCast = type.finalizerCast(); finalizerCast != -1) {
1532 const auto hook =
reinterpret_cast<QQmlFinalizerHook *>(
1533 reinterpret_cast<
char *>(instance) + finalizerCast);
1534 sharedState->finalizeHooks.push_back(hook);
1537 QQmlData *ddata = QQmlData::get(instance,
true);
1538 if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
1539 ddata->rootObjectInCreation =
true;
1540 sharedState->rootContext->setRootObjectInCreation(
false);
1543 const size_t instanceIndex = sharedState->allCreatedObjects.size();
1544 sharedState->allCreatedObjects.push_back(instance);
1546 initializeParent(instance, parent);
1547 initializeDData(obj, instance, ddata, flags);
1549 if (
const int parserStatusCast = type.parserStatusCast(); parserStatusCast != -1) {
1550 if (QQmlParserStatus *parserStatus =
reinterpret_cast<QQmlParserStatus*>(
1551 reinterpret_cast<
char *>(instance) + parserStatusCast)) {
1552 parserStatus->classBegin();
1555 Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
1556 sharedState->allParserStatusCallbacks.push_back({ instanceIndex, parserStatusCast });
1560 if (QQmlCustomParser *customParser = type.customParser();
1561 customParser && obj->hasFlag(QV4::CompiledData::Object::HasCustomParserBindings)) {
1562 customParser->engine = QQmlEnginePrivate::get(engine);
1563 customParser->imports = compilationUnit->typeNameCache().data();
1565 QList<
const QV4::CompiledData::Binding *> bindings;
1566 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1567 const QV4::CompiledData::Binding *binding = obj->bindingTable();
1568 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1569 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
1570 bindings << binding;
1572 customParser->applyBindings(instance, compilationUnit, bindings);
1574 customParser->engine =
nullptr;
1575 customParser->imports = (QQmlTypeNameCache*)
nullptr;
1578 initializePropertyCache(index, ddata, typeRef);
1579 return populateInstanceAndAliasBindings(index, instance, flags);
1582bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1584 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1587 QQmlObjectCreatorRecursionWatcher watcher(
this);
1588 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1603 while (!sharedState->allCreatedBindings.empty()) {
1604 QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.back();
1605 sharedState->allCreatedBindings.pop_back();
1608 if (!b->isAddedToObject())
1610 QQmlData *data = QQmlData::get(b->targetObject());
1612 data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
1613 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
1614 QQmlPropertyData::DontRemoveBinding);
1615 if (b->kind() == QQmlAbstractBinding::QmlBinding) {
1616 QQmlBinding *binding =
static_cast<QQmlBinding*>(b.data());
1617 if (!binding->hasError() && !binding->hasDependencies()
1618 && !binding->hasUnresolvedNames()) {
1619 b->removeFromObject();
1623 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1627 while (!sharedState->allQPropertyBindings.isEmpty()) {
1628 auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first();
1630 QQmlData *data = QQmlData::get(target);
1631 if (!data || !data->hasBindingBit(index)) {
1633 sharedState->allQPropertyBindings.pop_front();
1637 QUntypedBindable bindable;
1638 void *argv[] = { &bindable };
1640 target->metaObject()->metacall(target, QMetaObject::BindableProperty, index, argv);
1641 const bool success = bindable.setBinding(qmlBinding);
1643 const auto bindingPrivateRefCount = QPropertyBindingPrivate::get(qmlBinding)->refCount();
1646 sharedState->allQPropertyBindings.pop_front();
1649 if (success && bindingPrivateRefCount > 1) {
1650 if (
auto priv = QPropertyBindingPrivate::get(qmlBinding); priv->hasCustomVTable()) {
1651 auto qmlBindingPriv =
static_cast<QQmlPropertyBinding *>(priv);
1652 auto jsExpression = qmlBindingPriv->jsExpression();
1653 const bool canRemove = !qmlBinding.error().hasError()
1654 && !qmlBindingPriv->hasDependencies()
1655 && !jsExpression->hasUnresolvedNames();
1657 bindable.takeBinding();
1661 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1665 if (QQmlVME::componentCompleteEnabled()) {
1666 while (!sharedState->allParserStatusCallbacks.empty()) {
1667 QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
1668 const ParserStatus status = sharedState->allParserStatusCallbacks.back();
1669 sharedState->allParserStatusCallbacks.pop_back();
1671 const QQmlGuard<QObject> &instance = sharedState->allCreatedObjects[status.objectIndex];
1675 QQmlParserStatus *parserStatus
1676 =
reinterpret_cast<QQmlParserStatus *>(
1677 reinterpret_cast<
char *>(instance.data()) + status.parserStatusCast);
1678 parserStatus->componentComplete();
1680 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1685 for (QQmlFinalizerHook *hook: sharedState->finalizeHooks) {
1686 hook->componentFinalized();
1687 if (watcher.hasRecursed())
1690 sharedState->finalizeHooks.clear();
1692 while (sharedState->componentAttached) {
1693 QQmlComponentAttached *a = sharedState->componentAttached;
1694 a->removeFromList();
1695 QQmlData *d = QQmlData::get(a->parent());
1697 Q_ASSERT(d->context);
1698 d->context->addComponentAttached(a);
1699 if (QQmlVME::componentCompleteEnabled())
1700 emit a->completed();
1702 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1711void QQmlObjectCreator::clear()
1713 if (phase == Done || phase == Finalizing || phase == Startup)
1715 Q_ASSERT(phase != Startup);
1717 while (!sharedState->allCreatedObjects.empty()) {
1718 auto object = sharedState->allCreatedObjects.back();
1719 sharedState->allCreatedObjects.pop_back();
1720 if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
1725 while (sharedState->componentAttached) {
1726 QQmlComponentAttached *a = sharedState->componentAttached;
1727 a->removeFromList();
1733void QQmlObjectCreator::registerPostHocRequiredProperties(
const QV4::CompiledData::Binding *binding)
1735 const qsizetype oldRequiredPropertiesCount = sharedState->requiredProperties.size();
1736 QSet<QString> postHocRequired;
1737 for (
auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
1738 postHocRequired.insert(stringAt(it->nameIndex));
1739 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1741 for (
int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
1742 const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
1743 const QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
1745 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex()));
1746 if (!property->isRequired() && postHocRequired.end() == postHocIt)
1748 if (postHocIt != postHocRequired.end())
1749 postHocRequired.erase(postHocIt);
1750 if (isContextObject)
1751 sharedState->hadTopLevelRequiredProperties =
true;
1752 sharedState->requiredProperties.insert({_qobject, propertyData},
1753 RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex()), compilationUnit->finalUrl(), property->location, {}});
1757 const auto getPropertyCacheRange = [&]() -> std::pair<
int,
int> {
1775 QV4::ResolvedTypeReference *typeRef = resolvedType(_compiledObject->inheritedTypeNameIndex);
1778 if (binding->isAttachedProperty())
1779 return { 0, _propertyCache->propertyCount() };
1780 Q_ASSERT(binding->isGroupProperty());
1781 return { 0, _propertyCache->propertyOffset() + 1 };
1783 Q_ASSERT(!_compiledObject->hasFlag(QV4::CompiledData::Object::IsComponent));
1784 QQmlType type = typeRef->type();
1785 if (type.isComposite() || type.isInlineComponentType())
1786 return { _propertyCache->propertyOffset(), _propertyCache->propertyCount() };
1787 return { 0, _propertyCache->propertyCount() };
1789 const auto [offset, count] = getPropertyCacheRange();
1790 for (
int i = offset; i < count; ++i) {
1791 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1797 if (!propertyData->isRequired() && postHocRequired.isEmpty())
1799 QString name = propertyData->name(_qobject);
1800 const auto postHocIt = postHocRequired.constFind(name);
1801 if (postHocIt == postHocRequired.constEnd()) {
1802 if (!propertyData->isRequired())
1805 postHocRequired.erase(postHocIt);
1808 if (isContextObject)
1809 sharedState->hadTopLevelRequiredProperties =
true;
1810 sharedState->requiredProperties.insert(
1811 {_qobject, propertyData},
1812 RequiredPropertyInfo {
1813 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1817 if (binding && binding->isAttachedProperty()
1818 && sharedState->requiredProperties.size() != oldRequiredPropertiesCount) {
1821 QLatin1String(
"Attached property has required properties. This is not supported"));
1828 if (!postHocRequired.isEmpty()) {
1830 for (
int i = 0; i < offset; ++i) {
1831 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1834 QString name = propertyData->name(_qobject);
1835 const auto postHocIt = postHocRequired.constFind(name);
1836 if (postHocIt == postHocRequired.constEnd())
1838 postHocRequired.erase(postHocIt);
1840 if (isContextObject)
1841 sharedState->hadTopLevelRequiredProperties =
true;
1842 sharedState->requiredProperties.insert(
1843 {_qobject, propertyData},
1844 RequiredPropertyInfo {
1845 std::move(name), compilationUnit->finalUrl(), _compiledObject->location, {}
1850 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1851 recordError({}, QLatin1String(
"Property %1 was marked as required but does not exist").arg(*postHocRequired.begin()));
1854bool QQmlObjectCreator::populateInstance(
int index, QObject *instance, QObject *bindingTarget,
1855 const QQmlPropertyData *valueTypeProperty,
1856 const QV4::CompiledData::Binding *binding)
1859 QQmlData *declarativeData = QQmlData::get(instance,
true);
1861 qSwap(_qobject, instance);
1862 qSwap(_valueTypeProperty, valueTypeProperty);
1863 qSwap(_compiledObjectIndex, index);
1864 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
1865 qSwap(_compiledObject, obj);
1866 qSwap(_ddata, declarativeData);
1867 qSwap(_bindingTarget, bindingTarget);
1869 QV4::Scope valueScope(v4);
1870 QV4::ScopedValue scopeObjectProtector(valueScope);
1872 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
1874 QQmlVMEMetaObject *vmeMetaObject =
nullptr;
1875 if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) {
1876 Q_ASSERT(!cache.isNull());
1878 vmeMetaObject =
new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
1879 _ddata->propertyCache = cache;
1880 scopeObjectProtector = _ddata->jsWrapper.value();
1882 vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
1885 registerObjectWithContextById(_compiledObject, _qobject);
1887 qSwap(_propertyCache, cache);
1888 qSwap(_vmeMetaObject, vmeMetaObject);
1890 _ddata->compilationUnit = compilationUnit;
1891 if (_compiledObject->hasFlag(QV4::CompiledData::Object::HasDeferredBindings))
1892 _ddata->deferData(_compiledObjectIndex, compilationUnit, context, m_inlineComponentName);
1894 registerPostHocRequiredProperties(binding);
1896 if (_compiledObject->nFunctions > 0)
1898 setupBindings((binding && binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding))
1899 ? BindingMode::ApplyAll
1900 : BindingMode::ApplyImmediate);
1902 for (
int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
1907 _vmeMetaObject->connectAlias(_compiledObject, aliasIndex);
1908 if (!context->isIdValueSet(0))
1910 const QQmlPropertyData *aliasProperty =
1911 _propertyCache->property(_vmeMetaObject->aliasOffset() + aliasIndex);
1914 QObject *target = context->idValue(aliasProperty->aliasTargetObjectId());
1917 QQmlData *targetDData = QQmlData::get(target,
false);
1918 if (targetDData ==
nullptr || targetDData->propertyCache.isNull())
1921 const int targetPropertyIndex = aliasProperty->aliasTarget();
1922 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1924 const QQmlPropertyData *
const targetProperty = targetDData->propertyCache->property(coreIndex);
1925 if (!targetProperty)
1927 auto it = sharedState->requiredProperties.find({target, targetProperty});
1928 if (it != sharedState->requiredProperties.end()) {
1929 const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
1930 it->aliasesToRequired.push_back(
1931 AliasToRequiredInfo {
1932 compilationUnit->stringAt(alias->nameIndex()),
1933 compilationUnit->finalUrl()
1938 qSwap(_vmeMetaObject, vmeMetaObject);
1939 qSwap(_bindingTarget, bindingTarget);
1940 qSwap(_ddata, declarativeData);
1941 qSwap(_compiledObject, obj);
1942 qSwap(_compiledObjectIndex, index);
1943 qSwap(_valueTypeProperty, valueTypeProperty);
1944 qSwap(_qobject, instance);
1945 qSwap(_propertyCache, cache);
1947 return errors.isEmpty();
1951
1952
1953QQmlComponent *QQmlObjectCreator::createComponent(
1954 QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit,
int index,
1955 QObject *parent,
const QQmlRefPointer<QQmlContextData> &context)
1957 QQmlComponent *component =
new QQmlComponent(engine, compilationUnit, index, parent);
1958 QQmlComponentPrivate::get(component)->setCreationContext(context);
1959 QQmlData::get(component,
true);
1969void ObjectInCreationGCAnchorList::trackObject(QV4::ExecutionEngine *engine, QObject *instance)
1971 QV4::Value *wrapper = allocationScope->construct(1, QV4::QObjectWrapper::wrap(engine, instance));
1975 QV4::WriteBarrier::markCustom(engine, [wrapper](QV4::MarkStack *ms) {
1976 wrapper->heapObject()->mark(ms);
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
static QQmlType qmlTypeForObject(QObject *object)
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)