960 const QQmlProperty &prop,
const QV4::CompiledData::Binding *binding,
961 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
962 const QQmlRefPointer<QQmlContextData> &contextData,
963 QObject *scopeObject)
965 switch (binding->type()) {
966 case QV4::CompiledData::Binding::Type_Translation:
967 case QV4::CompiledData::Binding::Type_TranslationById:
968 return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject);
969 case QV4::CompiledData::Binding::Type_Script: {
970 const QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
971 if (id == QQmlBinding::Invalid) {
972 return QQmlAnyBinding::createFromCodeString(
973 prop, compilationUnit->bindingValueAsString(binding), scopeObject,
974 contextData, compilationUnit->finalUrlString(), binding->location.line());
976 QV4::Scope scope(contextData->engine()->handle());
977 QV4::Scoped<QV4::QmlContext> qmlCtxt(
978 scope, QV4::QmlContext::create(
979 scope.engine->rootContext(), contextData, scopeObject));
980 return QQmlAnyBinding::createFromFunction(
981 prop, compilationUnit->runtimeFunctions.at(id), scopeObject, contextData,
987 return QQmlAnyBinding();
1005 QQmlBind *q,
const QString &propertyPrefix,
1006 QQmlData::DeferredData *deferredData,
int objectIndex,
1007 const QV4::CompiledData::Binding *binding,
1008 QQmlComponentPrivate::ConstructionState *immediateState)
1010 const QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
1011 = deferredData->compilationUnit;
1012 QString propertySuffix = compilationUnit->stringAt(binding->propertyNameIndex);
1013 const int bindingIndex =
int(binding - compilationUnit->objectAt(objectIndex)->bindingTable());
1014 if (compilationUnit->bindingIsSignalHandlerExpression(objectIndex, bindingIndex)
1015 || compilationUnit->bindingIsSignalHandlerObject(objectIndex, bindingIndex)) {
1016 propertySuffix = *QQmlSignalNames::anyHandlerNameToSignalName(propertySuffix);
1017 }
else if (compilationUnit->bindingIsPropertyObserver(objectIndex, bindingIndex)) {
1018 propertySuffix = *QQmlSignalNames::changedHandlerNameToPropertyName(propertySuffix);
1020 const QString propertyName = propertyPrefix + propertySuffix;
1022 switch (binding->type()) {
1023 case QV4::CompiledData::Binding::Type_AttachedProperty:
1024 if (propertyPrefix.isEmpty()) {
1028 if (!immediateState)
1031 Q_ASSERT(compilationUnit->stringAt(compilationUnit->objectAt(binding->value.objectIndex)
1032 ->inheritedTypeNameIndex).isEmpty());
1034 const QV4::ResolvedTypeReference *typeReference
1035 = compilationUnit->resolvedType(binding->propertyNameIndex);
1036 Q_ASSERT(typeReference);
1037 QQmlType attachedType = typeReference->type();
1038 if (!attachedType.isValid()) {
1039 if (QQmlTypeLoader *typeLoader = compilationUnit->engine->typeLoader()) {
1040 const QQmlTypeNameCache::Result result
1041 = deferredData->context->imports()->query(propertySuffix, typeLoader);
1042 if (!result.isValid()) {
1043 qmlWarning(q).nospace()
1044 <<
"Unknown name " << propertySuffix <<
". The binding is ignored.";
1047 attachedType = result.type;
1051 QQmlContext *context = qmlContext(q);
1052 QObject *attachedObject = qmlAttachedPropertiesObject(
1053 q, attachedType.attachedPropertiesFunction(QQmlTypeLoader::get(context->engine())));
1054 if (!attachedObject) {
1055 qmlWarning(q).nospace() <<
"Could not create attached properties object '"
1056 << attachedType.typeName() <<
"'";
1060 initCreator(deferredData, QQmlContextData::get(context), immediateState);
1061 immediateState->creator()->populateDeferredInstance(
1062 q, deferredData->deferredIdx, binding->value.objectIndex, attachedObject,
1063 attachedObject,
nullptr, binding);
1067 case QV4::CompiledData::Binding::Type_GroupedProperty: {
1068 const QString pre = propertyName + u'.';
1069 const QV4::CompiledData::Object *subObj
1070 = compilationUnit->objectAt(binding->value.objectIndex);
1071 const QV4::CompiledData::Binding *subBinding = subObj->bindingTable();
1072 for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding)
1073 decodeBinding(q, pre, deferredData, binding->value.objectIndex, subBinding,
1081 QQmlBindEntry entry;
1082 QQmlContext *context = qmlContext(q);
1083 const QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1084 entry.prop = QQmlPropertyPrivate::create(
nullptr, propertyName, contextData,
1085 QQmlPropertyPrivate::InitFlag::AllowId);
1086 if (!entry.prop.isValid()) {
1089 if (!immediateState)
1092 QQmlProperty property = QQmlPropertyPrivate::create(
1093 q, propertyName, contextData, QQmlPropertyPrivate::InitFlag::AllowSignal);
1094 if (property.isValid()) {
1095 initCreator(deferredData, contextData, immediateState);
1096 immediateState->creator()->populateDeferredBinding(
1097 property, deferredData->deferredIdx, binding);
1099 qmlWarning(q).nospace() <<
"Unknown name " << propertyName
1100 <<
". The binding is ignored.";
1106 case GeneralizedGroup:
1108 case ObjectPropertyValue:
1109 warnIgnoredProperties(q);
1110 objectPropertyValueData.~ObjectPropertyValueData();
1113 new (&generalizedGroupData) GeneralizedGroupData;
1114 mode = GeneralizedGroup;
1118 const auto setVariant = [&entry](QV4::PersistentValue value) {
1119 entry.currentKind = entry.current.setVariant(value, entry.currentKind);
1122 const auto setBinding = [&entry](QQmlAnyBinding binding) {
1123 entry.currentKind = entry.current.set(binding, entry.currentKind);
1126 switch (binding->type()) {
1127 case QV4::CompiledData::Binding::Type_AttachedProperty:
1128 case QV4::CompiledData::Binding::Type_GroupedProperty:
1131 case QV4::CompiledData::Binding::Type_Translation:
1132 case QV4::CompiledData::Binding::Type_TranslationById:
1133 case QV4::CompiledData::Binding::Type_Script:
1135 if (!generalizedGroupData.delayedValues)
1136 createDelayedValues();
1137 const QString delayedName = QString::number(generalizedGroupData.entries.size());
1138 generalizedGroupData.delayedValues->insert(delayedName, QVariant());
1139 QQmlProperty bindingTarget
1140 = QQmlProperty(generalizedGroupData.delayedValues.get(), delayedName);
1141 Q_ASSERT(bindingTarget.isValid());
1142 QQmlAnyBinding anyBinding = createBinding(
1143 bindingTarget, binding, compilationUnit, contextData, q);
1144 anyBinding.installOn(bindingTarget);
1146 setBinding(createBinding(entry.prop, binding, compilationUnit, contextData, q));
1149 case QV4::CompiledData::Binding::Type_String:
1150 setVariant(QV4::PersistentValue(
1151 compilationUnit->engine,
1152 compilationUnit->runtimeStrings[binding->stringIndex]->asReturnedValue()));
1154 case QV4::CompiledData::Binding::Type_Number:
1155 setVariant(QV4::PersistentValue(
1156 compilationUnit->engine,
1157 QV4::Encode(compilationUnit->bindingValueAsNumber(binding))));
1159 case QV4::CompiledData::Binding::Type_Boolean:
1160 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode(binding->value.b)));
1162 case QV4::CompiledData::Binding::Type_Null:
1163 setVariant(QV4::PersistentValue(compilationUnit->engine, QV4::Encode::null()));
1165 case QV4::CompiledData::Binding::Type_Object:
1168 if (!immediateState)
1170 auto v4 = compilationUnit->engine;
1173 const QQmlProperty &property = entry.prop;
1174 QObject *bindingTargetObject = property.object();
1177 int objectToBeCreated = binding->value.objectIndex;
1179 auto context = qmlContext(bindingTargetObject);
1180 auto contextData = QQmlContextData::get(context);
1181 initCreator(deferredData, contextData, immediateState);
1182 QObject *newObject = immediateState->creator()->createObjectInContext(objectToBeCreated, bindingTargetObject, contextData);
1183 setVariant(QV4::PersistentValue(v4, QV4::QObjectWrapper::wrap(v4, newObject)));
1186 case QV4::CompiledData::Binding::Type_Invalid:
1190 generalizedGroupData.entries.append(std::move(entry));
1242void QQmlBindPrivate::buildBindEntries(QQmlBind *q, QQmlComponentPrivate::DeferredState *deferredState)
1244 QQmlData *data = QQmlData::get(q);
1245 if (data && !data->deferredData.isEmpty()) {
1246 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
1247 for (QQmlData::DeferredData *deferredData : data->deferredData) {
1248 QMultiHash<
int,
const QV4::CompiledData::Binding *> *bindings = &deferredData->bindings;
1249 if (deferredState) {
1250 QQmlComponentPrivate::ConstructionState constructionState;
1251 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1252 decodeBinding(q, QString(), deferredData, deferredData->deferredIdx, *it,
1253 &constructionState);
1256 if (constructionState.hasCreator()) {
1257 ++ep->inProgressCreations;
1258 constructionState.creator()->finalizePopulateDeferred();
1259 constructionState.appendCreatorErrors();
1260 deferredState->push_back(std::move(constructionState));
1263 for (
auto it = bindings->cbegin(); it != bindings->cend(); ++it)
1264 decodeBinding(q, QString(), deferredData, deferredData->deferredIdx, *it,
1269 if (deferredState) {
1270 data->releaseDeferredData();
1271 if (!deferredState->empty())
1272 QQmlComponentPrivate::completeDeferred(ep, deferredState);
1316 switch (entry->currentKind) {
1317 case QQmlBindEntryKind::V4Value: {
1318 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1319 QQmlVMEMetaObject *vmemo =
1320 QQmlVMEMetaObject::get(propPriv->object, propPriv->engine->handle());
1322 return QV4::RuntimeHelpers::strictEqual(
1324 QV4::Value::fromReturnedValue(vmemo->vmeProperty(propPriv->core.coreIndex())),
1325 *entry->current.v4Value.valueRef());
1327 case QQmlBindEntryKind::Variant: {
1328 const QV4::PersistentValue &v4Value = entry->current.v4Value;
1329 QMetaType propMetaType = entry->prop.propertyMetaType();
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341 QVariant valueAsVariant = v4Value.engine()->toVariant(*v4Value.valueRef(),
1343 if (propMetaType.flags() & QMetaType::IsQmlList) {
1346 QList<QObject *> expectedObjectList;
1347 QQmlListProperty<QObject> expectedAsListProp(
nullptr, &expectedObjectList);
1348 QQmlPropertyPrivate::convertToQQmlListProperty(&expectedAsListProp, propMetaType, valueAsVariant);
1350 QVariant actualValue = entry->prop.read();
1352 QQmlListReference* listReference = get_if<QQmlListReference>(&actualValue);
1353 Q_ASSERT(listReference);
1354 auto actualObjectList = QQmlListReferencePrivate::get(listReference)->property.toList<QList<QObject *>>();
1355 return std::equal(expectedObjectList.constBegin(), expectedObjectList.constEnd(),
1356 actualObjectList.constBegin(), actualObjectList.constEnd());
1358 }
else if (QMetaType varMetaType = valueAsVariant.metaType(); varMetaType != propMetaType) {
1359 QVariant converted = QQmlPropertyPrivate::convertToWriteTargetType(
1360 valueAsVariant, propMetaType);
1361 if (converted.isValid())
1362 valueAsVariant = std::move(converted);
1364 return valueAsVariant
1365 == entry->prop.read();
1367 case QQmlBindEntryKind::Binding:
1368 return entry->current.binding == QQmlAnyBinding::ofProperty(entry->prop);
1369 case QQmlBindEntryKind::None:
1378 if (!entry->prop.isValid() || (entry->currentKind == QQmlBindEntryKind::None))
1380 if (!entry->prop.object())
1390 switch (entry->previousKind) {
1391 case QQmlBindEntryKind::Binding:
1393 QQmlAnyBinding p = std::move(entry->previous.binding);
1395 p.installOn(entry->prop);
1398 case QQmlBindEntryKind::V4Value:
1400 QQmlAnyBinding::takeFrom(entry->prop);
1401 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1402 QQmlVMEMetaObject *vmemo =
1403 QQmlVMEMetaObject::get(propPriv->object, propPriv->engine->handle());
1405 vmemo->setVMEProperty(propPriv->core.coreIndex(),
1406 *entry->previous.v4Value.valueRef());
1410 case QQmlBindEntryKind::Variant:
1412 QQmlAnyBinding::takeFrom(entry->prop);
1413 const QV4::PersistentValue &v4Value = entry->previous.v4Value;
1414 entry->prop.write(v4Value.engine()->toVariant(
1415 *v4Value.valueRef(), entry->prop.propertyMetaType()));
1419 case QQmlBindEntryKind::None:
1426 if (entry->previousKind == QQmlBindEntryKind::None) {
1428 QQmlAnyBinding prevBind = QQmlAnyBinding::takeFrom(entry->prop);
1430 entry->previousKind = entry->previous.set(std::move(prevBind), entry->previousKind);
1433 auto propPriv = QQmlPropertyPrivate::get(entry->prop);
1434 auto propData = propPriv->core;
1435 if (!propPriv->valueTypeData.isValid() && propData.isVarProperty()) {
1436 QQmlVMEMetaObject *vmemo =
1437 QQmlVMEMetaObject::get(propPriv->object, propPriv->engine->handle());
1439 auto retVal = vmemo->vmeProperty(propData.coreIndex());
1440 entry->previousKind = entry->previous.set(
1441 QV4::PersistentValue(vmemo->engine(), retVal), entry->previousKind);
1442 }
else if (entry->prop.propertyMetaType().flags() & QMetaType::IsQmlList) {
1443 using namespace QV4;
1444 ExecutionEngine *v4 = qmlEngine(q_func())->handle();
1445 entry->previousKind = entry->previous.setVariant(
1446 QV4::PersistentValue(v4, QV4::QmlListWrapper::createOwned(v4, entry->prop)),
1447 entry->previousKind);
1451 entry->previousKind = entry->previous.set(
1452 propPriv->engine->handle(), entry->prop.read(), entry->previousKind);
1459 QQmlPropertyPrivate::removeBinding(entry->prop, QQmlPropertyPrivate::OverrideSticky);