4#include <private/qqmlcomponentandaliasresolver_p.h>
5#include <private/qqmlengine_p.h>
6#include <private/qqmlirbuilder_p.h>
7#include <private/qqmlirloader_p.h>
8#include <private/qqmlpropertycachecreator_p.h>
9#include <private/qqmlpropertyvalidator_p.h>
10#include <private/qqmlscriptblob_p.h>
11#include <private/qqmlscriptdata_p.h>
12#include <private/qqmltypecompiler_p.h>
13#include <private/qqmltypedata_p.h>
14#include <private/qqmltypeloaderqmldircontent_p.h>
16#include <QtCore/qloggingcategory.h>
17#include <QtCore/qcryptographichash.h>
42 m_typesResolved(
false), m_implicitImportLoaded(
false)
50 m_compositeSingletons.clear();
51 m_resolvedTypes.clear();
61 return m_compiledData.
data();
66 Q_ASSERT(!m_callbacks.contains(callback));
67 m_callbacks.append(callback);
72 Q_ASSERT(m_callbacks.contains(callback));
73 m_callbacks.removeOne(callback);
74 Q_ASSERT(!m_callbacks.contains(callback));
79 if (inlineComponentName.
isEmpty())
81 return m_inlineComponentData[inlineComponentName].qmlType;
84bool QQmlTypeData::tryLoadFromDiskCache()
103 restoreIR(std::move(*unit));
107 m_compiledData = unit;
111 auto object = m_compiledData->
objectAt(
i);
113 const auto inlineComponentTable =
object->inlineComponentTable();
114 for (
auto i = 0;
i !=
object->nInlineComponents; ++
i) {
127 if (!loadImplicitImport())
134 &&
import->qualifierIndex == 0
135 && !
import->version.hasMajorVersion()
136 && !
import->version.hasMinorVersion()) {
138 auto pendingImport = std::make_shared<PendingImport>(
166 for (
auto&& ic: ics) {
169 importUrl.setFragment(nameString);
199typename QQmlComponentAndAliasResolver<QV4::ExecutableCompilationUnit>::AliasResolutionResult
203 const CompiledObject *
obj = m_compiler->objectAt(objectIndex);
204 for (
auto alias =
obj->aliasesBegin(),
end =
obj->aliasesEnd(); alias !=
end; ++alias) {
207 return NoAliasResolved;
211 return AllAliasesResolved;
223QQmlError QQmlTypeData::createTypeAndPropertyCaches(
247 result = propertyCacheCreator.buildMetaObjectsIncrementally();
248 if (
result.error.isValid()) {
258 pendingGroupPropertyBindings.
clear();
261 }
while (
result.canResume);
272 for (
const auto &typeRef: typeRefs) {
273 if (typeRef.typeData) {
274 const auto unit = typeRef.typeData->compilationUnit()->unitData();
275 hash->addData({unit->md5Checksum,
sizeof(unit->md5Checksum)});
276 }
else if (
const QMetaObject *
mo = typeRef.type.metaObject()) {
279 hash->addData(propertyCache->checksum(checksums, &
ok));
289template<
typename ObjectContainer>
294 for (
int i = 0;
i != container->objectCount(); ++
i) {
295 auto root = container->objectAt(
i);
296 for (
auto it = root->inlineComponentsBegin();
it != root->inlineComponentsEnd(); ++
it) {
302 int(
it->objectIndex),
int(
it->nameIndex), 0, 0, 0);
304 icData->
insert(container->stringAt(
it->nameIndex), icDatum);
310template<
typename Container>
311void QQmlTypeData::setCompileUnit(
const Container &container)
313 for (
int i = 0;
i != container->objectCount(); ++
i) {
314 auto const root = container->objectAt(
i);
315 for (
auto it = root->inlineComponentsBegin();
it != root->inlineComponentsEnd(); ++
it) {
324 typeRef->setCompilationUnit(m_compiledData);
334 m_typeReferences.
clear();
336 const auto encounteredErrors =
errors();
338 qCDebug(DBG_DISK_CACHE) <<
e.toString();
339 m_compiledData.
reset();
347 for (
int ii = 0; ii < m_scripts.size(); ++ii) {
374 for (
auto it = std::as_const(m_resolvedTypes).
begin(),
end = std::as_const(m_resolvedTypes).
end();
it !=
end;
377 Q_ASSERT(!
type.typeData ||
type.typeData->isCompleteOrError() ||
type.type.isInlineComponentType());
379 if (
type.type.isInlineComponentType()) {
384 int lastDot =
typeName.lastIndexOf(u
'.');
387 QQmlTypeLoader::tr(
"Type %1 has no inline component type called %2")
392 if (
type.typeData &&
type.typeData->isError()) {
394 createError(
type, QQmlTypeLoader::tr(
"Type %1 unavailable").
arg(
typeName));
400 for (
int ii = 0; ii < m_compositeSingletons.size(); ++ii) {
403 if (
type.typeData &&
type.typeData->isError()) {
406 createError(
type, QQmlTypeLoader::tr(
"Type %1 unavailable").
arg(
typeName));
412 const bool isSingleton = m_document
416 finalUrl(), m_compiledData, isSingleton
423 setupICs(m_document, &m_inlineComponentData,
finalUrl(), m_compiledData);
425 setupICs(m_compiledData, &m_inlineComponentData,
finalUrl(), m_compiledData);
430 QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
431 if (
error.isValid()) {
438 const auto dependencyHasher = [&resolvedTypeCache,
this]() {
448 if (m_document.
isNull()) {
449 const QQmlError error = createTypeAndPropertyCaches(typeNameCache, resolvedTypeCache);
451 setCompileUnit(m_compiledData);
454 if (
error.isValid()) {
456 <<
"Failed to create property caches for"
458 <<
"because" <<
error.description();
461 <<
"Checksum mismatch for cached version of"
465 if (!loadFromSource())
477 if (!
ref->type().isInlineComponentType())
486 m_compiledData.
reset();
490 if (!m_document.
isNull()) {
492 compile(typeNameCache, &resolvedTypeCache, dependencyHasher);
496 setCompileUnit(m_document);
518 if (!
type.isValid()) {
520 error.setDescription(QQmlTypeLoader::tr(
"No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
523 }
else if (!
type.isCompositeSingleton()) {
525 error.setDescription(QQmlTypeLoader::tr(
"pragma Singleton used with a non composite singleton type %1").
arg(
type.qmlTypeName()));
532 if (
type.isValid() &&
type.isCompositeSingleton()) {
534 setError(QQmlTypeLoader::tr(
"qmldir defines type as singleton, but no pragma Singleton found in type %1.").
arg(
typeName));
543 for (
int scriptIndex = 0; scriptIndex < m_scripts.size(); ++scriptIndex) {
550 if (lastDotIndex != -1) {
551 enclosingNamespace = qualifier.
left(lastDotIndex).toString();
552 qualifier = qualifier.
mid(lastDotIndex+1);
555 m_compiledData->
typeNameCache->
add(qualifier.toString(), scriptIndex, enclosingNamespace);
565 while (!m_callbacks.isEmpty()) {
571bool QQmlTypeData::loadImplicitImport()
573 m_implicitImportLoaded =
true;
596 &implicitImportErrors);
599 if (!implicitImportErrors.
isEmpty()) {
609 m_backupSourceCode =
data;
611 if (tryLoadFromDiskCache())
617 if (!m_backupSourceCode.
exists() || m_backupSourceCode.
isEmpty()) {
619 setError(QQmlTypeLoader::tr(
"File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile"));
620 else if (!m_backupSourceCode.
exists())
621 setError(QQmlTypeLoader::tr(
"No such file or directory"));
623 setError(QQmlTypeLoader::tr(
"File is empty"));
627 if (!loadFromSource())
630 continueLoadFromIR();
641 continueLoadFromIR();
644bool QQmlTypeData::loadFromSource()
666 e.setDescription(msg.message);
683 continueLoadFromIR();
686void QQmlTypeData::continueLoadFromIR()
688 for (
auto const&
object: m_document->objects) {
689 for (
auto it =
object->inlineComponentsBegin();
it !=
object->inlineComponentsEnd(); ++
it) {
692 importUrl.setFragment(nameString);
704 if (!
finalUrl().scheme().isEmpty()) {
707 if (!loadImplicitImport())
710 auto implicitImport = std::make_shared<PendingImport>();
745 if (!m_typesResolved) {
750 if ((*it)->priority == 0) {
754 keyIt != keyEnd; ++keyIt) {
757 error.setDescription(QQmlTypeLoader::tr(
"module \"%1\" is not installed").arg(import->uri));
760 import->location.line()));
762 import->location.column()));
773 m_typesResolved =
true;
779 for (
int ii = 0; ii < m_callbacks.size(); ++ii) {
802 QQmlTypeCompiler compiler(enginePrivate,
this, m_document.
data(), typeNameCache, resolvedTypeCache, dependencyHasher);
803 m_compiledData = compiler.compile();
804 if (!m_compiledData) {
806 resolvedTypeCache->
clear();
807 setError(compiler.compilationErrors());
811 const bool trySaveToDisk =
writeCacheFile() && !typeRecompilation;
825void QQmlTypeData::resolveTypes()
835 if (!script.qualifier.isEmpty())
837 ref.qualifier = script.qualifier +
QLatin1Char(
'.') + script.nameSpace;
839 m_namespaces.
insert(script.qualifier);
841 ref.qualifier = script.nameSpace;
853 if (!csRef.prefix.isEmpty()) {
856 m_namespaces.
insert(csRef.prefix);
865 if (
ref.type.isCompositeSingleton()) {
868 qCWarning(lcCycle) <<
"Cyclic dependency detected between"
873 ref.prefix = csRef.prefix;
875 m_compositeSingletons <<
ref;
880 unresolvedRef !=
end; ++unresolvedRef) {
884 const bool reportErrors = unresolvedRef->errorWhenNotFound;
890 bool *selfReferenceDetection = unresolvedRef->needsCreation ?
nullptr : &
ref.selfReference;
892 if (!resolveType(
name, version,
ref, unresolvedRef->location.line(),
893 unresolvedRef->location.column(), reportErrors,
897 if (
ref.type.isComposite() && !
ref.selfReference) {
901 if (
ref.type.isInlineComponentType()) {
902 QUrl containingTypeUrl =
ref.type.sourceUrl();
904 if (!containingTypeUrl.
isEmpty()) {
906 if (typeData.data() !=
this) {
907 ref.typeData = typeData;
913 ref.version = version;
914 ref.location = unresolvedRef->location;
915 ref.needsCreation = unresolvedRef->needsCreation;
916 m_resolvedTypes.insert(unresolvedRef.key(),
ref);
920 if (!m_implicitImportLoaded)
921 loadImplicitImport();
924QQmlError QQmlTypeData::buildTypeResolutionCaches(
931 (*typeNameCache)->
add(
ns);
939 for (
auto resolvedType = m_resolvedTypes.constBegin(),
end = m_resolvedTypes.constEnd(); resolvedType !=
end; ++resolvedType) {
940 auto ref = std::make_unique<QV4::ResolvedTypeReference>();
942 if (resolvedType->typeData) {
946 ref->setCompilationUnit(resolvedType->typeData->compilationUnit());
947 if (resolvedType->type.isInlineComponentType()) {
952 const auto compilationUnit = resolvedType->typeData->compilationUnit();
958 }
else if (resolvedType->type.isInlineComponentType()) {
970 ref->setCompilationUnit(exUnit);
981 reason =
tr(
"Element is not creatable.");
988 ref->setTypePropertyCache(
992 ref->setVersion(resolvedType->version);
993 ref->doDynamicTypeCheck();
994 resolvedTypeCache->
insert(resolvedType.key(),
ref.release());
1001 TypeReference &
ref,
int lineNumber,
int columnNumber,
1003 bool *typeRecursionDetected)
1009 &typeNamespace, &
errors, registrationType,
1010 typeRecursionDetected);
1011 if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
1013 if (loadImplicitImport()) {
1017 &typeNamespace, &
errors, registrationType,
1018 typeRecursionDetected);
1024 if ((!typeFound || typeNamespace) && reportErrors) {
1029 if (typeNamespace) {
1030 error.setDescription(QQmlTypeLoader::tr(
"Namespace %1 cannot be used as a type").
arg(
typeName));
1037 error.setDescription(QQmlTypeLoader::tr(
"Unreported error adding script import to import database"));
1043 if (lineNumber != -1)
1044 error.setLine(lineNumber);
1045 if (columnNumber != -1)
1046 error.setColumn(columnNumber);
QByteArray chopped(qsizetype len) const
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
bool empty() const noexcept
This function is provided for STL compatibility.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
QV4::ExecutionEngine * handle() const
qsizetype size() const noexcept
bool isEmpty() const noexcept
void push_back(parameter_type t)
void prepend(rvalue_ref t)
void reserve(qsizetype size)
QDateTime sourceTimeStamp() const
QString readAll(QString *error) const
bool isError() const
Returns true if the status is Error.
bool isCompleteOrError() const
Returns true if the status is Complete or Error.
void addDependency(QQmlDataBlob *)
Wait for blob to become complete or to error.
QList< QQmlError > errors() const
Return the errors on this blob.
QUrl url() const
Returns the physical url of the data.
QQmlTypeLoader * typeLoader() const
QUrl finalUrl() const
Returns the logical URL to be used for resolving further URLs referred to in the code.
QList< QQmlDataBlob * > m_waitingOnMe
virtual void allDependenciesDone()
Called when all blobs waited for have completed.
QString finalUrlString() const
Returns the finalUrl() as a string.
Type type() const
Returns the type provided to the constructor.
void setError(const QQmlError &)
Mark this blob as having errors.
QString urlString() const
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlEngine class provides an environment for instantiating QML components.
The QQmlError class encapsulates a QML error.
The QQmlImportDatabase class manages the QML imports for a QQmlEngine.
void populateCache(QQmlTypeNameCache *cache) const
bool resolveType(const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
QList< CompositeSingletonReference > resolvedCompositeSingletons() const
QList< ScriptReference > resolvedScripts() const
QTypeRevision addImplicitImport(QQmlImportDatabase *importDb, QString *localQmldir, QList< QQmlError > *errors)
bool addInlineComponentImport(QQmlImportInstance *const importInstance, const QString &name, const QUrl importUrl)
void setBaseUrl(const QUrl &url, const QString &urlString=QString())
Sets the base URL to be used for all relative file imports added.
static bool isLocal(const QString &url)
QQmlPropertyCache::ConstPtr at(int index) const
QVector< QQmlError > validate()
QQmlRefPointer< T > & adopt(T *)
Takes ownership of other.
QQmlRefPointer< QQmlScriptData > scriptData() const
void done() override
Invoked once data has either been received or a network error occurred, and all dependencies are comp...
QV4::ExecutableCompilationUnit * compilationUnit() const
void registerCallback(TypeDataCallback *)
void completed() override
Invoked on the main thread sometime after done() was called on the load thread.
void downloadProgressChanged(qreal) override
Called when the download progress of this blob changes.
const QList< ScriptReference > & resolvedScripts() const
void unregisterCallback(TypeDataCallback *)
void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) override
QQmlType qmlType(const QString &inlineComponentName=QString()) const
void dataReceived(const SourceCodeData &) override
Invoked when data for the blob is received.
void scriptImported(const QQmlRefPointer< QQmlScriptBlob > &blob, const QV4::CompiledData::Location &location, const QString &nameSpace, const QString &qualifier) override
QString stringAt(int index) const override
QByteArray typeClassName() const
void allDependenciesDone() override
Called when all blobs waited for have completed.
QString typeNamespace() const
QQmlDirImports imports() const
std::shared_ptr< PendingImport > PendingImportPtr
bool readCacheFile() const
bool addImport(const QV4::CompiledData::Import *import, QQmlImports::ImportFlags, QList< QQmlError > *errors)
bool fetchQmldir(const QUrl &url, PendingImportPtr import, int priority, QList< QQmlError > *errors)
const QQmlImports * imports() const
bool writeCacheFile() const
QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus
QVector< PendingImportPtr > m_unresolvedImports
bool loadDependentImports(const QList< QQmlDirParser::Import > &imports, const QString &qualifier, QTypeRevision version, quint16 precedence, QQmlImports::ImportFlags flags, QList< QQmlError > *errors)
QQmlRefPointer< QQmlImports > m_importCache
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
QQmlEngine * engine() const
Return the QQmlEngine associated with this loader.
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
QQmlImportDatabase * importDatabase() const
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl)
Return a QQmlScriptBlob for url.
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath)
Return a QQmlTypeLoaderQmldirContent for absoluteFilePath.
void add(const QHashedString &name, int sciptIndex=-1, const QHashedString &nameSpace=QHashedString())
bool isCompositeSingleton() const
QTypeRevision version() const
QString noCreationReason() const
QString qmlTypeName() const
const QMetaObject * metaObject() const
QString elementName() const
bool containsRevisionedAttributes() const
T * data() const noexcept
Returns the value of the pointer referenced by this object.
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
QString scheme() const
Returns the scheme of the URL.
const CompiledObject * objectAt(int index) const
QQmlPropertyCacheVector propertyCaches
const CompiledData::Import * importAt(int index) const
void finalizeCompositeType(const QQmlType &type)
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
ResolvedTypeReference * resolvedType(int id) const
QVector< QQmlRefPointer< QQmlScriptData > > dependentScripts
ResolvedTypeReferenceMap resolvedTypes
bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
int inlineComponentId(const QString &inlineComponentName) const
QHash< QString, InlineComponentData > inlineComponentData
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
bool saveToDisk(const QUrl &unitUrl, QString *errorString)
static QQmlRefPointer< ExecutableCompilationUnit > create()
void setReferencesCompilationUnit(bool doReference)
QHash< int, QWidget * > hash
[35multi]
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
std::function< QByteArray()> DependentTypesHasher
DBusConnection const char DBusError * error
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLenum GLenum GLsizei count
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QQmlEngine * qmlEngine(const QObject *obj)
QT_BEGIN_NAMESPACE QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
static bool addTypeReferenceChecksumsToHash(const QList< QQmlTypeData::TypeReference > &typeRefs, QHash< quintptr, QByteArray > *checksums, QCryptographicHash *hash)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
QLatin1StringView QLatin1String
QNetworkAccessManager manager
\inmodule QtCore \reentrant
bool contains(const AT &t) const noexcept
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const
const AOTCompiledFunction * aotCompiledFunctions
const QV4::CompiledData::Unit * qmlData
static bool canCreateClassNameTypeByUrl(const QUrl &url)
QQmlRefPointer< QQmlScriptBlob > script
QV4::CompiledData::Location location
virtual void typeDataProgress(QQmlTypeData *, qreal)
virtual void typeDataReady(QQmlTypeData *)
QString qualifiedName() const
QString stringAt(uint index) const
const Unit * unitData() const
void collectFromObject(const CompiledObject *obj)
void collectFromObjects(Iterator it, Iterator end)
StringTableGenerator stringTable
QDateTime sourceTimeStamp
QString stringForIndex(int index) const
const QSet< QString > & illegalNames() const
bool addToHash(QCryptographicHash *hash, QHash< quintptr, QByteArray > *checksums) const
QVector< Object * > objects
QString stringAt(int index) const
QV4::Compiler::Module jsModule
QV4::CompiledData::CompilationUnit javaScriptCompilationUnit
QV4::Compiler::JSUnitGenerator jsGenerator