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 /src/qml | |
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)
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/common/qv4compileddata_p.h | 73 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 73 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlirloader.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 84 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator_p.h | 20 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertyvalidator.cpp | 83 | ||||
-rw-r--r-- | src/qml/qml/qqmltypecompiler.cpp | 116 | ||||
-rw-r--r-- | src/qml/types/qqmlbind.cpp | 15 | ||||
-rw-r--r-- | src/qml/types/qqmlconnections.cpp | 13 |
12 files changed, 277 insertions, 210 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); |