diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-04 15:26:30 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-05-17 11:15:14 +0200 |
commit | 530d3749c59971e9ec3a8a333c6783842ebb288e (patch) | |
tree | 1fccf496d7852eebcaee6de703eb7b9c112d2293 | |
parent | 8b03ab373660a6ff3df7bcdfc64e0acf6ca10b97 (diff) |
QML: Port QV4::CompiledData::Binding to new special integer bitfield
Task-number: QTBUG-99545
Change-Id: I9f8bc5fa45c61f77ee95b055a3d8de001da8f8c5
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 36ebee4e69182f0e44d87691d4740b271e1dcf38)
23 files changed, 362 insertions, 276 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index c5a80848b3..cb9e85d8ea 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -472,7 +472,7 @@ struct Binding { quint32_le propertyNameIndex; - enum ValueType : unsigned int { + enum Type : unsigned int { Type_Invalid, Type_Boolean, Type_Number, @@ -486,7 +486,7 @@ struct Binding Type_GroupProperty }; - enum Flags : unsigned int { + enum Flag : unsigned int { IsSignalHandlerExpression = 0x1, IsSignalHandlerObject = 0x2, IsOnAssignment = 0x4, @@ -499,11 +499,20 @@ struct Binding IsFunctionExpression = 0x200, IsPropertyObserver = 0x400 }; + Q_DECLARE_FLAGS(Flags, Flag); + + using FlagsField = quint32_le_bitfield_member<0, 16>; + using TypeField = quint32_le_bitfield_member<16, 16>; + quint32_le_bitfield_union<FlagsField, TypeField> flagsAndType; + + void clearFlags() { flagsAndType.set<FlagsField>(0); } + void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); } + bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; } + Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); } + + void setType(Type type) { flagsAndType.set<TypeField>(type); } + Type type() const { return Type(flagsAndType.get<TypeField>()); } - union { - quint32_le_bitfield<0, 16> flags; - quint32_le_bitfield<16, 16> type; - }; union { bool b; quint32_le constantValueIndex; @@ -517,24 +526,31 @@ struct Binding Location location; Location valueLocation; + bool hasSignalHandlerBindingFlag() const + { + const Flags bindingFlags = flags(); + return bindingFlags & IsSignalHandlerExpression + || bindingFlags & IsSignalHandlerObject + || bindingFlags & IsPropertyObserver; + } + bool isValueBinding() const { - if (type == Type_AttachedProperty - || type == Type_GroupProperty) - return false; - if (flags & IsSignalHandlerExpression - || flags & IsSignalHandlerObject - || flags & IsPropertyObserver) + switch (type()) { + case Type_AttachedProperty: + case Type_GroupProperty: return false; - return true; + default: + return !hasSignalHandlerBindingFlag(); + } } - bool isValueBindingNoAlias() const { return isValueBinding() && !(flags & IsBindingToAlias); } - bool isValueBindingToAlias() const { return isValueBinding() && (flags & IsBindingToAlias); } + bool isValueBindingNoAlias() const { return isValueBinding() && !hasFlag(IsBindingToAlias); } + bool isValueBindingToAlias() const { return isValueBinding() && hasFlag(IsBindingToAlias); } bool isSignalHandler() const { - if (flags & IsSignalHandlerExpression || flags & IsSignalHandlerObject || flags & IsPropertyObserver) { + if (hasSignalHandlerBindingFlag()) { Q_ASSERT(!isValueBinding()); Q_ASSERT(!isAttachedProperty()); Q_ASSERT(!isGroupProperty()); @@ -545,7 +561,7 @@ struct Binding bool isAttachedProperty() const { - if (type == Type_AttachedProperty) { + if (type() == Type_AttachedProperty) { Q_ASSERT(!isValueBinding()); Q_ASSERT(!isSignalHandler()); Q_ASSERT(!isGroupProperty()); @@ -556,7 +572,7 @@ struct Binding bool isGroupProperty() const { - if (type == Type_GroupProperty) { + if (type() == Type_GroupProperty) { Q_ASSERT(!isValueBinding()); Q_ASSERT(!isSignalHandler()); Q_ASSERT(!isAttachedProperty()); @@ -565,7 +581,7 @@ struct Binding return false; } - bool isFunctionExpression() const { return (flags & IsFunctionExpression); } + bool isFunctionExpression() const { return hasFlag(IsFunctionExpression); } //reverse of Lexer::singleEscape() static QString escapedString(const QString &string) @@ -610,16 +626,19 @@ struct Binding return tmp; } - bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; } - bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); } + bool isTranslationBinding() const + { + const Binding::Type bindingType = type(); + return bindingType == Type_Translation || bindingType == Type_TranslationById; + } + bool evaluatesToString() const { return type() == Type_String || isTranslationBinding(); } bool valueAsBoolean() const { - if (type == Type_Boolean) + if (type() == Type_Boolean) return value.b; return false; } - }; static_assert(sizeof(Binding) == 24, "Binding structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); @@ -1175,7 +1194,7 @@ struct TypeReferenceMap : QHash<int, TypeReference> auto binding = obj->bindingsBegin(); auto const bindingEnd = obj->bindingsEnd(); for ( ; binding != bindingEnd; ++binding) { - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) + if (binding->type() == QV4::CompiledData::Binding::Type_AttachedProperty) this->add(binding->propertyNameIndex, binding->location); } @@ -1357,7 +1376,7 @@ public: QString bindingValueAsString(const CompiledData::Binding *binding) const { using namespace CompiledData; - switch (binding->type) { + switch (binding->type()) { case Binding::Type_Script: case Binding::Type_String: return stringAt(binding->stringIndex); @@ -1380,14 +1399,14 @@ public: QString bindingValueAsScriptString(const CompiledData::Binding *binding) const { - return (binding->type == CompiledData::Binding::Type_String) + return (binding->type() == CompiledData::Binding::Type_String) ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex)) : bindingValueAsString(binding); } double bindingValueAsNumber(const CompiledData::Binding *binding) const { - if (binding->type != CompiledData::Binding::Type_Number) + if (binding->type() != CompiledData::Binding::Type_Number) return 0.0; return constants[binding->value.constantValueIndex].doubleValue(); } diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 9078b21ccd..cf8b6c1e8a 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -333,13 +333,17 @@ void Object::appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraDat QString Object::appendBinding(Binding *b, bool isListBinding) { const bool bindingToDefaultProperty = (b->propertyNameIndex == quint32(0)); - if (!isListBinding && !bindingToDefaultProperty - && b->type != QV4::CompiledData::Binding::Type_GroupProperty - && b->type != QV4::CompiledData::Binding::Type_AttachedProperty - && !(b->flags & QV4::CompiledData::Binding::IsOnAssignment)) { + if (!isListBinding + && !bindingToDefaultProperty + && b->type() != QV4::CompiledData::Binding::Type_GroupProperty + && b->type() != QV4::CompiledData::Binding::Type_AttachedProperty + && !b->hasFlag(QV4::CompiledData::Binding::IsOnAssignment)) { Binding *existing = findBinding(b->propertyNameIndex); - if (existing && existing->isValueBinding() == b->isValueBinding() && !(existing->flags & QV4::CompiledData::Binding::IsOnAssignment)) + if (existing + && existing->isValueBinding() == b->isValueBinding() + && !existing->hasFlag(QV4::CompiledData::Binding::IsOnAssignment)) { return tr("Property value set multiple times"); + } } if (bindingToDefaultProperty) insertSorted(b); @@ -1138,30 +1142,30 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST QQmlJS::SourceLocation loc = statement->firstSourceLocation(); binding->valueLocation.line = loc.startLine; binding->valueLocation.column = loc.startColumn; - binding->type = QV4::CompiledData::Binding::Type_Invalid; + binding->setType(QV4::CompiledData::Binding::Type_Invalid); if (_propertyDeclaration && _propertyDeclaration->isReadOnly) - binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration; + binding->setFlag(QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration); QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(statement); if (exprStmt) { QQmlJS::AST::ExpressionNode * const expr = exprStmt->expression; if (QQmlJS::AST::StringLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::StringLiteral *>(expr)) { - binding->type = QV4::CompiledData::Binding::Type_String; + binding->setType(QV4::CompiledData::Binding::Type_String); binding->stringIndex = registerString(lit->value.toString()); } else if (QQmlJS::AST::TemplateLiteral *templateLit = QQmlJS::AST::cast<QQmlJS::AST::TemplateLiteral *>(expr); templateLit && templateLit->hasNoSubstitution) { // A template literal without substitution is just a string. // With substitution, it could however be an arbitrarily complex expression - binding->type = QV4::CompiledData::Binding::Type_String; + binding->setType(QV4::CompiledData::Binding::Type_String); binding->stringIndex = registerString(templateLit->value.toString()); } else if (expr->kind == QQmlJS::AST::Node::Kind_TrueLiteral) { - binding->type = QV4::CompiledData::Binding::Type_Boolean; + binding->setType(QV4::CompiledData::Binding::Type_Boolean); binding->value.b = true; } else if (expr->kind == QQmlJS::AST::Node::Kind_FalseLiteral) { - binding->type = QV4::CompiledData::Binding::Type_Boolean; + binding->setType(QV4::CompiledData::Binding::Type_Boolean); binding->value.b = false; } else if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expr)) { - binding->type = QV4::CompiledData::Binding::Type_Number; + binding->setType(QV4::CompiledData::Binding::Type_Number); binding->value.constantValueIndex = jsGenerator->registerConstant(QV4::Encode(lit->value)); } else if (QQmlJS::AST::CallExpression *call = QQmlJS::AST::cast<QQmlJS::AST::CallExpression *>(expr)) { if (QQmlJS::AST::IdentifierExpression *base = QQmlJS::AST::cast<QQmlJS::AST::IdentifierExpression *>(call->base)) { @@ -1170,21 +1174,21 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST // below. } } else if (QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression *>(expr)) { - binding->flags |= QV4::CompiledData::Binding::IsFunctionExpression; + binding->setFlag(QV4::CompiledData::Binding::IsFunctionExpression); } else if (QQmlJS::AST::UnaryMinusExpression *unaryMinus = QQmlJS::AST::cast<QQmlJS::AST::UnaryMinusExpression *>(expr)) { if (QQmlJS::AST::NumericLiteral *lit = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(unaryMinus->expression)) { - binding->type = QV4::CompiledData::Binding::Type_Number; + binding->setType(QV4::CompiledData::Binding::Type_Number); binding->value.constantValueIndex = jsGenerator->registerConstant(QV4::Encode(-lit->value)); } } else if (QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr)) { - binding->type = QV4::CompiledData::Binding::Type_Null; + binding->setType(QV4::CompiledData::Binding::Type_Null); binding->value.nullMarker = 0; } } // Do binding instead - if (binding->type == QV4::CompiledData::Binding::Type_Invalid) { - binding->type = QV4::CompiledData::Binding::Type_Script; + if (binding->type() == QV4::CompiledData::Binding::Type_Invalid) { + binding->setType(QV4::CompiledData::Binding::Type_Script); CompiledFunctionOrExpression *expr = New<CompiledFunctionOrExpression>(); expr->node = statement; @@ -1211,8 +1215,8 @@ void IRBuilder::tryGeneratingTranslationBinding(QStringView base, AST::ArgumentL { auto registerMainString = [&](QStringView mainString) { return jsGenerator->registerString(mainString.toString()) ; }; auto registerCommentString = [&](QStringView commentString) { return jsGenerator->registerString(commentString.toString()); }; - auto finalizeTranslationData = [&](QV4::CompiledData::Binding::ValueType type, QV4::CompiledData::TranslationData translationData) { - binding->type = type; + auto finalizeTranslationData = [&](QV4::CompiledData::Binding::Type type, QV4::CompiledData::TranslationData translationData) { + binding->setType(type); if (type == QV4::CompiledData::Binding::Type_Translation || type == QV4::CompiledData::Binding::Type_TranslationById) binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData); else if (type == QV4::CompiledData::Binding::Type_String) @@ -1256,7 +1260,7 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio binding->offset = nameLocation.offset; binding->location.line = nameLocation.startLine; binding->location.column = nameLocation.startColumn; - binding->flags = 0; + binding->clearFlags(); setBindingValue(binding, value, parentNode); QString error = bindingsTarget()->appendBinding(binding, /*isListBinding*/false); if (!error.isEmpty()) { @@ -1280,21 +1284,21 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio const Object *obj = _objects.at(objectIndex); binding->valueLocation = obj->location; - binding->flags = 0; + binding->clearFlags(); if (_propertyDeclaration && _propertyDeclaration->isReadOnly) - binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration; + binding->setFlag(Binding::InitializerForReadOnlyDeclaration); // No type name on the initializer means it must be a group property if (_objects.at(objectIndex)->inheritedTypeNameIndex == emptyStringIndex) - binding->type = QV4::CompiledData::Binding::Type_GroupProperty; + binding->setType(Binding::Type_GroupProperty); else - binding->type = QV4::CompiledData::Binding::Type_Object; + binding->setType(Binding::Type_Object); if (isOnAssignment) - binding->flags |= QV4::CompiledData::Binding::IsOnAssignment; + binding->setFlag(Binding::IsOnAssignment); if (isListItem) - binding->flags |= QV4::CompiledData::Binding::IsListItem; + binding->setFlag(Binding::IsListItem); binding->value.objectIndex = objectIndex; QString error = bindingsTarget()->appendBinding(binding, isListItem); @@ -1476,15 +1480,15 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O binding->location.column = qualifiedIdElement->identifierToken.startColumn; binding->valueLocation.line = qualifiedIdElement->next->identifierToken.startLine; binding->valueLocation.column = qualifiedIdElement->next->identifierToken.startColumn; - binding->flags = 0; + binding->clearFlags(); if (onAssignment) - binding->flags |= QV4::CompiledData::Binding::IsOnAssignment; + binding->setFlag(QV4::CompiledData::Binding::IsOnAssignment); if (isAttachedProperty) - binding->type = QV4::CompiledData::Binding::Type_AttachedProperty; + binding->setType(QV4::CompiledData::Binding::Type_AttachedProperty); else - binding->type = QV4::CompiledData::Binding::Type_GroupProperty; + binding->setType(QV4::CompiledData::Binding::Type_GroupProperty); int objIndex = 0; if (!defineQMLObject(&objIndex, nullptr, binding->location, nullptr, nullptr)) @@ -1838,7 +1842,7 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding continue; QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr); *bindingToWrite = *b; - if (b->type == QV4::CompiledData::Binding::Type_Script) + if (b->type() == QV4::CompiledData::Binding::Type_Script) bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices.at(b->value.compiledScriptIndex); bindingPtr += sizeof(QV4::CompiledData::Binding); } @@ -1950,7 +1954,7 @@ bool JSCodeGen::compileComponent(int contextObject) if (obj->flags & QV4::CompiledData::Object::IsComponent) { Q_ASSERT(obj->bindingCount() == 1); const QV4::CompiledData::Binding *componentBinding = obj->firstBinding(); - Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object); + Q_ASSERT(componentBinding->type() == QV4::CompiledData::Binding::Type_Object); contextObject = componentBinding->value.objectIndex; } @@ -1979,11 +1983,12 @@ bool JSCodeGen::compileJavaScriptCodeInObjectsRecursively(int objectIndex, int s } for (const QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) { - if (binding->type < QV4::CompiledData::Binding::Type_Object) + const Binding::Type bindingType = binding->type(); + if (bindingType < QV4::CompiledData::Binding::Type_Object) continue; int target = binding->value.objectIndex; - int scope = binding->type == QV4::CompiledData::Binding::Type_Object ? target : scopeObjectIndex; + int scope = bindingType == QV4::CompiledData::Binding::Type_Object ? target : scopeObjectIndex; if (!compileJavaScriptCodeInObjectsRecursively(binding->value.objectIndex, scope)) return false; diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp index b543cd99e3..9a6f0de37d 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit.cpp +++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp @@ -882,7 +882,7 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind { using namespace CompiledData; #if QT_CONFIG(translation) - switch (binding->type) { + switch (binding->type()) { case Binding::Type_TranslationById: { const TranslationData &translation = data->translations()[binding->value.translationDataIndex]; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index c060ee70f8..e3840c8011 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1171,7 +1171,7 @@ void QQmlData::deferData( const QV4::CompiledData::Binding *binding = compiledObject->bindingTable(); for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) { const QQmlPropertyData *property = propertyData.at(i); - if (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding) + if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) deferData->bindings.insert(property ? property->coreIndex() : -1, binding); } diff --git a/src/qml/qml/qqmlirloader.cpp b/src/qml/qml/qqmlirloader.cpp index 6b8be0bb74..7b871a419a 100644 --- a/src/qml/qml/qqmlirloader.cpp +++ b/src/qml/qml/qqmlirloader.cpp @@ -119,7 +119,7 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali QmlIR::Binding *b = pool->New<QmlIR::Binding>(); *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i]; object->bindings->append(b); - if (b->type == QV4::CompiledData::Binding::Type_Script) { + if (b->type() == QV4::CompiledData::Binding::Type_Script) { functionIndices.append(b->value.compiledScriptIndex); b->value.compiledScriptIndex = functionIndices.count() - 1; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 8d8028a39d..cd94304b52 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -254,7 +254,7 @@ void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex, { doPopulateDeferred(instance, deferredIndex, [this, qmlProperty, binding]() { Q_ASSERT(qmlProperty); - Q_ASSERT(binding->flags & QV4::CompiledData::Binding::IsDeferredBinding); + Q_ASSERT(binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)); QQmlListProperty<void> savedList; qSwap(_currentList, savedList); @@ -312,7 +312,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QMetaType propertyType = property->propType(); if (property->isEnum()) { - if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) { + if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum)) { propertyType = QMetaType::fromType<int>(); } else { // ### This should be resolved earlier at compile time and the binding value should be changed accordingly. @@ -326,18 +326,18 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const auto assertOrNull = [&](bool ok) { - Q_ASSERT(ok || binding->type == QV4::CompiledData::Binding::Type_Null); + Q_ASSERT(ok || binding->type() == QV4::CompiledData::Binding::Type_Null); Q_UNUSED(ok); }; - auto assertType = [&](QV4::CompiledData::Binding::ValueType type) + auto assertType = [&](QV4::CompiledData::Binding::Type type) { - Q_ASSERT(binding->type == type || binding->type == QV4::CompiledData::Binding::Type_Null); + Q_ASSERT(binding->type()== type || binding->type() == QV4::CompiledData::Binding::Type_Null); Q_UNUSED(type); }; if (property->isQObject()) { - if (binding->type == QV4::CompiledData::Binding::Type_Null) { + if (binding->type() == QV4::CompiledData::Binding::Type_Null) { QObject *value = nullptr; const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags); Q_ASSERT(ok); @@ -348,7 +348,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const switch (propertyType.id()) { case QMetaType::QVariant: { - if (binding->type == QV4::CompiledData::Binding::Type_Number) { + if (binding->type() == QV4::CompiledData::Binding::Type_Number) { double n = compilationUnit->bindingValueAsNumber(binding); if (double(int(n)) == n) { if (property->isVarProperty()) { @@ -366,14 +366,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const property->writeProperty(_qobject, &value, propertyWriteFlags); } } - } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { + } else if (binding->type() == QV4::CompiledData::Binding::Type_Boolean) { if (property->isVarProperty()) { _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::fromBoolean(binding->valueAsBoolean())); } else { QVariant value(binding->valueAsBoolean()); property->writeProperty(_qobject, &value, propertyWriteFlags); } - } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + } else if (binding->type() == QV4::CompiledData::Binding::Type_Null) { if (property->isVarProperty()) { _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue()); } else { @@ -578,18 +578,24 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const break; } else if (propertyType == QMetaType::fromType<QJSValue>()) { QJSValue value; - if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Boolean: value = QJSValue(binding->valueAsBoolean()); - } else if (binding->type == QV4::CompiledData::Binding::Type_Number) { - double n = compilationUnit->bindingValueAsNumber(binding); - if (double(int(n)) == n) { + break; + case QV4::CompiledData::Binding::Type_Number: { + const double n = compilationUnit->bindingValueAsNumber(binding); + if (double(int(n)) == n) value = QJSValue(int(n)); - } else + else value = QJSValue(n); - } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + break; + } + case QV4::CompiledData::Binding::Type_Null: value = QJSValue::NullValue; - } else { + break; + default: value = QJSValue(compilationUnit->bindingValueAsString(binding)); + break; } property->writeProperty(_qobject, &value, propertyWriteFlags); break; @@ -629,8 +635,8 @@ void QQmlObjectCreator::setupBindings(BindingSetupFlags mode) if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType().id() == QMetaType::QString) { QV4::CompiledData::Binding idBinding; idBinding.propertyNameIndex = 0; // Not used - idBinding.flags = 0; - idBinding.type = QV4::CompiledData::Binding::Type_String; + idBinding.clearFlags(); + idBinding.setType(QV4::CompiledData::Binding::Type_String); idBinding.stringIndex = _compiledObject->idNameIndex; idBinding.location = _compiledObject->location; // ### setPropertyValue(idProperty, &idBinding); @@ -685,10 +691,10 @@ void QQmlObjectCreator::setupBindings(BindingSetupFlags mode) } - if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding) + if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding)) continue; - if (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding) { + if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) { if (!(mode & ApplyDeferred)) continue; } else if (!(mode & ApplyImmediate)) { @@ -744,7 +750,8 @@ void QQmlObjectCreator::setupBindings(BindingSetupFlags mode) bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProperty, const QV4::CompiledData::Binding *binding) { - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + const QV4::CompiledData::Binding::Type bindingType = binding->type(); + if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) { Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty()); QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex); Q_ASSERT(tr); @@ -776,11 +783,11 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper if (bindingProperty && bindingProperty->propType() == QMetaType::fromType<QQmlScriptString>()) { QQmlScriptString ss(compilationUnit->bindingValueAsScriptString(binding), context->asQQmlContext(), _scopeObject); - ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid; + ss.d.data()->bindingId = bindingType == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid; ss.d.data()->lineNumber = binding->location.line; ss.d.data()->columnNumber = binding->location.column; - ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String; - ss.d.data()->isNumberLiteral = binding->type == QV4::CompiledData::Binding::Type_Number; + ss.d.data()->isStringLiteral = bindingType == QV4::CompiledData::Binding::Type_String; + ss.d.data()->isNumberLiteral = bindingType == QV4::CompiledData::Binding::Type_Number; ss.d.data()->numberValue = compilationUnit->bindingValueAsNumber(binding); QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | @@ -792,13 +799,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper } QObject *createdSubObject = nullptr; - if (binding->type == QV4::CompiledData::Binding::Type_Object) { + if (bindingType == QV4::CompiledData::Binding::Type_Object) { createdSubObject = createInstance(binding->value.objectIndex, _bindingTarget); if (!createdSubObject) return false; } - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) { + if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) { const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex); if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) { @@ -855,9 +862,11 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper if (!bindingProperty) // ### error return true; - const bool allowedToRemoveBinding = !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) - && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment) - && !(binding->flags & QV4::CompiledData::Binding::IsPropertyObserver) + const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags(); + const bool allowedToRemoveBinding + = !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression) + && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) + && !(bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) && !_valueTypeProperty; if (_ddata->hasBindingBit(bindingProperty->coreIndex()) && allowedToRemoveBinding) { @@ -870,9 +879,9 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper pendingBindings.erase(it, pendingBindings.end()); } - if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression - || binding->flags & QV4::CompiledData::Binding::IsPropertyObserver) { + if (bindingType == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { + if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression + || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) { QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]; int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex()); QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression( @@ -963,8 +972,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper return true; } - if (binding->type == QV4::CompiledData::Binding::Type_Object) { - if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { + if (bindingType == QV4::CompiledData::Binding::Type_Object) { + if (bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) { // ### determine value source and interceptor casts ahead of time. QQmlType type = qmlTypeForObject(createdSubObject); Q_ASSERT(type.isValid()); @@ -1028,7 +1037,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper } // Assigning object to signal property? ### Qt 7: Remove that functionality - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) { + if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) { if (!bindingProperty->isFunction()) { recordError(binding->valueLocation, tr("Cannot assign an object to signal property %1").arg(bindingProperty->name(_qobject))); return false; @@ -1310,9 +1319,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo const QV4::CompiledData::Object *obj = compilationUnit->objectAt(index); const QV4::CompiledData::Binding *binding = obj->bindingTable(); for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) { - if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding) { + if (binding->hasFlag(QV4::CompiledData::Binding::IsCustomParserBinding)) bindings << binding; - } } customParser->applyBindings(instance, compilationUnit.data(), bindings); @@ -1653,7 +1661,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (_compiledObject->nFunctions > 0) setupFunctions(); - setupBindings((binding && (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding)) + setupBindings((binding && binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding)) ? BindingMode::ApplyAll : BindingMode::ApplyImmediate); diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index d542175647..45edb59cfb 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -110,8 +110,10 @@ QQmlBindingInstantiationContext::QQmlBindingInstantiationContext(int referencing bool QQmlBindingInstantiationContext::resolveInstantiatingProperty() { - if (!instantiatingBinding || instantiatingBinding->type != QV4::CompiledData::Binding::Type_GroupProperty) + if (!instantiatingBinding + || instantiatingBinding->type() != QV4::CompiledData::Binding::Type_GroupProperty) { return true; + } Q_ASSERT(referencingObjectIndex >= 0); Q_ASSERT(referencingObjectPropertyCache); diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index bf293a1cd3..3c85b8c3b4 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -298,7 +298,8 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur auto binding = obj->bindingsBegin(); auto end = obj->bindingsEnd(); for ( ; binding != end; ++binding) { - if (binding->type == QV4::CompiledData::Binding::Type_Object && (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)) { + if (binding->type() == QV4::CompiledData::Binding::Type_Object + && (binding->flags() & QV4::CompiledData::Binding::IsOnAssignment)) { // If the on assignment is inside a group property, we need to distinguish between QObject based // group properties and value type group properties. For the former the base type is derived from // the property that references us, for the latter we only need a meta-object on the referencing object @@ -344,7 +345,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur auto binding = obj->bindingsBegin(); auto end = obj->bindingsEnd(); for (; binding != end; ++binding) { - switch (binding->type) { + switch (binding->type()) { case QV4::CompiledData::Binding::Type_Object: case QV4::CompiledData::Binding::Type_GroupProperty: // We can resolve object and group properties if we have a property cache. @@ -879,12 +880,15 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl auto binding = object.bindingsBegin(); auto end = object.bindingsEnd(); for (; binding != end; ++binding) { - if (binding->type != QV4::CompiledData::Binding::Type_Object - && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty - && binding->type != QV4::CompiledData::Binding::Type_GroupProperty) - continue; - - collectObjectsWithAliasesRecursively(binding->value.objectIndex, objectsWithAliases); + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Object: + case QV4::CompiledData::Binding::Type_AttachedProperty: + case QV4::CompiledData::Binding::Type_GroupProperty: + collectObjectsWithAliasesRecursively(binding->value.objectIndex, objectsWithAliases); + break; + default: + break; + } } } diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp index 8e60afb57d..023a945e94 100644 --- a/src/qml/qml/qqmlpropertyvalidator.cpp +++ b/src/qml/qml/qqmlpropertyvalidator.cpp @@ -110,7 +110,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( if (obj->flags & QV4::CompiledData::Object::IsComponent && !(obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)) { Q_ASSERT(obj->nBindings == 1); const QV4::CompiledData::Binding *componentBinding = obj->bindingTable(); - Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object); + Q_ASSERT(componentBinding->type() == QV4::CompiledData::Binding::Type_Object); return validateObject(componentBinding->value.objectIndex, componentBinding); } @@ -135,7 +135,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( if (!binding->isGroupProperty()) continue; - if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) + if (binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment)) continue; if (populatingValueTypeGroupProperty) { @@ -164,9 +164,11 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( binding = obj->bindingTable(); for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) { QString name = stringAt(binding->propertyNameIndex); + const QV4::CompiledData::Binding::Type bindingType = binding->type(); + const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags(); if (customParser) { - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) { if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) { customBindings << binding; continue; @@ -179,13 +181,14 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( } bool bindingToDefaultProperty = false; - bool isGroupProperty = instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty; + bool isGroupProperty = instantiatingBinding + && instantiatingBinding->type() == QV4::CompiledData::Binding::Type_GroupProperty; bool notInRevision = false; QQmlPropertyData *pd = nullptr; if (!name.isEmpty()) { - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression - || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) { + if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression + || bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) { pd = propertyResolver.signal(name, ¬InRevision); } else { pd = propertyResolver.property(name, ¬InRevision, @@ -229,12 +232,12 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( return recordError(binding->location, tr("Invalid attached object assignment")); } - if (binding->type >= QV4::CompiledData::Binding::Type_Object + if (bindingType >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty() || binding->isGroupProperty())) { const bool populatingValueTypeGroupProperty = pd && QQmlMetaType::metaObjectForValueType(pd->propType()) - && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment); + && !binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment); const QVector<QQmlError> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, populatingValueTypeGroupProperty); @@ -243,24 +246,24 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( } // Signal handlers were resolved and checked earlier in the signal handler conversion pass. - if (binding->flags & (QV4::CompiledData::Binding::IsSignalHandlerExpression + if (binding->flags() & (QV4::CompiledData::Binding::IsSignalHandlerExpression | QV4::CompiledData::Binding::IsSignalHandlerObject | QV4::CompiledData::Binding::IsPropertyObserver)) { continue; } - if ((pd && binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) - || (!pd && binding->type == QV4::CompiledData::Binding::Type_GroupProperty)) { + if ((pd && bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) + || (!pd && bindingType == QV4::CompiledData::Binding::Type_GroupProperty)) { if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) { return recordError( binding->location, tr("%1 properties cannot be used here") - .arg(binding->type == QV4::CompiledData::Binding::Type_AttachedProperty + .arg(bindingType == QV4::CompiledData::Binding::Type_AttachedProperty ? QStringLiteral("Attached") : QStringLiteral("Group"))); } continue; - } else if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + } else if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) { continue; } @@ -271,15 +274,15 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( if (!pd->isWritable() && !pd->isQList() && !binding->isGroupProperty() - && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration) + && !(bindingFlags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration) ) { - if (assigningToGroupProperty && binding->type < QV4::CompiledData::Binding::Type_Object) + if (assigningToGroupProperty && bindingType < QV4::CompiledData::Binding::Type_Object) return recordError(binding->valueLocation, tr("Cannot assign a value directly to a grouped property")); return recordError(binding->valueLocation, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); } - if (!pd->isQList() && (binding->flags & QV4::CompiledData::Binding::IsListItem)) { + if (!pd->isQList() && (bindingFlags & QV4::CompiledData::Binding::IsListItem)) { QString error; if (pd->propType() == QMetaType::fromType<QQmlScriptString>()) error = tr( "Cannot assign multiple values to a script property"); @@ -290,7 +293,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( if (!bindingToDefaultProperty && !binding->isGroupProperty() - && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment) + && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment) && assigningToGroupProperty) { QV4::CompiledData::Location loc = binding->valueLocation; if (loc < (*assignedGroupProperty)->valueLocation) @@ -301,11 +304,11 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject( return recordError(loc, tr("Cannot assign a value directly to a grouped property")); } - if (binding->type < QV4::CompiledData::Binding::Type_Script) { + if (bindingType < QV4::CompiledData::Binding::Type_Script) { QQmlError bindingError = validateLiteralBinding(propertyCache, pd, binding); if (bindingError.isValid()) return recordError(bindingError); - } else if (binding->type == QV4::CompiledData::Binding::Type_Object) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Object) { QQmlError bindingError = validateObjectBinding(pd, name, binding); if (bindingError.isValid()) return recordError(bindingError); @@ -390,7 +393,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( QQmlError noError; if (property->isEnum()) { - if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) + if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum)) return noError; QString value = compilationUnit->bindingValueAsString(binding); @@ -408,7 +411,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } auto warnOrError = [&](const QString &error) { - if (binding->type == QV4::CompiledData::Binding::Type_Null) { + if (binding->type() == QV4::CompiledData::Binding::Type_Null) { QQmlError warning; warning.setUrl(compilationUnit->url()); warning.setLine(qmlConvertSourceCoordinate<quint32, int>(binding->valueLocation.line)); @@ -422,10 +425,11 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( return qQmlCompileError(binding->valueLocation, error); }; + const QV4::CompiledData::Binding::Type bindingType = binding->type(); const auto isStringBinding = [&]() -> bool { // validateLiteralBinding is not supposed to be used on scripts - Q_ASSERT(binding->type != QV4::CompiledData::Binding::Type_Script); - return binding->type == QV4::CompiledData::Binding::Type_String; + Q_ASSERT(bindingType != QV4::CompiledData::Binding::Type_Script); + return bindingType == QV4::CompiledData::Binding::Type_String; }; switch (property->propType().id()) { @@ -444,19 +448,17 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } break; case QMetaType::QByteArray: { - if (binding->type != QV4::CompiledData::Binding::Type_String) { + if (bindingType != QV4::CompiledData::Binding::Type_String) return warnOrError(tr("Invalid property assignment: byte array expected")); - } } break; case QMetaType::QUrl: { - if (binding->type != QV4::CompiledData::Binding::Type_String) { + if (bindingType != QV4::CompiledData::Binding::Type_String) return warnOrError(tr("Invalid property assignment: url expected")); - } } break; case QMetaType::UInt: { - if (binding->type == QV4::CompiledData::Binding::Type_Number) { + if (bindingType == QV4::CompiledData::Binding::Type_Number) { double d = compilationUnit->bindingValueAsNumber(binding); if (double(uint(d)) == d) return noError; @@ -465,7 +467,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } break; case QMetaType::Int: { - if (binding->type == QV4::CompiledData::Binding::Type_Number) { + if (bindingType == QV4::CompiledData::Binding::Type_Number) { double d = compilationUnit->bindingValueAsNumber(binding); if (double(int(d)) == d) return noError; @@ -474,13 +476,13 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } break; case QMetaType::Float: { - if (binding->type != QV4::CompiledData::Binding::Type_Number) { + if (bindingType != QV4::CompiledData::Binding::Type_Number) { return warnOrError(tr("Invalid property assignment: number expected")); } } break; case QMetaType::Double: { - if (binding->type != QV4::CompiledData::Binding::Type_Number) { + if (bindingType != QV4::CompiledData::Binding::Type_Number) { return warnOrError(tr("Invalid property assignment: number expected")); } } @@ -578,7 +580,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } break; case QMetaType::Bool: { - if (binding->type != QV4::CompiledData::Binding::Type_Boolean) { + if (bindingType != QV4::CompiledData::Binding::Type_Boolean) { return warnOrError(tr("Invalid property assignment: boolean expected")); } } @@ -610,12 +612,12 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( default: { // generate single literal value assignment to a list property if required if (property->propType() == QMetaType::fromType<QList<qreal> >()) { - if (binding->type != QV4::CompiledData::Binding::Type_Number) { + if (bindingType != QV4::CompiledData::Binding::Type_Number) { return warnOrError(tr("Invalid property assignment: number or array of numbers expected")); } break; } else if (property->propType() == QMetaType::fromType<QList<int> >()) { - bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number); + bool ok = (bindingType == QV4::CompiledData::Binding::Type_Number); if (ok) { double n = compilationUnit->bindingValueAsNumber(binding); if (double(int(n)) != n) @@ -625,12 +627,12 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( return warnOrError(tr("Invalid property assignment: int or array of ints expected")); break; } else if (property->propType() == QMetaType::fromType<QList<bool> >()) { - if (binding->type != QV4::CompiledData::Binding::Type_Boolean) { + if (bindingType != QV4::CompiledData::Binding::Type_Boolean) { return warnOrError(tr("Invalid property assignment: bool or array of bools expected")); } break; } else if (property->propType() == QMetaType::fromType<QList<QUrl> >()) { - if (binding->type != QV4::CompiledData::Binding::Type_String) { + if (bindingType != QV4::CompiledData::Binding::Type_String) { return warnOrError(tr("Invalid property assignment: url or array of urls expected")); } break; @@ -644,7 +646,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding( } else if (property->propType() == QMetaType::fromType<QQmlScriptString>()) { break; } else if (property->isQObject() - && binding->type == QV4::CompiledData::Binding::Type_Null) { + && bindingType == QV4::CompiledData::Binding::Type_Null) { break; } @@ -702,8 +704,8 @@ QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *propert { QQmlError noError; - if (binding->flags & QV4::CompiledData::Binding::IsOnAssignment) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Object); + if (binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment)) { + Q_ASSERT(binding->type() == QV4::CompiledData::Binding::Type_Object); bool isValueSource = false; bool isPropertyInterceptor = false; @@ -753,7 +755,8 @@ QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *propert } } return noError; - } else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) { + } else if (binding->hasFlag(QV4::CompiledData::Binding::IsSignalHandlerObject) + && property->isFunction()) { return noError; } else if (isPrimitiveType(propType)) { auto typeName = QString::fromUtf8(QMetaType(propType).name()); diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp index a9a69c9331..34ea7db029 100644 --- a/src/qml/qml/qqmltypecompiler.cpp +++ b/src/qml/qml/qqmltypecompiler.cpp @@ -340,7 +340,8 @@ bool SignalHandlerResolver::resolveSignalHandlerExpressions(const QmlIR::Object for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { const QString bindingPropertyName = stringAt(binding->propertyNameIndex); // Attached property? - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + const QV4::CompiledData::Binding::Type bindingType = binding->type(); + if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) { const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex); auto *typeRef = resolvedType(binding->propertyNameIndex); QQmlType type = typeRef ? typeRef->type() : QQmlType(); @@ -373,7 +374,8 @@ bool SignalHandlerResolver::resolveSignalHandlerExpressions(const QmlIR::Object QQmlPropertyData * const signalPropertyData = resolver.property(signalName, /*notInRevision ptr*/nullptr); QQmlPropertyData * const qPropertyData = !qPropertyName.isEmpty() ? resolver.property(qPropertyName) : nullptr; QString finalSignalHandlerPropertyName = signalName; - uint flags = QV4::CompiledData::Binding::IsSignalHandlerExpression; + QV4::CompiledData::Binding::Flag flag + = QV4::CompiledData::Binding::IsSignalHandlerExpression; const bool isPropertyObserver = !signalPropertyData && qPropertyData && qPropertyData->isBindable(); if (signal && !(qPropertyData && qPropertyData->isAlias() && isPropertyObserver)) { @@ -395,7 +397,7 @@ bool SignalHandlerResolver::resolveSignalHandlerExpressions(const QmlIR::Object } } else if (isPropertyObserver) { finalSignalHandlerPropertyName = qPropertyName; - flags = QV4::CompiledData::Binding::IsPropertyObserver; + flag = QV4::CompiledData::Binding::IsPropertyObserver; } else { if (notInRevision) { // Try assinging it as a property later @@ -443,13 +445,13 @@ bool SignalHandlerResolver::resolveSignalHandlerExpressions(const QmlIR::Object } // Binding object to signal means connect the signal to the object's default method. - if (binding->type == QV4::CompiledData::Binding::Type_Object) { - binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerObject; + if (bindingType == QV4::CompiledData::Binding::Type_Object) { + binding->setFlag(QV4::CompiledData::Binding::IsSignalHandlerObject); continue; } - if (binding->type != QV4::CompiledData::Binding::Type_Script) { - if (binding->type < QV4::CompiledData::Binding::Type_Script) { + if (bindingType != QV4::CompiledData::Binding::Type_Script) { + if (bindingType < QV4::CompiledData::Binding::Type_Script) { COMPILE_EXCEPTION(binding, tr("Cannot assign a value to a signal (expecting a script to be run)")); } else { COMPILE_EXCEPTION(binding, tr("Incorrectly specified signal assignment")); @@ -457,7 +459,7 @@ bool SignalHandlerResolver::resolveSignalHandlerExpressions(const QmlIR::Object } binding->propertyNameIndex = compiler->registerString(finalSignalHandlerPropertyName); - binding->flags |= flags; + binding->setFlag(flag); } return true; } @@ -481,12 +483,13 @@ bool QQmlEnumTypeResolver::resolveEnumBindings() QQmlPropertyResolver resolver(propertyCache); for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression - || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject - || binding->flags & QV4::CompiledData::Binding::IsPropertyObserver) + const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags(); + if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression + || bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject + || bindingFlags & QV4::CompiledData::Binding::IsPropertyObserver) continue; - if (binding->type != QV4::CompiledData::Binding::Type_Script) + if (binding->type() != QV4::CompiledData::Binding::Type_Script) continue; const QString propertyName = stringAt(binding->propertyNameIndex); @@ -508,10 +511,10 @@ bool QQmlEnumTypeResolver::resolveEnumBindings() bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, QStringView, int enumValue, bool) { - binding->type = QV4::CompiledData::Binding::Type_Number; + binding->setType(QV4::CompiledData::Binding::Type_Number); binding->value.constantValueIndex = compiler->registerConstant(QV4::Encode((double)enumValue)); // binding->setNumberValueInternal((double)enumValue); - binding->flags |= QV4::CompiledData::Binding::IsResolvedEnum; + binding->setFlag(QV4::CompiledData::Binding::IsResolvedEnum); return true; } @@ -521,10 +524,13 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, if (!prop->isEnum() && !isIntProp) return true; - if (!prop->isWritable() && !(binding->flags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)) - COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property").arg(stringAt(binding->propertyNameIndex))); + if (!prop->isWritable() + && !(binding->hasFlag(QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration))) { + COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property") + .arg(stringAt(binding->propertyNameIndex))); + } - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); + Q_ASSERT(binding->type() == QV4::CompiledData::Binding::Type_Script); const QString string = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); if (!string.constData()->isUpper()) return true; @@ -671,15 +677,21 @@ void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool if (!annotateScriptBindings) annotateScriptBindings = customParsers.contains(obj->inheritedTypeNameIndex); for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Script: + if (annotateScriptBindings) { + binding->stringIndex = compiler->registerString( + compiler->bindingAsString(obj, binding->value.compiledScriptIndex)); + } + break; + case QV4::CompiledData::Binding::Type_Object: + case QV4::CompiledData::Binding::Type_AttachedProperty: + case QV4::CompiledData::Binding::Type_GroupProperty: scanObjectRecursively(binding->value.objectIndex, annotateScriptBindings); - continue; - } else if (binding->type != QV4::CompiledData::Binding::Type_Script) - continue; - if (!annotateScriptBindings) - continue; - const QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); - binding->stringIndex = compiler->registerString(script); + break; + default: + break; + } } } @@ -708,7 +720,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases() bool notInRevision = false; QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), ¬InRevision) : defaultProperty; if (pd && pd->isAlias()) - binding->flags |= QV4::CompiledData::Binding::IsBindingToAlias; + binding->setFlag(QV4::CompiledData::Binding::IsBindingToAlias); } } } @@ -735,7 +747,7 @@ void QQmlScriptStringScanner::scan() QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty(); for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type != QV4::CompiledData::Binding::Type_Script) + if (binding->type() != QV4::CompiledData::Binding::Type_Script) continue; bool notInRevision = false; QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), ¬InRevision) : defaultProperty; @@ -781,9 +793,9 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty(); for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type != QV4::CompiledData::Binding::Type_Object) + if (binding->type() != QV4::CompiledData::Binding::Type_Object) continue; - if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) + if (binding->hasFlag(QV4::CompiledData::Binding::IsSignalHandlerObject)) continue; const QmlIR::Object *targetObject = qmlObjects->at(binding->value.objectIndex); @@ -862,7 +874,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI // The synthetic binding inside Component has no name. It's just "Component { Foo {} }". syntheticBinding->propertyNameIndex = 0; - syntheticBinding->type = QV4::CompiledData::Binding::Type_Object; + syntheticBinding->setType(QV4::CompiledData::Binding::Type_Object); QString error = syntheticComponent->appendBinding(syntheticBinding, /*isListBinding*/false); Q_ASSERT(error.isEmpty()); Q_UNUSED(error); @@ -938,7 +950,7 @@ bool QQmlComponentAndAliasResolver::resolve(int root) COMPILE_EXCEPTION(rootBinding, tr("Component elements may not contain properties other than id")); } - if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object) + if (rootBinding->next || rootBinding->type() != QV4::CompiledData::Binding::Type_Object) COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); // For the root object, we are going to collect ids/aliases and resolve them for as a separate @@ -1006,13 +1018,16 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex) return true; for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type != QV4::CompiledData::Binding::Type_Object - && binding->type != QV4::CompiledData::Binding::Type_AttachedProperty - && binding->type != QV4::CompiledData::Binding::Type_GroupProperty) - continue; - - if (!collectIdsAndAliases(binding->value.objectIndex)) - return false; + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Object: + case QV4::CompiledData::Binding::Type_AttachedProperty: + case QV4::CompiledData::Binding::Type_GroupProperty: + if (!collectIdsAndAliases(binding->value.objectIndex)) + return false; + break; + default: + break; + } } return true; @@ -1253,7 +1268,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( if (obj->flags & Object::IsComponent) { Q_ASSERT(obj->bindingCount() == 1); const Binding *componentBinding = obj->firstBinding(); - Q_ASSERT(componentBinding->type == Binding::Type_Object); + Q_ASSERT(componentBinding->type() == Binding::Type_Object); // Components are separate from their surrounding scope. They cannot be deferred. return scanObject(componentBinding->value.objectIndex, ScopeDeferred::False); } @@ -1304,16 +1319,16 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( QString name = stringAt(binding->propertyNameIndex); if (customParser) { - if (binding->type == Binding::Type_AttachedProperty) { + if (binding->type() == Binding::Type_AttachedProperty) { if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) { - binding->flags |= Binding::IsCustomParserBinding; + binding->setFlag(Binding::IsCustomParserBinding); obj->flags |= Object::HasCustomParserBindings; continue; } } else if (QmlIR::IRBuilder::isSignalPropertyName(name) && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) { obj->flags |= Object::HasCustomParserBindings; - binding->flags |= Binding::IsCustomParserBinding; + binding->setFlag(Binding::IsCustomParserBinding); continue; } } @@ -1338,9 +1353,10 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( if (!customParser) return false; - if (binding->flags & Binding::IsSignalHandlerExpression - || binding->flags & Binding::IsSignalHandlerObject - || binding->flags & Binding::IsPropertyObserver) { + const Binding::Flags bindingFlags = binding->flags(); + if (bindingFlags & Binding::IsSignalHandlerExpression + || bindingFlags & Binding::IsSignalHandlerObject + || bindingFlags & Binding::IsPropertyObserver) { // These signal handlers cannot be custom-parsed. We have already established // that the signal exists. return false; @@ -1348,13 +1364,13 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( // If the property isn't found, we may want to custom-parse the binding. obj->flags |= Object::HasCustomParserBindings; - binding->flags |= Binding::IsCustomParserBinding; + binding->setFlag(Binding::IsCustomParserBinding); return false; }(); bool seenSubObjectWithId = false; bool isExternal = false; - if (binding->type >= Binding::Type_Object) { + if (binding->type() >= Binding::Type_Object) { const bool isOwnProperty = hasPropertyData || binding->isAttachedProperty(); isExternal = !isOwnProperty && binding->isGroupProperty(); if (isOwnProperty || isExternal) { @@ -1383,7 +1399,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( qWarning("Binding on %s is not deferred as requested by the DeferredPropertyNames " "class info because one or more of its sub-objects contain an id.", qPrintable(name)); - } else if (binding->type == Binding::Type_GroupProperty) { + } else if (binding->type() == Binding::Type_GroupProperty) { // The binding may already be deferred via the surrounding scope. // e.g. PropertyChanges { control.contentItem.opacity: 0.75 } // Here, contentItem is a group property which prevents its deferral. But as @@ -1399,7 +1415,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( } } - if (binding->type >= Binding::Type_Object) { + if (binding->type() >= Binding::Type_Object) { if (isExternal && !isDeferred && !customParser) { COMPILE_EXCEPTION( binding, tr("Cannot assign to non-existent property \"%1\"").arg(name)); @@ -1407,7 +1423,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject( } if (isDeferred) { - binding->flags |= Binding::IsDeferredBinding; + binding->setFlag(Binding::IsDeferredBinding); obj->flags |= Object::HasDeferredBindings; } } diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index c474128553..582c833a52 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -731,7 +731,7 @@ static QQmlAnyBinding createBinding( const QQmlRefPointer<QQmlContextData> &contextData, QObject *scopeObject) { - switch (binding->type) { + switch (binding->type()) { case QV4::CompiledData::Binding::Type_Translation: case QV4::CompiledData::Binding::Type_TranslationById: return QQmlAnyBinding::createTranslationBinding(prop, compilationUnit, binding, scopeObject); @@ -767,8 +767,9 @@ void QQmlBindPrivate::decodeBinding( const QString propertyName = propertyPrefix + compilationUnit->stringAt(binding->propertyNameIndex); - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty - || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_GroupProperty: + case QV4::CompiledData::Binding::Type_AttachedProperty: { const QString pre = propertyName + u'.'; const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex); @@ -777,6 +778,9 @@ void QQmlBindPrivate::decodeBinding( decodeBinding(q, pre, deferredData, subBinding, immediateState); return; } + default: + break; + } QQmlBindEntry entry; QQmlContext *context = qmlContext(q); @@ -815,7 +819,7 @@ void QQmlBindPrivate::decodeBinding( entry.currentKind = entry.current.set(binding, entry.currentKind); }; - switch (binding->type) { + switch (binding->type()) { case QV4::CompiledData::Binding::Type_AttachedProperty: case QV4::CompiledData::Binding::Type_GroupProperty: Q_UNREACHABLE(); // Handled above @@ -849,6 +853,9 @@ void QQmlBindPrivate::decodeBinding( case QV4::CompiledData::Binding::Type_Null: setVariant(QVariant::fromValue(nullptr)); break; + case QV4::CompiledData::Binding::Type_Object: + case QV4::CompiledData::Binding::Type_Invalid: + break; } entries.append(std::move(entry)); diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index 73a3e60efc..283c3e0dd8 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -244,17 +244,20 @@ void QQmlConnectionsParser::verifyBindings(const QQmlRefPointer<QV4::ExecutableC return; } - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + if (binding->type() == QV4::CompiledData::Binding::Type_Script) + continue; + + if (binding->type() >= QV4::CompiledData::Binding::Type_Object) { const QV4::CompiledData::Object *target = compilationUnit->objectAt(binding->value.objectIndex); if (!compilationUnit->stringAt(target->inheritedTypeNameIndex).isEmpty()) error(binding, QQmlConnections::tr("Connections: nested objects not allowed")); else error(binding, QQmlConnections::tr("Connections: syntax error")); return; - } if (binding->type != QV4::CompiledData::Binding::Type_Script) { - error(binding, QQmlConnections::tr("Connections: script expected")); - return; } + + error(binding, QQmlConnections::tr("Connections: script expected")); + return; } } @@ -349,7 +352,7 @@ void QQmlConnections::connectSignalsToBindings() QQmlRefPointer<QQmlContextData> ctxtdata = ddata ? ddata->outerContext : nullptr; for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script); + Q_ASSERT(binding->type() == QV4::CompiledData::Binding::Type_Script); QString propName = d->compilationUnit->stringAt(binding->propertyNameIndex); QQmlProperty prop(target, propName); diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp index b0f3fd8f72..55f985752e 100644 --- a/src/qmlcompiler/qqmljscompiler.cpp +++ b/src/qmlcompiler/qqmljscompiler.cpp @@ -130,7 +130,7 @@ static void annotateListElements(QmlIR::Document *document) if (!listElementNames.contains(document->stringAt(object->inheritedTypeNameIndex))) continue; for (QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) { - if (binding->type != QV4::CompiledData::Binding::Type_Script) + if (binding->type() != QV4::CompiledData::Binding::Type_Script) continue; binding->stringIndex = document->registerString(object->bindingAsString(document, binding->value.compiledScriptIndex)); } @@ -142,7 +142,7 @@ static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc, { for (QmlIR::Object *object: qAsConst(doc.objects)) { for (auto binding = object->bindingsBegin(); binding != object->bindingsEnd(); ++binding) { - if (binding->type != QV4::CompiledData::Binding::Type_Script) + if (binding->type() != QV4::CompiledData::Binding::Type_Script) continue; const QString propName = doc.stringAt(binding->propertyNameIndex); if (!propName.startsWith(QLatin1String("on")) @@ -294,7 +294,7 @@ bool qCompileQmlFile(QmlIR::Document &irDocument, const QString &inputFileName, std::variant<QQmlJSAotFunction, QQmlJS::DiagnosticMessage> result; auto *module = v4CodeGen.module(); if (const auto *binding = bindingOrFunction.binding()) { - switch (binding->type) { + switch (binding->type()) { case QmlIR::Binding::Type_AttachedProperty: case QmlIR::Binding::Type_GroupProperty: effectiveScopes.insert( diff --git a/src/qmlcompiler/qqmljsfunctioninitializer.cpp b/src/qmlcompiler/qqmljsfunctioninitializer.cpp index 8cd3bb3536..dfc8d9632a 100644 --- a/src/qmlcompiler/qqmljsfunctioninitializer.cpp +++ b/src/qmlcompiler/qqmljsfunctioninitializer.cpp @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE * signature and the QML scope and doesn't visit the byte code. */ -static QString bindingTypeDescription(QmlIR::Binding::ValueType type) +static QString bindingTypeDescription(QmlIR::Binding::Type type) { switch (type) { case QmlIR::Binding::Type_Invalid: @@ -142,9 +142,9 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run( QQmlJSCompilePass::Function function; function.qmlScope = m_scopeType; - if (irBinding.type != QmlIR::Binding::Type_Script) { + if (irBinding.type() != QmlIR::Binding::Type_Script) { diagnose(u"Binding is not a script binding, but %1."_qs.arg( - bindingTypeDescription(QmlIR::Binding::ValueType(quint32(irBinding.type)))), + bindingTypeDescription(irBinding.type())), QtDebugMsg, bindingLocation, error); } diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index bcc948e0cd..fb4288b56d 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -1377,7 +1377,7 @@ handleTranslationBinding(QStringView base, QQmlJS::AST::ArgumentList *args, return 0; }; auto discardCommentString = [](QStringView) {return -1;}; - auto finalizeBinding = [&](QV4::CompiledData::Binding::ValueType type, + auto finalizeBinding = [&](QV4::CompiledData::Binding::Type type, QV4::CompiledData::TranslationData) { QQmlJSMetaPropertyBinding binding(location); if (type == QV4::CompiledData::Binding::Type_Translation) { diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index 6115f8bfe3..efd450c58e 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -2886,7 +2886,7 @@ void QQmlListModel::sync() bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) { - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + if (binding->type() >= QV4::CompiledData::Binding::Type_Object) { const quint32 targetObjectIndex = binding->value.objectIndex; const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex); QString objName = compilationUnit->stringAt(target->inheritedTypeNameIndex); @@ -2914,7 +2914,7 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCom if (!verifyProperty(compilationUnit, binding)) return false; } - } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { + } else if (binding->type() == QV4::CompiledData::Binding::Type_Script) { QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) { QByteArray script = scriptStr.toUtf8(); @@ -2937,7 +2937,8 @@ bool QQmlListModelParser::applyProperty( const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex); bool roleSet = false; - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + const QV4::CompiledData::Binding::Type bindingType = binding->type(); + if (bindingType >= QV4::CompiledData::Binding::Type_Object) { const quint32 targetObjectIndex = binding->value.objectIndex; const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex); @@ -2971,13 +2972,13 @@ bool QQmlListModelParser::applyProperty( value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding); } else if (binding->evaluatesToString()) { value = compilationUnit->bindingValueAsString(binding); - } else if (binding->type == QV4::CompiledData::Binding::Type_Number) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Number) { value = compilationUnit->bindingValueAsNumber(binding); - } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Boolean) { value = binding->valueAsBoolean(); - } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Null) { value = QVariant::fromValue(nullptr); - } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Script) { QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (definesEmptyList(scriptStr)) { const ListLayout::Role &role = model->getOrCreateListRole(elementName); @@ -3050,7 +3051,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4:: bool setRoles = false; for (const QV4::CompiledData::Binding *binding : bindings) { - if (binding->type != QV4::CompiledData::Binding::Type_Object) + if (binding->type() != QV4::CompiledData::Binding::Type_Object) continue; setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, /*outter element index*/-1); } diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index da631cb5ec..b453b288bd 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -318,7 +318,7 @@ private: // Look for override of name in this type for (auto binding = object->bindingsBegin(); binding != object->bindingsEnd(); ++binding) { if (compilationUnit->stringAt(binding->propertyNameIndex) == QLatin1String("name")) { - if (binding->type == QV4::CompiledData::Binding::Type_String) { + if (binding->type() == QV4::CompiledData::Binding::Type_String) { result.testCaseName = compilationUnit->stringAt(binding->stringIndex); } else { QQmlError error; @@ -348,7 +348,7 @@ private: } for (auto binding = object->bindingsBegin(); binding != object->bindingsEnd(); ++binding) { - if (binding->type == QV4::CompiledData::Binding::Type_Object) { + if (binding->type() == QV4::CompiledData::Binding::Type_Object) { const Object *child = compilationUnit->objectAt(binding->value.objectIndex); result << enumerateTestCases(compilationUnit, child); } diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index b2bba90159..0e12552551 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -250,18 +250,22 @@ public: void QQuickPropertyChangesParser::verifyList(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) { - if (binding->type == QV4::CompiledData::Binding::Type_Object) { - error(compilationUnit->objectAt(binding->value.objectIndex), QQuickPropertyChanges::tr("PropertyChanges does not support creating state-specific objects.")); - return; - } - - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty - || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_Object: + error(compilationUnit->objectAt(binding->value.objectIndex), + QQuickPropertyChanges::tr( + "PropertyChanges does not support creating state-specific objects.")); + break; + case QV4::CompiledData::Binding::Type_GroupProperty: + case QV4::CompiledData::Binding::Type_AttachedProperty: { const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex); const QV4::CompiledData::Binding *subBinding = subObj->bindingTable(); - for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) { + for (quint32 i = 0; i < subObj->nBindings; ++i, ++subBinding) verifyList(compilationUnit, subBinding); - } + break; + } + default: + break; } } @@ -284,8 +288,9 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, QString propertyName = propertyPrefix + compilationUnit->stringAt(binding->propertyNameIndex); - if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty - || binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) { + switch (binding->type()) { + case QV4::CompiledData::Binding::Type_GroupProperty: + case QV4::CompiledData::Binding::Type_AttachedProperty: { QString pre = propertyName + QLatin1Char('.'); const QV4::CompiledData::Object *subObj = compilationUnit->objectAt(binding->value.objectIndex); const QV4::CompiledData::Binding *subBinding = subObj->bindingTable(); @@ -294,6 +299,9 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, } return; } + default: + break; + } if (binding->isSignalHandler() || QmlIR::IRBuilder::isSignalPropertyName(propertyName)) { QQmlProperty prop = property(propertyName); @@ -310,7 +318,8 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, } } - if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) { + if (binding->type() == QV4::CompiledData::Binding::Type_Script + || binding->isTranslationBinding()) { QUrl url = QUrl(); int line = -1; int column = -1; @@ -334,7 +343,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, } QVariant var; - switch (binding->type) { + switch (binding->type()) { case QV4::CompiledData::Binding::Type_Script: case QV4::CompiledData::Binding::Type_Translation: case QV4::CompiledData::Binding::Type_TranslationById: diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index 5db5fed22a..20f9fabdcd 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -346,7 +346,7 @@ void tst_qmldiskcache::regenerateAfterChange() const QV4::CompiledData::Object *obj = qmlUnit->objectAt(0); QCOMPARE(quint32(obj->nBindings), quint32(1)); - QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Script)); + QCOMPARE(obj->bindingTable()->type(), QV4::CompiledData::Binding::Type_Script); QCOMPARE(quint32(obj->bindingTable()->value.compiledScriptIndex), quint32(0)); QCOMPARE(quint32(testUnit->functionTableSize), quint32(1)); @@ -374,7 +374,7 @@ void tst_qmldiskcache::regenerateAfterChange() const QV4::CompiledData::Object *obj = qmlUnit->objectAt(0); QCOMPARE(quint32(obj->nBindings), quint32(2)); - QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Number)); + QCOMPARE(obj->bindingTable()->type(), QV4::CompiledData::Binding::Type_Number); const QV4::Value value(testUnit->constants()[obj->bindingTable()->value.constantValueIndex]); QCOMPARE(value.doubleValue(), double(42)); @@ -420,7 +420,7 @@ void tst_qmldiskcache::registerImportForImplicitComponent() const QV4::CompiledData::Object *obj = qmlUnit->objectAt(0); QCOMPARE(quint32(obj->nBindings), quint32(1)); - QCOMPARE(quint32(obj->bindingTable()->type), quint32(QV4::CompiledData::Binding::Type_Object)); + QCOMPARE(obj->bindingTable()->type(), QV4::CompiledData::Binding::Type_Object); const QV4::CompiledData::Object *implicitComponent = qmlUnit->objectAt(obj->bindingTable()->value.objectIndex); QCOMPARE(testUnit->stringAtInternal(implicitComponent->inheritedTypeNameIndex), QStringLiteral("QML.") + componentType.elementName()); diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 2ec8264b88..72cff8b459 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -221,7 +221,7 @@ void EnumSupportingCustomParser::verifyBindings(const QQmlRefPointer<QV4::Execut return; } - if (binding->type != QV4::CompiledData::Binding::Type_Script) { + if (binding->type() != QV4::CompiledData::Binding::Type_Script) { error(binding, QStringLiteral("Custom parser invoked with the wrong property value. Expected script that evaluates to enum")); return; } diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index 09addff372..5d2b6b8c31 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -97,13 +97,13 @@ void tst_qqmltranslation::translation() const bool expectCompiledTranslation = compiledTranslations.contains(propertyName); if (expectCompiledTranslation) { - if (binding->type != QV4::CompiledData::Binding::Type_Translation) + if (binding->type() != QV4::CompiledData::Binding::Type_Translation) qDebug() << "binding for property" << propertyName << "is not a compiled translation"; - QCOMPARE(quint32(binding->type), quint32(QV4::CompiledData::Binding::Type_Translation)); + QCOMPARE(binding->type(), QV4::CompiledData::Binding::Type_Translation); } else { - if (binding->type == QV4::CompiledData::Binding::Type_Translation) + if (binding->type() == QV4::CompiledData::Binding::Type_Translation) qDebug() << "binding for property" << propertyName << "is not supposed to be a compiled translation"; - QVERIFY(binding->type != QV4::CompiledData::Binding::Type_Translation); + QVERIFY(binding->type() != QV4::CompiledData::Binding::Type_Translation); } } } @@ -149,11 +149,11 @@ void tst_qqmltranslation::idTranslation() for (quint32 i = 0; i < rootObject->nBindings; ++i, ++binding) { const QString propertyName = compilationUnit->stringAt(binding->propertyNameIndex); if (propertyName == "idTranslation") { - if (binding->type != QV4::CompiledData::Binding::Type_TranslationById) + if (binding->type() != QV4::CompiledData::Binding::Type_TranslationById) qDebug() << "binding for property" << propertyName << "is not a compiled translation"; - QCOMPARE(quint32(binding->type), quint32(QV4::CompiledData::Binding::Type_TranslationById)); + QCOMPARE(binding->type(), QV4::CompiledData::Binding::Type_TranslationById); } else { - QVERIFY(binding->type != QV4::CompiledData::Binding::Type_Translation); + QVERIFY(binding->type() != QV4::CompiledData::Binding::Type_Translation); } } } diff --git a/tools/qmltc/prototype/codegenerator.cpp b/tools/qmltc/prototype/codegenerator.cpp index 5ee1d980d5..34d059c836 100644 --- a/tools/qmltc/prototype/codegenerator.cpp +++ b/tools/qmltc/prototype/codegenerator.cpp @@ -167,11 +167,11 @@ private: public: bool operator()(const I &x, const I &y) const { - return orderTable[x->type] < orderTable[y->type]; + return orderTable[x->type()] < orderTable[y->type()]; } bool operator()(const T &x, const T &y) const { - return orderTable[x.type] < orderTable[y.type]; + return orderTable[x.type()] < orderTable[y.type()]; } }; @@ -758,7 +758,7 @@ void CodeGenerator::compileObjectElements(QQmlJSAotObject &compiled, const CodeG // predicate auto scriptBindingsBegin = std::find_if(sortedBindings.cbegin(), sortedBindings.cend(), - [](auto it) { return it->type == QmlIR::Binding::Type_Script; }); + [](auto it) { return it->type() == QmlIR::Binding::Type_Script; }); auto it = sortedBindings.cbegin(); for (; it != scriptBindingsBegin; ++it) compileBinding(compiled, **it, object, { object.type, u"this"_qs, u""_qs, false }); @@ -1183,8 +1183,8 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin // Note: unlike QQmlObjectCreator, we don't have to do a complicated // deferral logic for bindings: if a binding is deferred, it is not compiled // (potentially, with all the bindings inside of it), period. - if (binding.flags & QV4::CompiledData::Binding::IsDeferredBinding) { - if (binding.type == QmlIR::Binding::Type_GroupProperty) { + if (binding.flags() & QV4::CompiledData::Binding::IsDeferredBinding) { + if (binding.type() == QmlIR::Binding::Type_GroupProperty) { // TODO: we should warn about this in QmlCompiler library qCWarning(lcCodeGenerator) << QStringLiteral("Binding at line %1 column %2 is not deferred as it is a " @@ -1234,7 +1234,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin } }; - switch (binding.type) { + switch (binding.type()) { case QmlIR::Binding::Type_Boolean: { addPropertyLine(propertyName, p, binding.value.b ? u"true"_qs : u"false"_qs); break; @@ -1295,7 +1295,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin const QString qobjectParent = u"this"_qs; const QString objectAddr = accessor.name; - if (binding.flags & QmlIR::Binding::IsOnAssignment) { + if (binding.hasFlag(QmlIR::Binding::IsOnAssignment)) { const QString onAssignmentName = u"onAssign_" + propertyName; const auto uniqueId = UniqueStringId(current, onAssignmentName); if (!m_onAssignmentObjectsCreated.contains(uniqueId)) { @@ -1331,7 +1331,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin return; } - if (p.isList() || (binding.flags & QmlIR::Binding::IsListItem)) { + if (p.isList() || binding.hasFlag(QmlIR::Binding::IsListItem)) { const QString refName = u"listref_" + propertyName; const auto uniqueId = UniqueStringId(current, refName); if (!m_listReferencesCreated.contains(uniqueId)) { @@ -1345,7 +1345,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin } const auto setObjectBinding = [&](const QString &value) { - if (p.isList() || (binding.flags & QmlIR::Binding::IsListItem)) { + if (p.isList() || binding.hasFlag(QmlIR::Binding::IsListItem)) { const QString refName = u"listref_" + propertyName; current.endInit.body << refName + u".append(" + value + u");"; } else { @@ -1417,7 +1417,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin // TODO: there's a special QQmlComponentAttached, which has to be // called? c.f. qqmlobjectcreator.cpp's finalize() const auto compileComponent = [&](const QmlIR::Binding &b) { - Q_ASSERT(b.type == QmlIR::Binding::Type_Script); + Q_ASSERT(b.type() == QmlIR::Binding::Type_Script); compileScriptBindingOfComponent(current, irObject, type, b, m_doc->stringAt(b.propertyNameIndex)); }; @@ -1485,7 +1485,13 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin const auto isGroupAffectingBinding = [](const QmlIR::Binding &b) { // script bindings do not require value type group property variable // to actually be present. - return b.type != QmlIR::Binding::Type_Invalid && b.type != QmlIR::Binding::Type_Script; + switch (b.type()) { + case QmlIR::Binding::Type_Invalid: + case QmlIR::Binding::Type_Script: + return false; + default: + return true; + } }; const bool generateValueTypeCode = isValueType && std::any_of(irObject->bindingsBegin(), irObject->bindingsEnd(), @@ -1518,10 +1524,10 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin // predicate auto scriptBindingsBegin = std::find_if(sortedBindings.cbegin(), sortedBindings.cend(), - [](auto it) { return it->type == QmlIR::Binding::Type_Script; }); + [](auto it) { return it->type() == QmlIR::Binding::Type_Script; }); auto it = sortedBindings.cbegin(); for (; it != scriptBindingsBegin; ++it) { - Q_ASSERT((*it)->type != QmlIR::Binding::Type_Script); + Q_ASSERT((*it)->type() != QmlIR::Binding::Type_Script); compile(*it); } @@ -1541,7 +1547,7 @@ void CodeGenerator::compileBinding(QQmlJSAotObject ¤t, const QmlIR::Bindin // once the value is written back, process the script bindings for (; it != sortedBindings.cend(); ++it) { - Q_ASSERT((*it)->type == QmlIR::Binding::Type_Script); + Q_ASSERT((*it)->type() == QmlIR::Binding::Type_Script); compile(*it); } break; diff --git a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp index 611c317490..8eda649441 100644 --- a/tools/qmltc/prototype/qml2cppdefaultpasses.cpp +++ b/tools/qmltc/prototype/qml2cppdefaultpasses.cpp @@ -287,7 +287,7 @@ void verifyTypes(const Qml2CppContext &context, QList<Qml2CppObject> &objects) return; // attached property is special - if (binding.type == QmlIR::Binding::Type_AttachedProperty) { + if (binding.type() == QmlIR::Binding::Type_AttachedProperty) { const auto [attachedObject, attachedType] = objects.at(binding.value.objectIndex); if (!attachedObject || !attachedType) { context.recordError(binding.location, @@ -312,8 +312,8 @@ void verifyTypes(const Qml2CppContext &context, QList<Qml2CppObject> &objects) // TODO: why isList() needed here? if (!p.isWritable() && !p.isList() - && !(binding.flags & QmlIR::Binding::InitializerForReadOnlyDeclaration) - && binding.type != QmlIR::Binding::Type_GroupProperty) { + && !binding.hasFlag(QmlIR::Binding::InitializerForReadOnlyDeclaration) + && binding.type() != QmlIR::Binding::Type_GroupProperty) { context.recordError(binding.location, u"Binding on read-only property '" + propName + u"'"); } @@ -888,7 +888,7 @@ static void updateImplicitComponents(const Qml2CppContext &context, Qml2CppObjec QList<Qml2CppObject> &objects, Update update) { const auto checkAndUpdate = [&](const QmlIR::Binding &binding) { - if (binding.type != QmlIR::Binding::Type_Object) + if (binding.type() != QmlIR::Binding::Type_Object) return; if (object.irObject->flags & QV4::CompiledData::Object::IsComponent) // already set return; @@ -994,12 +994,15 @@ static void setObjectId(const Qml2CppContext &context, const QList<Qml2CppObject std::for_each(irObject->bindingsBegin(), irObject->bindingsEnd(), [&](const QmlIR::Binding &binding) { - if (binding.type != QV4::CompiledData::Binding::Type_Object - && binding.type != QV4::CompiledData::Binding::Type_AttachedProperty - && binding.type != QV4::CompiledData::Binding::Type_GroupProperty) { - return; + switch (binding.type()) { + case QV4::CompiledData::Binding::Type_Object: + case QV4::CompiledData::Binding::Type_AttachedProperty: + case QV4::CompiledData::Binding::Type_GroupProperty: + setObjectId(context, objects, binding.value.objectIndex, idToObjectIndex); + break; + default: + break; } - setObjectId(context, objects, binding.value.objectIndex, idToObjectIndex); }); } @@ -1096,14 +1099,14 @@ static void setDeferred(const Qml2CppContext &context, qsizetype objectIndex, } const auto setRecursive = [&](QmlIR::Binding &binding) { - if (binding.type >= QmlIR::Binding::Type_Object) + if (binding.type() >= QmlIR::Binding::Type_Object) setDeferred(context, binding.value.objectIndex, objects); // Note: recursive call here! const QString propName = findPropertyName(context, o.type, binding); Q_ASSERT(!propName.isEmpty()); if (o.type->isNameDeferred(propName)) { - binding.flags |= QV4::CompiledData::Binding::IsDeferredBinding; + binding.setFlag(QV4::CompiledData::Binding::IsDeferredBinding); o.irObject->flags |= QV4::CompiledData::Object::HasDeferredBindings; } }; |