Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4compileddata_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QV4COMPILEDDATA_P_H
4#define QV4COMPILEDDATA_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <functional>
18
19#include <QtCore/qcryptographichash.h>
20#include <QtCore/qhash.h>
21#include <QtCore/qhashfunctions.h>
22#include <QtCore/qlocale.h>
23#include <QtCore/qscopeguard.h>
24#include <QtCore/qstring.h>
25#include <QtCore/qstringlist.h>
26#include <QtCore/qurl.h>
27#include <QtCore/qvector.h>
28#include <QtCore/qversionnumber.h>
29
30#if QT_CONFIG(temporaryfile)
31#include <QtCore/qsavefile.h>
32#endif
33
34#include <private/qendian_p.h>
35#include <private/qqmlnullablevalue_p.h>
36#include <private/qqmlpropertycachevector_p.h>
37#include <private/qqmlrefcount_p.h>
38#include <private/qqmltype_p.h>
39#include <private/qv4compilationunitmapper_p.h>
40#include <private/qv4staticvalue_p.h>
41
42#include <functional>
43#include <limits.h>
44
45QT_BEGIN_NAMESPACE
46
47// Bump this whenever the compiler data structures change in an incompatible way.
48//
49// IMPORTANT:
50//
51// Also change the comment behind the number to describe the latest change. This has the added
52// benefit that if another patch changes the version too, it will result in a merge conflict, and
53// not get removed silently.
54#define QV4_DATA_STRUCTURE_VERSION 0x47 // Removed various counts
55
56class QIODevice;
57class QQmlTypeNameCache;
58class QQmlType;
59class QQmlEngine;
61class QQmlScriptData;
62
63namespace QQmlPrivate {
65}
66
67namespace QmlIR {
68struct Document;
69}
70
71namespace QV4 {
72namespace Heap {
73struct Module;
74struct String;
75struct InternalClass;
76};
77
78struct Function;
79class EvalISelFactory;
81
82namespace CompiledData {
83
84// index is per-object binding index
86
87// map from name index
89{
90 bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
91};
92
93struct String;
94struct Function;
95struct Lookup;
96struct RegExp;
97struct Unit;
98
99template <typename ItemType, typename Container, const ItemType *(Container::*IndexedGetter)(int index) const>
101{
102 TableIterator(const Container *container, int index) : container(container), index(index) {}
103 const Container *container;
104 int index;
105
106 const ItemType *operator->() { return (container->*IndexedGetter)(index); }
107 ItemType operator*() {return *operator->();}
108 void operator++() { ++index; }
109 bool operator==(const TableIterator &rhs) const { return index == rhs.index; }
110 bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
111};
112
114{
116 Location(quint32 l, quint32 c) : Location()
117 {
118 m_data.set<LineField>(l);
119 m_data.set<ColumnField>(c);
120 Q_ASSERT(m_data.get<LineField>() == l);
121 Q_ASSERT(m_data.get<ColumnField>() == c);
122 }
123
124 inline bool operator<(const Location &other) const {
125 return m_data.get<LineField>() < other.m_data.get<LineField>()
126 || (m_data.get<LineField>() == other.m_data.get<LineField>()
127 && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
128 }
129
130 friend size_t qHash(const Location &location, size_t seed = 0)
131 {
132 return QT_PREPEND_NAMESPACE(qHash)(location.m_data.data(), seed);
133 }
134
135 friend bool operator==(const Location &a, const Location &b)
136 {
137 return a.m_data.data()== b.m_data.data();
138 }
139
140 void set(quint32 line, quint32 column)
141 {
142 m_data.set<LineField>(line);
143 m_data.set<ColumnField>(column);
144 }
145
146 quint32 line() const { return m_data.get<LineField>(); }
147 quint32 column() const { return m_data.get<ColumnField>(); }
148
149private:
152
153 quint32_le_bitfield_union<LineField, ColumnField> m_data;
154};
155static_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");
156
157struct RegExp
158{
167
169
171 RegExp(quint32 flags, quint32 stringIndex) : RegExp()
172 {
173 m_data.set<FlagsField>(flags);
174 m_data.set<StringIndexField>(stringIndex);
175 }
176
177 quint32 flags() const { return m_data.get<FlagsField>(); }
178 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
179
180private:
183 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
184};
185static_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");
186
187struct Lookup
188{
195
196 enum Mode : unsigned int {
199 };
200
201 quint32 type() const { return m_data.get<TypeField>(); }
202 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
203 quint32 mode() const { return m_data.get<ModeField>(); }
204
206 Lookup(Type type, Mode mode, quint32 nameIndex) : Lookup()
207 {
208 m_data.set<TypeField>(type);
209 m_data.set<ModeField>(mode);
210 m_data.set<NameIndexField>(nameIndex);
211 }
212
213private:
216 // 1 bit left
218 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
219};
220static_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");
221
223{
225
226 void set(quint32 nameOffset, bool isAccessor)
227 {
228 m_data.set<NameOffsetField>(nameOffset);
229 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
230 }
231
232 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
233 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
234
235private:
238 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
239};
240static_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");
241
243{
245 // JSClassMember[nMembers]
246
247 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
248};
249static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
250
251struct String
252{
254
255 static int calculateSize(const QString &str) {
256 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
257 // would already break in other parts of the compilation process
258 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
259 }
260};
261
262static_assert (sizeof (String) == 4, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
263
266 qint32_le line; // signed because debug instructions get negative line numbers
268};
269static_assert(sizeof(CodeOffsetToLineAndStatement) == 12, "CodeOffsetToLineAndStatement structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
270
271struct Block
272{
277
278 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
279
280 static int calculateSize(int nLocals) {
281 int trailingData = nLocals*sizeof (quint32);
282 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
283 Q_ASSERT(size < INT_MAX);
284 return int(size);
285 }
286
287 static size_t align(size_t a) {
288 return (a + 7) & ~size_t(7);
289 }
290};
291static_assert(sizeof(Block) == 12, "Block structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
292
293enum class NamedBuiltin: unsigned int {
295};
296
297enum class CommonType : unsigned int {
298 // Actual named builtins
308
309 // Optimization for very common other types
311
312 // No type specified or not recognized
314};
315
317{
318 enum Flag {
319 NoFlag = 0x0,
320 Common = 0x1,
321 List = 0x2,
322 };
324
325 void set(Flags flags, quint32 typeNameIndexOrCommonType)
326 {
327 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
328 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
329 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
330 }
331
332 bool indexIsCommonType() const
333 {
334 return m_data.get<IndexIsCommonTypeField>() != 0;
335 }
336
337 bool isList() const
338 {
339 return m_data.get<IsListField>() != 0;
340 }
341
343 {
344 return m_data.get<TypeNameIndexOrCommonTypeField>();
345 }
346
347private:
351 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
352};
353static_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");
354
360static_assert(sizeof(Parameter) == 8, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
361
362// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
363// for unaligned access. The ordering of the fields is also from largest to smallest.
365{
366 enum Flags : unsigned int {
367 IsStrict = 0x1,
371 };
372
373 // Absolute offset into file where the code for this function is located.
376
380 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
385 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
386 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
387
391
395
397 {
398 return lineAndStatementNumberOffset() + nLineAndStatementNumbers * sizeof(CodeOffsetToLineAndStatement);
399 }
400
401 // Keep all unaligned data at the end
404
405 // quint32 formalsIndex[nFormals]
406 // quint32 localsIndex[nLocals]
407
408 const Parameter *formalsTable() const
409 {
410 return reinterpret_cast<const Parameter *>(
411 reinterpret_cast<const char *>(this) + formalsOffset);
412 }
413 const quint32_le *localsTable() const
414 {
415 return reinterpret_cast<const quint32_le *>(
416 reinterpret_cast<const char *>(this) + localsOffset);
417 }
419 {
420 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
421 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
422 }
423
424 // --- QQmlPropertyCacheCreator interface
425 const Parameter *formalsBegin() const { return formalsTable(); }
426 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
427 // ---
428
429 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
430
431 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
432
433 static int calculateSize(
434 int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions,
435 int labelInfoSize, int codeSize)
436 {
437 int trailingData = nFormals * sizeof(Parameter)
438 + (nLocals + nInnerfunctions + labelInfoSize) * sizeof (quint32)
439 + nLinesAndStatements * sizeof(CodeOffsetToLineAndStatement);
440 size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
441 Q_ASSERT(size < INT_MAX);
442 return int(size);
443 }
444
445 static size_t align(size_t a) {
446 return (a + 7) & ~size_t(7);
447 }
448};
449static_assert(sizeof(Function) == 56, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
450
462static_assert(sizeof(Method) == 12, "Method structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
463
464struct Class
465{
472
473 const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
474
475 static int calculateSize(int nStaticMethods, int nMethods) {
476 int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
477 size_t size = align(sizeof(Class) + trailingData);
478 Q_ASSERT(size < INT_MAX);
479 return int(size);
480 }
481
482 static size_t align(size_t a) {
483 return (a + 7) & ~size_t(7);
484 }
485};
486static_assert(sizeof(Class) == 24, "Class structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
487
489{
491
492 static int calculateSize(int size) {
493 int trailingData = 2 * size * sizeof(quint32_le);
494 size_t s = align(sizeof(TemplateObject) + trailingData);
495 Q_ASSERT(s < INT_MAX);
496 return int(s);
497 }
498
499 static size_t align(size_t a) {
500 return (a + 7) & ~size_t(7);
501 }
502
503 const quint32_le *stringTable() const {
504 return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1));
505 }
506
507 uint stringIndexAt(uint i) const {
508 return stringTable()[i];
509 }
510 uint rawStringIndexAt(uint i) const {
511 return stringTable()[size + i];
512 }
513};
514static_assert(sizeof(TemplateObject) == 4, "Template object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
515
524static_assert(sizeof(ExportEntry) == 20, "ExportEntry structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
525
533static_assert(sizeof(ImportEntry) == 16, "ImportEntry structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
534
535// Qml data structures
536
545static_assert(sizeof(TranslationData) == 16, "TranslationData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
546
548{
550
564
579
583
584 void clearFlags() { flagsAndType.set<FlagsField>(0); }
585 void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); }
586 bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; }
587 Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); }
588
589 void setType(Type type) { flagsAndType.set<TypeField>(type); }
590 Type type() const { return Type(flagsAndType.get<TypeField>()); }
591
592 union {
593 bool b;
595 quint32_le compiledScriptIndex; // used when Type_Script
597 quint32_le translationDataIndex; // used when Type_Translation
599 } value;
600 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
601
604
606 {
607 const Flags bindingFlags = flags();
608 return bindingFlags & IsSignalHandlerExpression
609 || bindingFlags & IsSignalHandlerObject
610 || bindingFlags & IsPropertyObserver;
611 }
612
613 bool isValueBinding() const
614 {
615 switch (type()) {
618 return false;
619 default:
621 }
622 }
623
626
627 bool isSignalHandler() const
628 {
630 Q_ASSERT(!isValueBinding());
631 Q_ASSERT(!isAttachedProperty());
632 Q_ASSERT(!isGroupProperty());
633 return true;
634 }
635 return false;
636 }
637
639 {
641 Q_ASSERT(!isValueBinding());
642 Q_ASSERT(!isSignalHandler());
643 Q_ASSERT(!isGroupProperty());
644 return true;
645 }
646 return false;
647 }
648
649 bool isGroupProperty() const
650 {
651 if (type() == Type_GroupProperty) {
652 Q_ASSERT(!isValueBinding());
653 Q_ASSERT(!isSignalHandler());
654 Q_ASSERT(!isAttachedProperty());
655 return true;
656 }
657 return false;
658 }
659
661
662 //reverse of Lexer::singleEscape()
663 static QString escapedString(const QString &string)
664 {
665 QString tmp = QLatin1String("\"");
666 for (int i = 0; i < string.size(); ++i) {
667 const QChar &c = string.at(i);
668 switch (c.unicode()) {
669 case 0x08:
670 tmp += QLatin1String("\\b");
671 break;
672 case 0x09:
673 tmp += QLatin1String("\\t");
674 break;
675 case 0x0A:
676 tmp += QLatin1String("\\n");
677 break;
678 case 0x0B:
679 tmp += QLatin1String("\\v");
680 break;
681 case 0x0C:
682 tmp += QLatin1String("\\f");
683 break;
684 case 0x0D:
685 tmp += QLatin1String("\\r");
686 break;
687 case 0x22:
688 tmp += QLatin1String("\\\"");
689 break;
690 case 0x27:
691 tmp += QLatin1String("\\\'");
692 break;
693 case 0x5C:
694 tmp += QLatin1String("\\\\");
695 break;
696 default:
697 tmp += c;
698 break;
699 }
700 }
701 tmp += QLatin1Char('\"');
702 return tmp;
703 }
704
706 {
707 const Binding::Type bindingType = type();
708 return bindingType == Type_Translation || bindingType == Type_TranslationById;
709 }
711
712 bool isNumberBinding() const { return type() == Type_Number; }
713
714 bool valueAsBoolean() const
715 {
716 if (type() == Type_Boolean)
717 return value.b;
718 return false;
719 }
720};
721
722static_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");
723
730
731static_assert(sizeof(InlineComponent) == 12, "InlineComponent structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
732
739static_assert(sizeof(EnumValue) == 12, "EnumValue structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
740
741struct Enum
742{
746
747 const EnumValue *enumValueAt(int idx) const {
748 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
749 }
750
751 static int calculateSize(int nEnumValues) {
752 return (sizeof(Enum)
753 + nEnumValues * sizeof(EnumValue)
754 + 7) & ~0x7;
755 }
756
757 // --- QQmlPropertyCacheCreatorInterface
758 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
759 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
760 int enumValueCount() const { return nEnumValues; }
761 // ---
762};
763static_assert(sizeof(Enum) == 12, "Enum structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
764
765struct Signal
766{
770 // Parameter parameters[1];
771
772 const Parameter *parameterAt(int idx) const {
773 return reinterpret_cast<const Parameter*>(this + 1) + idx;
774 }
775
776 static int calculateSize(int nParameters) {
777 return (sizeof(Signal)
778 + nParameters * sizeof(Parameter)
779 + 7) & ~0x7;
780 }
781
782 // --- QQmlPropertyCacheCceatorInterface
783 const Parameter *parametersBegin() const { return parameterAt(0); }
784 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
785 int parameterCount() const { return nParameters; }
786 // ---
787};
788static_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");
789
791{
792private:
795
801public:
810
811 quint32 nameIndex() const { return nameIndexAndFinal.get<NameIndexField>(); }
812 void setNameIndex(int nameIndex) { nameIndexAndFinal.set<NameIndexField>(nameIndex); }
813
814 bool isFinal() const { return nameIndexAndFinal.get<FinalField>(); }
815 void setIsFinal(bool final) { nameIndexAndFinal.set<FinalField>(final ? 1 : 0); }
816
818 {
819 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
820 data.set<IsCommonTypeField>(true);
821 }
822
824 if (isCommonType())
825 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
826 return CommonType::Invalid;
827 }
828
829 void setTypeNameIndex(int nameIndex)
830 {
831 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
832 data.set<IsCommonTypeField>(false);
833 }
834
835 int typeNameIndex() const
836 {
837 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
838 }
839
840 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
841 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
842
843 bool isList() const { return data.get<IsListField>(); }
844 void setIsList(bool isList) { data.set<IsListField>(isList); }
845
846 bool isRequired() const { return data.get<IsRequiredField>(); }
847 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
848
849 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
850 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
851};
852static_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");
853
857
858static_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");
859
860struct Alias {
861private:
864
865 // object id index (in QQmlContextData::idValues)
869
870public:
871
872 enum Flag : unsigned int {
875 // One bit vacant
876 };
877 Q_DECLARE_FLAGS(Flags, Flag)
878
882
883 union {
885 quint32_le localAliasIndex; // index in list of aliases local to the object (if targetObjectId == objectId)
886 };
889
890 bool hasFlag(Flag flag) const
891 {
892 return nameIndexAndFlags.get<FlagsField>() & flag;
893 }
894
895 void setFlag(Flag flag)
896 {
897 nameIndexAndFlags.set<FlagsField>(nameIndexAndFlags.get<FlagsField>() | flag);
898 }
899
901 {
902 nameIndexAndFlags.set<FlagsField>(0);
903 }
904
906 {
907 return nameIndexAndFlags.get<NameIndexField>();
908 }
909
910 void setNameIndex(quint32 nameIndex)
911 {
912 nameIndexAndFlags.set<NameIndexField>(nameIndex);
913 }
914
916 {
917 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<IdIndexField>();
918 }
919
920 void setIdIndex(quint32 idIndex)
921 {
922 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<IdIndexField>(idIndex);
923 }
924
925
927 {
928 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<AliasToLocalAliasField>();
929 }
930
931 void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
932 {
933 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<AliasToLocalAliasField>(isAliasToLocalAlias);
934 }
935
937 {
938 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<TargetObjectIdField>();
939 }
940
941 void setTargetObjectId(quint32 targetObjectId)
942 {
943 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<TargetObjectIdField>(targetObjectId);
944 }
945};
946static_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");
947
948struct Object
949{
950private:
954public:
955 enum Flag : unsigned int {
956 NoFlag = 0x0,
957 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
958 HasDeferredBindings = 0x2, // any of the bindings are deferred
962 };
964
965 // Depending on the use, this may be the type name to instantiate before instantiating this
966 // object. For grouped properties the type name will be empty and for attached properties
967 // it will be the name of the attached type.
972 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
980 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
981 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
993// Function[]
994// Property[]
995// Signal[]
996// Binding[]
997// InlineComponent[]
998// RequiredPropertyExtraData[]
999
1000 Flags flags() const
1001 {
1002 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1003 }
1004
1005 bool hasFlag(Flag flag) const
1006 {
1007 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1008 }
1009
1010 void setFlag(Flag flag)
1011 {
1012 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1013 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1014 }
1015
1016 void setFlags(Flags flags)
1017 {
1018 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1019 }
1020
1022 {
1023 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1024 }
1025
1026 void setHasAliasAsDefaultProperty(bool defaultAlias)
1027 {
1028 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1029 }
1030
1032 {
1033 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1034 }
1035
1036 void setObjectId(qint32 id)
1037 {
1038 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1039 }
1040
1041
1042 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1043 {
1044 return ( sizeof(Object)
1045 + nFunctions * sizeof(quint32)
1046 + nProperties * sizeof(Property)
1047 + nAliases * sizeof(Alias)
1048 + nEnums * sizeof(quint32)
1049 + nSignals * sizeof(quint32)
1050 + nBindings * sizeof(Binding)
1051 + nNamedObjectsInComponent * sizeof(int)
1052 + nInlineComponents * sizeof(InlineComponent)
1053 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1054 + 0x7
1055 ) & ~0x7;
1056 }
1057
1059 {
1060 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1061 }
1062
1064 {
1065 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1066 }
1067
1068 const Alias *aliasTable() const
1069 {
1070 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1071 }
1072
1073 const Binding *bindingTable() const
1074 {
1075 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1076 }
1077
1078 const Enum *enumAt(int idx) const
1079 {
1080 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1081 const quint32_le offset = offsetTable[idx];
1082 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1083 }
1084
1085 const Signal *signalAt(int idx) const
1086 {
1087 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1088 const quint32_le offset = offsetTable[idx];
1089 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1090 }
1091
1093 {
1094 return inlineComponentTable() + idx;
1095 }
1096
1098 {
1099 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1100 }
1101
1103 {
1104 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1105 }
1106
1111
1113 {
1114 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1115 }
1116
1117 // --- QQmlPropertyCacheCreator interface
1118 int propertyCount() const { return nProperties; }
1119 int aliasCount() const { return nAliases; }
1120 int enumCount() const { return nEnums; }
1121 int signalCount() const { return nSignals; }
1122 int functionCount() const { return nFunctions; }
1123 int inlineComponentCount() const { return nInlineComponents; }
1124
1125 const Binding *bindingsBegin() const { return bindingTable(); }
1126 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1127 int bindingCount() const { return nBindings; }
1128
1129 const Property *propertiesBegin() const { return propertyTable(); }
1130 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1131
1132 const Alias *aliasesBegin() const { return aliasTable(); }
1133 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1134
1136 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1137 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1138
1140 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1141 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1142
1144 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1145 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1146
1148 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1149 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1150
1151 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1152 // ---
1153};
1154static_assert(sizeof(Object) == 84, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1155
1157{
1158 enum ImportType : unsigned int {
1163 };
1165
1168
1172
1174 {
1175 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1176 }
1177};
1178static_assert(sizeof(Import) == 20, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1179
1181{
1186
1187 const Import *importAt(int idx) const {
1188 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1189 }
1190
1191 const Object *objectAt(int idx) const {
1192 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1193 const quint32_le offset = offsetTable[idx];
1194 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1195 }
1196};
1197static_assert(sizeof(QmlUnit) == 16, "QmlUnit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1198
1199static const char magic_str[] = "qv4cdata";
1200
1201struct Unit
1202{
1203 // DO NOT CHANGE THESE FIELDS EVER
1204 char magic[8];
1206 // END DO NOT CHANGE THESE FIELDS EVER
1207
1208 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1210 quint32_le unitSize; // Size of the Unit and any depending data.
1211
1212 char md5Checksum[16]; // checksum of all bytes following this field.
1214
1215 enum : unsigned int {
1217 StaticData = 0x2, // Unit data persistent in memory?
1219 IsSharedLibrary = 0x8, // .pragma shared?
1221 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1222 IsStrict = 0x40,
1233 };
1268
1270
1271 /* QML specific fields */
1272
1273 const QmlUnit *qmlUnit() const {
1274 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1275 }
1276
1278 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1279 }
1280
1281 bool isSingleton() const {
1282 return flags & Unit::IsSingleton;
1283 }
1284 /* end QML specific fields*/
1285
1286 QString stringAtInternal(uint idx) const {
1287 Q_ASSERT(idx < stringTableSize);
1288 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1289 const quint32_le offset = offsetTable[idx];
1290 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1291 Q_ASSERT(str->size >= 0);
1292#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1293 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1294 if (flags & StaticData)
1295 return QString::fromRawData(characters, str->size);
1296 return QString(characters, str->size);
1297#else
1298 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1299 QString qstr(str->size, Qt::Uninitialized);
1300 QChar *ch = qstr.data();
1301 for (int i = 0; i < str->size; ++i)
1302 ch[i] = QChar(quint16(characters[i]));
1303 return qstr;
1304#endif
1305 }
1306
1307 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1308 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1309 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1310 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1311
1312 const Function *functionAt(int idx) const {
1313 const quint32_le *offsetTable = functionOffsetTable();
1314 const quint32_le offset = offsetTable[idx];
1315 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1316 }
1317
1318 const Class *classAt(int idx) const {
1319 const quint32_le *offsetTable = classOffsetTable();
1320 const quint32_le offset = offsetTable[idx];
1321 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1322 }
1323
1324 const TemplateObject *templateObjectAt(int idx) const {
1325 const quint32_le *offsetTable = templateObjectOffsetTable();
1326 const quint32_le offset = offsetTable[idx];
1327 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1328 }
1329
1330 const Block *blockAt(int idx) const {
1331 const quint32_le *offsetTable = blockOffsetTable();
1332 const quint32_le offset = offsetTable[idx];
1333 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1334 }
1335
1336 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1337 const RegExp *regexpAt(int index) const {
1338 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1339 }
1340 const quint64_le *constants() const {
1341 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1342 }
1343
1344 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1345 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1346 const quint32_le offset = offsetTable[idx];
1347 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1348 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1349 *nMembers = klass->nMembers;
1350 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1351 }
1352
1354 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1355 }
1356
1358 if ( translationTableSize == 0)
1359 return nullptr;
1360 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1361 + offsetToTranslationTable
1362 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1363
1365 if ( translationTableSize == 0)
1366 return nullptr;
1367 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1368 + offsetToTranslationTable
1369 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1370
1371 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1372 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1373 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1374 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1375
1376 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1377
1378 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1379};
1380
1381static_assert(sizeof(Unit) == 200, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1382
1384{
1386 : location(loc)
1387 , needsCreation(false)
1388 , errorWhenNotFound(false)
1389 {}
1390 Location location; // first use
1391 bool needsCreation : 1; // whether the type needs to be creatable or not
1393};
1394
1395// Map from name index to location of first use.
1397{
1398 TypeReference &add(int nameIndex, const Location &loc) {
1399 Iterator it = find(nameIndex);
1400 if (it != end())
1401 return *it;
1402 return *insert(nameIndex, loc);
1403 }
1404
1405 template <typename CompiledObject>
1406 void collectFromObject(const CompiledObject *obj)
1407 {
1408 if (obj->inheritedTypeNameIndex != 0) {
1409 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1410 r.needsCreation = true;
1411 r.errorWhenNotFound = true;
1412 }
1413
1414 auto binding = obj->bindingsBegin();
1415 auto const bindingEnd = obj->bindingsEnd();
1416 for ( ; binding != bindingEnd; ++binding) {
1418 this->add(binding->propertyNameIndex, binding->location);
1419 }
1420
1421 auto ic = obj->inlineComponentsBegin();
1422 auto const icEnd = obj->inlineComponentsEnd();
1423 for (; ic != icEnd; ++ic) {
1424 this->add(ic->nameIndex, ic->location);
1425 }
1426 }
1427
1428 template <typename Iterator>
1429 void collectFromObjects(Iterator it, Iterator end)
1430 {
1431 for (; it != end; ++it)
1432 collectFromObject(*it);
1433 }
1434};
1435
1437
1439
1441 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1442 : qmlType(qmlType)
1443 , objectIndex(objectIndex)
1444 , nameIndex(nameIndex)
1445 {}
1446
1447 QQmlType qmlType;
1448 int objectIndex = -1;
1449 int nameIndex = -1;
1450};
1451
1453{
1455
1456 const Unit *data = nullptr;
1457 const QmlUnit *qmlData = nullptr;
1460
1461 // pointers either to data->constants() or little-endian memory copy.
1462 const StaticValue *constants = nullptr;
1463
1465
1467
1468 // index is object index. This allows fast access to the
1469 // property data when initializing bindings, avoiding expensive
1470 // lookups by string (property name).
1472
1475
1477
1478 QQmlType qmlType;
1479
1481
1482public:
1483 // --- interface for QQmlPropertyCacheCreator
1487
1488 // Empty dummy. We don't need to do this when loading from cache.
1490 {
1491 public:
1492 void insert(int, int) {}
1493 void clear() {}
1494
1495 // We have already checked uniqueness of IDs when creating the CU
1496 bool contains(int) { return false; }
1497 };
1498
1499 explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1500 const QString &fileName = QString(), const QString &finalUrlString = QString())
1501 : CompilationUnit(unitData, fileName, finalUrlString)
1502 {
1503 this->aotCompiledFunctions = aotCompiledFunctions;
1504 }
1505
1507 const Unit *unitData = nullptr, const QString &fileName = QString(),
1508 const QString &finalUrlString = QString());
1509
1511
1512 const Unit *unitData() const { return data; }
1513
1514 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1515 const QString &fileName = QString(), const QString &finalUrlString = QString())
1516 {
1517 data = unitData;
1518 qmlData = nullptr;
1519#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1520 delete [] constants;
1521#endif
1522 constants = nullptr;
1523 m_fileName.clear();
1524 m_finalUrlString.clear();
1525 if (!data)
1526 return;
1527
1528 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1529
1530#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1531 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1532 const quint64_le *littleEndianConstants = data->constants();
1533 for (uint i = 0; i < data->constantTableSize; ++i)
1534 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1535 constants = bigEndianConstants;
1536#else
1537 constants = reinterpret_cast<const StaticValue*>(data->constants());
1538#endif
1539
1540 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1541 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1542 }
1543
1544 QString stringAt(uint index) const
1545 {
1546 if (index < data->stringTableSize)
1547 return data->stringAtInternal(index);
1548
1549 const qsizetype dynamicIndex = index - data->stringTableSize;
1550 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1551 return dynamicStrings.at(dynamicIndex);
1552 }
1553
1554 QString fileName() const { return m_fileName; }
1555 QString finalUrlString() const { return m_finalUrlString; }
1556
1558 {
1559 using namespace CompiledData;
1560 switch (binding->type()) {
1561 case Binding::Type_Script:
1562 case Binding::Type_String:
1563 return stringAt(binding->stringIndex);
1564 case Binding::Type_Null:
1565 return QStringLiteral("null");
1567 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1568 case Binding::Type_Number:
1569 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1571 return QString();
1572 case Binding::Type_TranslationById:
1573 case Binding::Type_Translation:
1574 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1575 default:
1576 break;
1577 }
1578 return QString();
1579 }
1580
1582 {
1583 return (binding->type() == CompiledData::Binding::Type_String)
1584 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1585 : bindingValueAsString(binding);
1586 }
1587
1588 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1589 {
1591 return 0.0;
1592 return constants[binding->value.constantValueIndex].doubleValue();
1593 }
1594
1595 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1597 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1598 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString);
1599
1600 int importCount() const { return qmlData->nImports; }
1601 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1602
1603 Q_QML_EXPORT QStringList moduleRequests() const;
1604
1605 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1606 // warnings about that code. They include any potential URL interceptions and thus represent the
1607 // "physical" location of the code.
1608 //
1609 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1610 // They are _not_ intercepted and thus represent the "logical" name for the code.
1611
1612 QUrl url() const
1613 {
1614 if (!m_url.isValid())
1615 m_url = QUrl(fileName());
1616 return m_url;
1617 }
1618
1620 {
1621 if (!m_finalUrl.isValid())
1622 m_finalUrl = QUrl(finalUrlString());
1623 return m_finalUrl;
1624 }
1625
1626 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1627 ResolvedTypeReference *resolvedType(QMetaType type) const;
1628
1630 {
1631 return propertyCaches.isEmpty()
1632 ? QQmlPropertyCache::ConstPtr()
1633 : propertyCaches.at(/*root object*/0);
1634 }
1635
1636 int objectCount() const { return qmlData->nObjects; }
1637 const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); }
1638
1639 int inlineComponentId(const QString &inlineComponentName) const
1640 {
1641 for (uint i = 0; i < qmlData->nObjects; ++i) {
1642 auto *object = qmlData->objectAt(i);
1643 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1644 it != end; ++it) {
1645 if (stringAt(it->nameIndex) == inlineComponentName)
1646 return it->objectIndex;
1647 }
1648 }
1649 return -1;
1650 }
1651
1652 void finalizeCompositeType(const QQmlType &type);
1653
1654 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1655
1665
1670
1675
1677 {
1679 }
1680
1685
1687 {
1689 }
1690
1692 {
1694 }
1695
1696 bool isESModule() const
1697 {
1699 }
1700
1701 bool isSharedLibrary() const
1702 {
1704 }
1705
1707 {
1708 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1709 : unit(unit), object(object), index(index) {}
1713
1715 {
1716 return unit->functionAt(object->functionOffsetTable()[index]);
1717 }
1718
1719 void operator++() { ++index; }
1720 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1721 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1722 };
1723
1725 {
1726 return FunctionIterator(unitData(), object, 0);
1727 }
1728
1730 {
1731 return FunctionIterator(unitData(), object, object->nFunctions);
1732 }
1733
1734 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1735 QMetaType metaType() const { return qmlType.typeId(); }
1736
1737private:
1738 QString m_fileName; // initialized from data->sourceFileIndex
1739 QString m_finalUrlString; // initialized from data->finalUrlIndex
1740
1741 mutable QQmlNullableValue<QUrl> m_url;
1742 mutable QQmlNullableValue<QUrl> m_finalUrl;
1743};
1744
1746{
1748public:
1754
1756
1757 template<typename Char>
1758 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1759 {
1760 const quint32_le oldFlags = mutableFlags();
1761 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1762 mutableFlags() |= temporaryFlags;
1763 return writer(data<Char>(), size());
1764 }
1765
1766 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1767 QString *errorString)
1768 {
1769#if QT_CONFIG(temporaryfile)
1770 QSaveFile cacheFile(outputFileName);
1771 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1772 || cacheFile.write(data, size) != size
1773 || !cacheFile.commit()) {
1774 *errorString = cacheFile.errorString();
1775 return false;
1776 }
1777
1778 errorString->clear();
1779 return true;
1780#else
1781 Q_UNUSED(outputFileName);
1782 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1783 return false;
1784#endif
1785 }
1786
1787private:
1788 const Unit *unit;
1789 quint32 temporaryFlags;
1790
1791 quint32_le &mutableFlags() const
1792 {
1793 return const_cast<Unit *>(unit)->flags;
1794 }
1795
1796 template<typename Char>
1797 const Char *data() const
1798 {
1799 Q_STATIC_ASSERT(sizeof(Char) == 1);
1800 const Char *dataPtr;
1801 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1802 return dataPtr;
1803 }
1804
1805 quint32 size() const
1806 {
1807 return unit->unitSize;
1808 }
1809};
1810
1811
1812} // CompiledData namespace
1813} // QV4 namespace
1814
1817
1818QT_END_NAMESPACE
1819
1820#endif
static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size, QString *errorString)
bool saveToDisk(const std::function< bool(const Char *, quint32)> &writer) const
static const char magic_str[]
Definition qjsvalue.h:23
Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE)
#define QV4_DATA_STRUCTURE_VERSION
Q_DECLARE_OPERATORS_FOR_FLAGS(QV4::CompiledData::ParameterType::Flags)
void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
void setTargetObjectId(quint32 targetObjectId)
bool hasFlag(Flag flag) const
quint32_le_bitfield_union< IdIndexField, TargetObjectIdField, AliasToLocalAliasField > idIndexAndTargetObjectIdAndAliasToLocalAlias
void setNameIndex(quint32 nameIndex)
void setIdIndex(quint32 idIndex)
quint32_le_bitfield_union< FlagsField, TypeField > flagsAndType
bool hasFlag(Flag flag) const
static QString escapedString(const QString &string)
const quint32_le * localsTable() const
static size_t align(size_t a)
static int calculateSize(int nLocals)
static int calculateSize(int nStaticMethods, int nMethods)
static size_t align(size_t a)
const Method * methodTable() const
bool operator!=(const FunctionIterator &rhs) const
bool operator==(const FunctionIterator &rhs) const
FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
std::unique_ptr< CompilationUnitMapper > backingFile
QString bindingValueAsScriptString(const CompiledData::Binding *binding) const
QHash< QString, InlineComponentData > inlineComponentData
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit=nullptr, const QString &fileName=QString(), const QString &finalUrlString=QString())
int inlineComponentId(const QString &inlineComponentName) const
double bindingValueAsNumber(const CompiledData::Binding *binding) const
void finalizeCompositeType(const QQmlType &type)
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString)
ResolvedTypeReference * resolvedType(int id) const
const CompiledData::Function CompiledFunction
const QQmlPrivate::AOTCompiledFunction * aotCompiledFunctions
CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, const QString &fileName=QString(), const QString &finalUrlString=QString())
QVector< QQmlRefPointer< QQmlScriptData > > dependentScripts
ResolvedTypeReferenceMap resolvedTypes
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
QVector< BindingPropertyData > bindingPropertyDataPerObject
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
ListPropertyAssignBehavior listPropertyAssignBehavior() const
const CompiledObject * objectAt(int index) const
const CompiledData::Object CompiledObject
const CompiledData::Binding CompiledBinding
const CompiledData::Import * importAt(int index) const
Q_QML_EXPORT bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
QString bindingValueAsString(const CompiledData::Binding *binding) const
QQmlPropertyCache::ConstPtr rootPropertyCache() const
const EnumValue * enumValueAt(int idx) const
const EnumValue * enumValuesEnd() const
const EnumValue * enumValuesBegin() const
static int calculateSize(int nEnumValues)
const quint32_le * localsTable() const
static size_t align(size_t a)
const CodeOffsetToLineAndStatement * lineAndStatementNumberTable() const
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions, int labelInfoSize, int codeSize)
size_t lineAndStatementNumberOffset() const
const Parameter * formalsTable() const
const Parameter * formalsEnd() const
const Parameter * formalsBegin() const
const quint32_le * labelInfoTable() const
InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
Location(quint32 l, quint32 c)
void set(quint32 line, quint32 column)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool operator==(const Location &a, const Location &b)
Lookup(Type type, Mode mode, quint32 nameIndex)
TableIterator< Enum, Object, &Object::enumAt > EnumIterator
EnumIterator enumsBegin() const
Q_DECLARE_FLAGS(Flags, Flag)
const RequiredPropertyExtraData * requiredPropertyExtraDataAt(int idx) const
EnumIterator enumsEnd() const
const Enum * enumAt(int idx) const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const
const RequiredPropertyExtraData * requiredPropertyExtraDataTable() const
TableIterator< Signal, Object, &Object::signalAt > SignalIterator
const Binding * bindingsEnd() const
bool hasFlag(Flag flag) const
const Property * propertyTable() const
SignalIterator signalsBegin() const
quint32_le_bitfield_union< FlagsField, DefaultPropertyIsAliasField, IdField > flagsAndDefaultPropertyIsAliasAndId
InlineComponentIterator inlineComponentsEnd() const
const Alias * aliasTable() const
const InlineComponent * inlineComponentAt(int idx) const
const Property * propertiesEnd() const
const Binding * bindingTable() const
const Signal * signalAt(int idx) const
const Property * propertiesBegin() const
const quint32_le * functionOffsetTable() const
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
TableIterator< InlineComponent, Object, &Object::inlineComponentAt > InlineComponentIterator
const InlineComponent * inlineComponentTable() const
InlineComponentIterator inlineComponentsBegin() const
TableIterator< RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt > RequiredPropertyExtraDataIterator
SignalIterator signalsEnd() const
const Alias * aliasesEnd() const
const Binding * bindingsBegin() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const
void setHasAliasAsDefaultProperty(bool defaultAlias)
const Alias * aliasesBegin() const
const quint32_le * namedObjectsInComponentTable() const
void set(Flags flags, quint32 typeNameIndexOrCommonType)
void setNameIndex(int nameIndex)
void setIsReadOnly(bool isReadOnly)
void setTypeNameIndex(int nameIndex)
quint32_le_bitfield_union< CommonTypeOrTypeNameIndexField, IsRequiredField, IsCommonTypeField, IsListField, IsReadOnlyField > data
void setIsRequired(bool isRequired)
quint32_le_bitfield_union< NameIndexField, FinalField > nameIndexAndFinal
const Object * objectAt(int idx) const
const Import * importAt(int idx) const
RegExp(quint32 flags, quint32 stringIndex)
Q_DECLARE_FLAGS(Flags, Flag)
bool addToHash(QCryptographicHash *hash, QHash< quintptr, QByteArray > *checksums) const
const Parameter * parametersBegin() const
static int calculateSize(int nParameters)
const Parameter * parametersEnd() const
const Parameter * parameterAt(int idx) const
static int calculateSize(const QString &str)
bool operator==(const TableIterator &rhs) const
bool operator!=(const TableIterator &rhs) const
TableIterator(const Container *container, int index)
const quint32_le * stringTable() const
void collectFromObject(const CompiledObject *obj)
TypeReference & add(int nameIndex, const Location &loc)
void collectFromObjects(Iterator it, Iterator end)
quint32_le offsetToIndirectExportEntryTable
quint32_le * translationContextIndex()
const TranslationData * translations() const
const ExportEntry * indirectExportEntryTable() const
const quint64_le * constants() const
QString stringAtInternal(uint idx) const
const quint32_le * functionOffsetTable() const
bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const
const Function * functionAt(int idx) const
const TemplateObject * templateObjectAt(int idx) const
const ExportEntry * starExportEntryTable() const
const Lookup * lookupTable() const
const RegExp * regexpAt(int index) const
const Block * blockAt(int idx) const
const ExportEntry * localExportEntryTable() const
const quint32_le * translationContextIndex() const
const quint32_le * classOffsetTable() const
const quint32_le * moduleRequestTable() const
const Class * classAt(int idx) const
const ImportEntry * importEntryTable() const
const QmlUnit * qmlUnit() const
const quint32_le * blockOffsetTable() const
const JSClassMember * jsClassAt(int idx, int *nMembers) const
const quint32_le * templateObjectOffsetTable() const