612void QQmlBind::setObject(QObject *obj)
616 case QQmlBindPrivate::GeneralizedGroup:
618 warnIgnoredProperties(
this);
620 case QQmlBindPrivate::ObjectPropertyValue:
621 if (d->objectPropertyValueData.obj == obj)
624 case QQmlBindPrivate::Unknown:
627 new (&d->objectPropertyValueData) ObjectPropertyValueData;
628 d->mode = QQmlBindPrivate::ObjectPropertyValue;
634
640
641
642
643 const QQmlProperty whenProp(
this, QLatin1StringView(
"when"));
644 const auto potentialWhenBinding = QQmlAnyBinding::ofProperty(whenProp);
645 if (
auto abstractBinding = potentialWhenBinding.asAbstractBinding()) {
646 QQmlBinding *binding =
static_cast<QQmlBinding *>(abstractBinding);
647 if (binding->hasValidContext()) {
648 const auto boolType = QMetaType::fromType<
bool>();
650 binding->evaluate(&when, boolType);
651 if (when != d->when) {
659 case QQmlBindPrivate::GeneralizedGroup:
660 case QQmlBindPrivate::Unknown:
663 case QQmlBindPrivate::ObjectPropertyValue:
664 d->objectPropertyValueData.obj = obj;
665 if (d->componentComplete) {
666 setTarget(QQmlProperty(
667 d->objectPropertyValueData.obj, d->objectPropertyValueData.propName,
673 if (d->componentComplete && d->when)
677 emit objectChanged();
959 const QQmlProperty &prop,
const QV4::CompiledData::Binding *binding,
960 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
961 const QQmlRefPointer<QQmlContextData> &contextData,
962 QObject *scopeObject)
964 switch (binding->type()) {
965 case QV4::CompiledData::Binding::Type_Translation:
966 case QV4::CompiledData::Binding::Type_TranslationById:
967 return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject);
968 case QV4::CompiledData::Binding::Type_Script: {
969 const QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
970 if (id == QQmlBinding::Invalid) {
971 return QQmlAnyBinding::createFromCodeString(
972 prop, compilationUnit->bindingValueAsString(binding), scopeObject,
973 contextData, compilationUnit->finalUrlString(), binding->location.line());
975 QV4::Scope scope(contextData->engine()->handle());
976 QV4::Scoped<QV4::QmlContext> qmlCtxt(
977 scope, QV4::QmlContext::create(
978 scope.engine->rootContext(), contextData, scopeObject));
979 return QQmlAnyBinding::createFromFunction(
980 prop, compilationUnit->runtimeFunctions.at(id), scopeObject, contextData,
986 return QQmlAnyBinding();
1004 QQmlBind *q,
const QString &propertyPrefix,
1005 QQmlData::DeferredData *deferredData,
1006 const QV4::CompiledData::Binding *binding,
1007 QQmlComponentPrivate::ConstructionState *immediateState)
1009 const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
1010 = deferredData->compilationUnit;
1011 const QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
1012 const QString propertyName = propertyPrefix + propertySuffix;
1014 switch (binding->type()) {
1015 case QV4::CompiledData::Binding::Type_AttachedProperty:
1016 if (propertyPrefix.isEmpty()) {
1020 if (!immediateState)
1023 Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
1024 ->inheritedTypeNameIndex).isEmpty());
1026 const QV4::ResolvedTypeReference *typeReference
1027 = compilationUnit->resolvedType(binding->propertyNameIndex);
1028 Q_ASSERT(typeReference);
1029 QQmlType attachedType = typeReference->type();
1030 if (!attachedType.isValid()) {
1031 if (QQmlTypeLoader *typeLoader = compilationUnit->engine->typeLoader()) {
1032 const QQmlTypeNameCache::Result result
1033 = deferredData->context->imports()->query(propertySuffix, typeLoader);
1034 if (!result.isValid()) {
1035 qmlWarning(q).nospace()
1036 <<
"Unknown name " << propertySuffix <<
". The binding is ignored.";
1039 attachedType = result.type;
1043 QQmlContext *context = qmlContext(q);
1044 QObject *attachedObject = qmlAttachedPropertiesObject(
1045 q, attachedType.attachedPropertiesFunction(QQmlTypeLoader::get(context->engine())));
1046 if (!attachedObject) {
1047 qmlWarning(q).nospace() <<
"Could not create attached properties object '"
1048 << attachedType.typeName() <<
"'";
1052 initCreator(deferredData, QQmlContextData::get(context), immediateState);
1053 immediateState->creator()->populateDeferredInstance(
1054 q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
1055 attachedObject,
nullptr, binding);
1059 case QV4::CompiledData::Binding::Type_GroupProperty: {
1060 const QString pre = propertyName + u'.';
1061 const QV4::CompiledData::Object *subObj
1062 = compilationUnit->objectAt(binding->value.objectIndex);
1063 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
1064 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
1065 decodeBinding(q, pre, deferredData, subBinding, immediateState);
1072 QQmlBindEntry entry;
1073 QQmlContext *context = qmlContext(q);
1074 const QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1075 entry.prop = QQmlPropertyPrivate::create(
nullptr, propertyName, contextData,
1076 QQmlPropertyPrivate::InitFlag::AllowId);
1077 if (!entry.prop.isValid()) {
1080 if (!immediateState)
1083 QQmlProperty property = QQmlPropertyPrivate::create(
1084 q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
1085 if (property.isValid()) {
1086 initCreator(deferredData, contextData, immediateState);
1087 immediateState->creator()->populateDeferredBinding(
1088 property, deferredData->deferredIdx, binding);
1090 qmlWarning(q).nospace() <<
"Unknown name " << propertyName
1091 <<
". The binding is ignored.";
1097 case GeneralizedGroup:
1099 case ObjectPropertyValue:
1100 warnIgnoredProperties(q);
1101 objectPropertyValueData.~ObjectPropertyValueData();
1104 new (&generalizedGroupData) GeneralizedGroupData;
1105 mode = GeneralizedGroup;
1109 const auto setVariant = [&entry](QV4::PersistentValue value) {
1110 entry.currentKind = entry.current.setVariant(value, entry.currentKind);
1113 const auto setBinding = [&entry](QQmlAnyBinding binding) {
1114 entry.currentKind = entry.current.set(binding, entry.currentKind);
1117 switch (binding->type()) {
1118 case QV4::CompiledData::Binding::Type_AttachedProperty:
1119 case QV4::CompiledData::Binding::Type_GroupProperty:
1122 case QV4::CompiledData::Binding::Type_Translation:
1123 case QV4::CompiledData::Binding::Type_TranslationById:
1124 case QV4::CompiledData::Binding::Type_Script:
1126 if (!generalizedGroupData.delayedValues)
1127 createDelayedValues();
1128 const QString delayedName = QString::number(generalizedGroupData.entries.size());
1129 generalizedGroupData.delayedValues->insert(delayedName, QVariant());
1130 QQmlProperty bindingTarget
1131 = QQmlProperty(generalizedGroupData.delayedValues.get(), delayedName);
1132 Q_ASSERT(bindingTarget.isValid());
1133 QQmlAnyBinding anyBinding = createBinding(
1134 bindingTarget, binding, compilationUnit, contextData, q);
1135 anyBinding.installOn(bindingTarget);
1137 setBinding(createBinding(entry.prop, binding, compilationUnit, contextData, q));
1140 case QV4::CompiledData::Binding::Type_String:
1141 setVariant(QV4::PersistentValue(
1142 compilationUnit->engine,
1143 compilationUnit->runtimeStrings[binding->stringIndex]->asReturnedValue()));
1145 case QV4::CompiledData::Binding::Type_Number:
1146 setVariant(QV4::PersistentValue(
1147 compilationUnit->engine,
1148 compilationUnit->constants[binding->value.constantValueIndex].asReturnedValue()));
1150 case QV4::CompiledData::Binding::Type_Boolean:
1151 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode(binding->value.b)));
1153 case QV4::CompiledData::Binding::Type_Null:
1154 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode::null()));
1156 case QV4::CompiledData::Binding::Type_Object:
1157 case QV4::CompiledData::Binding::Type_Invalid:
1161 generalizedGroupData.entries.append(std::move(entry));
1213void QQmlBindPrivate::buildBindEntries(QQmlBind *q, QQmlComponentPrivate::DeferredState *deferredState)
1215 QQmlData *data = QQmlData::get(q);
1216 if (data && !data->deferredData.isEmpty()) {
1217 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
1218 for (QQmlData::DeferredData *deferredData : data->deferredData) {
1219 QMultiHash<
int,
const QV4::CompiledData::Binding *> *bindings = &deferredData->bindings;
1220 if (deferredState) {
1221 QQmlComponentPrivate::ConstructionState constructionState;
1222 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1223 decodeBinding(q, QString(), deferredData, *it, &constructionState);
1226 if (constructionState.hasCreator()) {
1227 ++ep->inProgressCreations;
1228 constructionState.creator()->finalizePopulateDeferred();
1229 constructionState.appendCreatorErrors();
1230 deferredState->push_back(std::move(constructionState));
1233 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1234 decodeBinding(q, QString(), deferredData, *it,
nullptr);
1238 if (deferredState) {
1239 data->releaseDeferredData();
1240 if (!deferredState->empty())
1241 QQmlComponentPrivate::completeDeferred(ep, deferredState);
1285 switch (entry->currentKind) {
1286 case QQmlBindEntryKind::V4Value: {
1287 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1288 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1290 return QV4::RuntimeHelpers::strictEqual(
1292 QV4::Value::fromReturnedValue(vmemo->vmeProperty(propPriv->core.coreIndex())),
1293 *entry->current.v4Value.valueRef());
1295 case QQmlBindEntryKind::Variant: {
1296 const QV4::PersistentValue &v4Value = entry->current.v4Value;
1297 QMetaType propMetaType = entry->prop.propertyMetaType();
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309 QVariant valueAsVariant = v4Value.engine()->toVariant(*v4Value.valueRef(),
1311 if (propMetaType.flags() & QMetaType::IsQmlList) {
1314 QList<QObject *> expectedObjectList;
1315 QQmlListProperty<QObject> expectedAsListProp(
nullptr, &expectedObjectList);
1316 QQmlPropertyPrivate::convertToQQmlListProperty(&expectedAsListProp, propMetaType, valueAsVariant);
1318 QVariant actualValue = entry->prop.read();
1320 QQmlListReference* listReference = get_if<QQmlListReference>(&actualValue);
1321 Q_ASSERT(listReference);
1322 auto actualObjectList = QQmlListReferencePrivate::get(listReference)->property.toList<QList<QObject *>>();
1323 return std::equal(expectedObjectList.constBegin(), expectedObjectList.constEnd(),
1324 actualObjectList.constBegin(), actualObjectList.constEnd());
1326 }
else if (QMetaType varMetaType = valueAsVariant.metaType(); varMetaType != propMetaType) {
1327 QVariant converted = QQmlPropertyPrivate::convertToWriteTargetType(
1328 valueAsVariant, propMetaType);
1329 if (converted.isValid())
1330 valueAsVariant = std::move(converted);
1332 return valueAsVariant
1333 == entry->prop.read();
1335 case QQmlBindEntryKind::Binding:
1336 return entry->current.binding == QQmlAnyBinding::ofProperty(entry->prop);
1337 case QQmlBindEntryKind::None:
1346 if (!entry->prop.isValid() || (entry->currentKind == QQmlBindEntryKind::None))
1348 if (!entry->prop.object())
1358 switch (entry->previousKind) {
1359 case QQmlBindEntryKind::Binding:
1361 QQmlAnyBinding p = std::move(entry->previous.binding);
1363 p.installOn(entry->prop);
1366 case QQmlBindEntryKind::V4Value:
1368 QQmlAnyBinding::takeFrom(entry->prop);
1369 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1370 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1372 vmemo->setVMEProperty(propPriv->core.coreIndex(),
1373 *entry->previous.v4Value.valueRef());
1377 case QQmlBindEntryKind::Variant:
1379 QQmlAnyBinding::takeFrom(entry->prop);
1380 const QV4::PersistentValue &v4Value = entry->previous.v4Value;
1381 entry->prop.write(v4Value.engine()->toVariant(
1382 *v4Value.valueRef(), entry->prop.propertyMetaType()));
1386 case QQmlBindEntryKind::None:
1393 if (entry->previousKind == QQmlBindEntryKind::None) {
1395 QQmlAnyBinding prevBind = QQmlAnyBinding::takeFrom(entry->prop);
1397 entry->previousKind = entry->previous.set(std::move(prevBind), entry->previousKind);
1400 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1401 auto propData = propPriv->core;
1402 if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
1403 QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(propPriv->object);
1405 auto retVal = vmemo->vmeProperty(propData.coreIndex());
1406 entry->previousKind = entry->previous.set(
1407 QV4::PersistentValue(vmemo->engine(), retVal), entry->previousKind);
1408 }
else if (entry->prop.propertyMetaType().flags() & QMetaType::IsQmlList) {
1409 using namespace QV4;
1410 ExecutionEngine *v4 = qmlEngine(q_func())->handle();
1411 entry->previousKind = entry->previous.setVariant(
1412 QV4::PersistentValue(v4, QV4::QmlListWrapper::createOwned(v4, entry->prop)),
1413 entry->previousKind);
1417 entry->previousKind = entry->previous.set(
1418 propPriv->engine->handle(), entry->prop.read(), entry->previousKind);
1425 QQmlPropertyPrivate::removeBinding(entry->prop, QQmlPropertyPrivate::OverrideSticky);