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 0x4e // Store resolved enum values inline in bindings
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 qint32_le resolvedEnumValue; // used when Type_Number and IsResolvedEnum: enum values are
615 // integers and stored inline rather than in the constant table
616 quint32_le compiledScriptIndex; // used when Type_Script
618 quint32_le translationDataIndex; // used when Type_Translation
620 } value;
621 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
622
625
627 {
628 const Flags bindingFlags = flags();
629 return bindingFlags & IsSignalHandlerExpression
630 || bindingFlags & IsSignalHandlerObject
631 || bindingFlags & IsPropertyObserver;
632 }
633
634 bool isValueBinding() const
635 {
636 switch (type()) {
639 return false;
640 default:
642 }
643 }
644
647
648 bool isSignalHandler() const
649 {
651 Q_ASSERT(!isValueBinding());
652 Q_ASSERT(!isAttachedProperty());
653 Q_ASSERT(!isGroupProperty());
654 return true;
655 }
656 return false;
657 }
658
660 {
662 Q_ASSERT(!isValueBinding());
663 Q_ASSERT(!isSignalHandler());
664 Q_ASSERT(!isGroupProperty());
665 return true;
666 }
667 return false;
668 }
669
670 bool isGroupProperty() const
671 {
672 if (type() == Type_GroupProperty) {
673 Q_ASSERT(!isValueBinding());
674 Q_ASSERT(!isSignalHandler());
675 Q_ASSERT(!isAttachedProperty());
676 return true;
677 }
678 return false;
679 }
680
682
683 //reverse of Lexer::singleEscape()
684 static QString escapedString(const QString &string)
685 {
686 QString tmp = QLatin1String("\"");
687 for (int i = 0; i < string.size(); ++i) {
688 const QChar &c = string.at(i);
689 switch (c.unicode()) {
690 case 0x08:
691 tmp += QLatin1String("\\b");
692 break;
693 case 0x09:
694 tmp += QLatin1String("\\t");
695 break;
696 case 0x0A:
697 tmp += QLatin1String("\\n");
698 break;
699 case 0x0B:
700 tmp += QLatin1String("\\v");
701 break;
702 case 0x0C:
703 tmp += QLatin1String("\\f");
704 break;
705 case 0x0D:
706 tmp += QLatin1String("\\r");
707 break;
708 case 0x22:
709 tmp += QLatin1String("\\\"");
710 break;
711 case 0x27:
712 tmp += QLatin1String("\\\'");
713 break;
714 case 0x5C:
715 tmp += QLatin1String("\\\\");
716 break;
717 default:
718 tmp += c;
719 break;
720 }
721 }
722 tmp += QLatin1Char('\"');
723 return tmp;
724 }
725
727 {
728 const Binding::Type bindingType = type();
729 return bindingType == Type_Translation || bindingType == Type_TranslationById;
730 }
732
733 bool isNumberBinding() const { return type() == Type_Number; }
734
735 bool valueAsBoolean() const
736 {
737 if (type() == Type_Boolean)
738 return value.b;
739 return false;
740 }
741};
742
743static_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");
744
751
752static_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");
753
759static_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");
760
761struct Enum
762{
766
767 const EnumValue *enumValueAt(int idx) const {
768 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
769 }
770
771 static int calculateSize(int nEnumValues) {
772 return (sizeof(Enum)
773 + nEnumValues * sizeof(EnumValue)
774 + 7) & ~0x7;
775 }
776
777 // --- QQmlPropertyCacheCreatorInterface
778 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
779 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
780 int enumValueCount() const { return nEnumValues; }
781 // ---
782};
783static_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");
784
785struct Signal
786{
790 // Parameter parameters[1];
791
792 const Parameter *parameterAt(int idx) const {
793 return reinterpret_cast<const Parameter*>(this + 1) + idx;
794 }
795
796 static int calculateSize(int nParameters) {
797 return (sizeof(Signal)
798 + nParameters * sizeof(Parameter)
799 + 7) & ~0x7;
800 }
801
802 // --- QQmlPropertyCacheCceatorInterface
803 const Parameter *parametersBegin() const { return parameterAt(0); }
804 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
805 int parameterCount() const { return nParameters; }
806 // ---
807};
808static_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");
809
810/*
811 * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
812 * for each index.
813 *
814 * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
815 * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
816 * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
817 * to mention the amount of memory needed to maintain such a StringTableGenerator.
818 * Therefore, after some preliminary analysis, it seems that even 20 bits
819 * should be a rather conservative cap.
820 *
821 * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
822 * unions like, let's say nameIndexAndAttributes.
823 *
824 * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
825 *
826 * NameIndexField IsVirtualField IsOverrideField IsFinalField
827 * |10100000101000111000001110000| 0 | 1 | 0 |
828 *
829 */
831{
832private:
837
843
844public:
854
855 quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
856 void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
857
858 bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
859 void setIsVirtual(bool isVirtual)
860 {
861 nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
862 }
863
864 bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
865 void setIsOverride(bool isOverride)
866 {
867 nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
868 }
869
870 bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
871 void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
872
874 {
875 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
876 data.set<IsCommonTypeField>(true);
877 }
878
880 if (isCommonType())
881 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
882 return CommonType::Invalid;
883 }
884
885 void setTypeNameIndex(int nameIndex)
886 {
887 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
888 data.set<IsCommonTypeField>(false);
889 }
890
891 int typeNameIndex() const
892 {
893 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
894 }
895
896 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
897 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
898
899 bool isList() const { return data.get<IsListField>(); }
900 void setIsList(bool isList) { data.set<IsListField>(isList); }
901
902 bool isRequired() const { return data.get<IsRequiredField>(); }
903 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
904
905 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
906 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
907};
908static_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");
909
913
914static_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");
915
916struct Alias
917{
918 bool isReadOnly() const { return m_nameIndexAndFlags.get<IsReadOnlyField>(); }
919 void setIsReadOnly(bool isReadOnly) { m_nameIndexAndFlags.set<IsReadOnlyField>(isReadOnly); }
920
921 quint32 nameIndex() const { return m_nameIndexAndFlags.get<NameIndexField>(); }
922 void setNameIndex(quint32 nameIndex)
923 {
924 m_nameIndexAndFlags.set<NameIndexField>(nameIndex);
925 }
926
927 quint32 idIndex() const { return m_idIndexField; }
928 void setIdIndex(quint32 idIndex) { m_idIndexField = idIndex; }
929
930 quint32 propertyNameIndex() const { return m_propertyNameIndex; }
931 void setPropertyNameIndex(quint32 propertyNameIndex)
932 {
933 m_propertyNameIndex = propertyNameIndex;
934 }
935
936 Location location() const { return m_location; }
937 void setLocation(Location location) { m_location = location; }
938
939 Location referenceLocation() const { return m_referenceLocation; }
940 void setReferenceLocation(Location referenceLocation)
941 {
942 m_referenceLocation = referenceLocation;
943 }
944
945private:
948
949 quint32_le_bitfield_union<NameIndexField, IsReadOnlyField> m_nameIndexAndFlags;
950 quint32_le m_idIndexField;
951 quint32_le m_propertyNameIndex; // string index
952 Location m_location;
953 Location m_referenceLocation;
954};
955static_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");
956
957struct Object
958{
959private:
963public:
964 enum Flag : unsigned int {
965 NoFlag = 0x0,
966 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
967 HasDeferredBindings = 0x2, // any of the bindings are deferred
971 };
973
974 // Depending on the use, this may be the type name to instantiate before instantiating this
975 // object. For grouped properties the type name will be empty and for attached properties
976 // it will be the name of the attached type.
981 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
989 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
990 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
1002// Function[]
1003// Property[]
1004// Signal[]
1005// Binding[]
1006// InlineComponent[]
1007// RequiredPropertyExtraData[]
1008
1009 Flags flags() const
1010 {
1011 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1012 }
1013
1014 bool hasFlag(Flag flag) const
1015 {
1016 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1017 }
1018
1019 void setFlag(Flag flag)
1020 {
1021 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1022 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1023 }
1024
1025 void setFlags(Flags flags)
1026 {
1027 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1028 }
1029
1031 {
1032 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1033 }
1034
1035 void setHasAliasAsDefaultProperty(bool defaultAlias)
1036 {
1037 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1038 }
1039
1041 {
1042 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1043 }
1044
1045 void setObjectId(qint32 id)
1046 {
1047 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1048 }
1049
1050
1051 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1052 {
1053 return ( sizeof(Object)
1054 + nFunctions * sizeof(quint32)
1055 + nProperties * sizeof(Property)
1056 + nAliases * sizeof(Alias)
1057 + nEnums * sizeof(quint32)
1058 + nSignals * sizeof(quint32)
1059 + nBindings * sizeof(Binding)
1060 + nNamedObjectsInComponent * sizeof(int)
1061 + nInlineComponents * sizeof(InlineComponent)
1062 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1063 + 0x7
1064 ) & ~0x7;
1065 }
1066
1068 {
1069 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1070 }
1071
1073 {
1074 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1075 }
1076
1077 const Alias *aliasTable() const
1078 {
1079 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1080 }
1081
1082 const Binding *bindingTable() const
1083 {
1084 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1085 }
1086
1087 const Enum *enumAt(int idx) const
1088 {
1089 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1090 const quint32_le offset = offsetTable[idx];
1091 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1092 }
1093
1094 const Signal *signalAt(int idx) const
1095 {
1096 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1097 const quint32_le offset = offsetTable[idx];
1098 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1099 }
1100
1102 {
1103 return inlineComponentTable() + idx;
1104 }
1105
1107 {
1108 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1109 }
1110
1112 {
1113 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1114 }
1115
1120
1122 {
1123 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1124 }
1125
1126 // --- QQmlPropertyCacheCreator interface
1127 int propertyCount() const { return nProperties; }
1128 int aliasCount() const { return nAliases; }
1129 int enumCount() const { return nEnums; }
1130 int signalCount() const { return nSignals; }
1131 int functionCount() const { return nFunctions; }
1132 int inlineComponentCount() const { return nInlineComponents; }
1133
1134 const Binding *bindingsBegin() const { return bindingTable(); }
1135 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1136 int bindingCount() const { return nBindings; }
1137
1138 const Property *propertiesBegin() const { return propertyTable(); }
1139 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1140
1141 const Alias *aliasesBegin() const { return aliasTable(); }
1142 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1143
1145 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1146 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1147
1149 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1150 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1151
1153 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1154 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1155
1157 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1158 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1159
1160 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1161 // ---
1162};
1163static_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");
1164
1166{
1167 enum ImportType : unsigned int {
1172 };
1174
1177
1181
1183 {
1184 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1185 }
1186};
1187static_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");
1188
1190{
1195
1196 const Import *importAt(int idx) const {
1197 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1198 }
1199
1200 const Object *objectAt(int idx) const {
1201 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1202 const quint32_le offset = offsetTable[idx];
1203 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1204 }
1205};
1206static_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");
1207
1208static const char magic_str[] = "qv4cdata";
1209
1210struct Unit
1211{
1212 // DO NOT CHANGE THESE FIELDS EVER
1213 char magic[8];
1215 // END DO NOT CHANGE THESE FIELDS EVER
1216
1217 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1219 quint32_le unitSize; // Size of the Unit and any depending data.
1220
1221 char md5Checksum[16]; // checksum of all bytes following this field.
1223
1224 enum : unsigned int {
1226 StaticData = 0x2, // Unit data persistent in memory?
1228 IsSharedLibrary = 0x8, // .pragma shared?
1230 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1231 IsStrict = 0x40,
1242 };
1277
1279
1280 /* QML specific fields */
1281
1282 const QmlUnit *qmlUnit() const {
1283 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1284 }
1285
1287 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1288 }
1289
1290 bool isSingleton() const {
1291 return flags & Unit::IsSingleton;
1292 }
1293
1295 // ListPropertyAssignReplace is the combination of both replace bits, so it must be tested
1296 // for an exact match.
1297 return (flags & Unit::ListPropertyAssignReplace) == Unit::ListPropertyAssignReplace;
1298 }
1299
1301 return flags & Unit::ListPropertyAssignReplaceIfNotDefault;
1302 }
1303 /* end QML specific fields*/
1304
1305 QString stringAtInternal(uint idx) const {
1306 Q_ASSERT(idx < stringTableSize);
1307 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1308 const quint32_le offset = offsetTable[idx];
1309 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1310 Q_ASSERT(str->size >= 0);
1311#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1312 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1313 if (flags & StaticData)
1314 return QString::fromRawData(characters, str->size);
1315 return QString(characters, str->size);
1316#else
1317 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1318 QString qstr(str->size, Qt::Uninitialized);
1319 QChar *ch = qstr.data();
1320 for (int i = 0; i < str->size; ++i)
1321 ch[i] = QChar(quint16(characters[i]));
1322 return qstr;
1323#endif
1324 }
1325
1326 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1327 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1328 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1329 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1330
1331 const Function *functionAt(int idx) const {
1332 const quint32_le *offsetTable = functionOffsetTable();
1333 const quint32_le offset = offsetTable[idx];
1334 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1335 }
1336
1337 const Class *classAt(int idx) const {
1338 const quint32_le *offsetTable = classOffsetTable();
1339 const quint32_le offset = offsetTable[idx];
1340 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1341 }
1342
1343 const TemplateObject *templateObjectAt(int idx) const {
1344 const quint32_le *offsetTable = templateObjectOffsetTable();
1345 const quint32_le offset = offsetTable[idx];
1346 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1347 }
1348
1349 const Block *blockAt(int idx) const {
1350 const quint32_le *offsetTable = blockOffsetTable();
1351 const quint32_le offset = offsetTable[idx];
1352 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1353 }
1354
1355 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1356 const RegExp *regexpAt(int index) const {
1357 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1358 }
1359 const quint64_le *constants() const {
1360 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1361 }
1362
1363 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1364 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1365 const quint32_le offset = offsetTable[idx];
1366 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1367 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1368 *nMembers = klass->nMembers;
1369 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1370 }
1371
1373 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1374 }
1375
1377 if ( translationTableSize == 0)
1378 return nullptr;
1379 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1380 + offsetToTranslationTable
1381 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1382
1384 if ( translationTableSize == 0)
1385 return nullptr;
1386 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1387 + offsetToTranslationTable
1388 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1389
1390 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1391 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1392 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1393 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1394
1395 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1396
1397 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1398};
1399
1400static_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");
1401
1403{
1405 : location(loc)
1406 , needsCreation(false)
1407 , errorWhenNotFound(false)
1408 {}
1409 Location location; // first use
1410 bool needsCreation : 1; // whether the type needs to be creatable or not
1412};
1413
1414// Map from name index to location of first use.
1416{
1417 TypeReference &add(int nameIndex, const Location &loc) {
1418 Iterator it = find(nameIndex);
1419 if (it != end())
1420 return *it;
1421 return *insert(nameIndex, loc);
1422 }
1423
1424 template <typename CompiledObject>
1425 void collectFromObject(const CompiledObject *obj)
1426 {
1427 if (obj->inheritedTypeNameIndex != 0) {
1428 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1429 r.needsCreation = true;
1430 r.errorWhenNotFound = true;
1431 }
1432
1433 auto binding = obj->bindingsBegin();
1434 auto const bindingEnd = obj->bindingsEnd();
1435 for ( ; binding != bindingEnd; ++binding) {
1437 this->add(binding->propertyNameIndex, binding->location);
1438 }
1439
1440 auto ic = obj->inlineComponentsBegin();
1441 auto const icEnd = obj->inlineComponentsEnd();
1442 for (; ic != icEnd; ++ic) {
1443 this->add(ic->nameIndex, ic->location);
1444 }
1445 }
1446
1447 template <typename Iterator>
1448 void collectFromObjects(Iterator it, Iterator end)
1449 {
1450 for (; it != end; ++it)
1451 collectFromObject(*it);
1452 }
1453};
1454
1456
1458
1460 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1461 : qmlType(qmlType)
1462 , objectIndex(objectIndex)
1463 , nameIndex(nameIndex)
1464 {}
1465
1466 QQmlType qmlType;
1467 int objectIndex = -1;
1468 int nameIndex = -1;
1469};
1470
1472{
1474
1475 const Unit *data = nullptr;
1476 const QmlUnit *qmlData = nullptr;
1480
1481 // pointers either to data->constants() or little-endian memory copy.
1482 const StaticValue *constants = nullptr;
1483
1485
1487
1488 // index is object index. This allows fast access to the
1489 // property data when initializing bindings, avoiding expensive
1490 // lookups by string (property name).
1492
1495
1497
1498 QQmlType qmlType;
1499
1501
1502public:
1503 // --- interface for QQmlPropertyCacheCreator
1507
1508 // Empty dummy. We don't need to do this when loading from cache.
1510 {
1511 public:
1512 void insert(int, int) {}
1513 void clear() {}
1514
1515 // We have already checked uniqueness of IDs when creating the CU
1516 bool contains(int) { return false; }
1517 };
1518
1519 explicit CompilationUnit(const Unit *unitData,
1520 const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1521 LookupValidationFn validateLookupSignatures,
1522 const QString &fileName = QString(),
1523 const QString &finalUrlString = QString())
1524 : CompilationUnit(unitData, fileName, finalUrlString)
1525 {
1526 this->aotCompiledFunctions = aotCompiledFunctions;
1527 this->validateLookupSignatures = validateLookupSignatures;
1528 }
1529
1531 const Unit *unitData = nullptr, const QString &fileName = QString(),
1532 const QString &finalUrlString = QString());
1533
1535
1536 const Unit *unitData() const { return data; }
1537
1538 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1539 const QString &fileName = QString(), const QString &finalUrlString = QString())
1540 {
1541 data = unitData;
1542 qmlData = nullptr;
1543#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1544 delete [] constants;
1545#endif
1546 constants = nullptr;
1547 m_fileName.clear();
1548 m_finalUrlString.clear();
1549 if (!data)
1550 return;
1551
1552 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1553
1554#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1555 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1556 const quint64_le *littleEndianConstants = data->constants();
1557 for (uint i = 0; i < data->constantTableSize; ++i)
1558 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1559 constants = bigEndianConstants;
1560#else
1561 constants = reinterpret_cast<const StaticValue*>(data->constants());
1562#endif
1563
1564 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1565 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1566 }
1567
1568 QString stringAt(uint index) const
1569 {
1570 if (index < data->stringTableSize)
1571 return data->stringAtInternal(index);
1572
1573 const qsizetype dynamicIndex = index - data->stringTableSize;
1574 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1575 return dynamicStrings.at(dynamicIndex);
1576 }
1577
1578 QString fileName() const { return m_fileName; }
1579 QString finalUrlString() const { return m_finalUrlString; }
1580
1582 {
1583 using namespace CompiledData;
1584 switch (binding->type()) {
1585 case Binding::Type_Script:
1586 case Binding::Type_String:
1587 return stringAt(binding->stringIndex);
1588 case Binding::Type_Null:
1589 return QStringLiteral("null");
1591 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1592 case Binding::Type_Number:
1593 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1595 return QString();
1596 case Binding::Type_TranslationById:
1597 case Binding::Type_Translation:
1598 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1599 default:
1600 break;
1601 }
1602 return QString();
1603 }
1604
1606 {
1607 return (binding->type() == CompiledData::Binding::Type_String)
1608 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1609 : bindingValueAsString(binding);
1610 }
1611
1612 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1613 {
1615 return 0.0;
1617 return binding->value.resolvedEnumValue;
1618 return constants[binding->value.constantValueIndex].doubleValue();
1619 }
1620
1621 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1623 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1624 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1625
1626 int importCount() const { return qmlData->nImports; }
1627 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1628
1629 Q_QML_EXPORT QStringList moduleRequests() const;
1630
1631 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1632 // warnings about that code. They include any potential URL interceptions and thus represent the
1633 // "physical" location of the code.
1634 //
1635 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1636 // They are _not_ intercepted and thus represent the "logical" name for the code.
1637
1638 QUrl url() const
1639 {
1640 if (!m_url.isValid())
1641 m_url = QUrl(fileName());
1642 return m_url;
1643 }
1644
1646 {
1647 if (!m_finalUrl.isValid())
1648 m_finalUrl = QUrl(finalUrlString());
1649 return m_finalUrl;
1650 }
1651
1652 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1653 ResolvedTypeReference *resolvedType(QMetaType type) const;
1654
1656 {
1657 return propertyCaches.isEmpty()
1658 ? QQmlPropertyCache::ConstPtr()
1659 : propertyCaches.at(/*root object*/0);
1660 }
1661
1662 int objectCount() const { return qmlData->nObjects; }
1663
1664 // Resolves implicit component wrapper indices (>= objectCount()) to the
1665 // wrapped child object index. Returns the index unchanged for real objects.
1666 int resolvedIndex(int index) const
1667 {
1668 if (index < objectCount())
1669 return index;
1670 const QQmlPropertyData *p = propertyCaches.at(index)->defaultProperty();
1671 Q_ASSERT(p && p->isComponentWrapper());
1672 return p->wrappedObjectIndex();
1673 }
1674
1675 const CompiledObject *objectAt(int index) const
1676 {
1678 }
1679
1680 // Returns the index of the implicit component wrapper, or -1.
1681 // Scans property caches at indices >= objectCount().
1682 int implicitComponentForObject(int index) const
1683 {
1684 for (int i = objectCount(), end = propertyCaches.count(); i < end; ++i) {
1685 const QQmlPropertyData *p = propertyCaches.at(i)->defaultProperty();
1686 Q_ASSERT(p && p->isComponentWrapper());
1687 if (p->wrappedObjectIndex() == index)
1688 return i;
1689 }
1690 return -1;
1691 }
1692
1693 int inlineComponentId(const QString &inlineComponentName) const
1694 {
1695 for (uint i = 0; i < qmlData->nObjects; ++i) {
1696 auto *object = qmlData->objectAt(i);
1697 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1698 it != end; ++it) {
1699 if (stringAt(it->nameIndex) == inlineComponentName)
1700 return it->objectIndex;
1701 }
1702 }
1703 return -1;
1704 }
1705
1706 void finalizeCompositeType(const QQmlType &type);
1707
1708 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1709
1720
1725
1730
1732 {
1734 }
1735
1740
1742 {
1744 }
1745
1747 {
1749 }
1750
1751 bool isESModule() const
1752 {
1754 }
1755
1756 bool isSharedLibrary() const
1757 {
1759 }
1760
1762 {
1763 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1764 : unit(unit), object(object), index(index) {}
1768
1770 {
1771 return unit->functionAt(object->functionOffsetTable()[index]);
1772 }
1773
1774 void operator++() { ++index; }
1775 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1776 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1777 };
1778
1780 {
1781 return FunctionIterator(unitData(), object, 0);
1782 }
1783
1785 {
1786 return FunctionIterator(unitData(), object, object->nFunctions);
1787 }
1788
1789 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1790 QMetaType metaType() const { return qmlType.typeId(); }
1791
1792private:
1793 QString m_fileName; // initialized from data->sourceFileIndex
1794 QString m_finalUrlString; // initialized from data->finalUrlIndex
1795
1796 mutable QQmlNullableValue<QUrl> m_url;
1797 mutable QQmlNullableValue<QUrl> m_finalUrl;
1798};
1799
1801{
1803public:
1809
1811
1812 template<typename Char>
1813 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1814 {
1815 const quint32_le oldFlags = mutableFlags();
1816 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1817 mutableFlags() |= temporaryFlags;
1818 return writer(data<Char>(), size());
1819 }
1820
1821 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1822 QString *errorString)
1823 {
1824#if QT_CONFIG(temporaryfile)
1825 QSaveFile cacheFile(outputFileName);
1826 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1827 || cacheFile.write(data, size) != size
1828 || !cacheFile.commit()) {
1829 *errorString = cacheFile.errorString();
1830 return false;
1831 }
1832
1833 errorString->clear();
1834 return true;
1835#else
1836 Q_UNUSED(outputFileName);
1837 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1838 return false;
1839#endif
1840 }
1841
1842private:
1843 const Unit *unit;
1844 quint32 temporaryFlags;
1845
1846 quint32_le &mutableFlags() const
1847 {
1848 return const_cast<Unit *>(unit)->flags;
1849 }
1850
1851 template<typename Char>
1852 const Char *data() const
1853 {
1854 Q_STATIC_ASSERT(sizeof(Char) == 1);
1855 const Char *dataPtr;
1856 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1857 return dataPtr;
1858 }
1859
1860 quint32 size() const
1861 {
1862 return unit->unitSize;
1863 }
1864};
1865
1866
1867} // CompiledData namespace
1868} // QV4 namespace
1869
1872
1873QT_END_NAMESPACE
1874
1875#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
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
CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, LookupValidationFn validateLookupSignatures, const QString &fileName=QString(), const QString &finalUrlString=QString())
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 isListPropertyAssignReplaceIfNotDefault() 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
bool isListPropertyAssignReplace() 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