574void QQmlBind::setObject(QObject *obj)
578 case QQmlBindPrivate::GeneralizedGroup:
580 warnIgnoredProperties(
this);
582 case QQmlBindPrivate::ObjectPropertyValue:
583 if (d->objectPropertyValueData.obj == obj)
586 case QQmlBindPrivate::Unknown:
589 new (&d->objectPropertyValueData) ObjectPropertyValueData;
590 d->mode = QQmlBindPrivate::ObjectPropertyValue;
596
602
603
604
605 const QQmlProperty whenProp(
this, QLatin1StringView(
"when"));
606 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
607 if (
auto abstractBinding = potentialWhenBinding.asAbstractBinding()) {
608 QQmlBinding *binding =
static_cast<QQmlBinding *>(abstractBinding);
609 if (binding->hasValidContext()) {
610 const auto boolType = QMetaType::fromType<
bool>();
612 binding->evaluate(&when, boolType);
613 if (when != d->when) {
621 case QQmlBindPrivate::GeneralizedGroup:
622 case QQmlBindPrivate::Unknown:
625 case QQmlBindPrivate::ObjectPropertyValue:
626 d->objectPropertyValueData.obj = obj;
627 if (d->componentComplete) {
628 setTarget(QQmlProperty(
629 d->objectPropertyValueData.obj, d->objectPropertyValueData.propName,
635 if (d->componentComplete && d->when)
639 emit objectChanged();
921 const QQmlProperty &prop,
const QV4::CompiledData::Binding *binding,
922 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
923 const QQmlRefPointer<QQmlContextData> &contextData,
924 QObject *scopeObject)
926 switch (binding->type()) {
927 case QV4::CompiledData::Binding::Type_Translation:
928 case QV4::CompiledData::Binding::Type_TranslationById:
929 return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject);
930 case QV4::CompiledData::Binding::Type_Script: {
931 const QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
932 if (id == QQmlBinding::Invalid) {
933 return QQmlAnyBinding::createFromCodeString(
934 prop, compilationUnit->bindingValueAsString(binding), scopeObject,
935 contextData, compilationUnit->finalUrlString(), binding->location.line());
937 QV4::Scope scope(contextData->engine()->handle());
938 QV4::Scoped<QV4::QmlContext> qmlCtxt(
939 scope, QV4::QmlContext::create(
940 scope.engine->rootContext(), contextData, scopeObject));
941 return QQmlAnyBinding::createFromFunction(
942 prop, compilationUnit->runtimeFunctions.at(id), scopeObject, contextData,
948 return QQmlAnyBinding();
966 QQmlBind *q,
const QString &propertyPrefix,
967 QQmlData::DeferredData *deferredData,
968 const QV4::CompiledData::Binding *binding,
969 QQmlComponentPrivate::ConstructionState *immediateState)
971 const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
972 = deferredData->compilationUnit;
973 const QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
974 const QString propertyName = propertyPrefix + propertySuffix;
976 switch (binding->type()) {
977 case QV4::CompiledData::Binding::Type_AttachedProperty:
978 if (propertyPrefix.isEmpty()) {
985 Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
986 ->inheritedTypeNameIndex).isEmpty());
988 const QV4::ResolvedTypeReference *typeReference
989 = compilationUnit->resolvedType(binding->propertyNameIndex);
990 Q_ASSERT(typeReference);
991 QQmlType attachedType = typeReference->type();
992 if (!attachedType.isValid()) {
993 if (QQmlTypeLoader *typeLoader = compilationUnit->engine->typeLoader()) {
994 const QQmlTypeNameCache::Result result
995 = deferredData->context->imports()->query(propertySuffix, typeLoader);
996 if (!result.isValid()) {
997 qmlWarning(q).nospace()
998 <<
"Unknown name " << propertySuffix <<
". The binding is ignored.";
1001 attachedType = result.type;
1005 QQmlContext *context = qmlContext(q);
1006 QObject *attachedObject = qmlAttachedPropertiesObject(
1007 q, attachedType.attachedPropertiesFunction(QQmlTypeLoader::get(context->engine())));
1008 if (!attachedObject) {
1009 qmlWarning(q).nospace() <<
"Could not create attached properties object '"
1010 << attachedType.typeName() <<
"'";
1014 initCreator(deferredData, QQmlContextData::get(context), immediateState);
1015 immediateState->creator()->populateDeferredInstance(
1016 q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
1017 attachedObject,
nullptr, binding);
1021 case QV4::CompiledData::Binding::Type_GroupProperty: {
1022 const QString pre = propertyName + u'.';
1023 const QV4::CompiledData::Object *subObj
1024 = compilationUnit->objectAt(binding->value.objectIndex);
1025 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
1026 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
1027 decodeBinding(q, pre, deferredData, subBinding, immediateState);
1034 QQmlBindEntry entry;
1035 QQmlContext *context = qmlContext(q);
1036 const QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1037 entry.prop = QQmlPropertyPrivate::create(
nullptr, propertyName, contextData,
1038 QQmlPropertyPrivate::InitFlag::AllowId);
1039 if (!entry.prop.isValid()) {
1042 if (!immediateState)
1045 QQmlProperty property = QQmlPropertyPrivate::create(
1046 q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
1047 if (property.isValid()) {
1048 initCreator(deferredData, contextData, immediateState);
1049 immediateState->creator()->populateDeferredBinding(
1050 property, deferredData->deferredIdx, binding);
1052 qmlWarning(q).nospace() <<
"Unknown name " << propertyName
1053 <<
". The binding is ignored.";
1059 case GeneralizedGroup:
1061 case ObjectPropertyValue:
1062 warnIgnoredProperties(q);
1063 objectPropertyValueData.~ObjectPropertyValueData();
1066 new (&generalizedGroupData) GeneralizedGroupData;
1067 mode = GeneralizedGroup;
1071 const auto setVariant = [&entry](QV4::PersistentValue value) {
1072 entry.currentKind = entry.current.setVariant(value, entry.currentKind);
1075 const auto setBinding = [&entry](QQmlAnyBinding binding) {
1076 entry.currentKind = entry.current.set(binding, entry.currentKind);
1079 switch (binding->type()) {
1080 case QV4::CompiledData::Binding::Type_AttachedProperty:
1081 case QV4::CompiledData::Binding::Type_GroupProperty:
1084 case QV4::CompiledData::Binding::Type_Translation:
1085 case QV4::CompiledData::Binding::Type_TranslationById:
1086 case QV4::CompiledData::Binding::Type_Script:
1088 if (!generalizedGroupData.delayedValues)
1089 createDelayedValues();
1090 const QString delayedName = QString::number(generalizedGroupData.entries.size());
1091 generalizedGroupData.delayedValues->insert(delayedName, QVariant());
1092 QQmlProperty bindingTarget
1093 = QQmlProperty(generalizedGroupData.delayedValues.get(), delayedName);
1094 Q_ASSERT(bindingTarget.isValid());
1095 QQmlAnyBinding anyBinding = createBinding(
1096 bindingTarget, binding, compilationUnit, contextData, q);
1097 anyBinding.installOn(bindingTarget);
1099 setBinding(createBinding(entry.prop, binding, compilationUnit, contextData, q));
1102 case QV4::CompiledData::Binding::Type_String:
1103 setVariant(QV4::PersistentValue(
1104 compilationUnit->engine,
1105 compilationUnit->runtimeStrings[binding->stringIndex]->asReturnedValue()));
1107 case QV4::CompiledData::Binding::Type_Number:
1108 setVariant(QV4::PersistentValue(
1109 compilationUnit->engine,
1110 compilationUnit->constants[binding->value.constantValueIndex].asReturnedValue()));
1112 case QV4::CompiledData::Binding::Type_Boolean:
1113 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode(binding->value.b)));
1115 case QV4::CompiledData::Binding::Type_Null:
1116 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode::null()));
1118 case QV4::CompiledData::Binding::Type_Object:
1119 case QV4::CompiledData::Binding::Type_Invalid:
1123 generalizedGroupData.entries.append(std::move(entry));
1175void QQmlBindPrivate::buildBindEntries(QQmlBind *q, QQmlComponentPrivate::DeferredState *deferredState)
1177 QQmlData *data = QQmlData::get(q);
1178 if (data && !data->deferredData.isEmpty()) {
1179 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
1180 for (QQmlData::DeferredData *deferredData : data->deferredData) {
1181 QMultiHash<
int,
const QV4::CompiledData::Binding *> *bindings = &deferredData->bindings;
1182 if (deferredState) {
1183 QQmlComponentPrivate::ConstructionState constructionState;
1184 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1185 decodeBinding(q, QString(), deferredData, *it, &constructionState);
1188 if (constructionState.hasCreator()) {
1189 ++ep->inProgressCreations;
1190 constructionState.creator()->finalizePopulateDeferred();
1191 constructionState.appendCreatorErrors();
1192 deferredState->push_back(std::move(constructionState));
1195 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1196 decodeBinding(q, QString(), deferredData, *it,
nullptr);
1200 if (deferredState) {
1201 data->releaseDeferredData();
1202 if (!deferredState->empty())
1203 QQmlComponentPrivate::completeDeferred(ep, deferredState);
1247 switch (entry->currentKind) {
1248 case QQmlBindEntryKind::V4Value: {
1249 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1250 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1252 return QV4::RuntimeHelpers::strictEqual(
1254 QV4::Value::fromReturnedValue(vmemo->vmeProperty(propPriv->core.coreIndex())),
1255 *entry->current.v4Value.valueRef());
1257 case QQmlBindEntryKind::Variant: {
1258 const QV4::PersistentValue &v4Value = entry->current.v4Value;
1259 QMetaType propMetaType = entry->prop.propertyMetaType();
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 QVariant valueAsVariant = v4Value.engine()->toVariant(*v4Value.valueRef(),
1273 if (propMetaType.flags() & QMetaType::IsQmlList) {
1276 QList<QObject *> expectedObjectList;
1277 QQmlListProperty<QObject> expectedAsListProp(
nullptr, &expectedObjectList);
1278 QQmlPropertyPrivate::convertToQQmlListProperty(&expectedAsListProp, propMetaType, valueAsVariant);
1280 QVariant actualValue = entry->prop.read();
1282 QQmlListReference* listReference = get_if<QQmlListReference>(&actualValue);
1283 Q_ASSERT(listReference);
1284 auto actualObjectList = QQmlListReferencePrivate::get(listReference)->property.toList<QList<QObject *>>();
1285 return std::equal(expectedObjectList.constBegin(), expectedObjectList.constEnd(),
1286 actualObjectList.constBegin(), actualObjectList.constEnd());
1288 }
else if (QMetaType varMetaType = valueAsVariant.metaType(); varMetaType != propMetaType) {
1289 QVariant converted = QQmlPropertyPrivate::convertToWriteTargetType(
1290 valueAsVariant, propMetaType);
1291 if (converted.isValid())
1292 valueAsVariant = std::move(converted);
1294 return valueAsVariant
1295 == entry->prop.read();
1297 case QQmlBindEntryKind::Binding:
1298 return entry->current.binding == QQmlAnyBinding::ofProperty(entry->prop);
1299 case QQmlBindEntryKind::None:
1308 if (!entry->prop.isValid() || (entry->currentKind == QQmlBindEntryKind::None))
1310 if (!entry->prop.object())
1320 switch (entry->previousKind) {
1321 case QQmlBindEntryKind::Binding:
1323 QQmlAnyBinding p = std::move(entry->previous.binding);
1325 p.installOn(entry->prop);
1328 case QQmlBindEntryKind::V4Value:
1330 QQmlAnyBinding::takeFrom(entry->prop);
1331 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1332 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1334 vmemo->setVMEProperty(propPriv->core.coreIndex(),
1335 *entry->previous.v4Value.valueRef());
1339 case QQmlBindEntryKind::Variant:
1341 QQmlAnyBinding::takeFrom(entry->prop);
1342 const QV4::PersistentValue &v4Value = entry->previous.v4Value;
1343 entry->prop.write(v4Value.engine()->toVariant(
1344 *v4Value.valueRef(), entry->prop.propertyMetaType()));
1348 case QQmlBindEntryKind::None:
1355 if (entry->previousKind == QQmlBindEntryKind::None) {
1357 QQmlAnyBinding prevBind = QQmlAnyBinding::takeFrom(entry->prop);
1359 entry->previousKind = entry->previous.set(std::move(prevBind), entry->previousKind);
1362 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1363 auto propData = propPriv->core;
1364 if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
1365 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1367 auto retVal = vmemo->vmeProperty(propData.coreIndex());
1368 entry->previousKind = entry->previous.set(
1369 QV4::PersistentValue(vmemo->engine, retVal), entry->previousKind);
1370 }
else if (entry->prop.propertyMetaType().flags() & QMetaType::IsQmlList) {
1371 using namespace QV4;
1372 ExecutionEngine *v4 = qmlEngine(q_func())->handle();
1373 entry->previousKind = entry->previous.setVariant(
1374 QV4::PersistentValue(v4, QV4::QmlListWrapper::createOwned(v4, entry->prop)),
1375 entry->previousKind);
1379 entry->previousKind = entry->previous.set(
1380 propPriv->engine->handle(), entry->prop.read(), entry->previousKind);
1387 QQmlPropertyPrivate::removeBinding(entry->prop, QQmlPropertyPrivate::OverrideSticky);