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// Qt-Security score:significant
4#ifndef QV4COMPILEDDATA_P_H
5#define QV4COMPILEDDATA_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <functional>
19
20#include <QtCore/qcryptographichash.h>
21#include <QtCore/qhash.h>
22#include <QtCore/qhashfunctions.h>
23#include <QtCore/qlocale.h>
24#include <QtCore/qscopeguard.h>
25#include <QtCore/qstring.h>
26#include <QtCore/qstringlist.h>
27#include <QtCore/qurl.h>
28#include <QtCore/qvector.h>
29#include <QtCore/qtyperevision.h>
30
31#if QT_CONFIG(temporaryfile)
32#include <QtCore/qsavefile.h>
33#endif
34
35#include <private/qendian_p.h>
36#include <private/qqmlnullablevalue_p.h>
37#include <private/qqmlpropertycachevector_p.h>
38#include <private/qqmlrefcount_p.h>
39#include <private/qqmltype_p.h>
40#include <private/qv4compilationunitmapper_p.h>
41#include <private/qv4staticvalue_p.h>
42
43#include <functional>
44#include <limits.h>
45
46QT_BEGIN_NAMESPACE
47
48// Bump this whenever the compiler data structures change in an incompatible way.
49//
50// IMPORTANT:
51//
52// Also change the comment behind the number to describe the latest change. This has the added
53// benefit that if another patch changes the version too, it will result in a merge conflict, and
54// not get removed silently.
55// Also update the comparison functions in qqmlpreviewdiff.cpp when you change the data structures.
56#define QV4_DATA_STRUCTURE_VERSION 0x4c // Dropped enum value location
57
58class QIODevice;
59class QQmlTypeNameCache;
60class QQmlType;
61class QQmlEngine;
63class QQmlScriptData;
64
65namespace QQmlPrivate {
67}
68
69namespace QmlIR {
70struct Document;
71}
72
73namespace QV4 {
74namespace Heap {
75struct Module;
76struct String;
77struct InternalClass;
78};
79
80struct Function;
81class EvalISelFactory;
83
84namespace CompiledData {
85
86// index is per-object binding index
88
89// map from name index
91{
92 bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
93};
94
95struct String;
96struct Function;
97struct Lookup;
98struct RegExp;
99struct Unit;
100
101template <typename ItemType, typename Container, const ItemType *(Container::*IndexedGetter)(int index) const>
103{
104 TableIterator(const Container *container, int index) : container(container), index(index) {}
105 const Container *container;
106 int index;
107
108 const ItemType *operator->() const { return (container->*IndexedGetter)(index); }
109 ItemType operator*() const {return *operator->();}
110
112 {
113 ++index;
114 return *this;
115 }
116
118 {
120 ++index;
121 return result;
122 }
123
124 TableIterator operator+(int offset) const { return TableIterator(container, index + offset); }
125 TableIterator operator-(int offset) const { return TableIterator(container, index - offset); }
126 int operator-(TableIterator other) const { return index - other.index; }
127
128 bool operator==(const TableIterator &rhs) const { return index == rhs.index; }
129 bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
130};
131
133{
135 Location(quint32 l, quint32 c) : Location()
136 {
137 m_data.set<LineField>(l);
138 m_data.set<ColumnField>(c);
139 Q_ASSERT(m_data.get<LineField>() == l);
140 Q_ASSERT(m_data.get<ColumnField>() == c);
141 }
142
143 inline bool operator<(const Location &other) const {
144 return m_data.get<LineField>() < other.m_data.get<LineField>()
145 || (m_data.get<LineField>() == other.m_data.get<LineField>()
146 && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
147 }
148
149 friend size_t qHash(const Location &location, size_t seed = 0)
150 {
151 return QT_PREPEND_NAMESPACE(qHash)(location.m_data.data(), seed);
152 }
153
154 friend bool comparesEqual(const Location &a, const Location &b) noexcept
155 {
156 return a.m_data.data()== b.m_data.data();
157 }
159
165
166 quint32 line() const { return m_data.get<LineField>(); }
167 quint32 column() const { return m_data.get<ColumnField>(); }
168
169private:
172
173 quint32_le_bitfield_union<LineField, ColumnField> m_data;
174};
175static_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");
176
177struct RegExp
178{
187
189
191 RegExp(quint32 flags, quint32 stringIndex) : RegExp()
192 {
193 m_data.set<FlagsField>(flags);
194 m_data.set<StringIndexField>(stringIndex);
195 }
196
197 quint32 flags() const { return m_data.get<FlagsField>(); }
198 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
199
200private:
203 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
204};
205static_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");
206
207struct Lookup
208{
215
216 enum Mode : unsigned int {
219 };
220
221 quint32 type() const { return m_data.get<TypeField>(); }
222 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
223 quint32 mode() const { return m_data.get<ModeField>(); }
224
226 Lookup(Type type, Mode mode, quint32 nameIndex) : Lookup()
227 {
228 m_data.set<TypeField>(type);
229 m_data.set<ModeField>(mode);
230 m_data.set<NameIndexField>(nameIndex);
231 }
232
233private:
236 // 1 bit left
238 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
239};
240static_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");
241
243{
245
246 void set(quint32 nameOffset, bool isAccessor)
247 {
248 m_data.set<NameOffsetField>(nameOffset);
249 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
250 }
251
252 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
253 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
254
255private:
258 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
259};
260static_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");
261
263{
265 // JSClassMember[nMembers]
266
267 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
268};
269static_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");
270
271struct String
272{
274
275 static int calculateSize(const QString &str) {
276 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
277 // would already break in other parts of the compilation process
278 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
279 }
280};
281
282static_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");
283
286 qint32_le line; // signed because debug instructions get negative line numbers
288};
289static_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");
290
291struct Block
292{
297
298 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
299
300 static int calculateSize(int nLocals) {
301 int trailingData = nLocals*sizeof (quint32);
302 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
303 Q_ASSERT(size < INT_MAX);
304 return int(size);
305 }
306
307 static size_t align(size_t a) {
308 return (a + 7) & ~size_t(7);
309 }
310};
311static_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");
312
313enum class NamedBuiltin: unsigned int {
315};
316
317enum class CommonType : unsigned int {
318 // Actual named builtins
328
329 // Optimization for very common other types
331
332 // No type specified or not recognized
334};
335
337{
338 enum Flag {
339 NoFlag = 0x0,
340 Common = 0x1,
341 List = 0x2,
342 };
344
345 void set(Flags flags, quint32 typeNameIndexOrCommonType)
346 {
347 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
348 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
349 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
350 }
351
352 bool indexIsCommonType() const
353 {
354 return m_data.get<IndexIsCommonTypeField>() != 0;
355 }
356
357 bool isList() const
358 {
359 return m_data.get<IsListField>() != 0;
360 }
361
363 {
364 return m_data.get<TypeNameIndexOrCommonTypeField>();
365 }
366
367private:
371 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
372};
373static_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");
374
380static_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");
381
382// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
383// for unaligned access. The ordering of the fields is also from largest to smallest.
385{
386 enum Flags : unsigned int {
387 IsStrict = 0x1,
391 };
392
393 // Absolute offset into file where the code for this function is located.
396
400 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
405 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
406 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
407
411
415
417 {
418 return lineAndStatementNumberOffset() + nLineAndStatementNumbers * sizeof(CodeOffsetToLineAndStatement);
419 }
420
421 // Keep all unaligned data at the end
424
425 // quint32 formalsIndex[nFormals]
426 // quint32 localsIndex[nLocals]
427
428 const Parameter *formalsTable() const
429 {
430 return reinterpret_cast<const Parameter *>(
431 reinterpret_cast<const char *>(this) + formalsOffset);
432 }
433 const quint32_le *localsTable() const
434 {
435 return reinterpret_cast<const quint32_le *>(
436 reinterpret_cast<const char *>(this) + localsOffset);
437 }
439 {
440 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
441 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
442 }
443
444 // --- QQmlPropertyCacheCreator interface
445 const Parameter *formalsBegin() const { return formalsTable(); }
446 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
447 // ---
448
449 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
450
451 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
452
453 static int calculateSize(
454 int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
455 {
456 const size_t trailingData = nFormals * sizeof(Parameter)
457 + (nLocals + labelInfoSize) * sizeof (quint32)
458 + nLinesAndStatements * sizeof(CodeOffsetToLineAndStatement);
459 size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
460 Q_ASSERT(size < INT_MAX);
461 return int(size);
462 }
463
464 static size_t align(size_t a) {
465 return (a + 7) & ~size_t(7);
466 }
467};
468static_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");
469
481static_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");
482
483struct Class
484{
491
492 const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
493
494 static int calculateSize(int nStaticMethods, int nMethods) {
495 int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
496 size_t size = align(sizeof(Class) + trailingData);
497 Q_ASSERT(size < INT_MAX);
498 return int(size);
499 }
500
501 static size_t align(size_t a) {
502 return (a + 7) & ~size_t(7);
503 }
504};
505static_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");
506
508{
510
511 static int calculateSize(int size) {
512 int trailingData = 2 * size * sizeof(quint32_le);
513 size_t s = align(sizeof(TemplateObject) + trailingData);
514 Q_ASSERT(s < INT_MAX);
515 return int(s);
516 }
517
518 static size_t align(size_t a) {
519 return (a + 7) & ~size_t(7);
520 }
521
522 const quint32_le *stringTable() const {
523 return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1));
524 }
525
526 uint stringIndexAt(uint i) const {
527 return stringTable()[i];
528 }
529 uint rawStringIndexAt(uint i) const {
530 return stringTable()[size + i];
531 }
532};
533static_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");
534
543static_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");
544
552static_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");
553
554// Qml data structures
555
564static_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");
565
567{
569
583
598
602
603 void clearFlags() { flagsAndType.set<FlagsField>(0); }
604 void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); }
605 bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; }
606 Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); }
607
608 void setType(Type type) { flagsAndType.set<TypeField>(type); }
609 Type type() const { return Type(flagsAndType.get<TypeField>()); }
610
611 union {
612 bool b;
614 quint32_le compiledScriptIndex; // used when Type_Script
616 quint32_le translationDataIndex; // used when Type_Translation
618 } value;
619 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
620
623
625 {
626 const Flags bindingFlags = flags();
627 return bindingFlags & IsSignalHandlerExpression
628 || bindingFlags & IsSignalHandlerObject
629 || bindingFlags & IsPropertyObserver;
630 }
631
632 bool isValueBinding() const
633 {
634 switch (type()) {
637 return false;
638 default:
640 }
641 }
642
645
646 bool isSignalHandler() const
647 {
649 Q_ASSERT(!isValueBinding());
650 Q_ASSERT(!isAttachedProperty());
651 Q_ASSERT(!isGroupProperty());
652 return true;
653 }
654 return false;
655 }
656
658 {
660 Q_ASSERT(!isValueBinding());
661 Q_ASSERT(!isSignalHandler());
662 Q_ASSERT(!isGroupProperty());
663 return true;
664 }
665 return false;
666 }
667
668 bool isGroupProperty() const
669 {
670 if (type() == Type_GroupProperty) {
671 Q_ASSERT(!isValueBinding());
672 Q_ASSERT(!isSignalHandler());
673 Q_ASSERT(!isAttachedProperty());
674 return true;
675 }
676 return false;
677 }
678
680
681 //reverse of Lexer::singleEscape()
682 static QString escapedString(const QString &string)
683 {
684 QString tmp = QLatin1String("\"");
685 for (int i = 0; i < string.size(); ++i) {
686 const QChar &c = string.at(i);
687 switch (c.unicode()) {
688 case 0x08:
689 tmp += QLatin1String("\\b");
690 break;
691 case 0x09:
692 tmp += QLatin1String("\\t");
693 break;
694 case 0x0A:
695 tmp += QLatin1String("\\n");
696 break;
697 case 0x0B:
698 tmp += QLatin1String("\\v");
699 break;
700 case 0x0C:
701 tmp += QLatin1String("\\f");
702 break;
703 case 0x0D:
704 tmp += QLatin1String("\\r");
705 break;
706 case 0x22:
707 tmp += QLatin1String("\\\"");
708 break;
709 case 0x27:
710 tmp += QLatin1String("\\\'");
711 break;
712 case 0x5C:
713 tmp += QLatin1String("\\\\");
714 break;
715 default:
716 tmp += c;
717 break;
718 }
719 }
720 tmp += QLatin1Char('\"');
721 return tmp;
722 }
723
725 {
726 const Binding::Type bindingType = type();
727 return bindingType == Type_Translation || bindingType == Type_TranslationById;
728 }
730
731 bool isNumberBinding() const { return type() == Type_Number; }
732
733 bool valueAsBoolean() const
734 {
735 if (type() == Type_Boolean)
736 return value.b;
737 return false;
738 }
739};
740
741static_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");
742
749
750static_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");
751
757static_assert(sizeof(EnumValue) == 8, "EnumValue structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
758
759struct Enum
760{
764
765 const EnumValue *enumValueAt(int idx) const {
766 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
767 }
768
769 static int calculateSize(int nEnumValues) {
770 return (sizeof(Enum)
771 + nEnumValues * sizeof(EnumValue)
772 + 7) & ~0x7;
773 }
774
775 // --- QQmlPropertyCacheCreatorInterface
776 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
777 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
778 int enumValueCount() const { return nEnumValues; }
779 // ---
780};
781static_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");
782
783struct Signal
784{
788 // Parameter parameters[1];
789
790 const Parameter *parameterAt(int idx) const {
791 return reinterpret_cast<const Parameter*>(this + 1) + idx;
792 }
793
794 static int calculateSize(int nParameters) {
795 return (sizeof(Signal)
796 + nParameters * sizeof(Parameter)
797 + 7) & ~0x7;
798 }
799
800 // --- QQmlPropertyCacheCceatorInterface
801 const Parameter *parametersBegin() const { return parameterAt(0); }
802 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
803 int parameterCount() const { return nParameters; }
804 // ---
805};
806static_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");
807
808/*
809 * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
810 * for each index.
811 *
812 * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
813 * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
814 * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
815 * to mention the amount of memory needed to maintain such a StringTableGenerator.
816 * Therefore, after some preliminary analysis, it seems that even 20 bits
817 * should be a rather conservative cap.
818 *
819 * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
820 * unions like, let's say nameIndexAndAttributes.
821 *
822 * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
823 *
824 * NameIndexField IsVirtualField IsOverrideField IsFinalField
825 * |10100000101000111000001110000| 0 | 1 | 0 |
826 *
827 */
829{
830private:
835
841
842public:
852
853 quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
854 void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
855
856 bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
857 void setIsVirtual(bool isVirtual)
858 {
859 nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
860 }
861
862 bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
863 void setIsOverride(bool isOverride)
864 {
865 nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
866 }
867
868 bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
869 void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
870
872 {
873 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
874 data.set<IsCommonTypeField>(true);
875 }
876
878 if (isCommonType())
879 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
880 return CommonType::Invalid;
881 }
882
883 void setTypeNameIndex(int nameIndex)
884 {
885 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
886 data.set<IsCommonTypeField>(false);
887 }
888
889 int typeNameIndex() const
890 {
891 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
892 }
893
894 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
895 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
896
897 bool isList() const { return data.get<IsListField>(); }
898 void setIsList(bool isList) { data.set<IsListField>(isList); }
899
900 bool isRequired() const { return data.get<IsRequiredField>(); }
901 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
902
903 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
904 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
905};
906static_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");
907
911
912static_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");
913
914struct Alias
915{
916 bool isReadOnly() const { return m_nameIndexAndFlags.get<IsReadOnlyField>(); }
917 void setIsReadOnly(bool isReadOnly) { m_nameIndexAndFlags.set<IsReadOnlyField>(isReadOnly); }
918
919 quint32 nameIndex() const { return m_nameIndexAndFlags.get<NameIndexField>(); }
920 void setNameIndex(quint32 nameIndex)
921 {
922 m_nameIndexAndFlags.set<NameIndexField>(nameIndex);
923 }
924
925 quint32 idIndex() const { return m_idIndexField; }
926 void setIdIndex(quint32 idIndex) { m_idIndexField = idIndex; }
927
928 quint32 propertyNameIndex() const { return m_propertyNameIndex; }
929 void setPropertyNameIndex(quint32 propertyNameIndex)
930 {
931 m_propertyNameIndex = propertyNameIndex;
932 }
933
934 Location location() const { return m_location; }
935 void setLocation(Location location) { m_location = location; }
936
937 Location referenceLocation() const { return m_referenceLocation; }
938 void setReferenceLocation(Location referenceLocation)
939 {
940 m_referenceLocation = referenceLocation;
941 }
942
943private:
946
947 quint32_le_bitfield_union<NameIndexField, IsReadOnlyField> m_nameIndexAndFlags;
948 quint32_le m_idIndexField;
949 quint32_le m_propertyNameIndex; // string index
950 Location m_location;
951 Location m_referenceLocation;
952};
953static_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");
954
955struct Object
956{
957private:
961public:
962 enum Flag : unsigned int {
963 NoFlag = 0x0,
964 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
965 HasDeferredBindings = 0x2, // any of the bindings are deferred
969 };
971
972 // Depending on the use, this may be the type name to instantiate before instantiating this
973 // object. For grouped properties the type name will be empty and for attached properties
974 // it will be the name of the attached type.
979 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
987 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
988 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
1000// Function[]
1001// Property[]
1002// Signal[]
1003// Binding[]
1004// InlineComponent[]
1005// RequiredPropertyExtraData[]
1006
1007 Flags flags() const
1008 {
1009 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1010 }
1011
1012 bool hasFlag(Flag flag) const
1013 {
1014 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1015 }
1016
1017 void setFlag(Flag flag)
1018 {
1019 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1020 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1021 }
1022
1023 void setFlags(Flags flags)
1024 {
1025 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1026 }
1027
1029 {
1030 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1031 }
1032
1033 void setHasAliasAsDefaultProperty(bool defaultAlias)
1034 {
1035 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1036 }
1037
1039 {
1040 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1041 }
1042
1043 void setObjectId(qint32 id)
1044 {
1045 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1046 }
1047
1048
1049 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1050 {
1051 return ( sizeof(Object)
1052 + nFunctions * sizeof(quint32)
1053 + nProperties * sizeof(Property)
1054 + nAliases * sizeof(Alias)
1055 + nEnums * sizeof(quint32)
1056 + nSignals * sizeof(quint32)
1057 + nBindings * sizeof(Binding)
1058 + nNamedObjectsInComponent * sizeof(int)
1059 + nInlineComponents * sizeof(InlineComponent)
1060 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1061 + 0x7
1062 ) & ~0x7;
1063 }
1064
1066 {
1067 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1068 }
1069
1071 {
1072 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1073 }
1074
1075 const Alias *aliasTable() const
1076 {
1077 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1078 }
1079
1080 const Binding *bindingTable() const
1081 {
1082 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1083 }
1084
1085 const Enum *enumAt(int idx) const
1086 {
1087 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1088 const quint32_le offset = offsetTable[idx];
1089 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1090 }
1091
1092 const Signal *signalAt(int idx) const
1093 {
1094 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1095 const quint32_le offset = offsetTable[idx];
1096 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1097 }
1098
1100 {
1101 return inlineComponentTable() + idx;
1102 }
1103
1105 {
1106 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1107 }
1108
1110 {
1111 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1112 }
1113
1118
1120 {
1121 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1122 }
1123
1124 // --- QQmlPropertyCacheCreator interface
1125 int propertyCount() const { return nProperties; }
1126 int aliasCount() const { return nAliases; }
1127 int enumCount() const { return nEnums; }
1128 int signalCount() const { return nSignals; }
1129 int functionCount() const { return nFunctions; }
1130 int inlineComponentCount() const { return nInlineComponents; }
1131
1132 const Binding *bindingsBegin() const { return bindingTable(); }
1133 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1134 int bindingCount() const { return nBindings; }
1135
1136 const Property *propertiesBegin() const { return propertyTable(); }
1137 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1138
1139 const Alias *aliasesBegin() const { return aliasTable(); }
1140 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1141
1143 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1144 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1145
1147 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1148 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1149
1151 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1152 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1153
1155 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1156 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1157
1158 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1159 // ---
1160};
1161static_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");
1162
1164{
1165 enum ImportType : unsigned int {
1170 };
1172
1175
1179
1181 {
1182 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1183 }
1184};
1185static_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");
1186
1188{
1193
1194 const Import *importAt(int idx) const {
1195 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1196 }
1197
1198 const Object *objectAt(int idx) const {
1199 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1200 const quint32_le offset = offsetTable[idx];
1201 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1202 }
1203};
1204static_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");
1205
1206static const char magic_str[] = "qv4cdata";
1207
1208struct Unit
1209{
1210 // DO NOT CHANGE THESE FIELDS EVER
1211 char magic[8];
1213 // END DO NOT CHANGE THESE FIELDS EVER
1214
1215 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1217 quint32_le unitSize; // Size of the Unit and any depending data.
1218
1219 char md5Checksum[16]; // checksum of all bytes following this field.
1221
1222 enum : unsigned int {
1224 StaticData = 0x2, // Unit data persistent in memory?
1226 IsSharedLibrary = 0x8, // .pragma shared?
1228 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1229 IsStrict = 0x40,
1240 };
1275
1277
1278 /* QML specific fields */
1279
1280 const QmlUnit *qmlUnit() const {
1281 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1282 }
1283
1285 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1286 }
1287
1288 bool isSingleton() const {
1289 return flags & Unit::IsSingleton;
1290 }
1291 /* end QML specific fields*/
1292
1293 QString stringAtInternal(uint idx) const {
1294 Q_ASSERT(idx < stringTableSize);
1295 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1296 const quint32_le offset = offsetTable[idx];
1297 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1298 Q_ASSERT(str->size >= 0);
1299#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1300 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1301 if (flags & StaticData)
1302 return QString::fromRawData(characters, str->size);
1303 return QString(characters, str->size);
1304#else
1305 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1306 QString qstr(str->size, Qt::Uninitialized);
1307 QChar *ch = qstr.data();
1308 for (int i = 0; i < str->size; ++i)
1309 ch[i] = QChar(quint16(characters[i]));
1310 return qstr;
1311#endif
1312 }
1313
1314 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1315 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1316 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1317 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1318
1319 const Function *functionAt(int idx) const {
1320 const quint32_le *offsetTable = functionOffsetTable();
1321 const quint32_le offset = offsetTable[idx];
1322 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1323 }
1324
1325 const Class *classAt(int idx) const {
1326 const quint32_le *offsetTable = classOffsetTable();
1327 const quint32_le offset = offsetTable[idx];
1328 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1329 }
1330
1331 const TemplateObject *templateObjectAt(int idx) const {
1332 const quint32_le *offsetTable = templateObjectOffsetTable();
1333 const quint32_le offset = offsetTable[idx];
1334 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1335 }
1336
1337 const Block *blockAt(int idx) const {
1338 const quint32_le *offsetTable = blockOffsetTable();
1339 const quint32_le offset = offsetTable[idx];
1340 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1341 }
1342
1343 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1344 const RegExp *regexpAt(int index) const {
1345 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1346 }
1347 const quint64_le *constants() const {
1348 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1349 }
1350
1351 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1352 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1353 const quint32_le offset = offsetTable[idx];
1354 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1355 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1356 *nMembers = klass->nMembers;
1357 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1358 }
1359
1361 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1362 }
1363
1365 if ( translationTableSize == 0)
1366 return nullptr;
1367 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1368 + offsetToTranslationTable
1369 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1370
1372 if ( translationTableSize == 0)
1373 return nullptr;
1374 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1375 + offsetToTranslationTable
1376 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1377
1378 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1379 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1380 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1381 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1382
1383 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1384
1385 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1386};
1387
1388static_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");
1389
1391{
1393 : location(loc)
1394 , needsCreation(false)
1395 , errorWhenNotFound(false)
1396 {}
1397 Location location; // first use
1398 bool needsCreation : 1; // whether the type needs to be creatable or not
1400};
1401
1402// Map from name index to location of first use.
1404{
1405 TypeReference &add(int nameIndex, const Location &loc) {
1406 Iterator it = find(nameIndex);
1407 if (it != end())
1408 return *it;
1409 return *insert(nameIndex, loc);
1410 }
1411
1412 template <typename CompiledObject>
1413 void collectFromObject(const CompiledObject *obj)
1414 {
1415 if (obj->inheritedTypeNameIndex != 0) {
1416 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1417 r.needsCreation = true;
1418 r.errorWhenNotFound = true;
1419 }
1420
1421 auto binding = obj->bindingsBegin();
1422 auto const bindingEnd = obj->bindingsEnd();
1423 for ( ; binding != bindingEnd; ++binding) {
1425 this->add(binding->propertyNameIndex, binding->location);
1426 }
1427
1428 auto ic = obj->inlineComponentsBegin();
1429 auto const icEnd = obj->inlineComponentsEnd();
1430 for (; ic != icEnd; ++ic) {
1431 this->add(ic->nameIndex, ic->location);
1432 }
1433 }
1434
1435 template <typename Iterator>
1436 void collectFromObjects(Iterator it, Iterator end)
1437 {
1438 for (; it != end; ++it)
1439 collectFromObject(*it);
1440 }
1441};
1442
1444
1446
1448 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1449 : qmlType(qmlType)
1450 , objectIndex(objectIndex)
1451 , nameIndex(nameIndex)
1452 {}
1453
1454 QQmlType qmlType;
1455 int objectIndex = -1;
1456 int nameIndex = -1;
1457};
1458
1460{
1462
1463 const Unit *data = nullptr;
1464 const QmlUnit *qmlData = nullptr;
1467
1468 // pointers either to data->constants() or little-endian memory copy.
1469 const StaticValue *constants = nullptr;
1470
1472
1474
1475 // index is object index. This allows fast access to the
1476 // property data when initializing bindings, avoiding expensive
1477 // lookups by string (property name).
1479
1482
1484
1485 QQmlType qmlType;
1486
1488
1489public:
1490 // --- interface for QQmlPropertyCacheCreator
1494
1495 // Empty dummy. We don't need to do this when loading from cache.
1497 {
1498 public:
1499 void insert(int, int) {}
1500 void clear() {}
1501
1502 // We have already checked uniqueness of IDs when creating the CU
1503 bool contains(int) { return false; }
1504 };
1505
1506 explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1507 const QString &fileName = QString(), const QString &finalUrlString = QString())
1508 : CompilationUnit(unitData, fileName, finalUrlString)
1509 {
1510 this->aotCompiledFunctions = aotCompiledFunctions;
1511 }
1512
1514 const Unit *unitData = nullptr, const QString &fileName = QString(),
1515 const QString &finalUrlString = QString());
1516
1518
1519 const Unit *unitData() const { return data; }
1520
1521 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1522 const QString &fileName = QString(), const QString &finalUrlString = QString())
1523 {
1524 data = unitData;
1525 qmlData = nullptr;
1526#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1527 delete [] constants;
1528#endif
1529 constants = nullptr;
1530 m_fileName.clear();
1531 m_finalUrlString.clear();
1532 if (!data)
1533 return;
1534
1535 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1536
1537#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1538 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1539 const quint64_le *littleEndianConstants = data->constants();
1540 for (uint i = 0; i < data->constantTableSize; ++i)
1541 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1542 constants = bigEndianConstants;
1543#else
1544 constants = reinterpret_cast<const StaticValue*>(data->constants());
1545#endif
1546
1547 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1548 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1549 }
1550
1551 QString stringAt(uint index) const
1552 {
1553 if (index < data->stringTableSize)
1554 return data->stringAtInternal(index);
1555
1556 const qsizetype dynamicIndex = index - data->stringTableSize;
1557 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1558 return dynamicStrings.at(dynamicIndex);
1559 }
1560
1561 QString fileName() const { return m_fileName; }
1562 QString finalUrlString() const { return m_finalUrlString; }
1563
1565 {
1566 using namespace CompiledData;
1567 switch (binding->type()) {
1568 case Binding::Type_Script:
1569 case Binding::Type_String:
1570 return stringAt(binding->stringIndex);
1571 case Binding::Type_Null:
1572 return QStringLiteral("null");
1574 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1575 case Binding::Type_Number:
1576 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1578 return QString();
1579 case Binding::Type_TranslationById:
1580 case Binding::Type_Translation:
1581 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1582 default:
1583 break;
1584 }
1585 return QString();
1586 }
1587
1589 {
1590 return (binding->type() == CompiledData::Binding::Type_String)
1591 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1592 : bindingValueAsString(binding);
1593 }
1594
1595 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1596 {
1598 return 0.0;
1599 return constants[binding->value.constantValueIndex].doubleValue();
1600 }
1601
1602 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1604 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1605 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1606
1607 int importCount() const { return qmlData->nImports; }
1608 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1609
1610 Q_QML_EXPORT QStringList moduleRequests() const;
1611
1612 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1613 // warnings about that code. They include any potential URL interceptions and thus represent the
1614 // "physical" location of the code.
1615 //
1616 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1617 // They are _not_ intercepted and thus represent the "logical" name for the code.
1618
1619 QUrl url() const
1620 {
1621 if (!m_url.isValid())
1622 m_url = QUrl(fileName());
1623 return m_url;
1624 }
1625
1627 {
1628 if (!m_finalUrl.isValid())
1629 m_finalUrl = QUrl(finalUrlString());
1630 return m_finalUrl;
1631 }
1632
1633 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1634 ResolvedTypeReference *resolvedType(QMetaType type) const;
1635
1637 {
1638 return propertyCaches.isEmpty()
1639 ? QQmlPropertyCache::ConstPtr()
1640 : propertyCaches.at(/*root object*/0);
1641 }
1642
1643 int objectCount() const { return qmlData->nObjects; }
1644
1645 // Resolves implicit component wrapper indices (>= objectCount()) to the
1646 // wrapped child object index. Returns the index unchanged for real objects.
1647 int resolvedIndex(int index) const
1648 {
1649 if (index < objectCount())
1650 return index;
1651 const QQmlPropertyData *p = propertyCaches.at(index)->defaultProperty();
1652 Q_ASSERT(p && p->isComponentWrapper());
1653 return p->wrappedObjectIndex();
1654 }
1655
1656 const CompiledObject *objectAt(int index) const
1657 {
1659 }
1660
1661 // Returns the index of the implicit component wrapper, or -1.
1662 // Scans property caches at indices >= objectCount().
1663 int implicitComponentForObject(int index) const
1664 {
1665 for (int i = objectCount(), end = propertyCaches.count(); i < end; ++i) {
1666 const QQmlPropertyData *p = propertyCaches.at(i)->defaultProperty();
1667 Q_ASSERT(p && p->isComponentWrapper());
1668 if (p->wrappedObjectIndex() == index)
1669 return i;
1670 }
1671 return -1;
1672 }
1673
1674 int inlineComponentId(const QString &inlineComponentName) const
1675 {
1676 for (uint i = 0; i < qmlData->nObjects; ++i) {
1677 auto *object = qmlData->objectAt(i);
1678 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1679 it != end; ++it) {
1680 if (stringAt(it->nameIndex) == inlineComponentName)
1681 return it->objectIndex;
1682 }
1683 }
1684 return -1;
1685 }
1686
1687 void finalizeCompositeType(const QQmlType &type);
1688
1689 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1690
1700
1705
1710
1712 {
1714 }
1715
1720
1722 {
1724 }
1725
1727 {
1729 }
1730
1731 bool isESModule() const
1732 {
1734 }
1735
1736 bool isSharedLibrary() const
1737 {
1739 }
1740
1742 {
1743 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1744 : unit(unit), object(object), index(index) {}
1748
1750 {
1751 return unit->functionAt(object->functionOffsetTable()[index]);
1752 }
1753
1754 void operator++() { ++index; }
1755 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1756 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1757 };
1758
1760 {
1761 return FunctionIterator(unitData(), object, 0);
1762 }
1763
1765 {
1766 return FunctionIterator(unitData(), object, object->nFunctions);
1767 }
1768
1769 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1770 QMetaType metaType() const { return qmlType.typeId(); }
1771
1772private:
1773 QString m_fileName; // initialized from data->sourceFileIndex
1774 QString m_finalUrlString; // initialized from data->finalUrlIndex
1775
1776 mutable QQmlNullableValue<QUrl> m_url;
1777 mutable QQmlNullableValue<QUrl> m_finalUrl;
1778};
1779
1781{
1783public:
1789
1791
1792 template<typename Char>
1793 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1794 {
1795 const quint32_le oldFlags = mutableFlags();
1796 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1797 mutableFlags() |= temporaryFlags;
1798 return writer(data<Char>(), size());
1799 }
1800
1801 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1802 QString *errorString)
1803 {
1804#if QT_CONFIG(temporaryfile)
1805 QSaveFile cacheFile(outputFileName);
1806 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1807 || cacheFile.write(data, size) != size
1808 || !cacheFile.commit()) {
1809 *errorString = cacheFile.errorString();
1810 return false;
1811 }
1812
1813 errorString->clear();
1814 return true;
1815#else
1816 Q_UNUSED(outputFileName);
1817 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1818 return false;
1819#endif
1820 }
1821
1822private:
1823 const Unit *unit;
1824 quint32 temporaryFlags;
1825
1826 quint32_le &mutableFlags() const
1827 {
1828 return const_cast<Unit *>(unit)->flags;
1829 }
1830
1831 template<typename Char>
1832 const Char *data() const
1833 {
1834 Q_STATIC_ASSERT(sizeof(Char) == 1);
1835 const Char *dataPtr;
1836 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1837 return dataPtr;
1838 }
1839
1840 quint32 size() const
1841 {
1842 return unit->unitSize;
1843 }
1844};
1845
1846
1847} // CompiledData namespace
1848} // QV4 namespace
1849
1852
1853QT_END_NAMESPACE
1854
1855#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
Combined button and popup list for selecting options.
static const char magic_str[]
Definition qjsvalue.h:24
Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE)
#define QV4_DATA_STRUCTURE_VERSION
Q_DECLARE_OPERATORS_FOR_FLAGS(QV4::CompiledData::ParameterType::Flags)
void setPropertyNameIndex(quint32 propertyNameIndex)
quint32 propertyNameIndex() const
void setIsReadOnly(bool isReadOnly)
void setReferenceLocation(Location referenceLocation)
void setNameIndex(quint32 nameIndex)
Location referenceLocation() const
void setIdIndex(quint32 idIndex)
void setLocation(Location location)
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
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const
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)
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())
int implicitComponentForObject(int index) const
ResolvedTypeReferenceMap resolvedTypes
QList< BindingPropertyData > bindingPropertyDataPerObject
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
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
QList< QQmlRefPointer< QQmlScriptData > > dependentScripts
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
size_t lineAndStatementNumberOffset() const
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
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)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool comparesEqual(const Location &a, const Location &b) noexcept
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)
void setIsVirtual(bool isVirtual)
quint32_le_bitfield_union< CommonTypeOrTypeNameIndexField, IsRequiredField, IsCommonTypeField, IsListField, IsReadOnlyField > data
quint32_le_bitfield_union< NameIndexField, IsVirtualField, IsOverrideField, IsFinalField > nameIndexAndVirtSpecifiers
void setIsOverride(bool isOverride)
void setIsRequired(bool isRequired)
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)
TableIterator operator+(int offset) const
const ItemType * operator->() const
int operator-(TableIterator other) const
TableIterator operator-(int offset) const
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