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 0x4c // Dropped enum value location
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 comparesEqual(const Location &a, const Location &b) noexcept
137 {
138 return a.m_data.data()== b.m_data.data();
139 }
141
147
148 quint32 line() const { return m_data.get<LineField>(); }
149 quint32 column() const { return m_data.get<ColumnField>(); }
150
151private:
154
155 quint32_le_bitfield_union<LineField, ColumnField> m_data;
156};
157static_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");
158
159struct RegExp
160{
169
171
173 RegExp(quint32 flags, quint32 stringIndex) : RegExp()
174 {
175 m_data.set<FlagsField>(flags);
176 m_data.set<StringIndexField>(stringIndex);
177 }
178
179 quint32 flags() const { return m_data.get<FlagsField>(); }
180 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
181
182private:
185 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
186};
187static_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");
188
189struct Lookup
190{
197
198 enum Mode : unsigned int {
201 };
202
203 quint32 type() const { return m_data.get<TypeField>(); }
204 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
205 quint32 mode() const { return m_data.get<ModeField>(); }
206
208 Lookup(Type type, Mode mode, quint32 nameIndex) : Lookup()
209 {
210 m_data.set<TypeField>(type);
211 m_data.set<ModeField>(mode);
212 m_data.set<NameIndexField>(nameIndex);
213 }
214
215private:
218 // 1 bit left
220 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
221};
222static_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");
223
225{
227
228 void set(quint32 nameOffset, bool isAccessor)
229 {
230 m_data.set<NameOffsetField>(nameOffset);
231 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
232 }
233
234 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
235 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
236
237private:
240 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
241};
242static_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");
243
245{
247 // JSClassMember[nMembers]
248
249 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
250};
251static_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");
252
253struct String
254{
256
257 static int calculateSize(const QString &str) {
258 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
259 // would already break in other parts of the compilation process
260 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
261 }
262};
263
264static_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");
265
268 qint32_le line; // signed because debug instructions get negative line numbers
270};
271static_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");
272
273struct Block
274{
279
280 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
281
282 static int calculateSize(int nLocals) {
283 int trailingData = nLocals*sizeof (quint32);
284 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
285 Q_ASSERT(size < INT_MAX);
286 return int(size);
287 }
288
289 static size_t align(size_t a) {
290 return (a + 7) & ~size_t(7);
291 }
292};
293static_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");
294
295enum class NamedBuiltin: unsigned int {
297};
298
299enum class CommonType : unsigned int {
300 // Actual named builtins
310
311 // Optimization for very common other types
313
314 // No type specified or not recognized
316};
317
319{
320 enum Flag {
321 NoFlag = 0x0,
322 Common = 0x1,
323 List = 0x2,
324 };
326
327 void set(Flags flags, quint32 typeNameIndexOrCommonType)
328 {
329 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
330 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
331 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
332 }
333
334 bool indexIsCommonType() const
335 {
336 return m_data.get<IndexIsCommonTypeField>() != 0;
337 }
338
339 bool isList() const
340 {
341 return m_data.get<IsListField>() != 0;
342 }
343
345 {
346 return m_data.get<TypeNameIndexOrCommonTypeField>();
347 }
348
349private:
353 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
354};
355static_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");
356
362static_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");
363
364// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
365// for unaligned access. The ordering of the fields is also from largest to smallest.
367{
368 enum Flags : unsigned int {
369 IsStrict = 0x1,
373 };
374
375 // Absolute offset into file where the code for this function is located.
378
382 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
387 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
388 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
389
393
397
399 {
400 return lineAndStatementNumberOffset() + nLineAndStatementNumbers * sizeof(CodeOffsetToLineAndStatement);
401 }
402
403 // Keep all unaligned data at the end
406
407 // quint32 formalsIndex[nFormals]
408 // quint32 localsIndex[nLocals]
409
410 const Parameter *formalsTable() const
411 {
412 return reinterpret_cast<const Parameter *>(
413 reinterpret_cast<const char *>(this) + formalsOffset);
414 }
415 const quint32_le *localsTable() const
416 {
417 return reinterpret_cast<const quint32_le *>(
418 reinterpret_cast<const char *>(this) + localsOffset);
419 }
421 {
422 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
423 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
424 }
425
426 // --- QQmlPropertyCacheCreator interface
427 const Parameter *formalsBegin() const { return formalsTable(); }
428 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
429 // ---
430
431 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
432
433 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
434
435 static int calculateSize(
436 int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
437 {
438 const size_t trailingData = nFormals * sizeof(Parameter)
439 + (nLocals + 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
739static_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");
740
741struct Enum
742{
746
747 const EnumValue *enumValueAt(int idx) const {
748 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
749 }
750
751 static int calculateSize(int nEnumValues) {
752 return (sizeof(Enum)
753 + nEnumValues * sizeof(EnumValue)
754 + 7) & ~0x7;
755 }
756
757 // --- QQmlPropertyCacheCreatorInterface
758 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
759 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
760 int enumValueCount() const { return nEnumValues; }
761 // ---
762};
763static_assert(sizeof(Enum) == 12, "Enum structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
764
765struct Signal
766{
770 // Parameter parameters[1];
771
772 const Parameter *parameterAt(int idx) const {
773 return reinterpret_cast<const Parameter*>(this + 1) + idx;
774 }
775
776 static int calculateSize(int nParameters) {
777 return (sizeof(Signal)
778 + nParameters * sizeof(Parameter)
779 + 7) & ~0x7;
780 }
781
782 // --- QQmlPropertyCacheCceatorInterface
783 const Parameter *parametersBegin() const { return parameterAt(0); }
784 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
785 int parameterCount() const { return nParameters; }
786 // ---
787};
788static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
789
790/*
791 * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
792 * for each index.
793 *
794 * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
795 * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
796 * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
797 * to mention the amount of memory needed to maintain such a StringTableGenerator.
798 * Therefore, after some preliminary analysis, it seems that even 20 bits
799 * should be a rather conservative cap.
800 *
801 * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
802 * unions like, let's say nameIndexAndAttributes.
803 *
804 * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
805 *
806 * NameIndexField IsVirtualField IsOverrideField IsFinalField
807 * |10100000101000111000001110000| 0 | 1 | 0 |
808 *
809 */
811{
812private:
817
823
824public:
834
835 quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
836 void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
837
838 bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
839 void setIsVirtual(bool isVirtual)
840 {
841 nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
842 }
843
844 bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
845 void setIsOverride(bool isOverride)
846 {
847 nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
848 }
849
850 bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
851 void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
852
854 {
855 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
856 data.set<IsCommonTypeField>(true);
857 }
858
860 if (isCommonType())
861 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
862 return CommonType::Invalid;
863 }
864
865 void setTypeNameIndex(int nameIndex)
866 {
867 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
868 data.set<IsCommonTypeField>(false);
869 }
870
871 int typeNameIndex() const
872 {
873 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
874 }
875
876 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
877 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
878
879 bool isList() const { return data.get<IsListField>(); }
880 void setIsList(bool isList) { data.set<IsListField>(isList); }
881
882 bool isRequired() const { return data.get<IsRequiredField>(); }
883 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
884
885 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
886 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
887};
888static_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");
889
893
894static_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");
895
896struct Alias
897{
898 bool isReadOnly() const { return m_nameIndexAndFlags.get<IsReadOnlyField>(); }
899 void setIsReadOnly(bool isReadOnly) { m_nameIndexAndFlags.set<IsReadOnlyField>(isReadOnly); }
900
901 quint32 nameIndex() const { return m_nameIndexAndFlags.get<NameIndexField>(); }
902 void setNameIndex(quint32 nameIndex)
903 {
904 m_nameIndexAndFlags.set<NameIndexField>(nameIndex);
905 }
906
907 quint32 idIndex() const { return m_idIndexField; }
908 void setIdIndex(quint32 idIndex) { m_idIndexField = idIndex; }
909
910 quint32 propertyNameIndex() const { return m_propertyNameIndex; }
911 void setPropertyNameIndex(quint32 propertyNameIndex)
912 {
913 m_propertyNameIndex = propertyNameIndex;
914 }
915
916 Location location() const { return m_location; }
917 void setLocation(Location location) { m_location = location; }
918
919 Location referenceLocation() const { return m_referenceLocation; }
920 void setReferenceLocation(Location referenceLocation)
921 {
922 m_referenceLocation = referenceLocation;
923 }
924
925private:
928
929 quint32_le_bitfield_union<NameIndexField, IsReadOnlyField> m_nameIndexAndFlags;
930 quint32_le m_idIndexField;
931 quint32_le m_propertyNameIndex; // string index
932 Location m_location;
933 Location m_referenceLocation;
934};
935static_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");
936
937struct Object
938{
939private:
943public:
944 enum Flag : unsigned int {
945 NoFlag = 0x0,
946 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
947 HasDeferredBindings = 0x2, // any of the bindings are deferred
951 };
953
954 // Depending on the use, this may be the type name to instantiate before instantiating this
955 // object. For grouped properties the type name will be empty and for attached properties
956 // it will be the name of the attached type.
961 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
969 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
970 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
982// Function[]
983// Property[]
984// Signal[]
985// Binding[]
986// InlineComponent[]
987// RequiredPropertyExtraData[]
988
989 Flags flags() const
990 {
991 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
992 }
993
994 bool hasFlag(Flag flag) const
995 {
996 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
997 }
998
999 void setFlag(Flag flag)
1000 {
1001 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1002 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1003 }
1004
1005 void setFlags(Flags flags)
1006 {
1007 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1008 }
1009
1011 {
1012 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1013 }
1014
1015 void setHasAliasAsDefaultProperty(bool defaultAlias)
1016 {
1017 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1018 }
1019
1021 {
1022 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1023 }
1024
1025 void setObjectId(qint32 id)
1026 {
1027 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1028 }
1029
1030
1031 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1032 {
1033 return ( sizeof(Object)
1034 + nFunctions * sizeof(quint32)
1035 + nProperties * sizeof(Property)
1036 + nAliases * sizeof(Alias)
1037 + nEnums * sizeof(quint32)
1038 + nSignals * sizeof(quint32)
1039 + nBindings * sizeof(Binding)
1040 + nNamedObjectsInComponent * sizeof(int)
1041 + nInlineComponents * sizeof(InlineComponent)
1042 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1043 + 0x7
1044 ) & ~0x7;
1045 }
1046
1048 {
1049 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1050 }
1051
1053 {
1054 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1055 }
1056
1057 const Alias *aliasTable() const
1058 {
1059 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1060 }
1061
1062 const Binding *bindingTable() const
1063 {
1064 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1065 }
1066
1067 const Enum *enumAt(int idx) const
1068 {
1069 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1070 const quint32_le offset = offsetTable[idx];
1071 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1072 }
1073
1074 const Signal *signalAt(int idx) const
1075 {
1076 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1077 const quint32_le offset = offsetTable[idx];
1078 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1079 }
1080
1082 {
1083 return inlineComponentTable() + idx;
1084 }
1085
1087 {
1088 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1089 }
1090
1092 {
1093 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1094 }
1095
1100
1102 {
1103 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1104 }
1105
1106 // --- QQmlPropertyCacheCreator interface
1107 int propertyCount() const { return nProperties; }
1108 int aliasCount() const { return nAliases; }
1109 int enumCount() const { return nEnums; }
1110 int signalCount() const { return nSignals; }
1111 int functionCount() const { return nFunctions; }
1112 int inlineComponentCount() const { return nInlineComponents; }
1113
1114 const Binding *bindingsBegin() const { return bindingTable(); }
1115 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1116 int bindingCount() const { return nBindings; }
1117
1118 const Property *propertiesBegin() const { return propertyTable(); }
1119 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1120
1121 const Alias *aliasesBegin() const { return aliasTable(); }
1122 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1123
1125 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1126 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1127
1129 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1130 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1131
1133 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1134 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1135
1137 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1138 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1139
1140 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1141 // ---
1142};
1143static_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");
1144
1146{
1147 enum ImportType : unsigned int {
1152 };
1154
1157
1161
1163 {
1164 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1165 }
1166};
1167static_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");
1168
1170{
1175
1176 const Import *importAt(int idx) const {
1177 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1178 }
1179
1180 const Object *objectAt(int idx) const {
1181 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1182 const quint32_le offset = offsetTable[idx];
1183 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1184 }
1185};
1186static_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");
1187
1188static const char magic_str[] = "qv4cdata";
1189
1190struct Unit
1191{
1192 // DO NOT CHANGE THESE FIELDS EVER
1193 char magic[8];
1195 // END DO NOT CHANGE THESE FIELDS EVER
1196
1197 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1199 quint32_le unitSize; // Size of the Unit and any depending data.
1200
1201 char md5Checksum[16]; // checksum of all bytes following this field.
1203
1204 enum : unsigned int {
1206 StaticData = 0x2, // Unit data persistent in memory?
1208 IsSharedLibrary = 0x8, // .pragma shared?
1210 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1211 IsStrict = 0x40,
1222 };
1257
1259
1260 /* QML specific fields */
1261
1262 const QmlUnit *qmlUnit() const {
1263 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1264 }
1265
1267 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1268 }
1269
1270 bool isSingleton() const {
1271 return flags & Unit::IsSingleton;
1272 }
1273 /* end QML specific fields*/
1274
1275 QString stringAtInternal(uint idx) const {
1276 Q_ASSERT(idx < stringTableSize);
1277 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1278 const quint32_le offset = offsetTable[idx];
1279 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1280 Q_ASSERT(str->size >= 0);
1281#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1282 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1283 if (flags & StaticData)
1284 return QString::fromRawData(characters, str->size);
1285 return QString(characters, str->size);
1286#else
1287 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1288 QString qstr(str->size, Qt::Uninitialized);
1289 QChar *ch = qstr.data();
1290 for (int i = 0; i < str->size; ++i)
1291 ch[i] = QChar(quint16(characters[i]));
1292 return qstr;
1293#endif
1294 }
1295
1296 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1297 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1298 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1299 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1300
1301 const Function *functionAt(int idx) const {
1302 const quint32_le *offsetTable = functionOffsetTable();
1303 const quint32_le offset = offsetTable[idx];
1304 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1305 }
1306
1307 const Class *classAt(int idx) const {
1308 const quint32_le *offsetTable = classOffsetTable();
1309 const quint32_le offset = offsetTable[idx];
1310 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1311 }
1312
1313 const TemplateObject *templateObjectAt(int idx) const {
1314 const quint32_le *offsetTable = templateObjectOffsetTable();
1315 const quint32_le offset = offsetTable[idx];
1316 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1317 }
1318
1319 const Block *blockAt(int idx) const {
1320 const quint32_le *offsetTable = blockOffsetTable();
1321 const quint32_le offset = offsetTable[idx];
1322 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1323 }
1324
1325 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1326 const RegExp *regexpAt(int index) const {
1327 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1328 }
1329 const quint64_le *constants() const {
1330 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1331 }
1332
1333 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1334 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1335 const quint32_le offset = offsetTable[idx];
1336 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1337 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1338 *nMembers = klass->nMembers;
1339 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1340 }
1341
1343 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1344 }
1345
1347 if ( translationTableSize == 0)
1348 return nullptr;
1349 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1350 + offsetToTranslationTable
1351 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1352
1354 if ( translationTableSize == 0)
1355 return nullptr;
1356 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1357 + offsetToTranslationTable
1358 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1359
1360 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1361 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1362 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1363 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1364
1365 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1366
1367 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1368};
1369
1370static_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");
1371
1373{
1375 : location(loc)
1376 , needsCreation(false)
1377 , errorWhenNotFound(false)
1378 {}
1379 Location location; // first use
1380 bool needsCreation : 1; // whether the type needs to be creatable or not
1382};
1383
1384// Map from name index to location of first use.
1386{
1387 TypeReference &add(int nameIndex, const Location &loc) {
1388 Iterator it = find(nameIndex);
1389 if (it != end())
1390 return *it;
1391 return *insert(nameIndex, loc);
1392 }
1393
1394 template <typename CompiledObject>
1395 void collectFromObject(const CompiledObject *obj)
1396 {
1397 if (obj->inheritedTypeNameIndex != 0) {
1398 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1399 r.needsCreation = true;
1400 r.errorWhenNotFound = true;
1401 }
1402
1403 auto binding = obj->bindingsBegin();
1404 auto const bindingEnd = obj->bindingsEnd();
1405 for ( ; binding != bindingEnd; ++binding) {
1407 this->add(binding->propertyNameIndex, binding->location);
1408 }
1409
1410 auto ic = obj->inlineComponentsBegin();
1411 auto const icEnd = obj->inlineComponentsEnd();
1412 for (; ic != icEnd; ++ic) {
1413 this->add(ic->nameIndex, ic->location);
1414 }
1415 }
1416
1417 template <typename Iterator>
1418 void collectFromObjects(Iterator it, Iterator end)
1419 {
1420 for (; it != end; ++it)
1421 collectFromObject(*it);
1422 }
1423};
1424
1426
1428
1430 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1431 : qmlType(qmlType)
1432 , objectIndex(objectIndex)
1433 , nameIndex(nameIndex)
1434 {}
1435
1436 QQmlType qmlType;
1437 int objectIndex = -1;
1438 int nameIndex = -1;
1439};
1440
1442{
1444
1445 const Unit *data = nullptr;
1446 const QmlUnit *qmlData = nullptr;
1449
1450 // pointers either to data->constants() or little-endian memory copy.
1451 const StaticValue *constants = nullptr;
1452
1454
1456
1457 // index is object index. This allows fast access to the
1458 // property data when initializing bindings, avoiding expensive
1459 // lookups by string (property name).
1461
1464
1466
1467 QQmlType qmlType;
1468
1470
1471public:
1472 // --- interface for QQmlPropertyCacheCreator
1476
1477 // Empty dummy. We don't need to do this when loading from cache.
1479 {
1480 public:
1481 void insert(int, int) {}
1482 void clear() {}
1483
1484 // We have already checked uniqueness of IDs when creating the CU
1485 bool contains(int) { return false; }
1486 };
1487
1488 explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1489 const QString &fileName = QString(), const QString &finalUrlString = QString())
1490 : CompilationUnit(unitData, fileName, finalUrlString)
1491 {
1492 this->aotCompiledFunctions = aotCompiledFunctions;
1493 }
1494
1496 const Unit *unitData = nullptr, const QString &fileName = QString(),
1497 const QString &finalUrlString = QString());
1498
1500
1501 const Unit *unitData() const { return data; }
1502
1503 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1504 const QString &fileName = QString(), const QString &finalUrlString = QString())
1505 {
1506 data = unitData;
1507 qmlData = nullptr;
1508#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1509 delete [] constants;
1510#endif
1511 constants = nullptr;
1512 m_fileName.clear();
1513 m_finalUrlString.clear();
1514 if (!data)
1515 return;
1516
1517 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1518
1519#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1520 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1521 const quint64_le *littleEndianConstants = data->constants();
1522 for (uint i = 0; i < data->constantTableSize; ++i)
1523 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1524 constants = bigEndianConstants;
1525#else
1526 constants = reinterpret_cast<const StaticValue*>(data->constants());
1527#endif
1528
1529 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1530 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1531 }
1532
1533 QString stringAt(uint index) const
1534 {
1535 if (index < data->stringTableSize)
1536 return data->stringAtInternal(index);
1537
1538 const qsizetype dynamicIndex = index - data->stringTableSize;
1539 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1540 return dynamicStrings.at(dynamicIndex);
1541 }
1542
1543 QString fileName() const { return m_fileName; }
1544 QString finalUrlString() const { return m_finalUrlString; }
1545
1547 {
1548 using namespace CompiledData;
1549 switch (binding->type()) {
1550 case Binding::Type_Script:
1551 case Binding::Type_String:
1552 return stringAt(binding->stringIndex);
1553 case Binding::Type_Null:
1554 return QStringLiteral("null");
1556 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1557 case Binding::Type_Number:
1558 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1560 return QString();
1561 case Binding::Type_TranslationById:
1562 case Binding::Type_Translation:
1563 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1564 default:
1565 break;
1566 }
1567 return QString();
1568 }
1569
1571 {
1572 return (binding->type() == CompiledData::Binding::Type_String)
1573 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1574 : bindingValueAsString(binding);
1575 }
1576
1577 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1578 {
1580 return 0.0;
1581 return constants[binding->value.constantValueIndex].doubleValue();
1582 }
1583
1584 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1586 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1587 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1588
1589 int importCount() const { return qmlData->nImports; }
1590 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1591
1592 Q_QML_EXPORT QStringList moduleRequests() const;
1593
1594 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1595 // warnings about that code. They include any potential URL interceptions and thus represent the
1596 // "physical" location of the code.
1597 //
1598 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1599 // They are _not_ intercepted and thus represent the "logical" name for the code.
1600
1601 QUrl url() const
1602 {
1603 if (!m_url.isValid())
1604 m_url = QUrl(fileName());
1605 return m_url;
1606 }
1607
1609 {
1610 if (!m_finalUrl.isValid())
1611 m_finalUrl = QUrl(finalUrlString());
1612 return m_finalUrl;
1613 }
1614
1615 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1616 ResolvedTypeReference *resolvedType(QMetaType type) const;
1617
1619 {
1620 return propertyCaches.isEmpty()
1621 ? QQmlPropertyCache::ConstPtr()
1622 : propertyCaches.at(/*root object*/0);
1623 }
1624
1625 int objectCount() const { return qmlData->nObjects; }
1626
1627 // Resolves implicit component wrapper indices (>= objectCount()) to the
1628 // wrapped child object index. Returns the index unchanged for real objects.
1629 int resolvedIndex(int index) const
1630 {
1631 if (index < objectCount())
1632 return index;
1633 const QQmlPropertyData *p = propertyCaches.at(index)->defaultProperty();
1634 Q_ASSERT(p && p->isComponentWrapper());
1635 return p->wrappedObjectIndex();
1636 }
1637
1638 const CompiledObject *objectAt(int index) const
1639 {
1641 }
1642
1643 // Returns the index of the implicit component wrapper, or -1.
1644 // Scans property caches at indices >= objectCount().
1645 int implicitComponentForObject(int index) const
1646 {
1647 for (int i = objectCount(), end = propertyCaches.count(); i < end; ++i) {
1648 const QQmlPropertyData *p = propertyCaches.at(i)->defaultProperty();
1649 Q_ASSERT(p && p->isComponentWrapper());
1650 if (p->wrappedObjectIndex() == index)
1651 return i;
1652 }
1653 return -1;
1654 }
1655
1656 int inlineComponentId(const QString &inlineComponentName) const
1657 {
1658 for (uint i = 0; i < qmlData->nObjects; ++i) {
1659 auto *object = qmlData->objectAt(i);
1660 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1661 it != end; ++it) {
1662 if (stringAt(it->nameIndex) == inlineComponentName)
1663 return it->objectIndex;
1664 }
1665 }
1666 return -1;
1667 }
1668
1669 void finalizeCompositeType(const QQmlType &type);
1670
1671 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1672
1682
1687
1692
1694 {
1696 }
1697
1702
1704 {
1706 }
1707
1709 {
1711 }
1712
1713 bool isESModule() const
1714 {
1716 }
1717
1718 bool isSharedLibrary() const
1719 {
1721 }
1722
1724 {
1725 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1726 : unit(unit), object(object), index(index) {}
1730
1732 {
1733 return unit->functionAt(object->functionOffsetTable()[index]);
1734 }
1735
1736 void operator++() { ++index; }
1737 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1738 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1739 };
1740
1742 {
1743 return FunctionIterator(unitData(), object, 0);
1744 }
1745
1747 {
1748 return FunctionIterator(unitData(), object, object->nFunctions);
1749 }
1750
1751 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1752 QMetaType metaType() const { return qmlType.typeId(); }
1753
1754private:
1755 QString m_fileName; // initialized from data->sourceFileIndex
1756 QString m_finalUrlString; // initialized from data->finalUrlIndex
1757
1758 mutable QQmlNullableValue<QUrl> m_url;
1759 mutable QQmlNullableValue<QUrl> m_finalUrl;
1760};
1761
1763{
1765public:
1771
1773
1774 template<typename Char>
1775 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1776 {
1777 const quint32_le oldFlags = mutableFlags();
1778 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1779 mutableFlags() |= temporaryFlags;
1780 return writer(data<Char>(), size());
1781 }
1782
1783 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1784 QString *errorString)
1785 {
1786#if QT_CONFIG(temporaryfile)
1787 QSaveFile cacheFile(outputFileName);
1788 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1789 || cacheFile.write(data, size) != size
1790 || !cacheFile.commit()) {
1791 *errorString = cacheFile.errorString();
1792 return false;
1793 }
1794
1795 errorString->clear();
1796 return true;
1797#else
1798 Q_UNUSED(outputFileName);
1799 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1800 return false;
1801#endif
1802 }
1803
1804private:
1805 const Unit *unit;
1806 quint32 temporaryFlags;
1807
1808 quint32_le &mutableFlags() const
1809 {
1810 return const_cast<Unit *>(unit)->flags;
1811 }
1812
1813 template<typename Char>
1814 const Char *data() const
1815 {
1816 Q_STATIC_ASSERT(sizeof(Char) == 1);
1817 const Char *dataPtr;
1818 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1819 return dataPtr;
1820 }
1821
1822 quint32 size() const
1823 {
1824 return unit->unitSize;
1825 }
1826};
1827
1828
1829} // CompiledData namespace
1830} // QV4 namespace
1831
1834
1835QT_END_NAMESPACE
1836
1837#endif
static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size, QString *errorString)
bool saveToDisk(const std::function< bool(const Char *, quint32)> &writer) const
Combined button and popup list for selecting options.
static const char magic_str[]
Definition qjsvalue.h:24
Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE)
#define QV4_DATA_STRUCTURE_VERSION
Q_DECLARE_OPERATORS_FOR_FLAGS(QV4::CompiledData::ParameterType::Flags)
void setPropertyNameIndex(quint32 propertyNameIndex)
quint32 propertyNameIndex() const
void setIsReadOnly(bool isReadOnly)
void setReferenceLocation(Location referenceLocation)
void setNameIndex(quint32 nameIndex)
Location referenceLocation() const
void setIdIndex(quint32 idIndex)
void setLocation(Location location)
quint32_le_bitfield_union< FlagsField, TypeField > flagsAndType
bool hasFlag(Flag flag) const
static QString escapedString(const QString &string)
const quint32_le * localsTable() const
static size_t align(size_t a)
static int calculateSize(int nLocals)
static int calculateSize(int nStaticMethods, int nMethods)
static size_t align(size_t a)
const Method * methodTable() const
bool operator!=(const FunctionIterator &rhs) const
bool operator==(const FunctionIterator &rhs) const
FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
std::unique_ptr< CompilationUnitMapper > backingFile
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const
QString bindingValueAsScriptString(const CompiledData::Binding *binding) const
QHash< QString, InlineComponentData > inlineComponentData
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit=nullptr, const QString &fileName=QString(), const QString &finalUrlString=QString())
int inlineComponentId(const QString &inlineComponentName) const
double bindingValueAsNumber(const CompiledData::Binding *binding) const
void finalizeCompositeType(const QQmlType &type)
ResolvedTypeReference * resolvedType(int id) const
const CompiledData::Function CompiledFunction
const QQmlPrivate::AOTCompiledFunction * aotCompiledFunctions
CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, const QString &fileName=QString(), const QString &finalUrlString=QString())
int implicitComponentForObject(int index) const
ResolvedTypeReferenceMap resolvedTypes
QList< BindingPropertyData > bindingPropertyDataPerObject
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
ListPropertyAssignBehavior listPropertyAssignBehavior() const
const CompiledObject * objectAt(int index) const
const CompiledData::Object CompiledObject
const CompiledData::Binding CompiledBinding
const CompiledData::Import * importAt(int index) const
QList< QQmlRefPointer< QQmlScriptData > > dependentScripts
Q_QML_EXPORT bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
QString bindingValueAsString(const CompiledData::Binding *binding) const
QQmlPropertyCache::ConstPtr rootPropertyCache() const
const EnumValue * enumValueAt(int idx) const
const EnumValue * enumValuesEnd() const
const EnumValue * enumValuesBegin() const
static int calculateSize(int nEnumValues)
const quint32_le * localsTable() const
static size_t align(size_t a)
const CodeOffsetToLineAndStatement * lineAndStatementNumberTable() const
size_t lineAndStatementNumberOffset() const
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
const Parameter * formalsTable() const
const Parameter * formalsEnd() const
const Parameter * formalsBegin() const
const quint32_le * labelInfoTable() const
InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
Location(quint32 l, quint32 c)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool comparesEqual(const Location &a, const Location &b) noexcept
Lookup(Type type, Mode mode, quint32 nameIndex)
TableIterator< Enum, Object, &Object::enumAt > EnumIterator
EnumIterator enumsBegin() const
Q_DECLARE_FLAGS(Flags, Flag)
const RequiredPropertyExtraData * requiredPropertyExtraDataAt(int idx) const
EnumIterator enumsEnd() const
const Enum * enumAt(int idx) const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const
const RequiredPropertyExtraData * requiredPropertyExtraDataTable() const
TableIterator< Signal, Object, &Object::signalAt > SignalIterator
const Binding * bindingsEnd() const
bool hasFlag(Flag flag) const
const Property * propertyTable() const
SignalIterator signalsBegin() const
quint32_le_bitfield_union< FlagsField, DefaultPropertyIsAliasField, IdField > flagsAndDefaultPropertyIsAliasAndId
InlineComponentIterator inlineComponentsEnd() const
const Alias * aliasTable() const
const InlineComponent * inlineComponentAt(int idx) const
const Property * propertiesEnd() const
const Binding * bindingTable() const
const Signal * signalAt(int idx) const
const Property * propertiesBegin() const
const quint32_le * functionOffsetTable() const
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
TableIterator< InlineComponent, Object, &Object::inlineComponentAt > InlineComponentIterator
const InlineComponent * inlineComponentTable() const
InlineComponentIterator inlineComponentsBegin() const
TableIterator< RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt > RequiredPropertyExtraDataIterator
SignalIterator signalsEnd() const
const Alias * aliasesEnd() const
const Binding * bindingsBegin() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const
void setHasAliasAsDefaultProperty(bool defaultAlias)
const Alias * aliasesBegin() const
const quint32_le * namedObjectsInComponentTable() const
void set(Flags flags, quint32 typeNameIndexOrCommonType)
void setNameIndex(int nameIndex)
void setIsReadOnly(bool isReadOnly)
void setTypeNameIndex(int nameIndex)
void setIsVirtual(bool isVirtual)
quint32_le_bitfield_union< CommonTypeOrTypeNameIndexField, IsRequiredField, IsCommonTypeField, IsListField, IsReadOnlyField > data
quint32_le_bitfield_union< NameIndexField, IsVirtualField, IsOverrideField, IsFinalField > nameIndexAndVirtSpecifiers
void setIsOverride(bool isOverride)
void setIsRequired(bool isRequired)
const Object * objectAt(int idx) const
const Import * importAt(int idx) const
RegExp(quint32 flags, quint32 stringIndex)
Q_DECLARE_FLAGS(Flags, Flag)
bool addToHash(QCryptographicHash *hash, QHash< quintptr, QByteArray > *checksums) const
const Parameter * parametersBegin() const
static int calculateSize(int nParameters)
const Parameter * parametersEnd() const
const Parameter * parameterAt(int idx) const
static int calculateSize(const QString &str)
bool operator==(const TableIterator &rhs) const
bool operator!=(const TableIterator &rhs) const
TableIterator(const Container *container, int index)
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