aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/common/qv4compileddata_p.h372
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp183
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h4
-rw-r--r--src/qml/compiler/qv4compiler.cpp43
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp5
-rw-r--r--src/qml/configure.pri2
-rw-r--r--src/qml/debugger/qqmldebug.cpp13
-rw-r--r--src/qml/debugger/qqmldebugconnector.cpp2
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h2
-rw-r--r--src/qml/inlinecomponentutils_p.h56
-rw-r--r--src/qml/jsruntime/qv4engine.cpp17
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp39
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h2
-rw-r--r--src/qml/jsruntime/qv4function.cpp3
-rw-r--r--src/qml/jsruntime/qv4global_p.h1
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp170
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h38
-rw-r--r--src/qml/jsruntime/qv4object.cpp59
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp4
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h5
-rw-r--r--src/qml/qml/qqmlbinding.cpp8
-rw-r--r--src/qml/qml/qqmlcomponent.cpp6
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp4
-rw-r--r--src/qml/qml/qqmlengine.cpp4
-rw-r--r--src/qml/qml/qqmlengine_p.h4
-rw-r--r--src/qml/qml/qqmlimport.cpp1
-rw-r--r--src/qml/qml/qqmlirloader.cpp11
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp119
-rw-r--r--src/qml/qml/qqmlprivate.h39
-rw-r--r--src/qml/qml/qqmlpropertycachecreator.cpp9
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h122
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp85
-rw-r--r--src/qml/qml/qqmlscriptblob.cpp8
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp133
-rw-r--r--src/qml/qml/qqmltypedata.cpp37
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp27
-rw-r--r--src/qml/types/qqmlconnections.cpp13
38 files changed, 1055 insertions, 599 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index be0ca3f477..413edead2a 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -120,18 +120,35 @@ struct TableIterator
struct Location
{
- union {
- quint32 _dummy;
- quint32_le_bitfield<0, 20> line;
- quint32_le_bitfield<20, 12> column;
- };
-
- Location() : _dummy(0) { }
+ Location() : m_data(QSpecialIntegerBitfieldZero) {}
+ Location(quint32 l, quint32 c) : Location()
+ {
+ m_data.set<LineField>(l);
+ m_data.set<ColumnField>(c);
+ Q_ASSERT(m_data.get<LineField>() == l);
+ Q_ASSERT(m_data.get<ColumnField>() == c);
+ }
inline bool operator<(const Location &other) const {
- return line < other.line ||
- (line == other.line && column < other.column);
+ return m_data.get<LineField>() < other.m_data.get<LineField>()
+ || (m_data.get<LineField>() == other.m_data.get<LineField>()
+ && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
}
+
+ void set(quint32 line, quint32 column)
+ {
+ m_data.set<LineField>(line);
+ m_data.set<ColumnField>(column);
+ }
+
+ quint32 line() const { return m_data.get<LineField>(); }
+ quint32 column() const { return m_data.get<ColumnField>(); }
+
+private:
+ using LineField = quint32_le_bitfield_member<0, 20>;
+ using ColumnField = quint32_le_bitfield_member<20, 12>;
+
+ quint32_le_bitfield_union<LineField, ColumnField> m_data;
};
static_assert(sizeof(Location) == 4, "Location structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -145,13 +162,21 @@ struct RegExp
RegExp_Unicode = 0x08,
RegExp_Sticky = 0x10
};
- union {
- quint32 _dummy;
- quint32_le_bitfield<0, 5> flags;
- quint32_le_bitfield<5, 27> stringIndex;
- };
- RegExp() : _dummy(0) { }
+ RegExp() : m_data(QSpecialIntegerBitfieldZero) {}
+ RegExp(quint32 flags, quint32 stringIndex) : RegExp()
+ {
+ m_data.set<FlagsField>(flags);
+ m_data.set<StringIndexField>(stringIndex);
+ }
+
+ quint32 flags() const { return m_data.get<FlagsField>(); }
+ quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
+
+private:
+ using FlagsField = quint32_le_bitfield_member<0, 5>;
+ using StringIndexField = quint32_le_bitfield_member<5, 27>;
+ quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
};
static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -164,25 +189,40 @@ struct Lookup
Type_QmlContextPropertyGetter = 3
};
- union {
- quint32 _dummy;
- quint32_le_bitfield<0, 4> type_and_flags;
- quint32_le_bitfield<4, 28> nameIndex;
- };
+ quint32 typeAndFlags() const { return m_data.get<TypeAndFlagsField>(); }
+ quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
- Lookup() : _dummy(0) { }
+ Lookup() : m_data(QSpecialIntegerBitfieldZero) {}
+ Lookup(Type type, quint32 nameIndex) : Lookup()
+ {
+ m_data.set<TypeAndFlagsField>(type);
+ m_data.set<NameIndexField>(nameIndex);
+ }
+
+private:
+ using TypeAndFlagsField = quint32_le_bitfield_member<0, 4>;
+ using NameIndexField = quint32_le_bitfield_member<4, 28>;
+ quint32_le_bitfield_union<TypeAndFlagsField, NameIndexField> m_data;
};
static_assert(sizeof(Lookup) == 4, "Lookup structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct JSClassMember
{
- union {
- quint32 _dummy;
- quint32_le_bitfield<0, 31> nameOffset;
- quint32_le_bitfield<31, 1> isAccessor;
- };
+ JSClassMember() : m_data(QSpecialIntegerBitfieldZero) {}
- JSClassMember() : _dummy(0) { }
+ void set(quint32 nameOffset, bool isAccessor)
+ {
+ m_data.set<NameOffsetField>(nameOffset);
+ m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
+ }
+
+ quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
+ bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
+
+private:
+ using NameOffsetField = quint32_le_bitfield_member<0, 31>;
+ using IsAccessorField = quint32_le_bitfield_member<31, 1>;
+ quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
};
static_assert(sizeof(JSClassMember) == 4, "JSClassMember structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -265,11 +305,26 @@ enum class BuiltinType : unsigned int {
struct ParameterType
{
- union {
- quint32 _dummy;
- quint32_le_bitfield<0, 1> indexIsBuiltinType;
- quint32_le_bitfield<1, 31> typeNameIndexOrBuiltinType;
- };
+ void set(bool indexIsBuiltinType, quint32 typeNameIndexOrBuiltinType)
+ {
+ m_data.set<IndexIsBuiltinTypeField>(indexIsBuiltinType ? 1 : 0);
+ m_data.set<TypeNameIndexOrBuiltinTypeField>(typeNameIndexOrBuiltinType);
+ }
+
+ bool indexIsBuiltinType() const
+ {
+ return m_data.get<IndexIsBuiltinTypeField>() != 0;
+ }
+
+ quint32 typeNameIndexOrBuiltinType() const
+ {
+ return m_data.get<TypeNameIndexOrBuiltinTypeField>();
+ }
+
+private:
+ using IndexIsBuiltinTypeField = quint32_le_bitfield_member<0, 1>;
+ using TypeNameIndexOrBuiltinTypeField = quint32_le_bitfield_member<1, 31>;
+ quint32_le_bitfield_union<IndexIsBuiltinTypeField, TypeNameIndexOrBuiltinTypeField> m_data;
};
static_assert(sizeof(ParameterType) == 4, "ParameterType structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -448,7 +503,7 @@ struct Binding
{
quint32_le propertyNameIndex;
- enum ValueType : unsigned int {
+ enum Type : unsigned int {
Type_Invalid,
Type_Boolean,
Type_Number,
@@ -462,7 +517,7 @@ struct Binding
Type_GroupProperty
};
- enum Flags : unsigned int {
+ enum Flag : unsigned int {
IsSignalHandlerExpression = 0x1,
IsSignalHandlerObject = 0x2,
IsOnAssignment = 0x4,
@@ -474,11 +529,20 @@ struct Binding
IsCustomParserBinding = 0x100,
IsFunctionExpression = 0x200
};
+ 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;
@@ -492,23 +556,29 @@ struct Binding
Location location;
Location valueLocation;
+ bool hasSignalHandlerBindingFlag() const
+ {
+ const Flags bindingFlags = flags();
+ return (bindingFlags & IsSignalHandlerExpression || bindingFlags & IsSignalHandlerObject);
+ }
+
bool isValueBinding() const
{
- if (type == Type_AttachedProperty
- || type == Type_GroupProperty)
+ switch (type()) {
+ case Type_AttachedProperty:
+ case Type_GroupProperty:
return false;
- if (flags & IsSignalHandlerExpression
- || flags & IsSignalHandlerObject)
- 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) {
+ if (hasSignalHandlerBindingFlag()) {
Q_ASSERT(!isValueBinding());
Q_ASSERT(!isAttachedProperty());
Q_ASSERT(!isGroupProperty());
@@ -519,7 +589,7 @@ struct Binding
bool isAttachedProperty() const
{
- if (type == Type_AttachedProperty) {
+ if (type() == Type_AttachedProperty) {
Q_ASSERT(!isValueBinding());
Q_ASSERT(!isSignalHandler());
Q_ASSERT(!isGroupProperty());
@@ -530,7 +600,7 @@ struct Binding
bool isGroupProperty() const
{
- if (type == Type_GroupProperty) {
+ if (type() == Type_GroupProperty) {
Q_ASSERT(!isValueBinding());
Q_ASSERT(!isSignalHandler());
Q_ASSERT(!isAttachedProperty());
@@ -539,7 +609,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)
@@ -584,16 +654,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");
@@ -666,32 +739,57 @@ static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected
struct Property
{
- quint32_le nameIndex;
- union {
- quint32_le_bitfield<0, 28> builtinTypeOrTypeNameIndex;
- quint32_le_bitfield<28, 1> isRequired;
- quint32_le_bitfield<29, 1> isBuiltinType;
- quint32_le_bitfield<30, 1> isList;
- quint32_le_bitfield<31, 1> isReadOnly;
- };
+private:
+ using BuiltinTypeOrTypeNameIndexField = quint32_le_bitfield_member<0, 28>;
+ using IsRequiredField = quint32_le_bitfield_member<28, 1>;
+ using IsBuiltinTypeField = quint32_le_bitfield_member<29, 1>;
+ using IsListField = quint32_le_bitfield_member<30, 1>;
+ using IsReadOnlyField = quint32_le_bitfield_member<31, 1>;
+public:
+ quint32_le nameIndex;
+ quint32_le_bitfield_union<
+ BuiltinTypeOrTypeNameIndexField,
+ IsRequiredField,
+ IsBuiltinTypeField,
+ IsListField,
+ IsReadOnlyField> data;
Location location;
void setBuiltinType(BuiltinType t)
{
- builtinTypeOrTypeNameIndex = static_cast<quint32>(t);
- isBuiltinType = true;
+ data.set<BuiltinTypeOrTypeNameIndexField>(static_cast<quint32>(t));
+ data.set<IsBuiltinTypeField>(true);
}
+
BuiltinType builtinType() const {
- if (isBuiltinType)
- return static_cast<BuiltinType>(quint32(builtinTypeOrTypeNameIndex));
+ if (data.get<IsBuiltinTypeField>() != 0)
+ return BuiltinType(data.get<BuiltinTypeOrTypeNameIndexField>());
return BuiltinType::InvalidBuiltin;
}
+
void setCustomType(int nameIndex)
{
- builtinTypeOrTypeNameIndex = nameIndex;
- isBuiltinType = false;
+ data.set<BuiltinTypeOrTypeNameIndexField>(nameIndex);
+ data.set<IsBuiltinTypeField>(false);
}
+
+ int customType() const
+ {
+ return data.get<IsBuiltinTypeField>() ? -1 : data.get<BuiltinTypeOrTypeNameIndexField>();
+ }
+
+ bool isBuiltinType() const { return data.get<IsBuiltinTypeField>(); }
+ uint builtinTypeOrTypeNameIndex() const { return data.get<BuiltinTypeOrTypeNameIndexField>(); }
+
+ bool isList() const { return data.get<IsListField>(); }
+ void setIsList(bool isList) { data.set<IsListField>(isList); }
+
+ bool isRequired() const { return data.get<IsRequiredField>(); }
+ void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
+
+ bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
+ void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
};
static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -702,20 +800,31 @@ struct RequiredPropertyExtraData {
static_assert (sizeof(RequiredPropertyExtraData) == 4, "RequiredPropertyExtraData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Alias {
- enum Flags : unsigned int {
+private:
+ using NameIndexField = quint32_le_bitfield_member<0, 29>;
+ using FlagsField = quint32_le_bitfield_member<29, 3>;
+
+ // object id index (in QQmlContextData::idValues)
+ using TargetObjectIdField = quint32_le_bitfield_member<0, 31>;
+ using AliasToLocalAliasField = quint32_le_bitfield_member<31, 1>;
+
+public:
+
+ enum Flag : unsigned int {
IsReadOnly = 0x1,
Resolved = 0x2,
AliasPointsToPointerObject = 0x4
};
- union {
- quint32_le_bitfield<0, 29> nameIndex;
- quint32_le_bitfield<29, 3> flags;
- };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ quint32_le_bitfield_union<NameIndexField, FlagsField> nameIndexAndFlags;
+
union {
quint32_le idIndex; // string index
- quint32_le_bitfield<0, 31> targetObjectId; // object id index (in QQmlContextData::idValues)
- quint32_le_bitfield<31, 1> aliasToLocalAlias;
+ quint32_le_bitfield_union<TargetObjectIdField, AliasToLocalAliasField>
+ targetObjectIdAndAliasToLocalAlias;
};
+
union {
quint32_le propertyNameIndex; // string index
qint32_le encodedMetaPropertyIndex;
@@ -724,16 +833,67 @@ struct Alias {
Location location;
Location referenceLocation;
- bool isObjectAlias() const {
- Q_ASSERT(flags & Resolved);
+ bool hasFlag(Flag flag) const
+ {
+ return nameIndexAndFlags.get<FlagsField>() & flag;
+ }
+
+ void setFlag(Flag flag)
+ {
+ nameIndexAndFlags.set<FlagsField>(nameIndexAndFlags.get<FlagsField>() | flag);
+ }
+
+ void clearFlags()
+ {
+ nameIndexAndFlags.set<FlagsField>(0);
+ }
+
+ quint32 nameIndex() const
+ {
+ return nameIndexAndFlags.get<NameIndexField>();
+ }
+
+ void setNameIndex(quint32 nameIndex)
+ {
+ nameIndexAndFlags.set<NameIndexField>(nameIndex);
+ }
+
+ bool isObjectAlias() const
+ {
+ Q_ASSERT(hasFlag(Resolved));
return encodedMetaPropertyIndex == -1;
}
+
+ bool isAliasToLocalAlias() const
+ {
+ return targetObjectIdAndAliasToLocalAlias.get<AliasToLocalAliasField>();
+ }
+
+ void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
+ {
+ targetObjectIdAndAliasToLocalAlias.set<AliasToLocalAliasField>(isAliasToLocalAlias);
+ }
+
+ quint32 targetObjectId() const
+ {
+ return targetObjectIdAndAliasToLocalAlias.get<TargetObjectIdField>();
+ }
+
+ void setTargetObjectId(quint32 targetObjectId)
+ {
+ targetObjectIdAndAliasToLocalAlias.set<TargetObjectIdField>(targetObjectId);
+ }
};
static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Object
{
- enum Flags : unsigned int {
+private:
+ using FlagsField = quint32_le_bitfield_member<0, 15>;
+ using DefaultPropertyIsAliasField = quint32_le_bitfield_member<15, 1>;
+ using IdField = quint32_le_bitfield_member<16, 16, qint32>;
+public:
+ enum Flag : unsigned int {
NoFlag = 0x0,
IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
HasDeferredBindings = 0x2, // any of the bindings are deferred
@@ -741,17 +901,15 @@ struct Object
IsInlineComponentRoot = 0x8,
InPartOfInlineComponent = 0x10
};
+ Q_DECLARE_FLAGS(Flags, Flag);
// Depending on the use, this may be the type name to instantiate before instantiating this
// object. For grouped properties the type name will be empty and for attached properties
// it will be the name of the attached type.
quint32_le inheritedTypeNameIndex;
quint32_le idNameIndex;
- union {
- quint32_le_bitfield<0, 15> flags;
- quint32_le_bitfield<15, 1> defaultPropertyIsAlias;
- qint32_le_bitfield<16, 16> id;
- };
+ quint32_le_bitfield_union<FlagsField, DefaultPropertyIsAliasField, IdField>
+ flagsAndDefaultPropertyIsAliasAndId;
qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
quint16_le nFunctions;
quint16_le nProperties;
@@ -780,6 +938,48 @@ struct Object
// InlineComponent[]
// RequiredPropertyExtraData[]
+ Flags flags() const
+ {
+ return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
+ }
+
+ bool hasFlag(Flag flag) const
+ {
+ return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
+ }
+
+ void setFlag(Flag flag)
+ {
+ flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
+ flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
+ }
+
+ void setFlags(Flags flags)
+ {
+ flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
+ }
+
+ bool hasAliasAsDefaultProperty() const
+ {
+ return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
+ }
+
+ void setHasAliasAsDefaultProperty(bool defaultAlias)
+ {
+ flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
+ }
+
+ qint32 objectId() const
+ {
+ return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
+ }
+
+ void setObjectId(qint32 id)
+ {
+ flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
+ }
+
+
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
{
return ( sizeof(Object)
@@ -1129,8 +1329,8 @@ struct TypeReferenceMap : QHash<int, TypeReference>
auto prop = obj->propertiesBegin();
auto const propEnd = obj->propertiesEnd();
for ( ; prop != propEnd; ++prop) {
- if (!prop->isBuiltinType) {
- TypeReference &r = this->add(prop->builtinTypeOrTypeNameIndex, prop->location);
+ if (!prop->isBuiltinType()) {
+ TypeReference &r = this->add(prop->builtinTypeOrTypeNameIndex(), prop->location);
r.errorWhenNotFound = true;
}
}
@@ -1138,7 +1338,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);
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 36b7f68de9..36269691fc 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -76,7 +76,7 @@ void Object::simplifyRequiredProperties() {
for (auto it = this->propertiesBegin(); it != this->propertiesEnd(); ++it) {
auto requiredIt = required.find(it->nameIndex);
if (requiredIt != required.end()) {
- it->isRequired = true;
+ it->setIsRequired(true);
required.erase(requiredIt);
}
}
@@ -106,20 +106,18 @@ bool Parameter::init(QV4::CompiledData::Parameter *param, const QV4::Compiler::J
bool Parameter::initType(QV4::CompiledData::ParameterType *paramType, const QV4::Compiler::JSUnitGenerator *stringGenerator, int typeNameIndex)
{
- paramType->indexIsBuiltinType = false;
- paramType->typeNameIndexOrBuiltinType = 0;
const QString typeName = stringGenerator->stringForIndex(typeNameIndex);
auto builtinType = stringToBuiltinType(typeName);
if (builtinType == QV4::CompiledData::BuiltinType::InvalidBuiltin) {
- if (typeName.isEmpty() || !typeName.at(0).isUpper())
+ if (typeName.isEmpty() || !typeName.at(0).isUpper()) {
+ paramType->set(false, 0);
return false;
- paramType->indexIsBuiltinType = false;
- paramType->typeNameIndexOrBuiltinType = typeNameIndex;
+ }
Q_ASSERT(quint32(typeNameIndex) < (1u << 31));
+ paramType->set(false, typeNameIndex);
} else {
- paramType->indexIsBuiltinType = true;
- paramType->typeNameIndexOrBuiltinType = static_cast<quint32>(builtinType);
Q_ASSERT(quint32(builtinType) < (1u << 31));
+ paramType->set(true, static_cast<quint32>(builtinType));
}
return true;
}
@@ -173,9 +171,7 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons
{
inheritedTypeNameIndex = typeNameIndex;
- location.line = loc.startLine;
- location.column = loc.startColumn;
-
+ location.set(loc.startLine, loc.startColumn);
idNameIndex = idIndex;
id = -1;
indexOfDefaultPropertyOrAlias = -1;
@@ -198,8 +194,8 @@ QString IRBuilder::sanityCheckFunctionNames(Object *obj, const QSet<QString> &il
QSet<int> functionNames;
for (auto functionit = obj->functionsBegin(); functionit != obj->functionsEnd(); ++functionit) {
Function *f = functionit.ptr;
- errorLocation->startLine = f->location.line;
- errorLocation->startColumn = f->location.column;
+ errorLocation->startLine = f->location.line();
+ errorLocation->startColumn = f->location.column();
if (functionNames.contains(f->nameIndex))
return tr("Duplicate method name");
functionNames.insert(f->nameIndex);
@@ -280,7 +276,7 @@ QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefau
target = this;
auto aliasWithSameName = std::find_if(target->aliases->begin(), target->aliases->end(), [&alias](const Alias &targetAlias){
- return targetAlias.nameIndex == alias->nameIndex;
+ return targetAlias.nameIndex() == alias->nameIndex();
});
if (aliasWithSameName != target->aliases->end())
return tr("Duplicate alias name");
@@ -323,13 +319,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);
@@ -397,8 +397,7 @@ void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString
import->type = QV4::CompiledData::Import::ImportScript;
import->uriIndex = jsGenerator->registerString(jsfile);
import->qualifierIndex = jsGenerator->registerString(module);
- import->location.line = lineNumber;
- import->location.column = column;
+ import->location.set(lineNumber, column);
document->imports << import;
}
@@ -413,8 +412,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString &
import->majorVersion = vmaj;
import->minorVersion = vmin;
import->qualifierIndex = jsGenerator->registerString(module);
- import->location.line = lineNumber;
- import->location.column = column;
+ import->location.set(lineNumber, column);
document->imports << import;
}
@@ -575,8 +573,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiInlineComponent *ast)
inlineComponent->nameIndex = registerString(ast->name.toString());
inlineComponent->objectIndex = idx;
auto location = ast->firstSourceLocation();
- inlineComponent->location.line = location.startLine;
- inlineComponent->location.column = location.startColumn;
+ inlineComponent->location.set(location.startLine, location.startColumn);
_object->appendInlineComponent(inlineComponent);
return false;
}
@@ -772,8 +769,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node)
import->minorVersion = -1;
}
- import->location.line = node->importToken.startLine;
- import->location.column = node->importToken.startColumn;
+ import->location.set(node->importToken.startLine, node->importToken.startColumn);
import->uriIndex = registerString(uri);
@@ -801,8 +797,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPragma *node)
return false;
}
- pragma->location.line = node->pragmaToken.startLine;
- pragma->location.column = node->pragmaToken.startColumn;
+ pragma->location.set(node->pragmaToken.startLine, node->pragmaToken.startColumn);
_pragmas.append(pragma);
return false;
@@ -835,8 +830,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiEnumDeclaration *node)
if (enumName.at(0).isLower())
COMPILE_EXCEPTION(node->enumToken, tr("Scoped enum names must begin with an upper case letter"));
- enumeration->location.line = node->enumToken.startLine;
- enumeration->location.column = node->enumToken.startColumn;
+ enumeration->location.set(node->enumToken.startLine, node->enumToken.startColumn);
enumeration->enumValues = New<PoolList<EnumValue>>();
@@ -855,8 +849,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiEnumDeclaration *node)
COMPILE_EXCEPTION(e->valueToken, tr("Enum value out of range"));
enumValue->value = e->value;
- enumValue->location.line = e->memberToken.startLine;
- enumValue->location.column = e->memberToken.startColumn;
+ enumValue->location.set(e->memberToken.startLine, e->memberToken.startColumn);
enumeration->enumValues->append(enumValue);
e = e->next;
@@ -880,8 +873,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
signal->nameIndex = registerString(signalName);
QQmlJS::SourceLocation loc = node->typeToken;
- signal->location.line = loc.startLine;
- signal->location.column = loc.startColumn;
+ signal->location.set(loc.startLine, loc.startColumn);
signal->parameters = New<PoolList<Parameter> >();
@@ -930,8 +922,8 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
const QStringRef &name = node->name;
Property *property = New<Property>();
- property->isReadOnly = node->isReadonlyMember;
- property->isRequired = node->isRequired;
+ property->setIsReadOnly(node->isReadonlyMember);
+ property->setIsRequired(node->isRequired);
QV4::CompiledData::BuiltinType builtinPropertyType = Parameter::stringToBuiltinType(memberType);
bool typeFound = builtinPropertyType != QV4::CompiledData::BuiltinType::InvalidBuiltin;
@@ -943,7 +935,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
property->setCustomType(registerString(memberType));
if (typeModifier == QLatin1String("list")) {
- property->isList = true;
+ property->setIsList(true);
} else if (!typeModifier.isEmpty()) {
recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
return false;
@@ -963,8 +955,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
property->nameIndex = registerString(propName);
QQmlJS::SourceLocation loc = node->firstSourceLocation();
- property->location.line = loc.startLine;
- property->location.column = loc.startColumn;
+ property->location.set(loc.startLine, loc.startColumn);
QQmlJS::SourceLocation errorLocation;
QString error;
@@ -1008,8 +999,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node)
Function *f = New<Function>();
QQmlJS::SourceLocation loc = funDecl->identifierToken;
- f->location.line = loc.startLine;
- f->location.column = loc.startColumn;
+ f->location.set(loc.startLine, loc.startColumn);
f->index = index;
f->nameIndex = registerString(funDecl->name.toString());
@@ -1089,26 +1079,25 @@ QStringRef IRBuilder::textRefAt(const QQmlJS::SourceLocation &first, const QQmlJ
void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, QQmlJS::AST::Node *parentNode)
{
QQmlJS::SourceLocation loc = statement->firstSourceLocation();
- binding->valueLocation.line = loc.startLine;
- binding->valueLocation.column = loc.startColumn;
- binding->type = QV4::CompiledData::Binding::Type_Invalid;
- if (_propertyDeclaration && _propertyDeclaration->isReadOnly)
- binding->flags |= QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration;
+ binding->valueLocation.set(loc.startLine, loc.startColumn);
+ binding->setType(QV4::CompiledData::Binding::Type_Invalid);
+ if (_propertyDeclaration && _propertyDeclaration->isReadOnly())
+ 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 (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)) {
@@ -1117,21 +1106,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;
@@ -1187,7 +1176,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
if (args)
return; // too many arguments, stop
- binding->type = QV4::CompiledData::Binding::Type_Translation;
+ binding->setType(QV4::CompiledData::Binding::Type_Translation);
binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData);
} else if (base == QLatin1String("qsTrId")) {
QV4::CompiledData::TranslationData translationData;
@@ -1220,7 +1209,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
if (args)
return; // too many arguments, stop
- binding->type = QV4::CompiledData::Binding::Type_TranslationById;
+ binding->setType(QV4::CompiledData::Binding::Type_TranslationById);
binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData);
} else if (base == QLatin1String("QT_TR_NOOP") || base == QLatin1String("QT_TRID_NOOP")) {
if (!args || !args->expression)
@@ -1237,7 +1226,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
if (args)
return; // too many arguments, stop
- binding->type = QV4::CompiledData::Binding::Type_String;
+ binding->setType(QV4::CompiledData::Binding::Type_String);
binding->stringIndex = jsGenerator->registerString(str.toString());
} else if (base == QLatin1String("QT_TRANSLATE_NOOP")) {
if (!args || !args->expression)
@@ -1258,7 +1247,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
if (args)
return; // too many arguments, stop
- binding->type = QV4::CompiledData::Binding::Type_String;
+ binding->setType(QV4::CompiledData::Binding::Type_String);
binding->stringIndex = jsGenerator->registerString(str.toString());
}
}
@@ -1295,9 +1284,8 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
binding->offset = nameLocation.offset;
- binding->location.line = nameLocation.startLine;
- binding->location.column = nameLocation.startColumn;
- binding->flags = 0;
+ binding->location.set(nameLocation.startLine, nameLocation.startColumn);
+ binding->clearFlags();
setBindingValue(binding, value, parentNode);
QString error = bindingsTarget()->appendBinding(binding, /*isListBinding*/false);
if (!error.isEmpty()) {
@@ -1315,27 +1303,26 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
binding->offset = nameLocation.offset;
- binding->location.line = nameLocation.startLine;
- binding->location.column = nameLocation.startColumn;
+ binding->location.set(nameLocation.startLine, nameLocation.startColumn);
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;
+ if (_propertyDeclaration && _propertyDeclaration->isReadOnly())
+ binding->setFlag(QV4::CompiledData::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);
@@ -1347,16 +1334,15 @@ void IRBuilder::appendBinding(const QQmlJS::SourceLocation &qualifiedNameLocatio
bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
{
Alias *alias = New<Alias>();
- alias->flags = 0;
+ alias->clearFlags();
if (node->isReadonlyMember)
- alias->flags |= QV4::CompiledData::Alias::IsReadOnly;
+ alias->setFlag(QV4::CompiledData::Alias::IsReadOnly);
const QString propName = node->name.toString();
- alias->nameIndex = registerString(propName);
+ alias->setNameIndex(registerString(propName));
QQmlJS::SourceLocation loc = node->firstSourceLocation();
- alias->location.line = loc.startLine;
- alias->location.column = loc.startColumn;
+ alias->location.set(loc.startLine, loc.startColumn);
alias->propertyNameIndex = emptyStringIndex;
@@ -1370,8 +1356,7 @@ bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
rhsLoc = node->statement->firstSourceLocation();
else
rhsLoc = node->semicolonToken;
- alias->referenceLocation.line = rhsLoc.startLine;
- alias->referenceLocation.column = rhsLoc.startColumn;
+ alias->referenceLocation.set(rhsLoc.startLine, rhsLoc.startColumn);
QStringList aliasReference;
@@ -1466,8 +1451,7 @@ bool IRBuilder::setId(const QQmlJS::SourceLocation &idLocation, QQmlJS::AST::Sta
COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times"));
_object->idNameIndex = registerString(idQString);
- _object->locationOfIdProperty.line = idLocation.startLine;
- _object->locationOfIdProperty.column = idLocation.startColumn;
+ _object->locationOfIdProperty.set(idLocation.startLine, idLocation.startColumn);
return true;
}
@@ -1513,19 +1497,23 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
binding->offset = qualifiedIdElement->identifierToken.offset;
- binding->location.line = qualifiedIdElement->identifierToken.startLine;
- binding->location.column = qualifiedIdElement->identifierToken.startColumn;
- binding->valueLocation.line = qualifiedIdElement->next->identifierToken.startLine;
- binding->valueLocation.column = qualifiedIdElement->next->identifierToken.startColumn;
- binding->flags = 0;
+ binding->location.set(qualifiedIdElement->identifierToken.startLine,
+ qualifiedIdElement->identifierToken.startColumn);
+ binding->valueLocation.set(qualifiedIdElement->next->identifierToken.startLine,
+ qualifiedIdElement->next->identifierToken.startColumn);
+ binding->location.set(qualifiedIdElement->identifierToken.startLine,
+ qualifiedIdElement->identifierToken.startColumn);
+ binding->valueLocation.set(qualifiedIdElement->next->identifierToken.startLine,
+ qualifiedIdElement->next->identifierToken.startColumn);
+ 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, QQmlJS::SourceLocation(), nullptr, nullptr))
@@ -1586,7 +1574,7 @@ bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement)
bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement)
{
- if (property->isBuiltinType || property->isList)
+ if (property->isBuiltinType() || property->isList())
return false;
QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement *>(statement);
if (!exprStmt)
@@ -1684,10 +1672,10 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
- objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
- objectToWrite->flags = o->flags;
+ objectToWrite->setHasAliasAsDefaultProperty(o->defaultPropertyIsAlias);
+ objectToWrite->setFlags(QV4::CompiledData::Object::Flags(o->flags));
objectToWrite->idNameIndex = o->idNameIndex;
- objectToWrite->id = o->id;
+ objectToWrite->setObjectId(o->id);
objectToWrite->location = o->location;
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
@@ -1862,7 +1850,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);
}
@@ -1972,7 +1960,7 @@ bool JSCodeGen::compileComponent(int contextObject)
if (obj->flags & QV4::CompiledData::Object::IsComponent && !obj->isInlineComponent) {
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;
}
for (auto it = obj->inlineComponentsBegin(); it != obj->inlineComponentsEnd(); ++it)
@@ -2000,11 +1988,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/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 9629a73199..8996777289 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -394,6 +394,10 @@ public:
int namedObjectsInComponentCount() const { return namedObjectsInComponent.size(); }
const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
+ bool hasFlag(QV4::CompiledData::Object::Flag flag) const { return flags & flag; }
+ qint32 objectId() const { return id; }
+ bool hasAliasAsDefaultProperty() const { return defaultPropertyIsAlias; }
+
private:
friend struct ::QQmlIRLoader;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 14cf0a0c8f..18e19cf01c 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -160,10 +160,7 @@ int QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
int QV4::Compiler::JSUnitGenerator::registerGetterLookup(int nameIndex)
{
- CompiledData::Lookup l;
- l.type_and_flags = CompiledData::Lookup::Type_Getter;
- l.nameIndex = nameIndex;
- lookups << l;
+ lookups << CompiledData::Lookup(CompiledData::Lookup::Type_Getter, nameIndex);
return lookups.size() - 1;
}
@@ -174,49 +171,37 @@ int QV4::Compiler::JSUnitGenerator::registerSetterLookup(const QString &name)
int QV4::Compiler::JSUnitGenerator::registerSetterLookup(int nameIndex)
{
- CompiledData::Lookup l;
- l.type_and_flags = CompiledData::Lookup::Type_Setter;
- l.nameIndex = nameIndex;
- lookups << l;
+ lookups << CompiledData::Lookup(CompiledData::Lookup::Type_Setter, nameIndex);
return lookups.size() - 1;
}
int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(int nameIndex)
{
- CompiledData::Lookup l;
- l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter;
- l.nameIndex = nameIndex;
- lookups << l;
+ lookups << CompiledData::Lookup(CompiledData::Lookup::Type_GlobalGetter, nameIndex);
return lookups.size() - 1;
}
int QV4::Compiler::JSUnitGenerator::registerQmlContextPropertyGetterLookup(int nameIndex)
{
- CompiledData::Lookup l;
- l.type_and_flags = CompiledData::Lookup::Type_QmlContextPropertyGetter;
- l.nameIndex = nameIndex;
- lookups << l;
+ lookups << CompiledData::Lookup(CompiledData::Lookup::Type_QmlContextPropertyGetter, nameIndex);
return lookups.size() - 1;
}
int QV4::Compiler::JSUnitGenerator::registerRegExp(QQmlJS::AST::RegExpLiteral *regexp)
{
- CompiledData::RegExp re;
- re.stringIndex = registerString(regexp->pattern.toString());
-
- re.flags = 0;
+ quint32 flags = 0;
if (regexp->flags & QQmlJS::Lexer::RegExp_Global)
- re.flags |= CompiledData::RegExp::RegExp_Global;
+ flags |= CompiledData::RegExp::RegExp_Global;
if (regexp->flags & QQmlJS::Lexer::RegExp_IgnoreCase)
- re.flags |= CompiledData::RegExp::RegExp_IgnoreCase;
+ flags |= CompiledData::RegExp::RegExp_IgnoreCase;
if (regexp->flags & QQmlJS::Lexer::RegExp_Multiline)
- re.flags |= CompiledData::RegExp::RegExp_Multiline;
+ flags |= CompiledData::RegExp::RegExp_Multiline;
if (regexp->flags & QQmlJS::Lexer::RegExp_Unicode)
- re.flags |= CompiledData::RegExp::RegExp_Unicode;
+ flags |= CompiledData::RegExp::RegExp_Unicode;
if (regexp->flags & QQmlJS::Lexer::RegExp_Sticky)
- re.flags |= CompiledData::RegExp::RegExp_Sticky;
+ flags |= CompiledData::RegExp::RegExp_Sticky;
- regexps.append(re);
+ regexps.append(CompiledData::RegExp(flags, registerString(regexp->pattern.toString())));
return regexps.size() - 1;
}
@@ -249,8 +234,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(const QStringList &members)
CompiledData::JSClassMember *member = reinterpret_cast<CompiledData::JSClassMember*>(jsClass + 1);
for (const auto &name : members) {
- member->nameOffset = registerString(name);
- member->isAccessor = false;
+ member->set(registerString(name), false);
++member;
}
@@ -468,8 +452,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
currentOffset += function->nLabelInfos * sizeof(quint32);
}
- function->location.line = irFunction->line;
- function->location.column = irFunction->column;
+ function->location.set(irFunction->line, irFunction->column);
function->codeOffset = currentOffset;
function->codeSize = irFunction->code.size();
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index a1ddee8234..bd3a456c36 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -57,10 +57,7 @@ using namespace QQmlJS::AST;
static CompiledData::Location location(const QQmlJS::SourceLocation &astLocation)
{
- CompiledData::Location target;
- target.line = astLocation.startLine;
- target.column = astLocation.startColumn;
- return target;
+ return CompiledData::Location(astLocation.startLine, astLocation.startColumn);
}
diff --git a/src/qml/configure.pri b/src/qml/configure.pri
index fcd2eacace..4506a5790d 100644
--- a/src/qml/configure.pri
+++ b/src/qml/configure.pri
@@ -13,7 +13,7 @@ defineTest(qtConfTest_detectPython) {
}
# Make tests.python.location available in configure.json.
- $${1}.location = $$shell_path($$python_path)
+ $${1}.location = $$shell_quote($$shell_path($$python_path))
export($${1}.location)
$${1}.cache += location
export($${1}.cache)
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 58b8ea2c4f..0ca56f3a70 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -44,17 +44,26 @@
#include <private/qqmlengine_p.h>
#include <private/qv4compileddata_p.h>
+#include <atomic>
#include <cstdio>
QT_REQUIRE_CONFIG(qml_debug);
QT_BEGIN_NAMESPACE
+#if __cplusplus >= 202002L
+# define Q_ATOMIC_FLAG_INIT {}
+#else
+# define Q_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT // deprecated in C++20
+#endif
+
+static std::atomic_flag s_printedWarning = Q_ATOMIC_FLAG_INIT;
+
QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
{
- if (!QQmlEnginePrivate::qml_debugging_enabled && printWarning)
+ if (printWarning && !s_printedWarning.test_and_set(std::memory_order_relaxed))
fprintf(stderr, "QML debugging is enabled. Only use this in a safe environment.\n");
- QQmlEnginePrivate::qml_debugging_enabled = true;
+ QQmlEnginePrivate::qml_debugging_enabled.store(true, std::memory_order_relaxed);
}
/*!
diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp
index 0ef40d6911..01a0723b76 100644
--- a/src/qml/debugger/qqmldebugconnector.cpp
+++ b/src/qml/debugger/qqmldebugconnector.cpp
@@ -111,7 +111,7 @@ QQmlDebugConnector *QQmlDebugConnector::instance()
if (!params)
return nullptr;
- if (!QQmlEnginePrivate::qml_debugging_enabled) {
+ if (!QQmlEnginePrivate::qml_debugging_enabled.load(std::memory_order_relaxed)) {
if (!params->arguments.isEmpty()) {
qWarning().noquote() << QString::fromLatin1(
"QML Debugger: Ignoring \"-qmljsdebugger=%1\". Debugging "
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index d3eedab1c6..ed1e011830 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -176,7 +176,7 @@ public:
RefLocation(QV4::ExecutableCompilationUnit *ref, const QUrl &url,
const QV4::CompiledData::Object *obj, const QString &type)
- : Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
+ : Location(QQmlSourceLocation(type, obj->location.line(), obj->location.column()), url),
locationType(Creating), sent(false)
{
unit = ref;
diff --git a/src/qml/inlinecomponentutils_p.h b/src/qml/inlinecomponentutils_p.h
index 7666457d98..c3ab0e1fe5 100644
--- a/src/qml/inlinecomponentutils_p.h
+++ b/src/qml/inlinecomponentutils_p.h
@@ -55,26 +55,38 @@
namespace icutils {
struct Node {
+private:
+ using IndexType = std::vector<QV4::CompiledData::InlineComponent>::size_type;
+ using IndexField = quint32_le_bitfield_member<0, 30, IndexType>;
+ using TemporaryMarkField = quint32_le_bitfield_member<30, 1>;
+ using PermanentMarkField = quint32_le_bitfield_member<31, 1>;
+ quint32_le_bitfield_union<IndexField, TemporaryMarkField, PermanentMarkField> m_data;
+
+public:
Node() = default;
Node(const Node &) = default;
Node(Node &&) = default;
Node& operator=(Node const &) = default;
Node& operator=(Node &&) = default;
- bool operator==(Node const &other) const {return index == other.index;}
+ bool operator==(Node const &other) const {return m_data.data() == other.m_data.data(); }
+
+ Node(IndexType s) : m_data(QSpecialIntegerBitfieldZero) { m_data.set<IndexField>(s); }
+
+ bool hasPermanentMark() const { return m_data.get<PermanentMarkField>(); }
+ bool hasTemporaryMark() const { return m_data.get<TemporaryMarkField>(); }
+
+ void setPermanentMark()
+ {
+ m_data.set<TemporaryMarkField>(0);
+ m_data.set<PermanentMarkField>(1);
+ }
- Node(std::vector<QV4::CompiledData::InlineComponent>::size_type s)
- : index{0}
+ void setTemporaryMark()
{
- index = quint32(s);
- temporaryMark = 0;
- permanentMark = 0;
+ m_data.set<TemporaryMarkField>(1);
}
- union {
- quint32_le_bitfield<0, 30> index;
- quint32_le_bitfield<30, 1> temporaryMark;
- quint32_le_bitfield<31, 1> permanentMark;
- };
+ IndexType index() const { return m_data.get<IndexField>(); }
};
using AdjacencyList = std::vector<std::vector<Node*>>;
@@ -109,8 +121,11 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, Adja
auto referencedInICObjectIndex = ic.objectIndex + 1;
while (int(referencedInICObjectIndex) < objectContainer->objectCount()) {
auto potentiallyReferencedInICObject = objectContainer->objectAt(referencedInICObjectIndex);
- bool stillInIC = !(potentiallyReferencedInICObject-> flags & QV4::CompiledData::Object::IsInlineComponentRoot)
- && (potentiallyReferencedInICObject-> flags & QV4::CompiledData::Object::InPartOfInlineComponent);
+ bool stillInIC
+ = !potentiallyReferencedInICObject->hasFlag(
+ QV4::CompiledData::Object::IsInlineComponentRoot)
+ && potentiallyReferencedInICObject->hasFlag(
+ QV4::CompiledData::Object::InPartOfInlineComponent);
if (!stillInIC)
break;
createEdgeFromTypeRef(objectContainer->resolvedType(potentiallyReferencedInICObject->inheritedTypeNameIndex));
@@ -120,21 +135,20 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, Adja
};
inline void topoVisit(Node *node, AdjacencyList &adjacencyList, bool &hasCycle, std::vector<Node> &nodesSorted) {
- if (node->permanentMark)
+ if (node->hasPermanentMark())
return;
- if (node->temporaryMark) {
+ if (node->hasTemporaryMark()) {
hasCycle = true;
return;
}
- node->temporaryMark = 1;
+ node->setTemporaryMark();
- auto const &edges = adjacencyList[node->index];
+ auto const &edges = adjacencyList[node->index()];
for (auto edgeTarget =edges.begin(); edgeTarget != edges.end(); ++edgeTarget) {
topoVisit(*edgeTarget, adjacencyList, hasCycle, nodesSorted);
}
- node->temporaryMark = 0;
- node->permanentMark = 1;
+ node->setPermanentMark();
nodesSorted.push_back(*node);
};
@@ -145,7 +159,7 @@ inline std::vector<Node> topoSort(std::vector<Node> &nodes, AdjacencyList &adjac
hasCycle = false;
auto currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
- return node.permanentMark == 0;
+ return !node.hasPermanentMark();
});
// Do a topological sort of all inline components
// afterwards, nodesSorted contains the nodes for the inline components in reverse topological order
@@ -153,7 +167,7 @@ inline std::vector<Node> topoSort(std::vector<Node> &nodes, AdjacencyList &adjac
Node& currentNode = *currentNodeIt;
topoVisit(&currentNode, adjacencyList, hasCycle, nodesSorted);
currentNodeIt = std::find_if(nodes.begin(), nodes.end(), [](const Node& node) {
- return node.permanentMark == 0;
+ return !node.hasPermanentMark();
});
}
return nodesSorted;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d26e991d3f..f5dca60559 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -300,6 +300,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
if (ok && envMaxGCStackSize > 0)
m_maxGCStackSize = envMaxGCStackSize;
+ // We allocate guard pages around our stacks.
+ const size_t guardPages = 2 * WTF::pageSize();
+
memoryManager = new QV4::MemoryManager(this);
if (maxCallDepth == -1) {
@@ -327,9 +330,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
// reserve space for the JS stack
// we allow it to grow to a bit more than m_maxJSStackSize, as we can overshoot due to ScopedValues
// allocated outside of JIT'ed methods.
- *jsStack = WTF::PageAllocation::allocate(m_maxJSStackSize + 256*1024, WTF::OSAllocator::JSVMStackPages,
- /* writable */ true, /* executable */ false,
- /* includesGuardPages */ true);
+ *jsStack = WTF::PageAllocation::allocate(
+ m_maxJSStackSize + 256*1024 + guardPages, WTF::OSAllocator::JSVMStackPages,
+ /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
jsStackBase = (Value *)jsStack->base();
#ifdef V4_USE_VALGRIND
VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, m_maxJSStackSize + 256*1024);
@@ -337,9 +340,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsStackTop = jsStackBase;
- *gcStack = WTF::PageAllocation::allocate(m_maxGCStackSize, WTF::OSAllocator::JSVMStackPages,
- /* writable */ true, /* executable */ false,
- /* includesGuardPages */ true);
+ *gcStack = WTF::PageAllocation::allocate(
+ m_maxGCStackSize + guardPages, WTF::OSAllocator::JSVMStackPages,
+ /* writable */ true, /* executable */ false, /* includesGuardPages */ true);
{
ok = false;
@@ -2030,7 +2033,7 @@ void ExecutionEngine::setQmlEngine(QQmlEngine *engine)
static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
{
- if (object->as<QV4::QObjectWrapper>() || object->internalClass()->isFrozen)
+ if (object->as<QV4::QObjectWrapper>() || object->internalClass()->isFrozen())
return;
QV4::Scope scope(v4);
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 5eb0e889b0..09a1e936ad 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -155,10 +155,10 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
data->regexpTableSize * sizeof(QV4::Value));
for (uint i = 0; i < data->regexpTableSize; ++i) {
const CompiledData::RegExp *re = data->regexpAt(i);
- uint f = re->flags;
+ uint f = re->flags();
const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
runtimeRegularExpressions[i] = QV4::RegExp::create(
- engine, stringAt(re->stringIndex), flags);
+ engine, stringAt(re->stringIndex()), flags);
}
if (data->lookupTableSize) {
@@ -169,7 +169,7 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
QV4::Lookup *l = runtimeLookups + i;
CompiledData::Lookup::Type type
- = CompiledData::Lookup::Type(uint(compiledLookups[i].type_and_flags));
+ = CompiledData::Lookup::Type(uint(compiledLookups[i].typeAndFlags()));
if (type == CompiledData::Lookup::Type_Getter)
l->getter = QV4::Lookup::getterGeneric;
else if (type == CompiledData::Lookup::Type_Setter)
@@ -178,7 +178,7 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
l->globalGetter = QV4::Lookup::globalGetterGeneric;
else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
- l->nameIndex = compiledLookups[i].nameIndex;
+ l->nameIndex = compiledLookups[i].nameIndex();
}
}
@@ -199,8 +199,8 @@ QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
runtimeClasses[i]
= runtimeClasses[i]->addMember(
engine->identifierTable->asPropertyKey(
- runtimeStrings[member->nameOffset]),
- member->isAccessor
+ runtimeStrings[member->nameOffset()]),
+ member->isAccessor()
? QV4::Attr_Accessor
: QV4::Attr_Data);
}
@@ -368,7 +368,7 @@ IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int com
const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
- namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
+ namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->objectId());
}
return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
}
@@ -421,13 +421,14 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
// We need to first iterate over all inline components, as the containing component might create instances of them
// and in that case we need to add its object count
for (auto nodeIt = nodesSorted.rbegin(); nodeIt != nodesSorted.rend(); ++nodeIt) {
- const auto &ic = allICs.at(nodeIt->index);
+ const auto &ic = allICs.at(nodeIt->index());
int lastICRoot = ic.objectIndex;
for (int i = ic.objectIndex; i<objectCount(); ++i) {
const QV4::CompiledData::Object *obj = objectAt(i);
- bool leftCurrentInlineComponent =
- (i != lastICRoot && obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)
- || !(obj->flags & QV4::CompiledData::Object::InPartOfInlineComponent);
+ bool leftCurrentInlineComponent
+ = (i != lastICRoot
+ && obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot))
+ || !obj->hasFlag(QV4::CompiledData::Object::InPartOfInlineComponent);
if (leftCurrentInlineComponent)
break;
inlineComponentData[lastICRoot].totalBindingCount += obj->nBindings;
@@ -457,9 +458,9 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
int objectCount = 0;
for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
const QV4::CompiledData::Object *obj = objectAt(i);
- if (obj->flags & QV4::CompiledData::Object::InPartOfInlineComponent) {
+ if (obj->hasFlag(QV4::CompiledData::Object::InPartOfInlineComponent))
continue;
- }
+
bindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
@@ -571,7 +572,9 @@ Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine)
if (!valuePtr) {
QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ engine->throwReferenceError(
+ referenceErrorMessage, fileName(),
+ entry.location.line(), entry.location.column());
return nullptr;
}
imports[i] = valuePtr;
@@ -587,7 +590,9 @@ Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine)
if (!dependentModuleUnit->resolveExport(importName)) {
QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ engine->throwReferenceError(
+ referenceErrorMessage, fileName(),
+ entry.location.line(), entry.location.column());
return nullptr;
}
}
@@ -858,7 +863,7 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *e
QString ExecutableCompilationUnit::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);
@@ -906,7 +911,7 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind
QString ExecutableCompilationUnit::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);
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 7bfb68da9d..29e82bf2d5 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -282,7 +282,7 @@ public:
QString bindingValueAsScriptString(const CompiledData::Binding *binding) const;
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/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index aeb4835c40..cf8a53cf9f 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -176,7 +176,8 @@ QString Function::prettyName(const Function *function, const void *code)
QQmlSourceLocation Function::sourceLocation() const
{
- return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column);
+ return QQmlSourceLocation(
+ sourceFile(), compiledFunction->location.line(), compiledFunction->location.column());
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 1cd2ecffa4..ccc55d869f 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -303,7 +303,6 @@ struct PropertyAttributes
void clear() { m_all = 0; }
bool isEmpty() const { return !m_all; }
- uint flags() const { return m_flags; }
uint all() const { return m_all; }
bool operator==(PropertyAttributes other) {
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 70849775cb..904c6a5eaf 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -178,7 +178,7 @@ void SharedInternalClassDataPrivate<PropertyKey>::setSize(uint s)
data->values.size = s;
}
-PropertyKey SharedInternalClassDataPrivate<PropertyKey>::at(uint i)
+PropertyKey SharedInternalClassDataPrivate<PropertyKey>::at(uint i) const
{
Q_ASSERT(data && i < size());
return PropertyKey::fromId(data->values.values[i].rawValue());
@@ -265,6 +265,13 @@ namespace Heap {
void InternalClass::init(ExecutionEngine *engine)
{
+// InternalClass is automatically zeroed during allocation:
+// prototype = nullptr;
+// parent = nullptr;
+// size = 0;
+// numRedundantTransitions = 0;
+// flags = 0;
+
Base::init();
new (&propertyTable) PropertyHash();
new (&nameMap) SharedInternalClassData<PropertyKey>(engine);
@@ -273,13 +280,6 @@ void InternalClass::init(ExecutionEngine *engine)
this->engine = engine;
vtable = QV4::InternalClass::staticVTable();
-// prototype = nullptr;
-// parent = nullptr;
-// size = 0;
- extensible = true;
- isFrozen = false;
- isSealed = false;
- isUsedAsProto = false;
protoId = engine->newProtoId();
// Also internal classes need an internal class pointer. Simply make it point to itself
@@ -300,10 +300,8 @@ void InternalClass::init(Heap::InternalClass *other)
prototype = other->prototype;
parent = other;
size = other->size;
- extensible = other->extensible;
- isSealed = other->isSealed;
- isFrozen = other->isFrozen;
- isUsedAsProto = other->isUsedAsProto;
+ numRedundantTransitions = other->numRedundantTransitions;
+ flags = other->flags;
protoId = engine->newProtoId();
internalClass.set(engine, other->internalClass);
@@ -365,7 +363,99 @@ static void addDummyEntry(InternalClass *newClass, PropertyHash::Entry e)
++newClass->size;
}
-Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
+static PropertyAttributes attributesFromFlags(int flags)
+{
+ PropertyAttributes attributes;
+ attributes.m_all = uchar(flags);
+ return attributes;
+}
+
+static Heap::InternalClass *cleanInternalClass(Heap::InternalClass *orig)
+{
+ if (++orig->numRedundantTransitions < Heap::InternalClass::MaxRedundantTransitions)
+ return orig;
+
+ // We will generally add quite a few transitions here. We have 255 redundant ones.
+ // We can expect at least as many significant ones in addition.
+ std::vector<InternalClassTransition> transitions;
+
+ Scope scope(orig->engine);
+ Scoped<QV4::InternalClass> child(scope, orig);
+
+ {
+ quint8 remainingRedundantTransitions = orig->numRedundantTransitions;
+ QSet<PropertyKey> properties;
+ int structureChanges = 0;
+
+ Scoped<QV4::InternalClass> parent(scope, orig->parent);
+ while (parent && remainingRedundantTransitions > 0) {
+ Q_ASSERT(child->d() != scope.engine->classes[ExecutionEngine::Class_Empty]);
+ const auto it = std::find_if(
+ parent->d()->transitions.begin(), parent->d()->transitions.end(),
+ [&child](const InternalClassTransition &t) {
+ return child->d() == t.lookup;
+ });
+ Q_ASSERT(it != parent->d()->transitions.end());
+
+ if (it->flags & InternalClassTransition::StructureChange) {
+ // A structural change. Each kind of structural change has to be recorded only once.
+ if ((structureChanges & it->flags) != it->flags) {
+ transitions.push_back(*it);
+ structureChanges |= it->flags;
+ } else {
+ --remainingRedundantTransitions;
+ }
+ } else if (!properties.contains(it->id)) {
+ // We only need the final state of the property.
+ properties.insert(it->id);
+
+ // Property removal creates _two_ redundant transitions.
+ // We don't have to replay either, but numRedundantTransitions only records one.
+ if (it->flags != 0)
+ transitions.push_back(*it);
+ } else {
+ --remainingRedundantTransitions;
+ }
+
+ child = parent->d();
+ parent = child->d()->parent;
+ Q_ASSERT(child->d() != parent->d());
+ }
+ }
+
+ for (auto it = transitions.rbegin(); it != transitions.rend(); ++it) {
+ switch (it->flags) {
+ case InternalClassTransition::NotExtensible:
+ child = child->d()->nonExtensible();
+ continue;
+ case InternalClassTransition::VTableChange:
+ child = child->d()->changeVTable(it->vtable);
+ continue;
+ case InternalClassTransition::PrototypeChange:
+ child = child->d()->changePrototype(it->prototype);
+ continue;
+ case InternalClassTransition::ProtoClass:
+ child = child->d()->asProtoClass();
+ continue;
+ case InternalClassTransition::Sealed:
+ child = child->d()->sealed();
+ continue;
+ case InternalClassTransition::Frozen:
+ child = child->d()->frozen();
+ continue;
+ default:
+ Q_ASSERT(it->flags != 0);
+ Q_ASSERT(it->flags < InternalClassTransition::StructureChange);
+ child = child->addMember(it->id, attributesFromFlags(it->flags));
+ continue;
+ }
+ }
+
+ return child->d();
+}
+
+Heap::InternalClass *InternalClass::changeMember(
+ PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
{
if (!data.isEmpty())
data.resolve();
@@ -381,7 +471,7 @@ Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, Propert
}
if (data == propertyData.at(idx))
- return static_cast<Heap::InternalClass *>(this);
+ return this;
Transition temp = { { identifier }, nullptr, int(data.all()) };
Transition &t = lookupOrInsertTransition(temp);
@@ -394,7 +484,8 @@ Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, Propert
Q_ASSERT(!propertyData.at(idx).isAccessor());
// add a dummy entry for the accessor
- entry->setterIndex = newClass->size;
+ if (entry)
+ entry->setterIndex = newClass->size;
e->setterIndex = newClass->size;
addDummyEntry(newClass, *e);
}
@@ -403,7 +494,8 @@ Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, Propert
t.lookup = newClass;
Q_ASSERT(t.lookup);
- return newClass;
+
+ return cleanInternalClass(newClass);
}
Heap::InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
@@ -413,7 +505,7 @@ Heap::InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
if (proto)
proto->setUsedAsProto();
Q_ASSERT(prototype != proto);
- Q_ASSERT(!proto || proto->internalClass->isUsedAsProto);
+ Q_ASSERT(!proto || proto->internalClass->isUsedAsProto());
Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::PrototypeChange };
temp.prototype = proto;
@@ -427,8 +519,7 @@ Heap::InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto)
newClass->prototype = proto;
t.lookup = newClass;
-
- return newClass;
+ return prototype ? cleanInternalClass(newClass) : newClass;
}
Heap::InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
@@ -449,12 +540,14 @@ Heap::InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
t.lookup = newClass;
Q_ASSERT(t.lookup);
Q_ASSERT(newClass->vtable);
- return newClass;
+ return vtable == QV4::InternalClass::staticVTable()
+ ? newClass
+ : cleanInternalClass(newClass);
}
Heap::InternalClass *InternalClass::nonExtensible()
{
- if (!extensible)
+ if (!isExtensible())
return this;
Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::NotExtensible};
@@ -463,7 +556,7 @@ Heap::InternalClass *InternalClass::nonExtensible()
return t.lookup;
Heap::InternalClass *newClass = engine->newClass(this);
- newClass->extensible = false;
+ newClass->flags |= NotExtensible;
t.lookup = newClass;
Q_ASSERT(t.lookup);
@@ -500,7 +593,7 @@ Heap::InternalClass *InternalClass::addMember(PropertyKey identifier, PropertyAt
Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
{
- Transition temp = { { identifier }, nullptr, (int)data.flags() };
+ Transition temp = { { identifier }, nullptr, int(data.all()) };
Transition &t = lookupOrInsertTransition(temp);
if (entry) {
@@ -553,21 +646,23 @@ void InternalClass::removeMember(QV4::Object *object, PropertyKey identifier)
changeMember(object, identifier, Attr_Invalid);
#ifndef QT_NO_DEBUG
- // we didn't remove the data slot, just made it inaccessible
- Q_ASSERT(object->internalClass()->size == oldClass->size);
+ // We didn't remove the data slot, just made it inaccessible.
+ // ... unless we've rebuilt the whole class. Then all the deleted properties are gone.
+ Q_ASSERT(object->internalClass()->numRedundantTransitions == 0
+ || object->internalClass()->size == oldClass->size);
#endif
}
Heap::InternalClass *InternalClass::sealed()
{
- if (isSealed)
+ if (isSealed())
return this;
Transition temp = { { PropertyKey::invalid() }, nullptr, InternalClassTransition::Sealed };
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup) {
- Q_ASSERT(t.lookup && t.lookup->isSealed);
+ Q_ASSERT(t.lookup && t.lookup->isSealed());
return t.lookup;
}
@@ -575,7 +670,7 @@ Heap::InternalClass *InternalClass::sealed()
Scoped<QV4::InternalClass> ic(scope, engine->newClass(this));
Heap::InternalClass *s = ic->d();
- if (!isFrozen) { // freezing also makes all properties non-configurable
+ if (!isFrozen()) { // freezing also makes all properties non-configurable
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
@@ -584,7 +679,7 @@ Heap::InternalClass *InternalClass::sealed()
s->propertyData.set(i, attrs);
}
}
- s->isSealed = true;
+ s->flags |= Sealed;
t.lookup = s;
return s;
@@ -592,14 +687,14 @@ Heap::InternalClass *InternalClass::sealed()
Heap::InternalClass *InternalClass::frozen()
{
- if (isFrozen)
+ if (isFrozen())
return this;
Transition temp = { { PropertyKey::invalid() }, nullptr, InternalClassTransition::Frozen };
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup) {
- Q_ASSERT(t.lookup && t.lookup->isFrozen);
+ Q_ASSERT(t.lookup && t.lookup->isFrozen());
return t.lookup;
}
@@ -616,7 +711,7 @@ Heap::InternalClass *InternalClass::frozen()
attrs.setConfigurable(false);
f->propertyData.set(i, attrs);
}
- f->isFrozen = true;
+ f->flags |= Frozen;
t.lookup = f;
return f;
@@ -640,7 +735,7 @@ InternalClass *InternalClass::cryopreserved()
bool InternalClass::isImplicitlyFrozen() const
{
- if (isFrozen)
+ if (isFrozen())
return true;
for (uint i = 0; i < size; ++i) {
@@ -656,7 +751,7 @@ bool InternalClass::isImplicitlyFrozen() const
Heap::InternalClass *InternalClass::asProtoClass()
{
- if (isUsedAsProto)
+ if (isUsedAsProto())
return this;
Transition temp = { { PropertyKey::invalid() }, nullptr, Transition::ProtoClass };
@@ -665,7 +760,7 @@ Heap::InternalClass *InternalClass::asProtoClass()
return t.lookup;
Heap::InternalClass *newClass = engine->newClass(this);
- newClass->isUsedAsProto = true;
+ newClass->flags |= UsedAsProto;
t.lookup = newClass;
Q_ASSERT(t.lookup);
@@ -685,7 +780,7 @@ static void updateProtoUsage(Heap::Object *o, Heap::InternalClass *ic)
void InternalClass::updateProtoUsage(Heap::Object *o)
{
- Q_ASSERT(isUsedAsProto);
+ Q_ASSERT(isUsedAsProto());
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_Empty);
Q_ASSERT(!ic->prototype);
@@ -698,6 +793,9 @@ void InternalClass::markObjects(Heap::Base *b, MarkStack *stack)
if (ic->prototype)
ic->prototype->mark(stack);
+ if (ic->parent)
+ ic->parent->mark(stack);
+
ic->nameMap.mark(stack);
}
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 403702ae55..a5a1471cf1 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -172,7 +172,7 @@ struct SharedInternalClassDataPrivate<PropertyAttributes> {
uint size() const { return m_size; }
void setSize(uint s) { m_size = s; }
- PropertyAttributes at(uint i) { Q_ASSERT(data && i < m_alloc); return data[i]; }
+ PropertyAttributes at(uint i) const { Q_ASSERT(data && i < m_alloc); return data[i]; }
void set(uint i, PropertyAttributes t) { Q_ASSERT(data && i < m_alloc); data[i] = t; }
void mark(MarkStack *) {}
@@ -197,7 +197,7 @@ struct SharedInternalClassDataPrivate<PropertyKey> {
uint size() const;
void setSize(uint s);
- PropertyKey at(uint i);
+ PropertyKey at(uint i) const;
void set(uint i, PropertyKey t);
void mark(MarkStack *s);
@@ -290,24 +290,33 @@ struct InternalClassTransition
int flags;
enum {
// range 0-0xff is reserved for attribute changes
- NotExtensible = 0x100,
- VTableChange = 0x200,
- PrototypeChange = 0x201,
- ProtoClass = 0x202,
- Sealed = 0x203,
- Frozen = 0x204
+ StructureChange = 0x100,
+ NotExtensible = StructureChange | (1 << 0),
+ VTableChange = StructureChange | (1 << 1),
+ PrototypeChange = StructureChange | (1 << 2),
+ ProtoClass = StructureChange | (1 << 3),
+ Sealed = StructureChange | (1 << 4),
+ Frozen = StructureChange | (1 << 5),
};
bool operator==(const InternalClassTransition &other) const
{ return id == other.id && flags == other.flags; }
bool operator<(const InternalClassTransition &other) const
- { return id < other.id || (id == other.id && flags < other.flags); }
+ { return flags < other.flags || (flags == other.flags && id < other.id); }
};
namespace Heap {
struct InternalClass : Base {
+ enum Flag {
+ NotExtensible = 1 << 0,
+ Sealed = 1 << 1,
+ Frozen = 1 << 2,
+ UsedAsProto = 1 << 3,
+ };
+ enum { MaxRedundantTransitions = 255 };
+
ExecutionEngine *engine;
const VTable *vtable;
quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
@@ -323,10 +332,13 @@ struct InternalClass : Base {
InternalClassTransition &lookupOrInsertTransition(const InternalClassTransition &t);
uint size;
- bool extensible;
- bool isSealed;
- bool isFrozen;
- bool isUsedAsProto;
+ quint8 numRedundantTransitions;
+ quint8 flags;
+
+ bool isExtensible() const { return !(flags & NotExtensible); }
+ bool isSealed() const { return flags & Sealed; }
+ bool isFrozen() const { return flags & Frozen; }
+ bool isUsedAsProto() const { return flags & UsedAsProto; }
void init(ExecutionEngine *engine);
void init(InternalClass *other);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index b723141caa..ac90a7fdb9 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -61,17 +61,52 @@ DEFINE_OBJECT_VTABLE(Object);
void Object::setInternalClass(Heap::InternalClass *ic)
{
- d()->internalClass.set(engine(), ic);
- if (ic->isUsedAsProto)
- ic->updateProtoUsage(d());
Q_ASSERT(ic && ic->vtable);
- uint nInline = d()->vtable()->nInlineProperties;
- if (ic->size <= nInline)
- return;
- bool hasMD = d()->memberData != nullptr;
- uint requiredSize = ic->size - nInline;
- if (!(hasMD && requiredSize) || (hasMD && d()->memberData->values.size < requiredSize))
- d()->memberData.set(ic->engine, MemberData::allocate(ic->engine, requiredSize, d()->memberData));
+ Heap::Object *p = d();
+
+ if (ic->numRedundantTransitions < p->internalClass.get()->numRedundantTransitions) {
+ // IC was rebuilt. The indices are different now. We need to move everything.
+
+ Scope scope(engine());
+
+ // We allocate before setting the new IC. Protect it from GC.
+ Scoped<InternalClass> newIC(scope, ic);
+
+ // Pick the members of the old IC that are still valid in the new IC.
+ // Order them by index in memberData (or inline data).
+ Scoped<MemberData> newMembers(scope, MemberData::allocate(scope.engine, ic->size));
+ for (uint i = 0; i < ic->size; ++i)
+ newMembers->set(scope.engine, i, get(ic->nameMap.at(i)));
+
+ p->internalClass.set(scope.engine, ic);
+ const uint nInline = p->vtable()->nInlineProperties;
+
+ if (ic->size > nInline)
+ p->memberData.set(scope.engine, MemberData::allocate(ic->engine, ic->size - nInline));
+ else
+ p->memberData.set(scope.engine, nullptr);
+
+ const auto &memberValues = newMembers->d()->values;
+ for (uint i = 0; i < ic->size; ++i)
+ setProperty(i, memberValues[i]);
+ } else {
+ // The old indices are still the same. No need to move any values.
+ // We may need to re-allocate, though.
+
+ p->internalClass.set(ic->engine, ic);
+ const uint nInline = p->vtable()->nInlineProperties;
+ if (ic->size > nInline) {
+ const uint requiredSize = ic->size - nInline;
+ if ((p->memberData ? p->memberData->values.size : 0) < requiredSize) {
+ p->memberData.set(ic->engine, MemberData::allocate(
+ ic->engine, requiredSize, p->memberData));
+ }
+ }
+ }
+
+ if (ic->isUsedAsProto())
+ ic->updateProtoUsage(p);
+
}
void Object::getProperty(const InternalClassEntry &entry, Property *p) const
@@ -958,7 +993,7 @@ bool Object::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property
bool Object::virtualIsExtensible(const Managed *m)
{
- return m->d()->internalClass->extensible;
+ return m->d()->internalClass->isExtensible();
}
bool Object::virtualPreventExtensions(Managed *m)
@@ -982,7 +1017,7 @@ bool Object::virtualSetPrototypeOf(Managed *m, const Object *proto)
Heap::Object *protod = proto ? proto->d() : nullptr;
if (current == protod)
return true;
- if (!o->internalClass()->extensible)
+ if (!o->internalClass()->isExtensible())
return false;
Heap::Object *p = protod;
while (p) {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 26e1074fe3..1f518966d6 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -50,8 +50,8 @@ FunctionLocation FunctionCall::resolveLocation() const
{
return FunctionLocation(m_function->name()->toQString(),
m_function->executableCompilationUnit()->fileName(),
- m_function->compiledFunction->location.line,
- m_function->compiledFunction->location.column);
+ m_function->compiledFunction->location.line(),
+ m_function->compiledFunction->location.column());
}
FunctionCallProperties FunctionCall::properties() const
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
index b2a2ec3dea..81f2331666 100644
--- a/src/qml/jsruntime/qv4propertykey_p.h
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -51,6 +51,7 @@
//
#include <private/qv4global_p.h>
+#include <QtCore/qhashfunctions.h>
QT_BEGIN_NAMESPACE
@@ -145,6 +146,10 @@ public:
bool operator ==(const PropertyKey &other) const { return val == other.val; }
bool operator !=(const PropertyKey &other) const { return val != other.val; }
bool operator <(const PropertyKey &other) const { return val < other.val; }
+ inline friend uint qHash(const PropertyKey &key, uint seed) noexcept
+ {
+ return QT_PREPEND_NAMESPACE(qHash)(key.val, seed);
+ }
};
}
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 194f7b4cf7..d7bd93aa0d 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -353,7 +353,9 @@ public:
QQmlSourceLocation sourceLocation() const override final
{
- return QQmlSourceLocation(m_compilationUnit->fileName(), m_binding->valueLocation.line, m_binding->valueLocation.column);
+ return QQmlSourceLocation(
+ m_compilationUnit->fileName(), m_binding->valueLocation.line(),
+ m_binding->valueLocation.column());
}
@@ -532,8 +534,8 @@ QString QQmlBinding::expressionIdentifier() const
{
if (auto f = function()) {
QString url = f->sourceFile();
- uint lineNumber = f->compiledFunction->location.line;
- uint columnNumber = f->compiledFunction->location.column;
+ uint lineNumber = f->compiledFunction->location.line();
+ uint columnNumber = f->compiledFunction->location.column();
return url + QString::asprintf(":%u:%u", lineNumber, columnNumber);
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index df193a0591..6e0956472f 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1436,8 +1436,10 @@ QQmlError QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(const RequiredP
}
error.setDescription(description);
error.setUrl(unsetRequiredProperty.fileUrl);
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(unsetRequiredProperty.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(unsetRequiredProperty.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(
+ unsetRequiredProperty.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(
+ unsetRequiredProperty.location.column()));
return error;
}
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 5e6e1187e2..172557b7c2 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -102,8 +102,8 @@ void QQmlCustomParser::clearErrors()
void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
error.setDescription(description);
exceptions << error;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 826a1a5ab4..852a673ebd 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -193,7 +193,7 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
\endcode
*/
-bool QQmlEnginePrivate::qml_debugging_enabled = false;
+std::atomic<bool> QQmlEnginePrivate::qml_debugging_enabled{false};
bool QQmlEnginePrivate::s_designerMode = false;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -1812,7 +1812,7 @@ void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCo
const QV4::CompiledData::Binding *binding = compiledObject->bindingTable();
for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) {
const QQmlPropertyData *property = propertyData.at(i);
- if (property && binding->flags & QV4::CompiledData::Binding::IsDeferredBinding)
+ if (property && binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding))
deferData->bindings.insert(property->coreIndex(), binding);
}
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 263c69e2d8..9160fd8aa2 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -80,6 +80,8 @@
#include <private/qjsengine_p.h>
#include <private/qqmldirparser_p.h>
+#include <atomic>
+
QT_BEGIN_NAMESPACE
class QQmlContext;
@@ -267,7 +269,7 @@ public:
static bool designerMode();
static void activateDesignerMode();
- static bool qml_debugging_enabled;
+ static std::atomic<bool> qml_debugging_enabled;
mutable QMutex networkAccessManagerMutex;
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 10c6c41338..e7263d1850 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -46,7 +46,6 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qlibraryinfo.h>
-#include <QtCore/qreadwritelock.h>
#include <QtQml/qqmlextensioninterface.h>
#include <QtQml/qqmlextensionplugin.h>
#include <private/qqmlextensionplugin_p.h>
diff --git a/src/qml/qml/qqmlirloader.cpp b/src/qml/qml/qqmlirloader.cpp
index 7fa3d211a6..b6b4372faf 100644
--- a/src/qml/qml/qqmlirloader.cpp
+++ b/src/qml/qml/qqmlirloader.cpp
@@ -94,10 +94,11 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali
object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
- object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
- object->isInlineComponent = serializedObject->flags & QV4::CompiledData::Object::IsInlineComponentRoot;
- object->flags = serializedObject->flags;
- object->id = serializedObject->id;
+ object->defaultPropertyIsAlias = serializedObject->hasAliasAsDefaultProperty();
+ object->isInlineComponent = serializedObject->hasFlag(
+ QV4::CompiledData::Object::IsInlineComponentRoot);
+ object->flags = serializedObject->flags();
+ object->id = serializedObject->objectId();
object->location = serializedObject->location;
object->locationOfIdProperty = serializedObject->locationOfIdProperty;
@@ -108,7 +109,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 6aeb567a86..33fbab6e6b 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -280,7 +280,7 @@ void QQmlObjectCreator::populateDeferred(QObject *instance, int deferredIndex,
if (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);
@@ -342,7 +342,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
int propertyType = property->propType();
if (property->isEnum()) {
- if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) {
+ if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum)) {
propertyType = QMetaType::Int;
} else {
// ### This should be resolved earlier at compile time and the binding value should be changed accordingly.
@@ -356,18 +356,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);
@@ -378,7 +378,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
switch (propertyType) {
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()) {
@@ -396,14 +396,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 {
@@ -659,18 +659,24 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
} else if (property->propType() == qMetaTypeId<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;
@@ -717,8 +723,8 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType() == 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);
@@ -772,10 +778,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
}
- 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 (!applyDeferredBindings)
continue;
} else {
@@ -803,7 +809,8 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
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);
@@ -826,11 +833,13 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
if (bindingProperty && bindingProperty->propType() == qMetaTypeId<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()->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()->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 = 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 |
@@ -842,7 +851,7 @@ 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;
@@ -851,7 +860,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
if (!bindingProperty) // ### error
return true;
- if (binding->type == QV4::CompiledData::Binding::Type_GroupProperty) {
+ const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
+ if (bindingType == QV4::CompiledData::Binding::Type_GroupProperty) {
const QV4::CompiledData::Object *obj = compilationUnit->objectAt(binding->value.objectIndex);
if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) {
@@ -892,13 +902,15 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
}
}
- if (_ddata->hasBindingBit(bindingProperty->coreIndex()) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
- && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
+ if (_ddata->hasBindingBit(bindingProperty->coreIndex())
+ && !(bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()));
- if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
+ if (bindingType == QV4::CompiledData::Binding::Type_Script
+ || binding->isTranslationBinding()) {
+ if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
@@ -954,8 +966,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());
@@ -1013,7 +1025,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
}
// Assigning object to signal property?
- 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;
@@ -1135,16 +1147,16 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
{
QQmlError error;
error.setUrl(compilationUnit->url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
error.setDescription(description);
errors << error;
}
void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
{
- if (object->id >= 0)
- context->setIdProperty(object->id, instance);
+ if (object->objectId() >= 0)
+ context->setIdProperty(object->objectId(), instance);
}
void QQmlObjectCreator::createQmlContext()
@@ -1169,7 +1181,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlParserStatus *parserStatus = nullptr;
bool installPropertyCache = true;
- if (obj->flags & QV4::CompiledData::Object::IsComponent) {
+ if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent);
typeName = QStringLiteral("<component>");
@@ -1261,13 +1273,13 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
compilationUnit.data(), obj, typeName, context->url()));
Q_UNUSED(typeName); // only relevant for tracing
- ddata->lineNumber = obj->location.line;
- ddata->columnNumber = obj->location.column;
+ ddata->lineNumber = obj->location.line();
+ ddata->columnNumber = obj->location.column();
ddata->setImplicitDestructible();
// inline components are root objects, but their index is != 0, so we need
// an additional check
- const bool isInlineComponent = obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot;
+ const bool isInlineComponent = obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot);
if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation || isInlineComponent) {
if (ddata->context) {
Q_ASSERT(ddata->context != context);
@@ -1300,7 +1312,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (isContextObject)
context->contextObject = instance;
- if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
+ if (customParser && obj->hasFlag(QV4::CompiledData::Object::HasCustomParserBindings)) {
customParser->engine = QQmlEnginePrivate::get(engine);
customParser->imports = compilationUnit->typeNameCache.data();
@@ -1308,9 +1320,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);
@@ -1506,7 +1517,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);
- if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings)
+ if (_compiledObject->hasFlag(QV4::CompiledData::Object::HasDeferredBindings))
_ddata->deferData(_compiledObjectIndex, compilationUnit, context);
QSet<QString> postHocRequired;
@@ -1519,7 +1530,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
// only compute stringAt if there's a chance for the lookup to succeed
auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex));
- if (!property->isRequired && postHocRequired.end() == postHocIt)
+ if (!property->isRequired() && postHocRequired.end() == postHocIt)
continue;
if (postHocIt != postHocRequired.end())
postHocRequired.erase(postHocIt);
@@ -1556,12 +1567,12 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
for (int aliasIndex = 0; aliasIndex != _compiledObject->aliasCount(); ++aliasIndex) {
const QV4::CompiledData::Alias* alias = _compiledObject->aliasesBegin() + aliasIndex;
const auto originalAlias = alias;
- while (alias->aliasToLocalAlias)
+ while (alias->isAliasToLocalAlias())
alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
if (!context->idValues->wasSet())
continue;
- QObject *target = context->idValues[alias->targetObjectId].data();
+ QObject *target = context->idValues[alias->targetObjectId()].data();
if (!target)
continue;
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
@@ -1573,7 +1584,11 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
continue;
auto it = sharedState->requiredProperties.find(targetProperty);
if (it != sharedState->requiredProperties.end())
- it->aliasesToRequired.push_back(AliasToRequiredInfo {compilationUnit->stringAt(originalAlias->nameIndex), compilationUnit->finalUrl()});
+ it->aliasesToRequired.push_back(
+ AliasToRequiredInfo {
+ compilationUnit->stringAt(originalAlias->nameIndex()),
+ compilationUnit->finalUrl()
+ });
}
qSwap(_vmeMetaObject, vmeMetaObject);
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index d6a9e73763..db0535c292 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -187,6 +187,23 @@ namespace QQmlPrivate
= QQmlPrivate::createSingletonInstance<T>;
};
+ // from https://en.cppreference.com/w/cpp/language/static:
+ // If a const non-inline (since C++17) static data member or a constexpr
+ // static data member (since C++11)(until C++17) is odr-used, a definition
+ // at namespace scope is still required, but it cannot have an initializer.
+ //
+ // If a static data member is declared constexpr, it is implicitly inline
+ // and does not need to be redeclared at namespace scope. This redeclaration
+ // without an initializer (formerly required as shown above) is still
+ // permitted, but is deprecated.
+ //
+ // TL;DR: redundant definitions for static constexpr are required in c++11
+ // but deprecated in c++17.
+ template<typename T>
+ constexpr CreateIntoFunction Constructors<T, true>::createInto;
+ template<typename T>
+ constexpr CreateSingletonFunction Constructors<T, true>::createSingletonInstance;
+
template<typename T>
struct Constructors<T, false>
{
@@ -194,6 +211,12 @@ namespace QQmlPrivate
static constexpr CreateSingletonFunction createSingletonInstance = nullptr;
};
+ // see comment above over the Constructors<T, true> definitions.
+ template<typename T>
+ constexpr CreateIntoFunction Constructors<T, false>::createInto;
+ template<typename T>
+ constexpr CreateSingletonFunction Constructors<T, false>::createSingletonInstance;
+
template<typename T, bool IsVoid = std::is_void<T>::value>
struct ExtendedType;
@@ -205,6 +228,12 @@ namespace QQmlPrivate
static constexpr const QMetaObject *staticMetaObject = nullptr;
};
+ // see comment above over the Constructors<T, true> definitions.
+ template<typename T>
+ constexpr const CreateParentFunction ExtendedType<T, true>::createParent;
+ template<typename T>
+ constexpr const QMetaObject* ExtendedType<T, true>::staticMetaObject;
+
// If it's not void, we actually want an error if the ctor or the metaobject is missing.
template<typename T>
struct ExtendedType<T, false>
@@ -213,6 +242,12 @@ namespace QQmlPrivate
static constexpr const QMetaObject *staticMetaObject = &T::staticMetaObject;
};
+ // see comment above over the Constructors<T, true> definitions.
+ template<typename T>
+ constexpr const CreateParentFunction ExtendedType<T, false>::createParent;
+ template<typename T>
+ constexpr const QMetaObject* ExtendedType<T, false>::staticMetaObject;
+
template<class From, class To, int N>
struct StaticCastSelectorClass
{
@@ -577,6 +612,10 @@ namespace QQmlPrivate
static constexpr bool Value = false;
};
+ // see comment above over the Constructors<T, true> definitions.
+ template<typename T, class C>
+ constexpr bool QmlSingleton<T, C>::Value;
+
template<class T>
struct QmlSingleton<T, QmlVoidT<typename T::QmlIsSingleton>>
{
diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp
index 88d80d88ab..1579fd3336 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);
@@ -144,6 +146,11 @@ void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(QQmlEnginePr
if (propertyCaches->at(groupPropertyObjectIndex))
continue;
+ if (!pendingBinding.referencingObjectPropertyCache) {
+ pendingBinding.referencingObjectPropertyCache
+ = propertyCaches->at(pendingBinding.referencingObjectIndex);
+ }
+
if (!pendingBinding.resolveInstantiatingProperty())
continue;
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 3fd6c8b4da..363e4d17fe 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -67,8 +67,8 @@ inline QQmlError qQmlCompileError(const QV4::CompiledData::Location &location,
const QString &description)
{
QQmlError error;
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
error.setDescription(description);
return error;
}
@@ -196,7 +196,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
// create meta objects for inline components before compiling actual root component
for (auto nodeIt = nodesSorted.rbegin(); nodeIt != nodesSorted.rend(); ++nodeIt) {
- const auto &ic = allICs[nodeIt->index];
+ const auto &ic = allICs[nodeIt->index()];
QV4::ResolvedTypeReference *typeRef = objectContainer->resolvedType(ic.nameIndex);
Q_ASSERT(propertyCaches->at(ic.objectIndex) == nullptr);
Q_ASSERT(typeRef->typePropertyCache.isNull()); // not set yet
@@ -226,7 +226,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
const CompiledObject *obj = objectContainer->objectAt(objectIndex);
bool needVMEMetaObject = isVMERequired == VMEMetaObjectIsRequired::Always || obj->propertyCount() != 0 || obj->aliasCount() != 0
|| obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0
- || (((obj->flags & QV4::CompiledData::Object::IsComponent)
+ || ((obj->hasFlag(QV4::CompiledData::Object::IsComponent)
|| (objectIndex == 0 && isAddressable(objectContainer->url())))
&& !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType);
@@ -234,7 +234,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
@@ -276,24 +277,24 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
}
}
- if (QQmlPropertyCache *thisCache = propertyCaches->at(objectIndex)) {
- auto binding = obj->bindingsBegin();
- auto end = obj->bindingsEnd();
- for ( ; binding != end; ++binding)
- if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
- QQmlBindingInstantiationContext context(objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
-
- // Binding to group property where we failed to look up the type of the
- // property? Possibly a group property that is an alias that's not resolved yet.
- // Let's attempt to resolve it after we're done with the aliases and fill in the
- // propertyCaches entry then.
- if (!context.resolveInstantiatingProperty())
- pendingGroupPropertyBindings->append(context);
-
- QQmlError error = buildMetaObjectRecursively(binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe);
- if (error.isValid())
- return error;
- }
+ QQmlPropertyCache *thisCache = propertyCaches->at(objectIndex);
+ auto binding = obj->bindingsBegin();
+ auto end = obj->bindingsEnd();
+ for ( ; binding != end; ++binding) {
+ if (binding->type() >= QV4::CompiledData::Binding::Type_Object) {
+ QQmlBindingInstantiationContext context(objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
+
+ // Binding to group property where we failed to look up the type of the
+ // property? Possibly a group property that is an alias that's not resolved yet.
+ // Let's attempt to resolve it after we're done with the aliases and fill in the
+ // propertyCaches entry then.
+ if (!thisCache || !context.resolveInstantiatingProperty())
+ pendingGroupPropertyBindings->append(context);
+
+ QQmlError error = buildMetaObjectRecursively(binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe);
+ if (error.isValid())
+ return error;
+ }
}
QQmlError noError;
@@ -390,7 +391,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
auto aend = obj->aliasesEnd();
for ( ; a != aend; ++a) {
bool notInRevision = false;
- QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), &notInRevision);
+ QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex()), &notInRevision);
if (d && d->isFinal())
return qQmlCompileError(a->location, QQmlPropertyCacheCreatorBase::tr("Cannot override FINAL property"));
}
@@ -438,7 +439,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
for ( ; a != aend; ++a) {
auto flags = QQmlPropertyData::defaultSignalFlags();
- QString changedSigName = stringAt(a->nameIndex) + QLatin1String("Changed");
+ QString changedSigName = stringAt(a->nameIndex()) + QLatin1String("Changed");
seenSignals.insert(changedSigName);
cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
@@ -556,12 +557,13 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
if (type == QV4::CompiledData::BuiltinType::Variant)
propertyFlags.type = QQmlPropertyData::Flags::QVariantType;
} else {
- Q_ASSERT(!p->isBuiltinType);
+ Q_ASSERT(!p->isBuiltinType());
QQmlType qmltype;
bool selfReference = false;
- if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr,
- nullptr, QQmlType::AnyRegistrationType, &selfReference)) {
+ if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex()), &qmltype,
+ nullptr, nullptr, nullptr, nullptr,
+ QQmlType::AnyRegistrationType, &selfReference)) {
return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type"));
}
@@ -592,13 +594,13 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
typeIds = compilationUnit->typeIdsForComponent();
}
- if (p->isList) {
+ if (p->isList()) {
propertyType = typeIds.listId;
} else {
propertyType = typeIds.id;
}
} else {
- if (p->isList) {
+ if (p->isList()) {
propertyType = qmltype.qListTypeId();
} else {
propertyType = qmltype.typeId();
@@ -606,18 +608,17 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
}
}
- if (p->isList)
+ if (p->isList())
propertyFlags.type = QQmlPropertyData::Flags::QListType;
else
propertyFlags.type = QQmlPropertyData::Flags::QObjectDerivedType;
}
- if (!p->isReadOnly && !p->isList)
+ if (!p->isReadOnly() && !p->isList())
propertyFlags.setIsWritable(true);
-
QString propertyName = stringAt(p->nameIndex);
- if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
+ if (!obj->hasAliasAsDefaultProperty() && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
propertyType, propertTypeMinorVersion, effectiveSignalIndex);
@@ -633,13 +634,14 @@ template <typename ObjectContainer>
inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const QV4::CompiledData::ParameterType &param,
QString *customTypeName)
{
- if (param.indexIsBuiltinType) {
+ if (param.indexIsBuiltinType()) {
// built-in type
- return metaTypeForPropertyType(static_cast<QV4::CompiledData::BuiltinType>(int(param.typeNameIndexOrBuiltinType)));
+ return metaTypeForPropertyType(
+ static_cast<QV4::CompiledData::BuiltinType>(param.typeNameIndexOrBuiltinType()));
}
// lazily resolved type
- const QString typeName = stringAt(param.typeNameIndexOrBuiltinType);
+ const QString typeName = stringAt(param.typeNameIndexOrBuiltinType());
if (customTypeName)
*customTypeName = typeName;
QQmlType qmltype;
@@ -702,7 +704,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
// from a binding.
for (int i = 1; i < objectContainer->objectCount(); ++i) {
const CompiledObject &component = *objectContainer->objectAt(i);
- if (!(component.flags & QV4::CompiledData::Object::IsComponent))
+ if (!component.hasFlag(QV4::CompiledData::Object::IsComponent))
continue;
const auto rootBinding = component.bindingsBegin();
@@ -725,12 +727,12 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasPropertie
auto alias = object.aliasesBegin();
auto end = object.aliasesEnd();
for ( ; alias != end; ++alias) {
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
- const int targetObjectIndex = objectForId(component, alias->targetObjectId);
+ const int targetObjectIndex = objectForId(component, alias->targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
- if (alias->aliasToLocalAlias)
+ if (alias->isAliasToLocalAlias())
continue;
if (alias->encodedMetaPropertyIndex == -1)
@@ -772,18 +774,21 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl
objectsWithAliases->append(objectIndex);
// Stop at Component boundary
- if (object.flags & QV4::CompiledData::Object::IsComponent && objectIndex != /*root object*/0)
+ if (object.hasFlag(QV4::CompiledData::Object::IsComponent) && objectIndex != /*root object*/0)
return;
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;
+ }
}
}
@@ -797,12 +802,12 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
propertyFlags->setIsAlias(true);
- if (alias.aliasToLocalAlias) {
+ if (alias.isAliasToLocalAlias()) {
const QV4::CompiledData::Alias *lastAlias = &alias;
QVarLengthArray<const QV4::CompiledData::Alias *, 4> seenAliases({lastAlias});
do {
- const int targetObjectIndex = objectForId(component, lastAlias->targetObjectId);
+ const int targetObjectIndex = objectForId(component, lastAlias->targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
const CompiledObject *targetObject = objectContainer->objectAt(targetObjectIndex);
Q_ASSERT(targetObject);
@@ -819,17 +824,17 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
seenAliases.append(targetAlias);
lastAlias = targetAlias;
- } while (lastAlias->aliasToLocalAlias);
+ } while (lastAlias->isAliasToLocalAlias());
return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv);
}
- const int targetObjectIndex = objectForId(component, alias.targetObjectId);
+ const int targetObjectIndex = objectForId(component, alias.targetObjectId());
Q_ASSERT(targetObjectIndex >= 0);
const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
if (alias.encodedMetaPropertyIndex == -1) {
- Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
+ Q_ASSERT(alias.hasFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject));
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
if (!typeRef) {
// Can be caused by the alias target not being a valid id or property. E.g.:
@@ -901,7 +906,8 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
}
}
- propertyFlags->setIsWritable(!(alias.flags & QV4::CompiledData::Alias::IsReadOnly) && writable);
+ propertyFlags->setIsWritable(!(alias.hasFlag(QV4::CompiledData::Alias::IsReadOnly))
+ && writable);
propertyFlags->setIsResettable(resettable);
return QQmlError();
}
@@ -924,7 +930,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
auto alias = object.aliasesBegin();
auto end = object.aliasesEnd();
for ( ; alias != end; ++alias, ++aliasIndex) {
- Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
+ Q_ASSERT(alias->hasFlag(QV4::CompiledData::Alias::Resolved));
int type = 0;
int minorVersion = 0;
@@ -933,9 +939,9 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
if (error.isValid())
return error;
- const QString propertyName = objectContainer->stringAt(alias->nameIndex);
+ const QString propertyName = objectContainer->stringAt(alias->nameIndex());
- if (object.defaultPropertyIsAlias && aliasIndex == object.indexOfDefaultPropertyOrAlias)
+ if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
propertyCache->_defaultPropertyName = propertyName;
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
@@ -951,7 +957,7 @@ inline int QQmlPropertyCacheAliasCreator<ObjectContainer>::objectForId(const Com
for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
const int candidateIndex = component.namedObjectsInComponentTable()[i];
const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
- if (candidate.id == id)
+ if (candidate.objectId() == id)
return candidateIndex;
}
return -1;
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 3a1f33113f..ae8e6e3982 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -104,10 +104,11 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
validateObject(it->objectIndex, /* instantiatingBinding*/ nullptr);
}
- if (obj->flags & QV4::CompiledData::Object::IsComponent && !(obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot)) {
+ if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)
+ && !obj->hasFlag(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);
}
@@ -131,7 +132,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) {
@@ -160,9 +161,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;
@@ -175,13 +178,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, &notInRevision);
} else {
pd = propertyResolver.property(name, &notInRevision,
@@ -218,11 +222,11 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
return recordError(binding->location, tr("Invalid attached object assignment"));
}
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
+ if (binding->type() >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
const bool populatingValueTypeGroupProperty
= pd
&& QQmlValueTypeFactory::metaObjectForMetaType(pd->propType())
- && !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment);
+ && !binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment);
const QVector<QQmlError> subObjectValidatorErrors
= validateObject(binding->value.objectIndex, binding,
populatingValueTypeGroupProperty);
@@ -231,11 +235,12 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
}
// Signal handlers were resolved and checked earlier in the signal handler conversion pass.
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ if (binding->hasFlag(QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ || binding->hasFlag(QV4::CompiledData::Binding::IsSignalHandlerObject)) {
continue;
+ }
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (binding->type() == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (instantiatingBinding && (instantiatingBinding->isAttachedProperty() || instantiatingBinding->isGroupProperty())) {
return recordError(binding->location, tr("Attached properties cannot be used here"));
}
@@ -249,15 +254,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() == qMetaTypeId<QQmlScriptString>())
error = tr( "Cannot assign multiple values to a script property");
@@ -268,7 +273,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)
@@ -279,11 +284,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);
@@ -366,7 +371,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
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);
@@ -384,11 +389,13 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
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));
- warning.setColumn(qmlConvertSourceCoordinate<quint32, int>(binding->valueLocation.column));
+ warning.setLine(qmlConvertSourceCoordinate<quint32, int>(
+ binding->valueLocation.line()));
+ warning.setColumn(qmlConvertSourceCoordinate<quint32, int>(
+ binding->valueLocation.column()));
warning.setDescription(error + tr(" - Assigning null to incompatible properties in QML "
"is deprecated. This will become a compile error in "
"future versions of Qt."));
@@ -398,6 +405,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
return qQmlCompileError(binding->valueLocation, error);
};
+ const QV4::CompiledData::Binding::Type bindingType = binding->type();
switch (property->propType()) {
case QMetaType::QVariant:
break;
@@ -414,19 +422,17 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
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;
@@ -435,7 +441,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
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;
@@ -444,13 +450,13 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
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"));
}
}
@@ -538,7 +544,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
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"));
}
}
@@ -594,12 +600,12 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
default: {
// generate single literal value assignment to a list property if required
if (property->propType() == qMetaTypeId<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() == qMetaTypeId<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)
@@ -609,12 +615,12 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
return warnOrError(tr("Invalid property assignment: int or array of ints expected"));
break;
} else if (property->propType() == qMetaTypeId<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() == qMetaTypeId<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;
@@ -628,7 +634,7 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
} else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
break;
} else if (property->isQObject()
- && binding->type == QV4::CompiledData::Binding::Type_Null) {
+ && bindingType == QV4::CompiledData::Binding::Type_Null) {
break;
}
@@ -690,8 +696,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;
@@ -740,7 +746,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::typeName(propType));
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp
index dac21f7ee7..18ea5db4c6 100644
--- a/src/qml/qml/qqmlscriptblob.cpp
+++ b/src/qml/qml/qqmlscriptblob.cpp
@@ -168,8 +168,8 @@ void QQmlScriptBlob::done()
QList<QQmlError> errors = script.script->errors();
QQmlError error;
error.setUrl(url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column()));
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
errors.prepend(error);
setError(errors);
@@ -237,8 +237,8 @@ void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::Exe
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
error.setUrl(m_importCache.baseUrl());
- error.setLine(import->location.line);
- error.setColumn(import->location.column);
+ error.setLine(import->location.line());
+ error.setColumn(import->location.column());
errors.prepend(error); // put it back on the list after filling out information.
setError(errors);
return;
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index f1a6b3bff2..c3c80a2ac5 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -174,8 +174,8 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
void QQmlTypeCompiler::recordError(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
error.setDescription(description);
error.setUrl(url());
errors << error;
@@ -335,7 +335,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
QString propertyName = 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();
@@ -438,13 +439,13 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
// 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"));
@@ -489,7 +490,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
foe->node = functionDeclaration;
binding->propertyNameIndex = compiler->registerString(propertyName);
- binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerExpression;
+ binding->setFlag(QV4::CompiledData::Binding::IsSignalHandlerExpression);
}
return true;
}
@@ -513,11 +514,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)
+ const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
+ if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
continue;
+ }
- if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ if (binding->type() != QV4::CompiledData::Binding::Type_Script)
continue;
const QString propertyName = stringAt(binding->propertyNameIndex);
@@ -548,10 +551,10 @@ bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QS
if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) {
COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName.toString()));
}
- 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;
}
@@ -561,10 +564,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;
@@ -694,15 +700,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;
+ }
}
}
@@ -731,7 +743,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
bool notInRevision = false;
QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), &notInRevision) : defaultProperty;
if (pd && pd->isAlias())
- binding->flags |= QV4::CompiledData::Binding::IsBindingToAlias;
+ binding->setFlag(QV4::CompiledData::Binding::IsBindingToAlias);
}
}
}
@@ -758,7 +770,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), &notInRevision) : defaultProperty;
@@ -804,9 +816,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);
@@ -871,7 +883,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
QmlIR::Binding *syntheticBinding = pool->New<QmlIR::Binding>();
*syntheticBinding = *binding;
- 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);
@@ -932,7 +944,7 @@ bool QQmlComponentAndAliasResolver::resolve()
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
@@ -1000,13 +1012,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;
@@ -1054,7 +1069,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex)
if (!atLeastOneAliasResolved && !_objectsWithAliases.isEmpty()) {
const QmlIR::Object *obj = qmlObjects->at(_objectsWithAliases.first());
for (auto alias = obj->aliasesBegin(), end = obj->aliasesEnd(); alias != end; ++alias) {
- if (!(alias->flags & QV4::CompiledData::Alias::Resolved)) {
+ if (!alias->hasFlag(QV4::CompiledData::Alias::Resolved)) {
recordError(alias->location, tr("Circular alias reference detected"));
return false;
}
@@ -1076,7 +1091,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
bool seenUnresolvedAlias = false;
for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next) {
- if (alias->flags & QV4::CompiledData::Alias::Resolved)
+ if (alias->hasFlag(QV4::CompiledData::Alias::Resolved))
continue;
seenUnresolvedAlias = true;
@@ -1092,8 +1107,8 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
const QmlIR::Object *targetObject = qmlObjects->at(targetObjectIndex);
Q_ASSERT(targetObject->id >= 0);
- alias->targetObjectId = targetObject->id;
- alias->aliasToLocalAlias = false;
+ alias->setTargetObjectId(targetObject->id);
+ alias->setIsAliasToLocalAlias(false);
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
@@ -1110,7 +1125,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
QQmlPropertyIndex propIdx;
if (property.isEmpty()) {
- alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
+ alias->setFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject);
} else {
QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex);
if (!targetCache) {
@@ -1129,7 +1144,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
bool aliasPointsToOtherAlias = false;
int localAliasIndex = 0;
for (auto targetAlias = targetObject->aliasesBegin(), end = targetObject->aliasesEnd(); targetAlias != end; ++targetAlias, ++localAliasIndex) {
- if (stringAt(targetAlias->nameIndex) == property) {
+ if (stringAt(targetAlias->nameIndex()) == property) {
aliasPointsToOtherAlias = true;
break;
}
@@ -1137,8 +1152,8 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
if (aliasPointsToOtherAlias) {
if (targetObjectIndex == objectIndex) {
alias->localAliasIndex = localAliasIndex;
- alias->aliasToLocalAlias = true;
- alias->flags |= QV4::CompiledData::Alias::Resolved;
+ alias->setIsAliasToLocalAlias(true);
+ alias->setFlag(QV4::CompiledData::Alias::Resolved);
++numResolvedAliases;
continue;
}
@@ -1200,12 +1215,12 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
}
} else {
if (targetProperty->isQObject())
- alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
+ alias->setFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject);
}
}
alias->encodedMetaPropertyIndex = propIdx.toEncoded();
- alias->flags |= QV4::CompiledData::Alias::Resolved;
+ alias->setFlag(QV4::CompiledData::Alias::Resolved);
numResolvedAliases++;
}
@@ -1241,7 +1256,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
if (obj->flags & QV4::CompiledData::Object::IsComponent && !obj->isInlineComponent) {
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);
return scanObject(componentBinding->value.objectIndex);
}
@@ -1279,16 +1294,16 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
QString name = stringAt(binding->propertyNameIndex);
if (customParser) {
- if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (binding->type() == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
- binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ binding->setFlag(QV4::CompiledData::Binding::IsCustomParserBinding);
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
continue;
}
} else if (QmlIR::IRBuilder::isSignalPropertyName(name)
&& !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
- binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ binding->setFlag(QV4::CompiledData::Binding::IsCustomParserBinding);
continue;
}
}
@@ -1307,7 +1322,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
bool seenSubObjectWithId = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
+ if (binding->type() >= QV4::CompiledData::Binding::Type_Object
+ && (pd || binding->isAttachedProperty())) {
qSwap(_seenObjectWithId, seenSubObjectWithId);
const bool subObjectValid = scanObject(binding->value.objectIndex);
qSwap(_seenObjectWithId, seenSubObjectWithId);
@@ -1316,21 +1332,24 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
_seenObjectWithId |= seenSubObjectWithId;
}
- if (!seenSubObjectWithId && binding->type != QV4::CompiledData::Binding::Type_GroupProperty
+ if (!seenSubObjectWithId
+ && binding->type() != QV4::CompiledData::Binding::Type_GroupProperty
&& !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
- binding->flags |= QV4::CompiledData::Binding::IsDeferredBinding;
+ binding->setFlag(QV4::CompiledData::Binding::IsDeferredBinding);
obj->flags |= QV4::CompiledData::Object::HasDeferredBindings;
}
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
+ if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
continue;
+ }
if (!pd) {
if (customParser) {
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
- binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ binding->setFlag(QV4::CompiledData::Binding::IsCustomParserBinding);
}
}
}
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index ebd139b6a9..c7bfcc55b1 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -203,8 +203,8 @@ bool QQmlTypeData::tryLoadFromDiskCache()
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
error.setUrl(m_importCache.baseUrl());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
errors.prepend(error); // put it back on the list after filling out information.
setError(errors);
return false;
@@ -324,8 +324,8 @@ void QQmlTypeData::done()
QList<QQmlError> errors = script.script->errors();
QQmlError error;
error.setUrl(url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(script.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(script.location.column()));
error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->urlString()));
errors.prepend(error);
setError(errors);
@@ -348,8 +348,8 @@ void QQmlTypeData::done()
QList<QQmlError> errors = type.typeData ? type.typeData->errors() : QList<QQmlError>{};
QQmlError error;
error.setUrl(url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column()));
error.setDescription(QQmlTypeLoader::tr("Type %1 has no inline component type called %2").arg(typeName.leftRef(lastDot), type.type.pendingResolutionName()));
errors.prepend(error);
setError(errors);
@@ -364,8 +364,8 @@ void QQmlTypeData::done()
QList<QQmlError> errors = type.typeData->errors();
QQmlError error;
error.setUrl(url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column()));
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
@@ -383,8 +383,8 @@ void QQmlTypeData::done()
QList<QQmlError> errors = type.typeData->errors();
QQmlError error;
error.setUrl(url());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(type.location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(type.location.column()));
error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
errors.prepend(error);
setError(errors);
@@ -696,8 +696,8 @@ void QQmlTypeData::continueLoadFromIR()
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
error.setUrl(m_importCache.baseUrl());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
errors.prepend(error); // put it back on the list after filling out information.
setError(errors);
return;
@@ -723,8 +723,10 @@ void QQmlTypeData::allDependenciesDone()
QQmlError error;
error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri));
error.setUrl(m_importCache.baseUrl());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(
+ import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(
+ import->location.column()));
errors.prepend(error);
}
}
@@ -858,8 +860,8 @@ void QQmlTypeData::resolveTypes()
bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference;
- if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line,
- unresolvedRef->location.column, reportErrors,
+ if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line(),
+ unresolvedRef->location.column(), reportErrors,
QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors)
return;
@@ -881,8 +883,7 @@ void QQmlTypeData::resolveTypes()
ref.majorVersion = majorVersion;
ref.minorVersion = minorVersion;
- ref.location.line = unresolvedRef->location.line;
- ref.location.column = unresolvedRef->location.column;
+ ref.location = unresolvedRef->location;
ref.needsCreation = unresolvedRef->needsCreation;
m_resolvedTypes.insert(unresolvedRef.key(), ref);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 1d66e756fa..01aba47a9a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -697,8 +697,8 @@ void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob)
Q_ASSERT(errors.size());
QQmlError error(errors.takeFirst());
error.setUrl(m_importCache.baseUrl());
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(import->location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(import->location.column()));
errors.prepend(error); // put it back on the list after filling out information.
setError(errors);
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index aa9f4bc1bd..1e0e4e419f 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -231,17 +231,14 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
if (!aliasData->isObjectAlias()) {
QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[aliasData->targetObjectId].data();
+ QObject *target = ctxt->idValues[aliasData->targetObjectId()].data();
if (!target)
return;
- QQmlData *targetDData = QQmlData::get(target, /*create*/false);
- if (!targetDData)
- return;
QQmlPropertyIndex encodedIndex = QQmlPropertyIndex::fromEncoded(aliasData->encodedMetaPropertyIndex);
int coreIndex = encodedIndex.coreIndex();
int valueTypeIndex = encodedIndex.valueTypeIndex();
- const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
+ const QQmlPropertyData *pd = QQmlData::ensurePropertyCache(qmlEngine(target), target)->property(coreIndex);
if (pd && valueTypeIndex != -1 && !QQmlValueTypeFactory::valueType(pd->propType())) {
// deep alias
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(metaObject->compilationUnit->engine->qmlEngine());
@@ -758,7 +755,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
}
break;
case QV4::CompiledData::BuiltinType::InvalidBuiltin:
- if (property.isList) {
+ if (property.isList()) {
// when reading from the list, we need to find the correct MetaObject,
// namely this. However, obejct->metaObject might point to any MetaObject
// down the inheritance hierarchy, so we need to store how far we have
@@ -866,7 +863,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
case QV4::CompiledData::BuiltinType::InvalidBuiltin:
- if (property.isList) {
+ if (property.isList()) {
// Writing such a property is not supported. Content is added through the list property
// methods.
} else {
@@ -888,18 +885,20 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (id < aliasCount) {
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id];
- if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
- *reinterpret_cast<void **>(a[0]) = nullptr;
+ if (aliasData->hasFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject)
+ && c == QMetaObject::ReadProperty){
+ *reinterpret_cast<void **>(a[0]) = nullptr;
+ }
if (!ctxt) return -1;
- while (aliasData->aliasToLocalAlias)
+ while (aliasData->isAliasToLocalAlias())
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
QQmlContext *context = ctxt->asQQmlContext();
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
- QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId].data();
+ QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId()].data();
if (!target)
return -1;
@@ -1260,9 +1259,9 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
const int aliasId = index - propOffset() - compiledObject->nProperties;
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
- while (aliasData->aliasToLocalAlias)
+ while (aliasData->isAliasToLocalAlias())
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- *target = ctxt->idValues[aliasData->targetObjectId].data();
+ *target = ctxt->idValues[aliasData->targetObjectId()].data();
if (!*target)
return false;
@@ -1290,7 +1289,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
}
endpoint->metaObject = this;
- endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings);
+ endpoint->connect(&ctxt->idValues[aliasData->targetObjectId()].bindings);
endpoint->tryConnect();
}
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 29ed62cd39..4a4e6ce12c 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -247,17 +247,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;
}
}
@@ -352,7 +355,7 @@ void QQmlConnections::connectSignalsToBindings()
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);