aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/common/qv4compileddata_p.h52
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h3
-rw-r--r--src/quicktestutils/qml/qmlutils.cpp35
-rw-r--r--src/quicktestutils/qml/qmlutils_p.h54
5 files changed, 138 insertions, 8 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index 01121bd008..e00e3aedd0 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
// Also change the comment behind the number to describe the latest change. This has the added
// benefit that if another patch changes the version too, it will result in a merge conflict, and
// not get removed silently.
-#define QV4_DATA_STRUCTURE_VERSION 0x48 // Hotfix 6.10 - meta object change
+#define QV4_DATA_STRUCTURE_VERSION 0x49 // Added isVirtual and isOverride fields to property
class QIODevice;
class QQmlTypeNameCache;
@@ -788,19 +788,43 @@ struct Signal
};
static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+/*
+ * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
+ * for each index.
+ *
+ * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
+ * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
+ * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
+ * to mention the amount of memory needed to maintain such a StringTableGenerator.
+ * Therefore, after some preliminary analysis, it seems that even 20 bits
+ * should be a rather conservative cap.
+ *
+ * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
+ * unions like, let's say nameIndexAndAttributes.
+ *
+ * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
+ *
+ * NameIndexField IsVirtualField IsOverrideField IsFinalField
+ * |10100000101000111000001110000| 0 | 1 | 0 |
+ *
+ */
struct Property
{
private:
- using NameIndexField = quint32_le_bitfield_member<0, 31>;
- using FinalField = quint32_le_bitfield_member<31, 1>;
+ using NameIndexField = quint32_le_bitfield_member<0, 29>;
+ using IsVirtualField = quint32_le_bitfield_member<29, 1>;
+ using IsOverrideField = quint32_le_bitfield_member<30, 1>;
+ using IsFinalField = quint32_le_bitfield_member<31, 1>;
using CommonTypeOrTypeNameIndexField = quint32_le_bitfield_member<0, 28>;
using IsRequiredField = quint32_le_bitfield_member<28, 1>;
using IsCommonTypeField = 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_bitfield_union<NameIndexField, FinalField> nameIndexAndFinal;
+ quint32_le_bitfield_union<NameIndexField, IsVirtualField, IsOverrideField, IsFinalField>
+ nameIndexAndVirtSpecifiers;
quint32_le_bitfield_union<
CommonTypeOrTypeNameIndexField,
IsRequiredField,
@@ -809,11 +833,23 @@ public:
IsReadOnlyField> data;
Location location;
- quint32 nameIndex() const { return nameIndexAndFinal.get<NameIndexField>(); }
- void setNameIndex(int nameIndex) { nameIndexAndFinal.set<NameIndexField>(nameIndex); }
+ quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
+ void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
+
+ bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
+ void setIsVirtual(bool isVirtual)
+ {
+ nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
+ }
+
+ bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
+ void setIsOverride(bool isOverride)
+ {
+ nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
+ }
- bool isFinal() const { return nameIndexAndFinal.get<FinalField>(); }
- void setIsFinal(bool final) { nameIndexAndFinal.set<FinalField>(final ? 1 : 0); }
+ bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
+ void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
void setCommonType(CommonType t)
{
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index bf124a2272..1605ab5f59 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1045,6 +1045,8 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
Property *property = New<Property>();
property->setIsReadOnly(node->isReadonly());
property->setIsRequired(node->isRequired());
+ property->setIsVirtual(node->isVirtual());
+ property->setIsOverride(node->isOverride());
property->setIsFinal(node->isFinal());
const QV4::CompiledData::CommonType builtinPropertyType
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 68b2b462f6..441830e33b 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -464,6 +464,9 @@ struct Q_QML_COMPILER_EXPORT Pragma
struct Q_QML_COMPILER_EXPORT Document
{
+ // disable it explicitly, it's implicitly deleted because of the Engine::_pool
+ Q_DISABLE_COPY_MOVE(Document)
+
Document(const QString &fileName, const QString &finalUrl, bool debugMode);
QString code;
QQmlJS::Engine jsParserEngine;
diff --git a/src/quicktestutils/qml/qmlutils.cpp b/src/quicktestutils/qml/qmlutils.cpp
index 5f573e790b..528a843f17 100644
--- a/src/quicktestutils/qml/qmlutils.cpp
+++ b/src/quicktestutils/qml/qmlutils.cpp
@@ -137,6 +137,41 @@ void gc(QQmlEngine &engine, GCFlags flags)
gc(*engine.handle(), flags);
}
+namespace Syntax {
+
+auto stringView(const Word &word) -> QLatin1StringView
+{
+ return std::holds_alternative<Token>(word) ? spellFor(std::get<Token>(word))
+ : std::get<QLatin1StringView>(word);
+}
+
+auto toString(const Phrase &phrase) -> QString
+{
+ QString result;
+ for (const auto &word : phrase) {
+ result += stringView(word) + QLatin1Char(' ');
+ }
+ return result;
+}
+
+// comfort
+auto operator+(const Word &word, const Phrase &phrase) -> Phrase
+{
+ return Phrase{ word } + phrase;
+};
+
+auto operator+(const Word &word1, const Word &word2) -> Phrase
+{
+ return Phrase{ word1, word2 };
+};
+
+auto objectDeclaration(Phrase &&objectMember, QLatin1StringView objName) -> Phrase
+{
+ return Phrase{} << Word(objName) << Word(Token::T_LBRACE) << std::move(objectMember)
+ << Word(Token::T_RBRACE);
+}
+
+} // namespace Syntax
QT_END_NAMESPACE
diff --git a/src/quicktestutils/qml/qmlutils_p.h b/src/quicktestutils/qml/qmlutils_p.h
index d8d28256ac..d4fc83c270 100644
--- a/src/quicktestutils/qml/qmlutils_p.h
+++ b/src/quicktestutils/qml/qmlutils_p.h
@@ -22,6 +22,7 @@
#include <QtCore/QStringList>
#include <QtTest/QTest>
#include <QtCore/private/qglobal_p.h>
+#include <private/qqmljsgrammar_p.h>
QT_BEGIN_NAMESPACE
@@ -122,6 +123,59 @@ void gc(QV4::ExecutionEngine &engine, GCFlags flags = GCFlags::None);
bool gcDone(QQmlEngine *engine);
void gc(QQmlEngine &engine, GCFlags flags = GCFlags::None);
+namespace Syntax {
+using Token = QQmlJSGrammar::VariousConstants;
+// TODO(QTBUG-138020)
+constexpr auto spellFor(Token token) -> QLatin1StringView
+{
+ switch (token) {
+ case Token::T_COLON:
+ return QLatin1StringView(":");
+ case Token::T_LBRACE:
+ return QLatin1StringView("{");
+ case Token::T_RBRACE:
+ return QLatin1StringView("}");
+ case Token::T_VAR:
+ return QLatin1StringView("var");
+ case Token::T_PROPERTY:
+ return QLatin1StringView("property");
+ case Token::T_DEFAULT:
+ return QLatin1StringView("default");
+ case Token::T_READONLY:
+ return QLatin1StringView("readonly");
+ case Token::T_REQUIRED:
+ return QLatin1StringView("required");
+ case Token::T_FINAL:
+ return QLatin1StringView("final");
+ case Token::T_VIRTUAL:
+ return QLatin1StringView("virtual");
+ case Token::T_OVERRIDE:
+ return QLatin1StringView("override");
+ default:
+ break;
+ }
+ Q_UNREACHABLE_RETURN({});
+}
+
+using Word = std::variant<Token, QLatin1StringView>;
+auto stringView(const Word &word) -> QLatin1StringView;
+
+using Phrase = QList<Word>;
+auto toString(const Phrase &phrase) -> QString;
+
+// comfort
+auto operator+(const Word &word, const Phrase &phrase) -> Phrase;
+auto operator+(const Word &word1, const Word &word2) -> Phrase;
+
+// if such declaration generating functions start to grow it might be worth creating a dedicated
+// more optimized generator
+
+// can probably be generalized later to accept QList<Phrase> if needed
+auto objectDeclaration(Phrase &&objectMember = {},
+ QLatin1StringView objName = QLatin1StringView("QtObject")) -> Phrase;
+
+} // namespace Syntax
+
QT_END_NAMESPACE
#endif // QQMLTESTUTILS_P_H