6#include <private/qjsvalue_p.h>
7#include <private/qqmlanybinding_p.h>
8#include <private/qqmlbinding_p.h>
9#include <private/qqmlboundsignal_p.h>
10#include <private/qqmlcomponent_p.h>
11#include <private/qqmlcomponentattached_p.h>
12#include <private/qqmlcustomparser_p.h>
13#include <private/qqmldebugconnector_p.h>
14#include <private/qqmldebugserviceinterfaces_p.h>
15#include <private/qqmlengine_p.h>
16#include <private/qqmlpropertybinding_p.h>
17#include <private/qqmlpropertyvalueinterceptor_p.h>
18#include <private/qqmlscriptdata_p.h>
19#include <private/qqmlscriptstring_p.h>
20#include <private/qqmlsourcecoordinate_p.h>
21#include <private/qqmlstringconverters_p.h>
22#include <private/qqmlvaluetypeproxybinding_p.h>
23#include <private/qqmlvme_p.h>
24#include <private/qqmlvmemetaobject_p.h>
25#include <private/qv4function_p.h>
26#include <private/qv4functionobject_p.h>
27#include <private/qv4generatorobject_p.h>
28#include <private/qv4qobjectwrapper_p.h>
29#include <private/qv4referenceobject_p.h>
30#include <private/qv4resolvedtypereference_p.h>
32#include <qtqml_tracepoints_p.h>
34#include <QtCore/qscopedvaluerollback.h>
35#include <QtCore/qloggingcategory.h>
43"struct ExecutionEngine;"\
44"class ExecutableCompilationUnit;"\
45"namespace CompiledData {"\
46"struct Object;"\
47"}}"\
48"class QQmlEngine;"
51Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_entry,
const QV4::ExecutableCompilationUnit *compilationUnit,
const QV4::CompiledData::Object *object,
const QUrl &url)
52Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_exit,
const QString &typeName)
54QQmlObjectCreator::QQmlObjectCreator(
55 const QQmlRefPointer<QQmlContextData> &parentContext,
56 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
57 const QQmlRefPointer<QQmlContextData> &creationContext,
58 const QString &inlineComponentName,
59 QQmlIncubatorPrivate *incubator)
61 , m_inlineComponentName(inlineComponentName)
62 , compilationUnit(compilationUnit)
63 , propertyCaches(compilationUnit->propertyCachesPtr())
64 , sharedState(
new QQmlObjectCreatorSharedState, QQmlRefPointer<QQmlObjectCreatorSharedState>::Adopt)
65 , topLevelCreator(
true)
66 , isContextObject(
true)
67 , incubator(incubator)
71 sharedState->componentAttached =
nullptr;
72 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
73 sharedState->creationContext = creationContext;
74 sharedState->rootContext.reset();
75 sharedState->hadTopLevelRequiredProperties =
false;
77 if (
auto profiler = QQmlEnginePrivate::get(engine)->profiler) {
78 Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
79 sharedState->profiler.init(profiler));
85QQmlObjectCreator::QQmlObjectCreator(
const QQmlRefPointer<QQmlContextData> &parentContext,
86 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
const QString inlineComponentName,
87 QQmlObjectCreatorSharedState *inheritedSharedState,
bool isContextObject)
89 , m_inlineComponentName(inlineComponentName)
90 , compilationUnit(compilationUnit)
91 , propertyCaches(compilationUnit->propertyCachesPtr())
92 , sharedState(inheritedSharedState)
93 , topLevelCreator(
false)
94 , isContextObject(isContextObject)
100void QQmlObjectCreator::init(
const QQmlRefPointer<QQmlContextData> &providedParentContext)
102 parentContext = providedParentContext;
103 engine = parentContext->engine();
104 v4 = engine->handle();
106 Q_ASSERT(compilationUnit);
107 Q_ASSERT(compilationUnit->engine == v4);
108 if (!compilationUnit->runtimeStrings)
109 compilationUnit->populate();
111 qmlUnit = compilationUnit->unitData();
113 _scopeObject =
nullptr;
114 _bindingTarget =
nullptr;
115 _valueTypeProperty =
nullptr;
116 _compiledObject =
nullptr;
117 _compiledObjectIndex = -1;
119 _vmeMetaObject =
nullptr;
120 _qmlContext =
nullptr;
123QQmlObjectCreator::~QQmlObjectCreator()
125 if (topLevelCreator) {
129 QQmlObjectCreatorRecursionWatcher watcher(
this);
131 while (sharedState->componentAttached) {
132 QQmlComponentAttached *a = sharedState->componentAttached;
138QObject *QQmlObjectCreator::create(
int subComponentIndex, QObject *parent, QQmlInstantiationInterrupt *interrupt,
int flags)
140 if (phase == CreatingObjectsPhase2) {
141 phase = ObjectsCreated;
142 return context->contextObject();
144 Q_ASSERT(phase == Startup);
145 phase = CreatingObjects;
148 bool isComponentRoot =
false;
150 if (subComponentIndex == -1) {
152 isComponentRoot =
true;
154 Q_ASSERT(subComponentIndex >= 0);
155 if (flags & CreationFlags::InlineComponent) {
156 if (compilationUnit->componentsAreBound()
157 && compilationUnit != parentContext->typeCompilationUnit()) {
158 recordError({}, tr(
"Cannot instantiate bound inline component in different file"));
159 phase = ObjectsCreated;
162 objectToCreate = subComponentIndex;
163 isComponentRoot =
true;
165 Q_ASSERT(flags & CreationFlags::NormalObject);
166 if (compilationUnit->componentsAreBound()
167 && sharedState->creationContext != parentContext) {
168 recordError({}, tr(
"Cannot instantiate bound component "
169 "outside its creation context"));
170 phase = ObjectsCreated;
173 const QV4::CompiledData::Object *compObj = compilationUnit->objectAt(subComponentIndex);
174 objectToCreate = compObj->bindingTable()->value.objectIndex;
178 context = QQmlEnginePrivate::get(engine)->createInternalContext(
179 compilationUnit, parentContext, subComponentIndex, isComponentRoot);
181 if (!sharedState->rootContext) {
182 sharedState->rootContext = context;
183 sharedState->rootContext->setIncubator(incubator);
184 sharedState->rootContext->setRootObjectInCreation(
true);
187 QV4::Scope scope(v4);
189 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack() || topLevelCreator);
191 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(scope);
193 if (!isComponentRoot && sharedState->creationContext) {
195 QV4::ScopedValue scripts(scope, sharedState->creationContext->importedScripts());
196 context->setImportedScripts(v4, scripts);
199 QObject *instance = createInstance(objectToCreate, parent,
true);
201 QQmlData *ddata = QQmlData::get(instance);
203 ddata->compilationUnit = compilationUnit;
207 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList();
209 phase = CreatingObjectsPhase2;
211 if (interrupt && interrupt->shouldInterrupt())
214 phase = ObjectsCreated;
217 if (QQmlEngineDebugService *service
218 = QQmlDebugConnector::service<QQmlEngineDebugService>()) {
219 if (!parentContext->isInternal())
220 parentContext->asQQmlContextPrivate()->appendInstance(instance);
221 service->objectCreated(engine, instance);
222 }
else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
223 parentContext->asQQmlContextPrivate()->appendInstance(instance);
230void QQmlObjectCreator::beginPopulateDeferred(
const QQmlRefPointer<QQmlContextData> &newContext)
232 context = newContext;
233 sharedState->rootContext = newContext;
235 Q_ASSERT(topLevelCreator);
236 Q_ASSERT(!sharedState->allJavaScriptObjects.canTrack());
239 QV4::Scope valueScope(v4);
240 sharedState->allJavaScriptObjects = ObjectInCreationGCAnchorList(valueScope);
243void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex,
244 const QQmlPropertyPrivate *qmlProperty,
245 const QV4::CompiledData::Binding *binding)
247 doPopulateDeferred(instance, deferredIndex, [
this, qmlProperty, binding]() {
248 Q_ASSERT(qmlProperty);
249 Q_ASSERT(binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding));
251 QQmlListProperty<
void> savedList;
252 qSwap(_currentList, savedList);
254 const QQmlPropertyData &property = qmlProperty->core;
256 if (property.propType().flags().testFlag(QMetaType::IsQmlList)) {
257 void *argv[1] = { (
void*)&_currentList };
258 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property.coreIndex(), argv);
259 }
else if (_currentList.object) {
260 _currentList = QQmlListProperty<
void>();
263 setPropertyBinding(&property, binding);
265 qSwap(_currentList, savedList);
269void QQmlObjectCreator::populateDeferred(QObject *instance,
int deferredIndex)
271 doPopulateDeferred(instance, deferredIndex, [
this]() { setupBindings(ApplyDeferred); });
274bool QQmlObjectCreator::populateDeferredProperties(QObject *instance,
275 const QQmlData::DeferredData *deferredData)
277 beginPopulateDeferred(deferredData->context);
278 populateDeferred(instance, deferredData->deferredIdx);
279 finalizePopulateDeferred();
280 return errors.isEmpty();
283void QQmlObjectCreator::populateDeferredBinding(
const QQmlProperty &qmlProperty,
int deferredIndex,
284 const QV4::CompiledData::Binding *binding)
287 populateDeferred(qmlProperty.object(), deferredIndex, QQmlPropertyPrivate::get(qmlProperty),
290 populateDeferred(qmlProperty.object(), deferredIndex);
294void QQmlObjectCreator::populateDeferredInstance(
295 QObject *outerObject,
int deferredIndex,
int index, QObject *instance,
296 QObject *bindingTarget,
const QQmlPropertyData *valueTypeProperty,
297 const QV4::CompiledData::Binding *binding)
299 doPopulateDeferred(outerObject, deferredIndex, [&]() {
300 populateInstance(index, instance, bindingTarget, valueTypeProperty, binding);
304void QQmlObjectCreator::finalizePopulateDeferred()
306 phase = ObjectsCreated;
309void QQmlObjectCreator::setPropertyValue(
const QQmlPropertyData *property,
const QV4::CompiledData::Binding *binding)
311 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
312 QV4::Scope scope(v4);
314 QMetaType propertyType = property->propType();
316 if (property->isEnum()) {
317 if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum) ||
320 (property->isAlias() && binding->isNumberBinding())) {
321 propertyType = property->propType().underlyingType();
324 QVariant value = compilationUnit->bindingValueAsString(binding);
325 bool ok = QQmlPropertyPrivate::write(_qobject, *property, value, context);
332 auto assertOrNull = [&](
bool ok)
334 Q_ASSERT(ok || binding->type() == QV4::CompiledData::Binding::Type_Null);
338 auto assertType = [&](QV4::CompiledData::Binding::Type type)
340 Q_ASSERT(binding->type()== type || binding->type() == QV4::CompiledData::Binding::Type_Null);
344 if (property->isQObject()) {
345 if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
346 QObject *value =
nullptr;
347 const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags);
354 switch (propertyType.id()) {
355 case QMetaType::QVariant: {
356 if (binding->type() == QV4::CompiledData::Binding::Type_Number) {
357 double n = compilationUnit->bindingValueAsNumber(binding);
358 if (
double(
int(n)) == n) {
359 if (property->isVarProperty()) {
360 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromInt32(
int(n)));
364 property->writeProperty(_qobject, &value, propertyWriteFlags);
367 if (property->isVarProperty()) {
368 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromDouble(n));
371 property->writeProperty(_qobject, &value, propertyWriteFlags);
374 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Boolean) {
375 if (property->isVarProperty()) {
376 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean()));
378 QVariant value(binding->valueAsBoolean());
379 property->writeProperty(_qobject, &value, propertyWriteFlags);
381 }
else if (binding->type() == QV4::CompiledData::Binding::Type_Null) {
382 if (property->isVarProperty()) {
383 _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue());
385 QVariant nullValue = QVariant::fromValue(
nullptr);
386 property->writeProperty(_qobject, &nullValue, propertyWriteFlags);
389 QString stringValue = compilationUnit->bindingValueAsString(binding);
390 if (property->isVarProperty()) {
391 QV4::ScopedString s(scope, v4->newString(stringValue));
392 _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
394 QVariant value = stringValue;
395 property->writeProperty(_qobject, &value, propertyWriteFlags);
400 case QMetaType::QString: {
401 assertOrNull(binding->evaluatesToString());
402 QString value = compilationUnit->bindingValueAsString(binding);
403 property->writeProperty(_qobject, &value, propertyWriteFlags);
406 case QMetaType::QStringList: {
407 assertOrNull(binding->evaluatesToString());
408 QStringList value(compilationUnit->bindingValueAsString(binding));
409 property->writeProperty(_qobject, &value, propertyWriteFlags);
412 case QMetaType::QByteArray: {
413 assertType(QV4::CompiledData::Binding::Type_String);
414 QByteArray value(compilationUnit->bindingValueAsString(binding).toUtf8());
415 property->writeProperty(_qobject, &value, propertyWriteFlags);
418 case QMetaType::QUrl: {
419 assertType(QV4::CompiledData::Binding::Type_String);
420 const QString string = compilationUnit->bindingValueAsString(binding);
421 QUrl value = (!string.isEmpty() && QQmlPropertyPrivate::resolveUrlsOnAssignment())
422 ? compilationUnit->finalUrl().resolved(QUrl(string))
424 property->writeProperty(_qobject, &value, propertyWriteFlags);
427 case QMetaType::UInt: {
428 assertType(QV4::CompiledData::Binding::Type_Number);
429 double d = compilationUnit->bindingValueAsNumber(binding);
430 uint value = uint(d);
431 property->writeProperty(_qobject, &value, propertyWriteFlags);
435 case QMetaType::Int: {
436 assertType(QV4::CompiledData::Binding::Type_Number);
437 double d = compilationUnit->bindingValueAsNumber(binding);
439 property->writeProperty(_qobject, &value, propertyWriteFlags);
443 case QMetaType::SChar: {
444 assertType(QV4::CompiledData::Binding::Type_Number);
445 double d = compilationUnit->bindingValueAsNumber(binding);
446 qint8 value = qint8(d);
447 property->writeProperty(_qobject, &value, propertyWriteFlags);
450 case QMetaType::UChar: {
451 assertType(QV4::CompiledData::Binding::Type_Number);
452 double d = compilationUnit->bindingValueAsNumber(binding);
453 quint8 value = quint8(d);
454 property->writeProperty(_qobject, &value, propertyWriteFlags);
457 case QMetaType::Short: {
458 assertType(QV4::CompiledData::Binding::Type_Number);
459 double d = compilationUnit->bindingValueAsNumber(binding);
460 qint16 value = qint16(d);
461 property->writeProperty(_qobject, &value, propertyWriteFlags);
464 case QMetaType::UShort: {
465 assertType(QV4::CompiledData::Binding::Type_Number);
466 double d = compilationUnit->bindingValueAsNumber(binding);
467 quint16 value = quint16(d);
468 property->writeProperty(_qobject, &value, propertyWriteFlags);
471 case QMetaType::LongLong: {
472 assertType(QV4::CompiledData::Binding::Type_Number);
473 double d = compilationUnit->bindingValueAsNumber(binding);
474 qint64 value = qint64(d);
475 property->writeProperty(_qobject, &value, propertyWriteFlags);
478 case QMetaType::ULongLong: {
479 assertType(QV4::CompiledData::Binding::Type_Number);
480 double d = compilationUnit->bindingValueAsNumber(binding);
481 quint64 value = quint64(d);
482 property->writeProperty(_qobject, &value, propertyWriteFlags);
486 case QMetaType::Float: {
487 assertType(QV4::CompiledData::Binding::Type_Number);
488 float value =
float(compilationUnit->bindingValueAsNumber(binding));
489 property->writeProperty(_qobject, &value, propertyWriteFlags);
492 case QMetaType::Double: {
493 assertType(QV4::CompiledData::Binding::Type_Number);
494 double value = compilationUnit->bindingValueAsNumber(binding);
495 property->writeProperty(_qobject, &value, propertyWriteFlags);
498 case QMetaType::QColor: {
499 QVariant data = QQmlValueTypeProvider::createValueType(
500 compilationUnit->bindingValueAsString(binding), propertyType);
501 if (data.isValid()) {
502 property->writeProperty(_qobject, data.data(), propertyWriteFlags);
506#if QT_CONFIG(datestring)
507 case QMetaType::QDate: {
509 QDate value = QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
511 property->writeProperty(_qobject, &value, propertyWriteFlags);
514 case QMetaType::QTime: {
516 QTime value = QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
518 property->writeProperty(_qobject, &value, propertyWriteFlags);
521 case QMetaType::QDateTime: {
523 QDateTime value = QQmlStringConverters::dateTimeFromString(
524 compilationUnit->bindingValueAsString(binding), &ok);
526 property->writeProperty(_qobject, &value, propertyWriteFlags);
530 case QMetaType::QPoint: {
532 QPoint value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok).toPoint();
534 property->writeProperty(_qobject, &value, propertyWriteFlags);
537 case QMetaType::QPointF: {
539 QPointF value = QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
541 property->writeProperty(_qobject, &value, propertyWriteFlags);
544 case QMetaType::QSize: {
546 QSize value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok).toSize();
548 property->writeProperty(_qobject, &value, propertyWriteFlags);
551 case QMetaType::QSizeF: {
553 QSizeF value = QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
555 property->writeProperty(_qobject, &value, propertyWriteFlags);
558 case QMetaType::QRect: {
560 QRect value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok).toRect();
562 property->writeProperty(_qobject, &value, propertyWriteFlags);
565 case QMetaType::QRectF: {
567 QRectF value = QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
569 property->writeProperty(_qobject, &value, propertyWriteFlags);
572 case QMetaType::Bool: {
573 assertType(QV4::CompiledData::Binding::Type_Boolean);
574 bool value = binding->valueAsBoolean();
575 property->writeProperty(_qobject, &value, propertyWriteFlags);
578 case QMetaType::QVector2D:
579 case QMetaType::QVector3D:
580 case QMetaType::QVector4D:
581 case QMetaType::QQuaternion: {
582 QVariant result = QQmlValueTypeProvider::createValueType(
583 compilationUnit->bindingValueAsString(binding), propertyType);
584 assertOrNull(result.isValid());
585 property->writeProperty(_qobject, result.data(), propertyWriteFlags);
590 if (propertyType == QMetaType::fromType<QList<qreal>>()) {
591 assertType(QV4::CompiledData::Binding::Type_Number);
593 value.append(compilationUnit->bindingValueAsNumber(binding));
594 property->writeProperty(_qobject, &value, propertyWriteFlags);
596 }
else if (propertyType == QMetaType::fromType<QList<
int>>()) {
597 assertType(QV4::CompiledData::Binding::Type_Number);
598 double n = compilationUnit->bindingValueAsNumber(binding);
600 value.append(
int(n));
601 property->writeProperty(_qobject, &value, propertyWriteFlags);
603 }
else if (propertyType == QMetaType::fromType<QList<
bool>>()) {
604 assertType(QV4::CompiledData::Binding::Type_Boolean);
606 value.append(binding->valueAsBoolean());
607 property->writeProperty(_qobject, &value, propertyWriteFlags);
609 }
else if (propertyType == QMetaType::fromType<QList<QUrl>>()) {
610 assertType(QV4::CompiledData::Binding::Type_String);
611 const QUrl url(compilationUnit->bindingValueAsString(binding));
613 QQmlPropertyPrivate::resolveUrlsOnAssignment()
614 ? compilationUnit->finalUrl().resolved(url)
617 property->writeProperty(_qobject, &value, propertyWriteFlags);
619 }
else if (propertyType == QMetaType::fromType<QList<QString>>()) {
620 assertOrNull(binding->evaluatesToString());
621 QList<QString> value;
622 value.append(compilationUnit->bindingValueAsString(binding));
623 property->writeProperty(_qobject, &value, propertyWriteFlags);
625 }
else if (propertyType == QMetaType::fromType<QJSValue>()) {
627 switch (binding->type()) {
628 case QV4::CompiledData::Binding::Type_Boolean:
629 value = QJSValue(binding->valueAsBoolean());
631 case QV4::CompiledData::Binding::Type_Number: {
632 const double n = compilationUnit->bindingValueAsNumber(binding);
633 if (
double(
int(n)) == n)
634 value = QJSValue(
int(n));
639 case QV4::CompiledData::Binding::Type_Null:
640 value = QJSValue::NullValue;
643 value = QJSValue(compilationUnit->bindingValueAsString(binding));
646 property->writeProperty(_qobject, &value, propertyWriteFlags);
650 switch (binding->type()) {
651 case QV4::CompiledData::Binding::Type_Boolean:
652 source = binding->valueAsBoolean();
654 case QV4::CompiledData::Binding::Type_Number: {
655 const double n = compilationUnit->bindingValueAsNumber(binding);
656 if (
double(
int(n)) == n)
662 case QV4::CompiledData::Binding::Type_Null:
663 source = QVariant::fromValue<std::nullptr_t>(
nullptr);
665 case QV4::CompiledData::Binding::Type_Invalid:
668 source = compilationUnit->bindingValueAsString(binding);
672 QVariant target = QQmlValueTypeProvider::createValueType(
673 source, propertyType, engine->handle());
674 if (target.isValid()) {
675 property->writeProperty(_qobject, target.data(), propertyWriteFlags);
681 QString stringValue = compilationUnit->bindingValueAsString(binding);
682 QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
683 recordError(binding->location, tr(
"Cannot assign value %1 to property"
684" %2").arg(stringValue, QString::fromUtf8(metaProperty.name())));
693 const QMetaObject *mo = object->metaObject();
694 while (mo && !type.isValid()) {
695 type = QQmlMetaType::qmlType(mo);
696 mo = mo->superClass();
701void QQmlObjectCreator::setupBindings(BindingSetupFlags mode)
703 QQmlListProperty<
void> savedList;
704 qSwap(_currentList, savedList);
706 const QV4::CompiledData::BindingPropertyData *propertyData
707 = compilationUnit->bindingPropertyDataPerObjectAt(_compiledObjectIndex);
709 if (_compiledObject->idNameIndex) {
710 const QQmlPropertyData *idProperty = propertyData->last();
711 Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String(
"id"));
712 if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) {
713 QV4::CompiledData::Binding idBinding;
714 idBinding.propertyNameIndex = 0;
715 idBinding.clearFlags();
716 idBinding.setType(QV4::CompiledData::Binding::Type_String);
717 idBinding.stringIndex = _compiledObject->idNameIndex;
718 idBinding.location = _compiledObject->location;
719 idBinding.value.nullMarker = 0;
720 setPropertyValue(idProperty, &idBinding);
725 if (_valueTypeProperty) {
726 QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
728 if (binding && binding->kind() != QQmlAbstractBinding::ValueTypeProxy) {
729 QQmlPropertyPrivate::removeBinding(
730 _bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()),
731 QQmlPropertyPrivate::OverrideSticky);
732 }
else if (binding) {
733 QQmlValueTypeProxyBinding *proxy =
static_cast<QQmlValueTypeProxyBinding *>(binding);
735 if (qmlTypeForObject(_bindingTarget).isValid()) {
736 quint32 bindingSkipList = 0;
738 const QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
740 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
741 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
742 const QQmlPropertyData *property = binding->propertyNameIndex != 0
743 ? _propertyCache->property(stringAt(binding->propertyNameIndex),
747 bindingSkipList |= (1 << property->coreIndex());
750 proxy->removeBindings(bindingSkipList);
755 int currentListPropertyIndex = -1;
757 const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
758 for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
759 const QQmlPropertyData *
const property = propertyData->at(i);
761 const QQmlPropertyData *targetProperty = property;
762 if (targetProperty->isAlias()) {
764 QQmlPropertyIndex originalIndex(targetProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
765 auto [targetObject, targetIndex] = QQmlPropertyPrivate::findAliasTarget(_bindingTarget, originalIndex);
766 QQmlData *data = QQmlData::get(targetObject);
767 Q_ASSERT(data && data->propertyCache);
768 targetProperty = data->propertyCache->property(targetIndex.coreIndex());
769 sharedState->requiredProperties.remove({targetObject, targetProperty});
771 sharedState->requiredProperties.remove({_bindingTarget, property});
775 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
778 if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) {
779 if (!(mode & ApplyDeferred))
781 }
else if (!(mode & ApplyImmediate)) {
785 if (property && property->propType().flags().testFlag(QMetaType::IsQmlList)) {
786 if (property->coreIndex() != currentListPropertyIndex) {
787 void *argv[1] = { (
void*)&_currentList };
788 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
789 currentListPropertyIndex = property->coreIndex();
792 const QMetaObject *
const metaobject = _qobject->metaObject();
793 const int qmlListBehavorClassInfoIndex = metaobject->indexOfClassInfo(
"QML.ListPropertyAssignBehavior");
794 if (qmlListBehavorClassInfoIndex != -1) {
795 const char *overrideBehavior =
796 metaobject->classInfo(qmlListBehavorClassInfoIndex).value();
797 if (!strcmp(overrideBehavior,
799 if (_currentList.clear) {
800 _currentList.clear(&_currentList);
803 bool isDefaultProperty =
804 (property->name(_qobject)
805 == QString::fromUtf8(
807 ->classInfo(metaobject->indexOfClassInfo(
810 if (!isDefaultProperty
811 && (!strcmp(overrideBehavior,
812 "ReplaceIfNotDefault"))) {
813 if (_currentList.clear) {
814 _currentList.clear(&_currentList);
820 }
else if (_currentList.object) {
821 _currentList = QQmlListProperty<
void>();
822 currentListPropertyIndex = -1;
825 if (!setPropertyBinding(property, binding))
829 qSwap(_currentList, savedList);
832bool QQmlObjectCreator::setPropertyBinding(
const QQmlPropertyData *bindingProperty,
const QV4::CompiledData::Binding *binding)
834 const QV4::CompiledData::Binding::Type bindingType = binding->type();
835 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
836 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
837 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
839 Q_ASSERT(stringAt(obj->inheritedTypeNameIndex).isEmpty());
840 QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
842 QQmlType attachedType = tr->type();
843 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
844 if (!attachedType.isValid()) {
845 QQmlTypeNameCache::Result res
846 = context->imports()->query(stringAt(binding->propertyNameIndex), typeLoader);
848 attachedType = res.type;
854 sharedState->profiler,
855 profiler.update(compilationUnit.data(), obj, attachedType.qmlTypeName(),
858 QObject *qmlObject = qmlAttachedPropertiesObject(
859 _qobject, attachedType.attachedPropertiesFunction(typeLoader));
861 recordError(binding->location,
862 QStringLiteral(
"Could not create attached properties object '%1'")
863 .arg(QString::fromUtf8(attachedType.typeName())));
867 const size_t objectIndex = sharedState->allCreatedObjects.size();
868 sharedState->allCreatedObjects.push_back(qmlObject);
869 const QQmlType attachedObjectType
870 = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(typeLoader));
871 const int parserStatusCast = attachedObjectType.parserStatusCast();
872 QQmlParserStatus *parserStatus =
nullptr;
873 if (parserStatusCast != -1)
874 parserStatus =
reinterpret_cast<QQmlParserStatus*>(
reinterpret_cast<
char *>(qmlObject) + parserStatusCast);
876 parserStatus->classBegin();
878 sharedState->allParserStatusCallbacks.push_back({objectIndex, parserStatusCast});
881 if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject,
888 if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) {
889 QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding),
890 context->asQQmlContext(), _scopeObject);
891 ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
892 ss.d.data()->lineNumber = binding->location.line();
893 ss.d.data()->columnNumber = binding->location.column();
894 ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String;
895 ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number;
896 ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding);
898 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
899 QQmlPropertyData::RemoveBindingOnAliasWrite;
900 int propertyWriteStatus = -1;
901 void *argv[] = { &ss,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
902 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
906 QObject *createdSubObject =
nullptr;
907 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
910 QScopedValueRollback topLevelRequired(sharedState->hadTopLevelRequiredProperties);
911 createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget);
912 if (!createdSubObject)
916 if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) {
917 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
918 if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
920 QObject *groupObject =
nullptr;
921 QQmlGadgetPtrWrapper *valueType =
nullptr;
922 const QQmlPropertyData *valueTypeProperty =
nullptr;
923 QObject *bindingTarget = _bindingTarget;
924 int groupObjectIndex = binding->value.objectIndex;
926 if (!bindingProperty) {
927 for (
int i = 0, end = compilationUnit->objectCount(); i != end; ++i) {
928 const QV4::CompiledData::Object *external = compilationUnit->objectAt(i);
929 if (external->idNameIndex == binding->propertyNameIndex) {
930 bindingTarget = groupObject = context->idValue(external->objectId());
936 }
else if (QQmlMetaType::isValueType(bindingProperty->propType())) {
937 valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
939 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
943 valueType->read(_qobject, bindingProperty->coreIndex());
945 groupObject = valueType;
946 valueTypeProperty = bindingProperty;
948 void *argv[1] = { &groupObject };
949 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
951 QQmlPropertyIndex index(bindingProperty->coreIndex());
952 auto anyBinding = QQmlAnyBinding::ofProperty(_qobject, index);
956 anyBinding.refresh();
957 QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, bindingProperty->coreIndex(), argv);
960 recordError(binding->location, tr(
"Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
965 bindingTarget = groupObject;
968 if (!populateInstance(groupObjectIndex, groupObject, bindingTarget, valueTypeProperty,
975 _qobject, bindingProperty->coreIndex(),
976 QQmlPropertyData::BypassInterceptor,
977 QV4::ReferenceObject::AllProperties);
984 if (!bindingProperty)
987 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
988 const bool allowedToRemoveBinding
989 = !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
990 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
991 && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver)
992 && !_valueTypeProperty;
994 if (allowedToRemoveBinding) {
995 if (bindingProperty->acceptsQBinding()) {
996 removePendingBinding(_bindingTarget, bindingProperty->coreIndex());
998 QQmlPropertyPrivate::removeBinding(
999 _bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()),
1000 QQmlPropertyPrivate::OverrideSticky);
1004 if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
1005 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
1006 || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) {
1007 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1008 int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
1009 QQmlBoundSignalExpression *expr =
new QQmlBoundSignalExpression(
1010 _bindingTarget, signalIndex, context,
1011 _scopeObject, runtimeFunction, currentQmlContext());
1013 if (bindingProperty->notifiesViaBindable()) {
1014 auto target = _bindingTarget;
1015 if (bindingProperty->isAlias()) {
1020 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1021 auto [aliasTargetObject, aliasTargetIndex] = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1022 target = aliasTargetObject;
1023 QQmlData *data = QQmlData::get(target);
1024 Q_ASSERT(data && data->propertyCache);
1025 bindingProperty = data->propertyCache->property(aliasTargetIndex.coreIndex());
1027 auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
1028 QUntypedBindable bindable;
1029 void *argv[] = { &bindable };
1030 target->qt_metacall(QMetaObject::BindableProperty, bindingProperty->coreIndex(), argv);
1031 Q_ASSERT(bindable.isValid());
1032 bindable.observe(&observer);
1034 QQmlBoundSignal *bs =
new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
1035 bs->takeExpression(expr);
1037 }
else if (bindingProperty->acceptsQBinding()) {
1038 QUntypedPropertyBinding qmlBinding;
1039 if (binding->isTranslationBinding()) {
1040 qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
1042 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1043 QQmlPropertyIndex index(bindingProperty->coreIndex(), -1);
1044 qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext(), _bindingTarget, index);
1046 sharedState.data()->allQPropertyBindings.push_back(DeferredQPropertyBinding {_bindingTarget, bindingProperty->coreIndex(), qmlBinding });
1048 QQmlData *data = QQmlData::get(_bindingTarget,
true);
1049 data->setBindingBit(_bindingTarget, bindingProperty->coreIndex());
1056 QQmlBinding::Ptr qmlBinding;
1057 const QQmlPropertyData *targetProperty = bindingProperty;
1058 const QQmlPropertyData *subprop =
nullptr;
1059 if (_valueTypeProperty) {
1060 targetProperty = _valueTypeProperty;
1061 subprop = bindingProperty;
1063 if (binding->isTranslationBinding()) {
1064 qmlBinding = QQmlBinding::createTranslationBinding(
1065 compilationUnit, binding, _scopeObject, context);
1067 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
1068 qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
1069 context, currentQmlContext());
1072 auto bindingTarget = _bindingTarget;
1073 auto valueTypeProperty = _valueTypeProperty;
1074 auto assignBinding = [qmlBinding, bindingTarget, targetProperty, subprop, bindingProperty, valueTypeProperty](QQmlObjectCreatorSharedState *sharedState)
mutable ->
bool {
1075 if (!qmlBinding->setTarget(bindingTarget, *targetProperty, subprop) && targetProperty->isAlias())
1078 sharedState->allCreatedBindings.push_back(qmlBinding);
1080 if (bindingProperty->isAlias()) {
1081 QQmlPropertyPrivate::setBinding(qmlBinding.data(), QQmlPropertyPrivate::DontEnable);
1083 qmlBinding->addToObject();
1085 if (!valueTypeProperty) {
1086 QQmlData *targetDeclarativeData = QQmlData::get(bindingTarget);
1087 Q_ASSERT(targetDeclarativeData);
1088 targetDeclarativeData->setPendingBindingBit(bindingTarget, bindingProperty->coreIndex());
1094 if (!assignBinding(sharedState.data()))
1095 pendingAliasBindings.push_back(assignBinding);
1100 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
1101 if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) {
1103 QQmlType type = qmlTypeForObject(createdSubObject);
1104 Q_ASSERT(type.isValid());
1106 int valueSourceCast = type.propertyValueSourceCast();
1107 if (valueSourceCast != -1) {
1108 QQmlPropertyValueSource *vs =
reinterpret_cast<QQmlPropertyValueSource *>(
reinterpret_cast<
char *>(createdSubObject) + valueSourceCast);
1109 QObject *target = createdSubObject->parent();
1111 if (_valueTypeProperty) {
1112 prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
1113 bindingProperty, context);
1115 prop = QQmlPropertyPrivate::restore(target, *bindingProperty,
nullptr, context);
1117 vs->setTarget(prop);
1120 int valueInterceptorCast = type.propertyValueInterceptorCast();
1121 if (valueInterceptorCast != -1) {
1122 QQmlPropertyValueInterceptor *vi =
reinterpret_cast<QQmlPropertyValueInterceptor *>(
reinterpret_cast<
char *>(createdSubObject) + valueInterceptorCast);
1123 QObject *target = createdSubObject->parent();
1125 QQmlPropertyIndex propertyIndex;
1126 if (bindingProperty->isAlias()) {
1127 QQmlPropertyIndex originalIndex(bindingProperty->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
1128 auto aliasTarget = QQmlPropertyPrivate::findAliasTarget(target, originalIndex);
1129 target = aliasTarget.targetObject;
1130 QQmlData *data = QQmlData::get(target);
1131 if (!data || !data->propertyCache) {
1132 qWarning() <<
"can't resolve property alias for 'on' assignment";
1137 QQmlPropertyData targetPropertyData = *data->propertyCache->property(aliasTarget.targetIndex.coreIndex());
1138 auto prop = QQmlPropertyPrivate::restore(
1139 target, targetPropertyData,
nullptr, context);
1140 vi->setTarget(prop);
1141 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1144 if (_valueTypeProperty) {
1145 prop = QQmlPropertyPrivate::restore(
1146 target, *_valueTypeProperty, bindingProperty, context);
1148 prop = QQmlPropertyPrivate::restore(
1149 target, *bindingProperty,
nullptr, context);
1151 vi->setTarget(prop);
1152 propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
1155 QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
1157 mo =
new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
1158 mo->registerInterceptor(propertyIndex, vi);
1165 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
1166 if (!bindingProperty->isFunction()) {
1167 recordError(binding->valueLocation, tr(
"Cannot assign an object to signal property %1").arg(bindingProperty->name(_qobject)));
1170 QMetaMethod method = QQmlMetaType::defaultMethod(createdSubObject);
1171 if (!method.isValid()) {
1172 recordError(binding->valueLocation, tr(
"Cannot assign object type %1 with no default method").arg(QString::fromLatin1(createdSubObject->metaObject()->className())));
1175 qCWarning(lcQmlDefaultMethod) <<
"Assigning an object to a signal handler is deprecated. "
1176 "Instead, create the object, give it an id, and call the desired slot "
1177 "from the signal handler. The object is:" << createdSubObject;
1179 QMetaMethod signalMethod = _qobject->metaObject()->method(bindingProperty->coreIndex());
1180 if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
1181 recordError(binding->valueLocation,
1182 tr(
"Cannot connect mismatched signal/slot %1 vs %2")
1183 .arg(QString::fromUtf8(method.methodSignature()))
1184 .arg(QString::fromUtf8(signalMethod.methodSignature())));
1188 QQmlPropertyPrivate::connect(_qobject, bindingProperty->coreIndex(), createdSubObject, method.methodIndex());
1192 QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor |
1193 QQmlPropertyData::RemoveBindingOnAliasWrite;
1194 int propertyWriteStatus = -1;
1195 void *argv[] = {
nullptr,
nullptr, &propertyWriteStatus, &propertyWriteFlags };
1197 if (
const char *iid = QQmlMetaType::interfaceIId(bindingProperty->propType())) {
1198 void *ptr = createdSubObject->qt_metacast(iid);
1201 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1203 recordError(binding->location, tr(
"Cannot assign object to interface property"));
1206 }
else if (bindingProperty->propType() == QMetaType::fromType<QVariant>()) {
1207 if (bindingProperty->isVarProperty()) {
1208 QV4::Scope scope(v4);
1209 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1210 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1212 QVariant value = QVariant::fromValue(createdSubObject);
1214 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1216 }
else if (bindingProperty->propType() == QMetaType::fromType<QJSValue>()) {
1217 QV4::Scope scope(v4);
1218 QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(engine->handle(), createdSubObject));
1219 if (bindingProperty->isVarProperty()) {
1220 _vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
1223 QJSValuePrivate::setValue(&value, wrappedObject);
1225 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1227 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::IsQmlList)) {
1228 Q_ASSERT(_currentList.object);
1230 void *itemToAdd = createdSubObject;
1232 QMetaType listItemType = QQmlMetaType::listValueType(bindingProperty->propType());
1233 if (listItemType.isValid()) {
1234 const char *iid = QQmlMetaType::interfaceIId(listItemType);
1236 itemToAdd = createdSubObject->qt_metacast(iid);
1239 if (_currentList.append)
1240 _currentList.append(&_currentList, itemToAdd);
1242 recordError(binding->location, tr(
"Cannot assign object to read only list"));
1245 }
else if (bindingProperty->propType().flags().testFlag(QMetaType::PointerToQObject)) {
1247 argv[0] = &createdSubObject;
1248 QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
1250 QVariant target = QQmlValueTypeProvider::createValueType(
1251 QVariant::fromValue(createdSubObject), bindingProperty->propType(), v4);
1252 if (target.isValid())
1253 bindingProperty->writeProperty(_qobject, target.data(), propertyWriteFlags);
1255 recordError(binding->location, tr(
"Cannot construct value type from given object"));
1260 if (bindingProperty->isQList()) {
1261 recordError(binding->location, tr(
"Cannot assign primitives to lists"));
1265 setPropertyValue(bindingProperty, binding);
1269void QQmlObjectCreator::setupFunctions()
1271 QV4::Scope scope(v4);
1272 QV4::ScopedValue function(scope);
1273 QV4::ScopedContext qmlContext(scope, currentQmlContext());
1275 const quint32_le *functionIdx = _compiledObject->functionOffsetTable();
1276 for (quint32 i = 0; i < _compiledObject->nFunctions; ++i, ++functionIdx) {
1277 QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[*functionIdx];
1278 const QString name = runtimeFunction->name()->toQString();
1280 const QQmlPropertyData *property = _propertyCache->property(name, _qobject, context);
1281 if (!property->isVMEFunction())
1284 if (runtimeFunction->isGenerator())
1285 function = QV4::GeneratorFunction::create(qmlContext, runtimeFunction);
1287 function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
1288 _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
1292void QQmlObjectCreator::recordError(
const QV4::CompiledData::Location &location,
const QString &description)
1295 error.setUrl(compilationUnit->url());
1296 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(location.line()));
1297 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(location.column()));
1298 error.setDescription(description);
1302void QQmlObjectCreator::registerObjectWithContextById(
const QV4::CompiledData::Object *object, QObject *instance)
const
1304 if (object->objectId() >= 0)
1305 context->setIdValue(object->objectId(), instance);
1308QObject *QQmlObjectCreator::createInstance(
int index, QObject *parent,
bool isContextObject)
1310 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1311 QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
1312 Q_TRACE(QQmlObjectCreator_createInstance_entry, compilationUnit.data(), obj, context->url());
1314 Q_TRACE_EXIT(QQmlObjectCreator_createInstance_exit, typeName);
1316 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1318 bool isComponent =
false;
1319 QObject *instance =
nullptr;
1320 QQmlData *ddata =
nullptr;
1321 QQmlCustomParser *customParser =
nullptr;
1323 QQmlParserStatus *parserStatus =
nullptr;
1324 int parserStatusCast = 0;
1325 size_t instanceIndex = 0;
1327 bool installPropertyCache =
true;
1329 if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)) {
1331 instance = createComponent(engine, compilationUnit.data(), index, parent, context);
1332 typeName = QStringLiteral(
"<component>");
1333 ddata = QQmlData::get(instance);
1336 QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
1338 installPropertyCache = !typeRef->isFullyDynamicType();
1339 const QQmlType type = typeRef->type();
1340 Q_ASSERT(type.isValid());
1341 typeName = type.qmlTypeName();
1342 if (!type.isComposite() && !type.isInlineComponentType()) {
1344 instance = type.createWithQQmlData();
1346 recordError(obj->location, tr(
"Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
1350 const int finalizerCast = type.finalizerCast();
1351 if (finalizerCast != -1) {
1352 auto hook =
reinterpret_cast<QQmlFinalizerHook *>(
reinterpret_cast<
char *>(instance) + finalizerCast);
1353 sharedState->finalizeHooks.push_back(hook);
1356 parserStatusCast = type.parserStatusCast();
1357 if (parserStatusCast != -1)
1358 parserStatus =
reinterpret_cast<QQmlParserStatus*>(
reinterpret_cast<
char *>(instance) + parserStatusCast);
1360 customParser = type.customParser();
1362 if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
1363 QQmlData *ddata = QQmlData::get(instance,
true);
1364 ddata->rootObjectInCreation =
true;
1365 sharedState->rootContext->setRootObjectInCreation(
false);
1368 instanceIndex = sharedState->allCreatedObjects.size();
1369 sharedState->allCreatedObjects.push_back(instance);
1371 if (type.isSingleton()) {
1374 tr(
"Composite Singleton Type %1 is not creatable")
1375 .arg(stringAt(obj->inheritedTypeNameIndex)));
1379 QQmlRefPointer<QV4::ExecutableCompilationUnit> executableCu = typeRef->isSelfReference()
1381 : engine->handle()->executableCompilationUnit(typeRef->compilationUnit());
1382 Q_ASSERT(executableCu);
1384 if (!type.isInlineComponentType()) {
1385 QQmlObjectCreator subCreator(
1386 context, executableCu,
1388 sharedState.data(), isContextObject);
1389 instance = subCreator.create();
1391 errors += subCreator.errors;
1395 const QString inlineComponentName = type.elementName();
1397 const int inlineComponentId = executableCu->inlineComponentId(inlineComponentName);
1398 QQmlObjectCreator subCreator(
1399 context, executableCu, inlineComponentName, sharedState.data(),
1401 instance = subCreator.create(
1402 inlineComponentId,
nullptr,
nullptr, CreationFlags::InlineComponent);
1404 errors += subCreator.errors;
1409 if (instance->isWidgetType()) {
1410 if (parent && parent->isWidgetType()) {
1411 QAbstractDeclarativeData::setWidgetParent(instance, parent);
1416 }
else if (parent) {
1417 QQml_setParent_noEvent(instance, parent);
1420 ddata = QQmlData::get(instance,
true);
1423 Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
1424 compilationUnit.data(), obj, typeName, context->url()));
1427 ddata->lineNumber = obj->location.line();
1428 ddata->columnNumber = obj->location.column();
1430 ddata->setImplicitDestructible();
1433 const bool documentRoot =
static_cast<quint32>(index) == 0
1434 || ddata->rootObjectInCreation
1435 || obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot);
1436 context->installContext(
1437 ddata, documentRoot ? QQmlContextData::DocumentRoot : QQmlContextData::OrdinaryObject);
1440 parserStatus->classBegin();
1443 Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
1444 sharedState->allParserStatusCallbacks.push_back({ instanceIndex, parserStatusCast });
1449 if (isContextObject)
1450 context->setContextObject(instance);
1452 if (customParser && obj->hasFlag(QV4::CompiledData::Object::HasCustomParserBindings)) {
1453 customParser->engine = QQmlEnginePrivate::get(engine);
1454 customParser->imports = compilationUnit->typeNameCache().data();
1456 QList<
const QV4::CompiledData::Binding *> bindings;
1457 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index);
1458 const QV4::CompiledData::Binding *binding = obj->bindingTable();
1459 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
1460 if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding))
1461 bindings << binding;
1463 customParser->applyBindings(instance, compilationUnit, bindings);
1465 customParser->engine =
nullptr;
1466 customParser->imports = (QQmlTypeNameCache*)
nullptr;
1470 registerObjectWithContextById(obj, instance);
1474 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(index);
1475 Q_ASSERT(!cache.isNull());
1476 if (installPropertyCache)
1477 ddata->propertyCache = cache;
1479 QObject *scopeObject = instance;
1480 qSwap(_scopeObject, scopeObject);
1482 Q_ASSERT(sharedState->allJavaScriptObjects.canTrack());
1483 sharedState->allJavaScriptObjects.trackObject(v4, instance);
1485 QV4::Scope valueScope(v4);
1486 QV4::QmlContext *qmlContext =
static_cast<QV4::QmlContext *>(valueScope.constructUndefined(1));
1488 qSwap(_qmlContext, qmlContext);
1490 bool ok = populateInstance(index, instance, instance,
nullptr);
1492 if (isContextObject && !pendingAliasBindings.empty()) {
1493 bool processedAtLeastOneBinding =
false;
1495 processedAtLeastOneBinding =
false;
1496 for (std::vector<PendingAliasBinding>::iterator it = pendingAliasBindings.begin();
1497 it != pendingAliasBindings.end(); ) {
1498 if ((*it)(sharedState.data())) {
1499 it = pendingAliasBindings.erase(it);
1500 processedAtLeastOneBinding =
true;
1505 }
while (processedAtLeastOneBinding && pendingAliasBindings.empty());
1506 Q_ASSERT(pendingAliasBindings.empty());
1510 pendingAliasBindings.clear();
1513 qSwap(_qmlContext, qmlContext);
1514 qSwap(_scopeObject, scopeObject);
1516 return ok ? instance :
nullptr;
1519bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
1521 Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
1524 QQmlObjectCreatorRecursionWatcher watcher(
this);
1525 QScopedValueRollback<QQmlObjectCreator*> ocRestore(QQmlEnginePrivate::get(engine)->activeObjectCreator,
this);
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1540 while (!sharedState->allCreatedBindings.empty()) {
1541 QQmlAbstractBinding::Ptr b = sharedState->allCreatedBindings.back();
1542 sharedState->allCreatedBindings.pop_back();
1545 if (!b->isAddedToObject())
1547 QQmlData *data = QQmlData::get(b->targetObject());
1549 data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
1550 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
1551 QQmlPropertyData::DontRemoveBinding);
1552 if (b->kind() == QQmlAbstractBinding::QmlBinding) {
1553 QQmlBinding *binding =
static_cast<QQmlBinding*>(b.data());
1554 if (!binding->hasError() && !binding->hasDependencies()
1555 && !binding->hasUnresolvedNames()) {
1556 b->removeFromObject();
1560 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1564 while (!sharedState->allQPropertyBindings.isEmpty()) {
1565 auto& [target, index, qmlBinding] = sharedState->allQPropertyBindings.first();
1567 QQmlData *data = QQmlData::get(target);
1568 if (!data || !data->hasBindingBit(index)) {
1570 sharedState->allQPropertyBindings.pop_front();
1574 QUntypedBindable bindable;
1575 void *argv[] = { &bindable };
1577 target->metaObject()->metacall(target, QMetaObject::BindableProperty, index, argv);
1578 const bool success = bindable.setBinding(qmlBinding);
1580 const auto bindingPrivateRefCount = QPropertyBindingPrivate::get(qmlBinding)->refCount();
1583 sharedState->allQPropertyBindings.pop_front();
1586 if (success && bindingPrivateRefCount > 1) {
1587 if (
auto priv = QPropertyBindingPrivate::get(qmlBinding); priv->hasCustomVTable()) {
1588 auto qmlBindingPriv =
static_cast<QQmlPropertyBinding *>(priv);
1589 auto jsExpression = qmlBindingPriv->jsExpression();
1590 const bool canRemove = !qmlBinding.error().hasError()
1591 && !qmlBindingPriv->hasDependencies()
1592 && !jsExpression->hasUnresolvedNames();
1594 bindable.takeBinding();
1598 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1602 if (QQmlVME::componentCompleteEnabled()) {
1603 while (!sharedState->allParserStatusCallbacks.empty()) {
1604 QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
1605 const ParserStatus status = sharedState->allParserStatusCallbacks.back();
1606 sharedState->allParserStatusCallbacks.pop_back();
1608 const QQmlGuard<QObject> &instance = sharedState->allCreatedObjects[status.objectIndex];
1612 QQmlParserStatus *parserStatus
1613 =
reinterpret_cast<QQmlParserStatus *>(
1614 reinterpret_cast<
char *>(instance.data()) + status.parserStatusCast);
1615 parserStatus->componentComplete();
1617 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1622 for (QQmlFinalizerHook *hook: sharedState->finalizeHooks) {
1623 hook->componentFinalized();
1624 if (watcher.hasRecursed())
1627 sharedState->finalizeHooks.clear();
1629 while (sharedState->componentAttached) {
1630 QQmlComponentAttached *a = sharedState->componentAttached;
1631 a->removeFromList();
1632 QQmlData *d = QQmlData::get(a->parent());
1634 Q_ASSERT(d->context);
1635 d->context->addComponentAttached(a);
1636 if (QQmlVME::componentCompleteEnabled())
1637 emit a->completed();
1639 if (watcher.hasRecursed() || interrupt.shouldInterrupt())
1648void QQmlObjectCreator::clear()
1650 if (phase == Done || phase == Finalizing || phase == Startup)
1652 Q_ASSERT(phase != Startup);
1654 while (!sharedState->allCreatedObjects.empty()) {
1655 auto object = sharedState->allCreatedObjects.back();
1656 sharedState->allCreatedObjects.pop_back();
1657 if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
1662 while (sharedState->componentAttached) {
1663 QQmlComponentAttached *a = sharedState->componentAttached;
1664 a->removeFromList();
1670bool QQmlObjectCreator::populateInstance(
int index, QObject *instance, QObject *bindingTarget,
1671 const QQmlPropertyData *valueTypeProperty,
1672 const QV4::CompiledData::Binding *binding)
1675 QQmlData *declarativeData = QQmlData::get(instance,
true);
1677 qSwap(_qobject, instance);
1678 qSwap(_valueTypeProperty, valueTypeProperty);
1679 qSwap(_compiledObjectIndex, index);
1680 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(_compiledObjectIndex);
1681 qSwap(_compiledObject, obj);
1682 qSwap(_ddata, declarativeData);
1683 qSwap(_bindingTarget, bindingTarget);
1685 QV4::Scope valueScope(v4);
1686 QV4::ScopedValue scopeObjectProtector(valueScope);
1688 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(_compiledObjectIndex);
1690 QQmlVMEMetaObject *vmeMetaObject =
nullptr;
1691 if (propertyCaches->needsVMEMetaObject(_compiledObjectIndex)) {
1692 Q_ASSERT(!cache.isNull());
1694 vmeMetaObject =
new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
1695 _ddata->propertyCache = cache;
1696 scopeObjectProtector = _ddata->jsWrapper.value();
1698 vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
1701 registerObjectWithContextById(_compiledObject, _qobject);
1703 qSwap(_propertyCache, cache);
1704 qSwap(_vmeMetaObject, vmeMetaObject);
1706 _ddata->compilationUnit = compilationUnit;
1707 if (_compiledObject->hasFlag(QV4::CompiledData::Object::HasDeferredBindings))
1708 _ddata->deferData(_compiledObjectIndex, compilationUnit, context, m_inlineComponentName);
1710 const qsizetype oldRequiredPropertiesCount = sharedState->requiredProperties.size();
1711 QSet<QString> postHocRequired;
1712 for (
auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
1713 postHocRequired.insert(stringAt(it->nameIndex));
1714 bool hadInheritedRequiredProperties = !postHocRequired.empty();
1716 for (
int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
1717 const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
1718 const QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
1720 auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex()));
1721 if (!property->isRequired() && postHocRequired.end() == postHocIt)
1723 if (postHocIt != postHocRequired.end())
1724 postHocRequired.erase(postHocIt);
1725 if (isContextObject)
1726 sharedState->hadTopLevelRequiredProperties =
true;
1727 sharedState->requiredProperties.insert({_qobject, propertyData},
1728 RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex()), compilationUnit->finalUrl(), property->location, {}});
1732 const auto getPropertyCacheRange = [&]() -> std::pair<
int,
int> {
1750 QV4::ResolvedTypeReference *typeRef = resolvedType(_compiledObject->inheritedTypeNameIndex);
1753 if (binding->isAttachedProperty())
1754 return { 0, _propertyCache->propertyCount() };
1755 Q_ASSERT(binding->isGroupProperty());
1756 return { 0, _propertyCache->propertyOffset() + 1 };
1758 Q_ASSERT(!_compiledObject->hasFlag(QV4::CompiledData::Object::IsComponent));
1759 QQmlType type = typeRef->type();
1760 if (type.isComposite() || type.isInlineComponentType())
1761 return { _propertyCache->propertyOffset(), _propertyCache->propertyCount() };
1762 return { 0, _propertyCache->propertyCount() };
1764 const auto [offset, count] = getPropertyCacheRange();
1765 for (
int i = offset; i < count; ++i) {
1766 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1772 if (!propertyData->isRequired() && postHocRequired.isEmpty())
1774 QString name = propertyData->name(_qobject);
1775 auto postHocIt = postHocRequired.find(name);
1776 if (!propertyData->isRequired() && postHocRequired.end() == postHocIt )
1779 if (postHocIt != postHocRequired.end())
1780 postHocRequired.erase(postHocIt);
1782 if (isContextObject)
1783 sharedState->hadTopLevelRequiredProperties =
true;
1784 sharedState->requiredProperties.insert(
1785 {_qobject, propertyData},
1786 RequiredPropertyInfo {
1787 name, compilationUnit->finalUrl(), _compiledObject->location, {} });
1790 if (binding && binding->isAttachedProperty()
1791 && sharedState->requiredProperties.size() != oldRequiredPropertiesCount) {
1794 QLatin1String(
"Attached property has required properties. This is not supported"));
1801 if (!postHocRequired.isEmpty()) {
1803 for (
int i = 0; i < offset; ++i) {
1804 const QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
1807 QString name = propertyData->name(_qobject);
1808 auto postHocIt = postHocRequired.find(name);
1809 if (postHocRequired.end() == postHocIt)
1811 postHocRequired.erase(postHocIt);
1813 if (isContextObject)
1814 sharedState->hadTopLevelRequiredProperties =
true;
1815 sharedState->requiredProperties.insert(
1816 {_qobject, propertyData},
1817 RequiredPropertyInfo {
1818 name, compilationUnit->finalUrl(), _compiledObject->location, {} });
1822 if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
1823 recordError({}, QLatin1String(
"Property %1 was marked as required but does not exist").arg(*postHocRequired.begin()));
1825 if (_compiledObject->nFunctions > 0)
1827 setupBindings((binding && binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding))
1828 ? BindingMode::ApplyAll
1829 : BindingMode::ApplyImmediate);
1831 for (
int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
1836 _vmeMetaObject->connectAlias(_compiledObject, aliasIndex);
1837 const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
1838 const auto originalAlias = alias;
1839 while (alias->isAliasToLocalAlias())
1840 alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
1841 if (!context->isIdValueSet(0))
1843 QObject *target = context->idValue(alias->targetObjectId());
1846 QQmlData *targetDData = QQmlData::get(target,
false);
1847 if (targetDData ==
nullptr || targetDData->propertyCache.isNull())
1850 const QQmlPropertyData *aliasProperty =
1851 _propertyCache->property(_vmeMetaObject->aliasOffset() + aliasIndex);
1854 const int targetPropertyIndex = aliasProperty->aliasTarget();
1855 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1857 const QQmlPropertyData *
const targetProperty = targetDData->propertyCache->property(coreIndex);
1858 if (!targetProperty)
1860 auto it = sharedState->requiredProperties.find({target, targetProperty});
1861 if (it != sharedState->requiredProperties.end())
1862 it->aliasesToRequired.push_back(
1863 AliasToRequiredInfo {
1864 compilationUnit->stringAt(originalAlias->nameIndex()),
1865 compilationUnit->finalUrl()
1869 qSwap(_vmeMetaObject, vmeMetaObject);
1870 qSwap(_bindingTarget, bindingTarget);
1871 qSwap(_ddata, declarativeData);
1872 qSwap(_compiledObject, obj);
1873 qSwap(_compiledObjectIndex, index);
1874 qSwap(_valueTypeProperty, valueTypeProperty);
1875 qSwap(_qobject, instance);
1876 qSwap(_propertyCache, cache);
1878 return errors.isEmpty();
1882
1883
1884QQmlComponent *QQmlObjectCreator::createComponent(
1885 QQmlEngine *engine, QV4::ExecutableCompilationUnit *compilationUnit,
int index,
1886 QObject *parent,
const QQmlRefPointer<QQmlContextData> &context)
1888 QQmlComponent *component =
new QQmlComponent(engine, compilationUnit, index, parent);
1889 QQmlComponentPrivate::get(component)->setCreationContext(context);
1890 QQmlData::get(component,
true);
1900void ObjectInCreationGCAnchorList::trackObject(QV4::ExecutionEngine *engine, QObject *instance)
1902 QV4::Value *wrapper = allocationScope->construct(1, QV4::QObjectWrapper::wrap(engine, instance));
1906 QV4::WriteBarrier::markCustom(engine, [wrapper](QV4::MarkStack *ms) {
1907 wrapper->heapObject()->mark(ms);
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
static QQmlType qmlTypeForObject(QObject *object)
QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator)