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/qversionnumber.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#define QV4_DATA_STRUCTURE_VERSION 0x4a // Removed run-time generated details from Alias
56
57class QIODevice;
58class QQmlTypeNameCache;
59class QQmlType;
60class QQmlEngine;
62class QQmlScriptData;
63
64namespace QQmlPrivate {
66}
67
68namespace QmlIR {
69struct Document;
70}
71
72namespace QV4 {
73namespace Heap {
74struct Module;
75struct String;
76struct InternalClass;
77};
78
79struct Function;
80class EvalISelFactory;
82
83namespace CompiledData {
84
85// index is per-object binding index
87
88// map from name index
90{
91 bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
92};
93
94struct String;
95struct Function;
96struct Lookup;
97struct RegExp;
98struct Unit;
99
100template <typename ItemType, typename Container, const ItemType *(Container::*IndexedGetter)(int index) const>
102{
103 TableIterator(const Container *container, int index) : container(container), index(index) {}
104 const Container *container;
105 int index;
106
107 const ItemType *operator->() { return (container->*IndexedGetter)(index); }
108 ItemType operator*() {return *operator->();}
109 void operator++() { ++index; }
110 bool operator==(const TableIterator &rhs) const { return index == rhs.index; }
111 bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
112};
113
115{
117 Location(quint32 l, quint32 c) : Location()
118 {
119 m_data.set<LineField>(l);
120 m_data.set<ColumnField>(c);
121 Q_ASSERT(m_data.get<LineField>() == l);
122 Q_ASSERT(m_data.get<ColumnField>() == c);
123 }
124
125 inline bool operator<(const Location &other) const {
126 return m_data.get<LineField>() < other.m_data.get<LineField>()
127 || (m_data.get<LineField>() == other.m_data.get<LineField>()
128 && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
129 }
130
131 friend size_t qHash(const Location &location, size_t seed = 0)
132 {
133 return QT_PREPEND_NAMESPACE(qHash)(location.m_data.data(), seed);
134 }
135
136 friend bool operator==(const Location &a, const Location &b)
137 {
138 return a.m_data.data()== b.m_data.data();
139 }
140
141 void set(quint32 line, quint32 column)
142 {
143 m_data.set<LineField>(line);
144 m_data.set<ColumnField>(column);
145 }
146
147 quint32 line() const { return m_data.get<LineField>(); }
148 quint32 column() const { return m_data.get<ColumnField>(); }
149
150private:
153
154 quint32_le_bitfield_union<LineField, ColumnField> m_data;
155};
156static_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");
157
158struct RegExp
159{
168
170
172 RegExp(quint32 flags, quint32 stringIndex) : RegExp()
173 {
174 m_data.set<FlagsField>(flags);
175 m_data.set<StringIndexField>(stringIndex);
176 }
177
178 quint32 flags() const { return m_data.get<FlagsField>(); }
179 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
180
181private:
184 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
185};
186static_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");
187
188struct Lookup
189{
196
197 enum Mode : unsigned int {
200 };
201
202 quint32 type() const { return m_data.get<TypeField>(); }
203 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
204 quint32 mode() const { return m_data.get<ModeField>(); }
205
207 Lookup(Type type, Mode mode, quint32 nameIndex) : Lookup()
208 {
209 m_data.set<TypeField>(type);
210 m_data.set<ModeField>(mode);
211 m_data.set<NameIndexField>(nameIndex);
212 }
213
214private:
217 // 1 bit left
219 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
220};
221static_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");
222
224{
226
227 void set(quint32 nameOffset, bool isAccessor)
228 {
229 m_data.set<NameOffsetField>(nameOffset);
230 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
231 }
232
233 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
234 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
235
236private:
239 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
240};
241static_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");
242
244{
246 // JSClassMember[nMembers]
247
248 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
249};
250static_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");
251
252struct String
253{
255
256 static int calculateSize(const QString &str) {
257 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
258 // would already break in other parts of the compilation process
259 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
260 }
261};
262
263static_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");
264
267 qint32_le line; // signed because debug instructions get negative line numbers
269};
270static_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");
271
272struct Block
273{
278
279 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
280
281 static int calculateSize(int nLocals) {
282 int trailingData = nLocals*sizeof (quint32);
283 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
284 Q_ASSERT(size < INT_MAX);
285 return int(size);
286 }
287
288 static size_t align(size_t a) {
289 return (a + 7) & ~size_t(7);
290 }
291};
292static_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");
293
294enum class NamedBuiltin: unsigned int {
296};
297
298enum class CommonType : unsigned int {
299 // Actual named builtins
309
310 // Optimization for very common other types
312
313 // No type specified or not recognized
315};
316
318{
319 enum Flag {
320 NoFlag = 0x0,
321 Common = 0x1,
322 List = 0x2,
323 };
325
326 void set(Flags flags, quint32 typeNameIndexOrCommonType)
327 {
328 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
329 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
330 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
331 }
332
333 bool indexIsCommonType() const
334 {
335 return m_data.get<IndexIsCommonTypeField>() != 0;
336 }
337
338 bool isList() const
339 {
340 return m_data.get<IsListField>() != 0;
341 }
342
344 {
345 return m_data.get<TypeNameIndexOrCommonTypeField>();
346 }
347
348private:
352 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
353};
354static_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");
355
361static_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");
362
363// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
364// for unaligned access. The ordering of the fields is also from largest to smallest.
366{
367 enum Flags : unsigned int {
368 IsStrict = 0x1,
372 };
373
374 // Absolute offset into file where the code for this function is located.
377
381 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
386 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
387 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
388
392
396
398 {
399 return lineAndStatementNumberOffset() + nLineAndStatementNumbers * sizeof(CodeOffsetToLineAndStatement);
400 }
401
402 // Keep all unaligned data at the end
405
406 // quint32 formalsIndex[nFormals]
407 // quint32 localsIndex[nLocals]
408
409 const Parameter *formalsTable() const
410 {
411 return reinterpret_cast<const Parameter *>(
412 reinterpret_cast<const char *>(this) + formalsOffset);
413 }
414 const quint32_le *localsTable() const
415 {
416 return reinterpret_cast<const quint32_le *>(
417 reinterpret_cast<const char *>(this) + localsOffset);
418 }
420 {
421 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
422 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
423 }
424
425 // --- QQmlPropertyCacheCreator interface
426 const Parameter *formalsBegin() const { return formalsTable(); }
427 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
428 // ---
429
430 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
431
432 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
433
434 static int calculateSize(
435 int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions,
436 int labelInfoSize, int codeSize)
437 {
438 int trailingData = nFormals * sizeof(Parameter)
439 + (nLocals + nInnerfunctions + labelInfoSize) * sizeof (quint32)
440 + nLinesAndStatements * sizeof(CodeOffsetToLineAndStatement);
441 size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
442 Q_ASSERT(size < INT_MAX);
443 return int(size);
444 }
445
446 static size_t align(size_t a) {
447 return (a + 7) & ~size_t(7);
448 }
449};
450static_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");
451
463static_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");
464
465struct Class
466{
473
474 const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
475
476 static int calculateSize(int nStaticMethods, int nMethods) {
477 int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
478 size_t size = align(sizeof(Class) + trailingData);
479 Q_ASSERT(size < INT_MAX);
480 return int(size);
481 }
482
483 static size_t align(size_t a) {
484 return (a + 7) & ~size_t(7);
485 }
486};
487static_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");
488
490{
492
493 static int calculateSize(int size) {
494 int trailingData = 2 * size * sizeof(quint32_le);
495 size_t s = align(sizeof(TemplateObject) + trailingData);
496 Q_ASSERT(s < INT_MAX);
497 return int(s);
498 }
499
500 static size_t align(size_t a) {
501 return (a + 7) & ~size_t(7);
502 }
503
504 const quint32_le *stringTable() const {
505 return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1));
506 }
507
508 uint stringIndexAt(uint i) const {
509 return stringTable()[i];
510 }
511 uint rawStringIndexAt(uint i) const {
512 return stringTable()[size + i];
513 }
514};
515static_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");
516
525static_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");
526
534static_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");
535
536// Qml data structures
537
546static_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");
547
549{
551
565
580
584
585 void clearFlags() { flagsAndType.set<FlagsField>(0); }
586 void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); }
587 bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; }
588 Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); }
589
590 void setType(Type type) { flagsAndType.set<TypeField>(type); }
591 Type type() const { return Type(flagsAndType.get<TypeField>()); }
592
593 union {
594 bool b;
596 quint32_le compiledScriptIndex; // used when Type_Script
598 quint32_le translationDataIndex; // used when Type_Translation
600 } value;
601 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
602
605
607 {
608 const Flags bindingFlags = flags();
609 return bindingFlags & IsSignalHandlerExpression
610 || bindingFlags & IsSignalHandlerObject
611 || bindingFlags & IsPropertyObserver;
612 }
613
614 bool isValueBinding() const
615 {
616 switch (type()) {
619 return false;
620 default:
622 }
623 }
624
627
628 bool isSignalHandler() const
629 {
631 Q_ASSERT(!isValueBinding());
632 Q_ASSERT(!isAttachedProperty());
633 Q_ASSERT(!isGroupProperty());
634 return true;
635 }
636 return false;
637 }
638
640 {
642 Q_ASSERT(!isValueBinding());
643 Q_ASSERT(!isSignalHandler());
644 Q_ASSERT(!isGroupProperty());
645 return true;
646 }
647 return false;
648 }
649
650 bool isGroupProperty() const
651 {
652 if (type() == Type_GroupProperty) {
653 Q_ASSERT(!isValueBinding());
654 Q_ASSERT(!isSignalHandler());
655 Q_ASSERT(!isAttachedProperty());
656 return true;
657 }
658 return false;
659 }
660
662
663 //reverse of Lexer::singleEscape()
664 static QString escapedString(const QString &string)
665 {
666 QString tmp = QLatin1String("\"");
667 for (int i = 0; i < string.size(); ++i) {
668 const QChar &c = string.at(i);
669 switch (c.unicode()) {
670 case 0x08:
671 tmp += QLatin1String("\\b");
672 break;
673 case 0x09:
674 tmp += QLatin1String("\\t");
675 break;
676 case 0x0A:
677 tmp += QLatin1String("\\n");
678 break;
679 case 0x0B:
680 tmp += QLatin1String("\\v");
681 break;
682 case 0x0C:
683 tmp += QLatin1String("\\f");
684 break;
685 case 0x0D:
686 tmp += QLatin1String("\\r");
687 break;
688 case 0x22:
689 tmp += QLatin1String("\\\"");
690 break;
691 case 0x27:
692 tmp += QLatin1String("\\\'");
693 break;
694 case 0x5C:
695 tmp += QLatin1String("\\\\");
696 break;
697 default:
698 tmp += c;
699 break;
700 }
701 }
702 tmp += QLatin1Char('\"');
703 return tmp;
704 }
705
707 {
708 const Binding::Type bindingType = type();
709 return bindingType == Type_Translation || bindingType == Type_TranslationById;
710 }
712
713 bool isNumberBinding() const { return type() == Type_Number; }
714
715 bool valueAsBoolean() const
716 {
717 if (type() == Type_Boolean)
718 return value.b;
719 return false;
720 }
721};
722
723static_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");
724
731
732static_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");
733
740static_assert(sizeof(EnumValue) == 12, "EnumValue structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
741
742struct Enum
743{
747
748 const EnumValue *enumValueAt(int idx) const {
749 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
750 }
751
752 static int calculateSize(int nEnumValues) {
753 return (sizeof(Enum)
754 + nEnumValues * sizeof(EnumValue)
755 + 7) & ~0x7;
756 }
757
758 // --- QQmlPropertyCacheCreatorInterface
759 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
760 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
761 int enumValueCount() const { return nEnumValues; }
762 // ---
763};
764static_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");
765
766struct Signal
767{
771 // Parameter parameters[1];
772
773 const Parameter *parameterAt(int idx) const {
774 return reinterpret_cast<const Parameter*>(this + 1) + idx;
775 }
776
777 static int calculateSize(int nParameters) {
778 return (sizeof(Signal)
779 + nParameters * sizeof(Parameter)
780 + 7) & ~0x7;
781 }
782
783 // --- QQmlPropertyCacheCceatorInterface
784 const Parameter *parametersBegin() const { return parameterAt(0); }
785 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
786 int parameterCount() const { return nParameters; }
787 // ---
788};
789static_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");
790
791/*
792 * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
793 * for each index.
794 *
795 * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
796 * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
797 * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
798 * to mention the amount of memory needed to maintain such a StringTableGenerator.
799 * Therefore, after some preliminary analysis, it seems that even 20 bits
800 * should be a rather conservative cap.
801 *
802 * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
803 * unions like, let's say nameIndexAndAttributes.
804 *
805 * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
806 *
807 * NameIndexField IsVirtualField IsOverrideField IsFinalField
808 * |10100000101000111000001110000| 0 | 1 | 0 |
809 *
810 */
812{
813private:
818
824
825public:
835
836 quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
837 void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
838
839 bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
840 void setIsVirtual(bool isVirtual)
841 {
842 nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
843 }
844
845 bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
846 void setIsOverride(bool isOverride)
847 {
848 nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
849 }
850
851 bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
852 void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
853
855 {
856 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
857 data.set<IsCommonTypeField>(true);
858 }
859
861 if (isCommonType())
862 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
863 return CommonType::Invalid;
864 }
865
866 void setTypeNameIndex(int nameIndex)
867 {
868 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
869 data.set<IsCommonTypeField>(false);
870 }
871
872 int typeNameIndex() const
873 {
874 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
875 }
876
877 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
878 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
879
880 bool isList() const { return data.get<IsListField>(); }
881 void setIsList(bool isList) { data.set<IsListField>(isList); }
882
883 bool isRequired() const { return data.get<IsRequiredField>(); }
884 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
885
886 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
887 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
888};
889static_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");
890
894
895static_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");
896
897struct Alias
898{
899 bool isReadOnly() const { return m_nameIndexAndFlags.get<IsReadOnlyField>(); }
900 void setIsReadOnly(bool isReadOnly) { m_nameIndexAndFlags.set<IsReadOnlyField>(isReadOnly); }
901
902 quint32 nameIndex() const { return m_nameIndexAndFlags.get<NameIndexField>(); }
903 void setNameIndex(quint32 nameIndex)
904 {
905 m_nameIndexAndFlags.set<NameIndexField>(nameIndex);
906 }
907
908 quint32 idIndex() const { return m_idIndexField; }
909 void setIdIndex(quint32 idIndex) { m_idIndexField = idIndex; }
910
911 quint32 propertyNameIndex() const { return m_propertyNameIndex; }
912 void setPropertyNameIndex(quint32 propertyNameIndex)
913 {
914 m_propertyNameIndex = propertyNameIndex;
915 }
916
917 Location location() const { return m_location; }
918 void setLocation(Location location) { m_location = location; }
919
920 Location referenceLocation() const { return m_referenceLocation; }
921 void setReferenceLocation(Location referenceLocation)
922 {
923 m_referenceLocation = referenceLocation;
924 }
925
926private:
929
930 quint32_le_bitfield_union<NameIndexField, IsReadOnlyField> m_nameIndexAndFlags;
931 quint32_le m_idIndexField;
932 quint32_le m_propertyNameIndex; // string index
933 Location m_location;
934 Location m_referenceLocation;
935};
936static_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");
937
938struct Object
939{
940private:
944public:
945 enum Flag : unsigned int {
946 NoFlag = 0x0,
947 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
948 HasDeferredBindings = 0x2, // any of the bindings are deferred
952 };
954
955 // Depending on the use, this may be the type name to instantiate before instantiating this
956 // object. For grouped properties the type name will be empty and for attached properties
957 // it will be the name of the attached type.
962 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
970 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
971 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
983// Function[]
984// Property[]
985// Signal[]
986// Binding[]
987// InlineComponent[]
988// RequiredPropertyExtraData[]
989
990 Flags flags() const
991 {
992 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
993 }
994
995 bool hasFlag(Flag flag) const
996 {
997 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
998 }
999
1000 void setFlag(Flag flag)
1001 {
1002 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1003 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1004 }
1005
1006 void setFlags(Flags flags)
1007 {
1008 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1009 }
1010
1012 {
1013 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1014 }
1015
1016 void setHasAliasAsDefaultProperty(bool defaultAlias)
1017 {
1018 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1019 }
1020
1022 {
1023 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1024 }
1025
1026 void setObjectId(qint32 id)
1027 {
1028 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1029 }
1030
1031
1032 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1033 {
1034 return ( sizeof(Object)
1035 + nFunctions * sizeof(quint32)
1036 + nProperties * sizeof(Property)
1037 + nAliases * sizeof(Alias)
1038 + nEnums * sizeof(quint32)
1039 + nSignals * sizeof(quint32)
1040 + nBindings * sizeof(Binding)
1041 + nNamedObjectsInComponent * sizeof(int)
1042 + nInlineComponents * sizeof(InlineComponent)
1043 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1044 + 0x7
1045 ) & ~0x7;
1046 }
1047
1049 {
1050 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1051 }
1052
1054 {
1055 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1056 }
1057
1058 const Alias *aliasTable() const
1059 {
1060 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1061 }
1062
1063 const Binding *bindingTable() const
1064 {
1065 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1066 }
1067
1068 const Enum *enumAt(int idx) const
1069 {
1070 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1071 const quint32_le offset = offsetTable[idx];
1072 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1073 }
1074
1075 const Signal *signalAt(int idx) const
1076 {
1077 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1078 const quint32_le offset = offsetTable[idx];
1079 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1080 }
1081
1083 {
1084 return inlineComponentTable() + idx;
1085 }
1086
1088 {
1089 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1090 }
1091
1093 {
1094 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1095 }
1096
1101
1103 {
1104 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1105 }
1106
1107 // --- QQmlPropertyCacheCreator interface
1108 int propertyCount() const { return nProperties; }
1109 int aliasCount() const { return nAliases; }
1110 int enumCount() const { return nEnums; }
1111 int signalCount() const { return nSignals; }
1112 int functionCount() const { return nFunctions; }
1113 int inlineComponentCount() const { return nInlineComponents; }
1114
1115 const Binding *bindingsBegin() const { return bindingTable(); }
1116 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1117 int bindingCount() const { return nBindings; }
1118
1119 const Property *propertiesBegin() const { return propertyTable(); }
1120 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1121
1122 const Alias *aliasesBegin() const { return aliasTable(); }
1123 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1124
1126 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1127 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1128
1130 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1131 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1132
1134 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1135 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1136
1138 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1139 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1140
1141 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1142 // ---
1143};
1144static_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");
1145
1147{
1148 enum ImportType : unsigned int {
1153 };
1155
1158
1162
1164 {
1165 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1166 }
1167};
1168static_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");
1169
1171{
1176
1177 const Import *importAt(int idx) const {
1178 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1179 }
1180
1181 const Object *objectAt(int idx) const {
1182 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1183 const quint32_le offset = offsetTable[idx];
1184 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1185 }
1186};
1187static_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");
1188
1189static const char magic_str[] = "qv4cdata";
1190
1191struct Unit
1192{
1193 // DO NOT CHANGE THESE FIELDS EVER
1194 char magic[8];
1196 // END DO NOT CHANGE THESE FIELDS EVER
1197
1198 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1200 quint32_le unitSize; // Size of the Unit and any depending data.
1201
1202 char md5Checksum[16]; // checksum of all bytes following this field.
1204
1205 enum : unsigned int {
1207 StaticData = 0x2, // Unit data persistent in memory?
1209 IsSharedLibrary = 0x8, // .pragma shared?
1211 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1212 IsStrict = 0x40,
1223 };
1258
1260
1261 /* QML specific fields */
1262
1263 const QmlUnit *qmlUnit() const {
1264 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1265 }
1266
1268 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1269 }
1270
1271 bool isSingleton() const {
1272 return flags & Unit::IsSingleton;
1273 }
1274 /* end QML specific fields*/
1275
1276 QString stringAtInternal(uint idx) const {
1277 Q_ASSERT(idx < stringTableSize);
1278 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1279 const quint32_le offset = offsetTable[idx];
1280 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1281 Q_ASSERT(str->size >= 0);
1282#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1283 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1284 if (flags & StaticData)
1285 return QString::fromRawData(characters, str->size);
1286 return QString(characters, str->size);
1287#else
1288 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1289 QString qstr(str->size, Qt::Uninitialized);
1290 QChar *ch = qstr.data();
1291 for (int i = 0; i < str->size; ++i)
1292 ch[i] = QChar(quint16(characters[i]));
1293 return qstr;
1294#endif
1295 }
1296
1297 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1298 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1299 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1300 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1301
1302 const Function *functionAt(int idx) const {
1303 const quint32_le *offsetTable = functionOffsetTable();
1304 const quint32_le offset = offsetTable[idx];
1305 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1306 }
1307
1308 const Class *classAt(int idx) const {
1309 const quint32_le *offsetTable = classOffsetTable();
1310 const quint32_le offset = offsetTable[idx];
1311 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1312 }
1313
1314 const TemplateObject *templateObjectAt(int idx) const {
1315 const quint32_le *offsetTable = templateObjectOffsetTable();
1316 const quint32_le offset = offsetTable[idx];
1317 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1318 }
1319
1320 const Block *blockAt(int idx) const {
1321 const quint32_le *offsetTable = blockOffsetTable();
1322 const quint32_le offset = offsetTable[idx];
1323 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1324 }
1325
1326 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1327 const RegExp *regexpAt(int index) const {
1328 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1329 }
1330 const quint64_le *constants() const {
1331 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1332 }
1333
1334 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1335 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1336 const quint32_le offset = offsetTable[idx];
1337 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1338 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1339 *nMembers = klass->nMembers;
1340 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1341 }
1342
1344 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1345 }
1346
1348 if ( translationTableSize == 0)
1349 return nullptr;
1350 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1351 + offsetToTranslationTable
1352 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1353
1355 if ( translationTableSize == 0)
1356 return nullptr;
1357 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1358 + offsetToTranslationTable
1359 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1360
1361 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1362 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1363 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1364 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1365
1366 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1367
1368 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1369};
1370
1371static_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");
1372
1374{
1376 : location(loc)
1377 , needsCreation(false)
1378 , errorWhenNotFound(false)
1379 {}
1380 Location location; // first use
1381 bool needsCreation : 1; // whether the type needs to be creatable or not
1383};
1384
1385// Map from name index to location of first use.
1387{
1388 TypeReference &add(int nameIndex, const Location &loc) {
1389 Iterator it = find(nameIndex);
1390 if (it != end())
1391 return *it;
1392 return *insert(nameIndex, loc);
1393 }
1394
1395 template <typename CompiledObject>
1396 void collectFromObject(const CompiledObject *obj)
1397 {
1398 if (obj->inheritedTypeNameIndex != 0) {
1399 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1400 r.needsCreation = true;
1401 r.errorWhenNotFound = true;
1402 }
1403
1404 auto binding = obj->bindingsBegin();
1405 auto const bindingEnd = obj->bindingsEnd();
1406 for ( ; binding != bindingEnd; ++binding) {
1408 this->add(binding->propertyNameIndex, binding->location);
1409 }
1410
1411 auto ic = obj->inlineComponentsBegin();
1412 auto const icEnd = obj->inlineComponentsEnd();
1413 for (; ic != icEnd; ++ic) {
1414 this->add(ic->nameIndex, ic->location);
1415 }
1416 }
1417
1418 template <typename Iterator>
1419 void collectFromObjects(Iterator it, Iterator end)
1420 {
1421 for (; it != end; ++it)
1422 collectFromObject(*it);
1423 }
1424};
1425
1427
1429
1431 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1432 : qmlType(qmlType)
1433 , objectIndex(objectIndex)
1434 , nameIndex(nameIndex)
1435 {}
1436
1437 QQmlType qmlType;
1438 int objectIndex = -1;
1439 int nameIndex = -1;
1440};
1441
1443{
1445
1446 const Unit *data = nullptr;
1447 const QmlUnit *qmlData = nullptr;
1450
1451 // pointers either to data->constants() or little-endian memory copy.
1452 const StaticValue *constants = nullptr;
1453
1455
1457
1458 // index is object index. This allows fast access to the
1459 // property data when initializing bindings, avoiding expensive
1460 // lookups by string (property name).
1462
1465
1467
1468 QQmlType qmlType;
1469
1471
1472public:
1473 // --- interface for QQmlPropertyCacheCreator
1477
1478 // Empty dummy. We don't need to do this when loading from cache.
1480 {
1481 public:
1482 void insert(int, int) {}
1483 void clear() {}
1484
1485 // We have already checked uniqueness of IDs when creating the CU
1486 bool contains(int) { return false; }
1487 };
1488
1489 explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1490 const QString &fileName = QString(), const QString &finalUrlString = QString())
1491 : CompilationUnit(unitData, fileName, finalUrlString)
1492 {
1493 this->aotCompiledFunctions = aotCompiledFunctions;
1494 }
1495
1497 const Unit *unitData = nullptr, const QString &fileName = QString(),
1498 const QString &finalUrlString = QString());
1499
1501
1502 const Unit *unitData() const { return data; }
1503
1504 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1505 const QString &fileName = QString(), const QString &finalUrlString = QString())
1506 {
1507 data = unitData;
1508 qmlData = nullptr;
1509#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1510 delete [] constants;
1511#endif
1512 constants = nullptr;
1513 m_fileName.clear();
1514 m_finalUrlString.clear();
1515 if (!data)
1516 return;
1517
1518 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1519
1520#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1521 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1522 const quint64_le *littleEndianConstants = data->constants();
1523 for (uint i = 0; i < data->constantTableSize; ++i)
1524 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1525 constants = bigEndianConstants;
1526#else
1527 constants = reinterpret_cast<const StaticValue*>(data->constants());
1528#endif
1529
1530 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1531 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1532 }
1533
1534 QString stringAt(uint index) const
1535 {
1536 if (index < data->stringTableSize)
1537 return data->stringAtInternal(index);
1538
1539 const qsizetype dynamicIndex = index - data->stringTableSize;
1540 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1541 return dynamicStrings.at(dynamicIndex);
1542 }
1543
1544 QString fileName() const { return m_fileName; }
1545 QString finalUrlString() const { return m_finalUrlString; }
1546
1548 {
1549 using namespace CompiledData;
1550 switch (binding->type()) {
1551 case Binding::Type_Script:
1552 case Binding::Type_String:
1553 return stringAt(binding->stringIndex);
1554 case Binding::Type_Null:
1555 return QStringLiteral("null");
1557 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1558 case Binding::Type_Number:
1559 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1561 return QString();
1562 case Binding::Type_TranslationById:
1563 case Binding::Type_Translation:
1564 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1565 default:
1566 break;
1567 }
1568 return QString();
1569 }
1570
1572 {
1573 return (binding->type() == CompiledData::Binding::Type_String)
1574 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1575 : bindingValueAsString(binding);
1576 }
1577
1578 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1579 {
1581 return 0.0;
1582 return constants[binding->value.constantValueIndex].doubleValue();
1583 }
1584
1585 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1587 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1588 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1589
1590 int importCount() const { return qmlData->nImports; }
1591 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1592
1593 Q_QML_EXPORT QStringList moduleRequests() const;
1594
1595 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1596 // warnings about that code. They include any potential URL interceptions and thus represent the
1597 // "physical" location of the code.
1598 //
1599 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1600 // They are _not_ intercepted and thus represent the "logical" name for the code.
1601
1602 QUrl url() const
1603 {
1604 if (!m_url.isValid())
1605 m_url = QUrl(fileName());
1606 return m_url;
1607 }
1608
1610 {
1611 if (!m_finalUrl.isValid())
1612 m_finalUrl = QUrl(finalUrlString());
1613 return m_finalUrl;
1614 }
1615
1616 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1617 ResolvedTypeReference *resolvedType(QMetaType type) const;
1618
1620 {
1621 return propertyCaches.isEmpty()
1622 ? QQmlPropertyCache::ConstPtr()
1623 : propertyCaches.at(/*root object*/0);
1624 }
1625
1626 int objectCount() const { return qmlData->nObjects; }
1627 const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); }
1628
1629 int inlineComponentId(const QString &inlineComponentName) const
1630 {
1631 for (uint i = 0; i < qmlData->nObjects; ++i) {
1632 auto *object = qmlData->objectAt(i);
1633 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1634 it != end; ++it) {
1635 if (stringAt(it->nameIndex) == inlineComponentName)
1636 return it->objectIndex;
1637 }
1638 }
1639 return -1;
1640 }
1641
1642 void finalizeCompositeType(const QQmlType &type);
1643
1644 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1645
1655
1660
1665
1667 {
1669 }
1670
1675
1677 {
1679 }
1680
1682 {
1684 }
1685
1686 bool isESModule() const
1687 {
1689 }
1690
1691 bool isSharedLibrary() const
1692 {
1694 }
1695
1697 {
1698 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1699 : unit(unit), object(object), index(index) {}
1703
1705 {
1706 return unit->functionAt(object->functionOffsetTable()[index]);
1707 }
1708
1709 void operator++() { ++index; }
1710 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1711 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1712 };
1713
1715 {
1716 return FunctionIterator(unitData(), object, 0);
1717 }
1718
1720 {
1721 return FunctionIterator(unitData(), object, object->nFunctions);
1722 }
1723
1724 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1725 QMetaType metaType() const { return qmlType.typeId(); }
1726
1727private:
1728 QString m_fileName; // initialized from data->sourceFileIndex
1729 QString m_finalUrlString; // initialized from data->finalUrlIndex
1730
1731 mutable QQmlNullableValue<QUrl> m_url;
1732 mutable QQmlNullableValue<QUrl> m_finalUrl;
1733};
1734
1736{
1738public:
1744
1746
1747 template<typename Char>
1748 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1749 {
1750 const quint32_le oldFlags = mutableFlags();
1751 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1752 mutableFlags() |= temporaryFlags;
1753 return writer(data<Char>(), size());
1754 }
1755
1756 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1757 QString *errorString)
1758 {
1759#if QT_CONFIG(temporaryfile)
1760 QSaveFile cacheFile(outputFileName);
1761 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1762 || cacheFile.write(data, size) != size
1763 || !cacheFile.commit()) {
1764 *errorString = cacheFile.errorString();
1765 return false;
1766 }
1767
1768 errorString->clear();
1769 return true;
1770#else
1771 Q_UNUSED(outputFileName);
1772 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1773 return false;
1774#endif
1775 }
1776
1777private:
1778 const Unit *unit;
1779 quint32 temporaryFlags;
1780
1781 quint32_le &mutableFlags() const
1782 {
1783 return const_cast<Unit *>(unit)->flags;
1784 }
1785
1786 template<typename Char>
1787 const Char *data() const
1788 {
1789 Q_STATIC_ASSERT(sizeof(Char) == 1);
1790 const Char *dataPtr;
1791 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1792 return dataPtr;
1793 }
1794
1795 quint32 size() const
1796 {
1797 return unit->unitSize;
1798 }
1799};
1800
1801
1802} // CompiledData namespace
1803} // QV4 namespace
1804
1807
1808QT_END_NAMESPACE
1809
1810#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())
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
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions, int labelInfoSize, int codeSize)
size_t lineAndStatementNumberOffset() const
const Parameter * formalsTable() const
const Parameter * formalsEnd() const
const Parameter * formalsBegin() const
const quint32_le * labelInfoTable() const
InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
Location(quint32 l, quint32 c)
void set(quint32 line, quint32 column)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool operator==(const Location &a, const Location &b)
Lookup(Type type, Mode mode, quint32 nameIndex)
TableIterator< Enum, Object, &Object::enumAt > EnumIterator
EnumIterator enumsBegin() const
Q_DECLARE_FLAGS(Flags, Flag)
const RequiredPropertyExtraData * requiredPropertyExtraDataAt(int idx) const
EnumIterator enumsEnd() const
const Enum * enumAt(int idx) const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const
const RequiredPropertyExtraData * requiredPropertyExtraDataTable() const
TableIterator< Signal, Object, &Object::signalAt > SignalIterator
const Binding * bindingsEnd() const
bool hasFlag(Flag flag) const
const Property * propertyTable() const
SignalIterator signalsBegin() const
quint32_le_bitfield_union< FlagsField, DefaultPropertyIsAliasField, IdField > flagsAndDefaultPropertyIsAliasAndId
InlineComponentIterator inlineComponentsEnd() const
const Alias * aliasTable() const
const InlineComponent * inlineComponentAt(int idx) const
const Property * propertiesEnd() const
const Binding * bindingTable() const
const Signal * signalAt(int idx) const
const Property * propertiesBegin() const
const quint32_le * functionOffsetTable() const
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
TableIterator< InlineComponent, Object, &Object::inlineComponentAt > InlineComponentIterator
const InlineComponent * inlineComponentTable() const
InlineComponentIterator inlineComponentsBegin() const
TableIterator< RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt > RequiredPropertyExtraDataIterator
SignalIterator signalsEnd() const
const Alias * aliasesEnd() const
const Binding * bindingsBegin() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const
void setHasAliasAsDefaultProperty(bool defaultAlias)
const Alias * aliasesBegin() const
const quint32_le * namedObjectsInComponentTable() const
void set(Flags flags, quint32 typeNameIndexOrCommonType)
void setNameIndex(int nameIndex)
void setIsReadOnly(bool isReadOnly)
void setTypeNameIndex(int nameIndex)
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)
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