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 0x49 // Added isVirtual and isOverride fields to property
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 {
898private:
901
902 // object id index (in QQmlContextData::idValues)
906
907public:
908
909 enum Flag : unsigned int {
912 // One bit vacant
913 };
914 Q_DECLARE_FLAGS(Flags, Flag)
915
919
920 union {
922 quint32_le localAliasIndex; // index in list of aliases local to the object (if targetObjectId == objectId)
923 };
926
927 bool hasFlag(Flag flag) const
928 {
929 return nameIndexAndFlags.get<FlagsField>() & flag;
930 }
931
932 void setFlag(Flag flag)
933 {
934 nameIndexAndFlags.set<FlagsField>(nameIndexAndFlags.get<FlagsField>() | flag);
935 }
936
938 {
939 nameIndexAndFlags.set<FlagsField>(0);
940 }
941
943 {
944 return nameIndexAndFlags.get<NameIndexField>();
945 }
946
947 void setNameIndex(quint32 nameIndex)
948 {
949 nameIndexAndFlags.set<NameIndexField>(nameIndex);
950 }
951
953 {
954 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<IdIndexField>();
955 }
956
957 void setIdIndex(quint32 idIndex)
958 {
959 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<IdIndexField>(idIndex);
960 }
961
962
964 {
965 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<AliasToLocalAliasField>();
966 }
967
968 void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
969 {
970 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<AliasToLocalAliasField>(isAliasToLocalAlias);
971 }
972
974 {
975 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<TargetObjectIdField>();
976 }
977
978 void setTargetObjectId(quint32 targetObjectId)
979 {
980 idIndexAndTargetObjectIdAndAliasToLocalAlias.set<TargetObjectIdField>(targetObjectId);
981 }
982};
983static_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");
984
985struct Object
986{
987private:
991public:
992 enum Flag : unsigned int {
993 NoFlag = 0x0,
994 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
995 HasDeferredBindings = 0x2, // any of the bindings are deferred
999 };
1001
1002 // Depending on the use, this may be the type name to instantiate before instantiating this
1003 // object. For grouped properties the type name will be empty and for attached properties
1004 // it will be the name of the attached type.
1009 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
1017 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
1018 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
1030// Function[]
1031// Property[]
1032// Signal[]
1033// Binding[]
1034// InlineComponent[]
1035// RequiredPropertyExtraData[]
1036
1037 Flags flags() const
1038 {
1039 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1040 }
1041
1042 bool hasFlag(Flag flag) const
1043 {
1044 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1045 }
1046
1047 void setFlag(Flag flag)
1048 {
1049 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1050 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1051 }
1052
1053 void setFlags(Flags flags)
1054 {
1055 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1056 }
1057
1059 {
1060 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1061 }
1062
1063 void setHasAliasAsDefaultProperty(bool defaultAlias)
1064 {
1065 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1066 }
1067
1069 {
1070 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1071 }
1072
1073 void setObjectId(qint32 id)
1074 {
1075 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1076 }
1077
1078
1079 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1080 {
1081 return ( sizeof(Object)
1082 + nFunctions * sizeof(quint32)
1083 + nProperties * sizeof(Property)
1084 + nAliases * sizeof(Alias)
1085 + nEnums * sizeof(quint32)
1086 + nSignals * sizeof(quint32)
1087 + nBindings * sizeof(Binding)
1088 + nNamedObjectsInComponent * sizeof(int)
1089 + nInlineComponents * sizeof(InlineComponent)
1090 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1091 + 0x7
1092 ) & ~0x7;
1093 }
1094
1096 {
1097 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1098 }
1099
1101 {
1102 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1103 }
1104
1105 const Alias *aliasTable() const
1106 {
1107 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1108 }
1109
1110 const Binding *bindingTable() const
1111 {
1112 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1113 }
1114
1115 const Enum *enumAt(int idx) const
1116 {
1117 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1118 const quint32_le offset = offsetTable[idx];
1119 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1120 }
1121
1122 const Signal *signalAt(int idx) const
1123 {
1124 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1125 const quint32_le offset = offsetTable[idx];
1126 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1127 }
1128
1130 {
1131 return inlineComponentTable() + idx;
1132 }
1133
1135 {
1136 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1137 }
1138
1140 {
1141 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1142 }
1143
1148
1150 {
1151 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1152 }
1153
1154 // --- QQmlPropertyCacheCreator interface
1155 int propertyCount() const { return nProperties; }
1156 int aliasCount() const { return nAliases; }
1157 int enumCount() const { return nEnums; }
1158 int signalCount() const { return nSignals; }
1159 int functionCount() const { return nFunctions; }
1160 int inlineComponentCount() const { return nInlineComponents; }
1161
1162 const Binding *bindingsBegin() const { return bindingTable(); }
1163 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1164 int bindingCount() const { return nBindings; }
1165
1166 const Property *propertiesBegin() const { return propertyTable(); }
1167 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1168
1169 const Alias *aliasesBegin() const { return aliasTable(); }
1170 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1171
1173 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1174 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1175
1177 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1178 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1179
1181 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1182 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1183
1185 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1186 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1187
1188 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1189 // ---
1190};
1191static_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");
1192
1194{
1195 enum ImportType : unsigned int {
1200 };
1202
1205
1209
1211 {
1212 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1213 }
1214};
1215static_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");
1216
1218{
1223
1224 const Import *importAt(int idx) const {
1225 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1226 }
1227
1228 const Object *objectAt(int idx) const {
1229 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1230 const quint32_le offset = offsetTable[idx];
1231 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1232 }
1233};
1234static_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");
1235
1236static const char magic_str[] = "qv4cdata";
1237
1238struct Unit
1239{
1240 // DO NOT CHANGE THESE FIELDS EVER
1241 char magic[8];
1243 // END DO NOT CHANGE THESE FIELDS EVER
1244
1245 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1247 quint32_le unitSize; // Size of the Unit and any depending data.
1248
1249 char md5Checksum[16]; // checksum of all bytes following this field.
1251
1252 enum : unsigned int {
1254 StaticData = 0x2, // Unit data persistent in memory?
1256 IsSharedLibrary = 0x8, // .pragma shared?
1258 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1259 IsStrict = 0x40,
1270 };
1305
1307
1308 /* QML specific fields */
1309
1310 const QmlUnit *qmlUnit() const {
1311 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1312 }
1313
1315 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1316 }
1317
1318 bool isSingleton() const {
1319 return flags & Unit::IsSingleton;
1320 }
1321 /* end QML specific fields*/
1322
1323 QString stringAtInternal(uint idx) const {
1324 Q_ASSERT(idx < stringTableSize);
1325 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1326 const quint32_le offset = offsetTable[idx];
1327 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1328 Q_ASSERT(str->size >= 0);
1329#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1330 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1331 if (flags & StaticData)
1332 return QString::fromRawData(characters, str->size);
1333 return QString(characters, str->size);
1334#else
1335 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1336 QString qstr(str->size, Qt::Uninitialized);
1337 QChar *ch = qstr.data();
1338 for (int i = 0; i < str->size; ++i)
1339 ch[i] = QChar(quint16(characters[i]));
1340 return qstr;
1341#endif
1342 }
1343
1344 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1345 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1346 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1347 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1348
1349 const Function *functionAt(int idx) const {
1350 const quint32_le *offsetTable = functionOffsetTable();
1351 const quint32_le offset = offsetTable[idx];
1352 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1353 }
1354
1355 const Class *classAt(int idx) const {
1356 const quint32_le *offsetTable = classOffsetTable();
1357 const quint32_le offset = offsetTable[idx];
1358 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1359 }
1360
1361 const TemplateObject *templateObjectAt(int idx) const {
1362 const quint32_le *offsetTable = templateObjectOffsetTable();
1363 const quint32_le offset = offsetTable[idx];
1364 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1365 }
1366
1367 const Block *blockAt(int idx) const {
1368 const quint32_le *offsetTable = blockOffsetTable();
1369 const quint32_le offset = offsetTable[idx];
1370 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1371 }
1372
1373 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1374 const RegExp *regexpAt(int index) const {
1375 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1376 }
1377 const quint64_le *constants() const {
1378 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1379 }
1380
1381 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1382 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1383 const quint32_le offset = offsetTable[idx];
1384 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1385 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1386 *nMembers = klass->nMembers;
1387 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1388 }
1389
1391 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1392 }
1393
1395 if ( translationTableSize == 0)
1396 return nullptr;
1397 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1398 + offsetToTranslationTable
1399 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1400
1402 if ( translationTableSize == 0)
1403 return nullptr;
1404 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1405 + offsetToTranslationTable
1406 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1407
1408 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1409 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1410 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1411 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1412
1413 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1414
1415 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1416};
1417
1418static_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");
1419
1421{
1423 : location(loc)
1424 , needsCreation(false)
1425 , errorWhenNotFound(false)
1426 {}
1427 Location location; // first use
1428 bool needsCreation : 1; // whether the type needs to be creatable or not
1430};
1431
1432// Map from name index to location of first use.
1434{
1435 TypeReference &add(int nameIndex, const Location &loc) {
1436 Iterator it = find(nameIndex);
1437 if (it != end())
1438 return *it;
1439 return *insert(nameIndex, loc);
1440 }
1441
1442 template <typename CompiledObject>
1443 void collectFromObject(const CompiledObject *obj)
1444 {
1445 if (obj->inheritedTypeNameIndex != 0) {
1446 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1447 r.needsCreation = true;
1448 r.errorWhenNotFound = true;
1449 }
1450
1451 auto binding = obj->bindingsBegin();
1452 auto const bindingEnd = obj->bindingsEnd();
1453 for ( ; binding != bindingEnd; ++binding) {
1455 this->add(binding->propertyNameIndex, binding->location);
1456 }
1457
1458 auto ic = obj->inlineComponentsBegin();
1459 auto const icEnd = obj->inlineComponentsEnd();
1460 for (; ic != icEnd; ++ic) {
1461 this->add(ic->nameIndex, ic->location);
1462 }
1463 }
1464
1465 template <typename Iterator>
1466 void collectFromObjects(Iterator it, Iterator end)
1467 {
1468 for (; it != end; ++it)
1469 collectFromObject(*it);
1470 }
1471};
1472
1474
1476
1478 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1479 : qmlType(qmlType)
1480 , objectIndex(objectIndex)
1481 , nameIndex(nameIndex)
1482 {}
1483
1484 QQmlType qmlType;
1485 int objectIndex = -1;
1486 int nameIndex = -1;
1487};
1488
1490{
1492
1493 const Unit *data = nullptr;
1494 const QmlUnit *qmlData = nullptr;
1497
1498 // pointers either to data->constants() or little-endian memory copy.
1499 const StaticValue *constants = nullptr;
1500
1502
1504
1505 // index is object index. This allows fast access to the
1506 // property data when initializing bindings, avoiding expensive
1507 // lookups by string (property name).
1509
1512
1514
1515 QQmlType qmlType;
1516
1518
1519public:
1520 // --- interface for QQmlPropertyCacheCreator
1524
1525 // Empty dummy. We don't need to do this when loading from cache.
1527 {
1528 public:
1529 void insert(int, int) {}
1530 void clear() {}
1531
1532 // We have already checked uniqueness of IDs when creating the CU
1533 bool contains(int) { return false; }
1534 };
1535
1536 explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1537 const QString &fileName = QString(), const QString &finalUrlString = QString())
1538 : CompilationUnit(unitData, fileName, finalUrlString)
1539 {
1540 this->aotCompiledFunctions = aotCompiledFunctions;
1541 }
1542
1544 const Unit *unitData = nullptr, const QString &fileName = QString(),
1545 const QString &finalUrlString = QString());
1546
1548
1549 const Unit *unitData() const { return data; }
1550
1551 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1552 const QString &fileName = QString(), const QString &finalUrlString = QString())
1553 {
1554 data = unitData;
1555 qmlData = nullptr;
1556#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1557 delete [] constants;
1558#endif
1559 constants = nullptr;
1560 m_fileName.clear();
1561 m_finalUrlString.clear();
1562 if (!data)
1563 return;
1564
1565 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1566
1567#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1568 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1569 const quint64_le *littleEndianConstants = data->constants();
1570 for (uint i = 0; i < data->constantTableSize; ++i)
1571 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1572 constants = bigEndianConstants;
1573#else
1574 constants = reinterpret_cast<const StaticValue*>(data->constants());
1575#endif
1576
1577 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1578 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1579 }
1580
1581 QString stringAt(uint index) const
1582 {
1583 if (index < data->stringTableSize)
1584 return data->stringAtInternal(index);
1585
1586 const qsizetype dynamicIndex = index - data->stringTableSize;
1587 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1588 return dynamicStrings.at(dynamicIndex);
1589 }
1590
1591 QString fileName() const { return m_fileName; }
1592 QString finalUrlString() const { return m_finalUrlString; }
1593
1595 {
1596 using namespace CompiledData;
1597 switch (binding->type()) {
1598 case Binding::Type_Script:
1599 case Binding::Type_String:
1600 return stringAt(binding->stringIndex);
1601 case Binding::Type_Null:
1602 return QStringLiteral("null");
1604 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1605 case Binding::Type_Number:
1606 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1608 return QString();
1609 case Binding::Type_TranslationById:
1610 case Binding::Type_Translation:
1611 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1612 default:
1613 break;
1614 }
1615 return QString();
1616 }
1617
1619 {
1620 return (binding->type() == CompiledData::Binding::Type_String)
1621 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1622 : bindingValueAsString(binding);
1623 }
1624
1625 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1626 {
1628 return 0.0;
1629 return constants[binding->value.constantValueIndex].doubleValue();
1630 }
1631
1632 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1634 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1635 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1636
1637 int importCount() const { return qmlData->nImports; }
1638 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1639
1640 Q_QML_EXPORT QStringList moduleRequests() const;
1641
1642 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1643 // warnings about that code. They include any potential URL interceptions and thus represent the
1644 // "physical" location of the code.
1645 //
1646 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1647 // They are _not_ intercepted and thus represent the "logical" name for the code.
1648
1649 QUrl url() const
1650 {
1651 if (!m_url.isValid())
1652 m_url = QUrl(fileName());
1653 return m_url;
1654 }
1655
1657 {
1658 if (!m_finalUrl.isValid())
1659 m_finalUrl = QUrl(finalUrlString());
1660 return m_finalUrl;
1661 }
1662
1663 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1664 ResolvedTypeReference *resolvedType(QMetaType type) const;
1665
1667 {
1668 return propertyCaches.isEmpty()
1669 ? QQmlPropertyCache::ConstPtr()
1670 : propertyCaches.at(/*root object*/0);
1671 }
1672
1673 int objectCount() const { return qmlData->nObjects; }
1674 const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); }
1675
1676 int inlineComponentId(const QString &inlineComponentName) const
1677 {
1678 for (uint i = 0; i < qmlData->nObjects; ++i) {
1679 auto *object = qmlData->objectAt(i);
1680 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1681 it != end; ++it) {
1682 if (stringAt(it->nameIndex) == inlineComponentName)
1683 return it->objectIndex;
1684 }
1685 }
1686 return -1;
1687 }
1688
1689 void finalizeCompositeType(const QQmlType &type);
1690
1691 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1692
1702
1707
1712
1714 {
1716 }
1717
1722
1724 {
1726 }
1727
1729 {
1731 }
1732
1733 bool isESModule() const
1734 {
1736 }
1737
1738 bool isSharedLibrary() const
1739 {
1741 }
1742
1744 {
1745 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1746 : unit(unit), object(object), index(index) {}
1750
1752 {
1753 return unit->functionAt(object->functionOffsetTable()[index]);
1754 }
1755
1756 void operator++() { ++index; }
1757 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1758 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1759 };
1760
1762 {
1763 return FunctionIterator(unitData(), object, 0);
1764 }
1765
1767 {
1768 return FunctionIterator(unitData(), object, object->nFunctions);
1769 }
1770
1771 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1772 QMetaType metaType() const { return qmlType.typeId(); }
1773
1774private:
1775 QString m_fileName; // initialized from data->sourceFileIndex
1776 QString m_finalUrlString; // initialized from data->finalUrlIndex
1777
1778 mutable QQmlNullableValue<QUrl> m_url;
1779 mutable QQmlNullableValue<QUrl> m_finalUrl;
1780};
1781
1783{
1785public:
1791
1793
1794 template<typename Char>
1795 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1796 {
1797 const quint32_le oldFlags = mutableFlags();
1798 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1799 mutableFlags() |= temporaryFlags;
1800 return writer(data<Char>(), size());
1801 }
1802
1803 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1804 QString *errorString)
1805 {
1806#if QT_CONFIG(temporaryfile)
1807 QSaveFile cacheFile(outputFileName);
1808 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1809 || cacheFile.write(data, size) != size
1810 || !cacheFile.commit()) {
1811 *errorString = cacheFile.errorString();
1812 return false;
1813 }
1814
1815 errorString->clear();
1816 return true;
1817#else
1818 Q_UNUSED(outputFileName);
1819 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1820 return false;
1821#endif
1822 }
1823
1824private:
1825 const Unit *unit;
1826 quint32 temporaryFlags;
1827
1828 quint32_le &mutableFlags() const
1829 {
1830 return const_cast<Unit *>(unit)->flags;
1831 }
1832
1833 template<typename Char>
1834 const Char *data() const
1835 {
1836 Q_STATIC_ASSERT(sizeof(Char) == 1);
1837 const Char *dataPtr;
1838 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1839 return dataPtr;
1840 }
1841
1842 quint32 size() const
1843 {
1844 return unit->unitSize;
1845 }
1846};
1847
1848
1849} // CompiledData namespace
1850} // QV4 namespace
1851
1854
1855QT_END_NAMESPACE
1856
1857#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 setIsAliasToLocalAlias(bool isAliasToLocalAlias)
void setTargetObjectId(quint32 targetObjectId)
bool hasFlag(Flag flag) const
quint32_le_bitfield_union< IdIndexField, TargetObjectIdField, AliasToLocalAliasField > idIndexAndTargetObjectIdAndAliasToLocalAlias
void setNameIndex(quint32 nameIndex)
void setIdIndex(quint32 idIndex)
quint32_le_bitfield_union< FlagsField, TypeField > flagsAndType
bool hasFlag(Flag flag) const
static QString escapedString(const QString &string)
const quint32_le * localsTable() const
static size_t align(size_t a)
static int calculateSize(int nLocals)
static int calculateSize(int nStaticMethods, int nMethods)
static size_t align(size_t a)
const Method * methodTable() const
bool operator!=(const FunctionIterator &rhs) const
bool operator==(const FunctionIterator &rhs) const
FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
std::unique_ptr< CompilationUnitMapper > backingFile
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