Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmltypeloader.cpp
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
4#include <private/qqmltypeloader_p.h>
5
6#include <private/qqmldirdata_p.h>
7#include <private/qqmlprofiler_p.h>
8#include <private/qqmlscriptblob_p.h>
9#include <private/qqmltypedata_p.h>
10#include <private/qqmltypeloaderqmldircontent_p.h>
11#include <private/qqmltypeloaderthread_p.h>
12#include <private/qqmlsourcecoordinate_p.h>
13
14#include <QtQml/qqmlabstracturlinterceptor.h>
15#include <QtQml/qqmlengine.h>
16#include <QtQml/qqmlextensioninterface.h>
17#include <QtQml/qqmlfile.h>
18
19#include <qtqml_tracepoints_p.h>
20
21#include <QtCore/qdir.h>
22#include <QtCore/qdiriterator.h>
23#include <QtCore/qfile.h>
24#include <QtCore/qthread.h>
25
26#include <functional>
27
28// #define DATABLOB_DEBUG
29#ifdef DATABLOB_DEBUG
30#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
31#else
32#define ASSERT_LOADTHREAD()
33#endif
34
35
37
38namespace {
39
40 template<typename LockType>
42 {
43 LockType& lock;
44 LockHolder(LockType *l) : lock(*l) { lock.lock(); }
45 ~LockHolder() { lock.unlock(); }
46 };
47}
48
49Q_TRACE_POINT(qtqml, QQmlCompiling_entry, const QUrl &url)
50Q_TRACE_POINT(qtqml, QQmlCompiling_exit)
51
52
82void QQmlTypeLoader::invalidate()
83{
84 if (m_thread) {
85 shutdownThread();
86 delete m_thread;
87 m_thread = nullptr;
88 }
89
90#if QT_CONFIG(qml_network)
91 // Need to delete the network replies after
92 // the loader thread is shutdown as it could be
93 // getting new replies while we clear them
94 m_networkReplies.clear();
95#endif // qml_network
96}
97
98#if QT_CONFIG(qml_debug)
100{
101 Q_ASSERT(!m_profiler);
102 m_profiler.reset(profiler);
103}
104#endif
105
108 {
109 loader->loadThread(blob);
110 }
112 {
113 loader->m_thread->load(blob);
114 }
116 {
117 loader->m_thread->loadAsync(blob);
118 }
119};
120
124
126 {
127 loader->loadWithStaticDataThread(blob, data);
128 }
130 {
131 loader->m_thread->loadWithStaticData(blob, data);
132 }
134 {
135 loader->m_thread->loadWithStaticDataAsync(blob, data);
136 }
137};
138
142
144 {
145 loader->loadWithCachedUnitThread(blob, unit);
146 }
148 {
149 loader->m_thread->loadWithCachedUnit(blob, unit);
150 }
152 {
153 loader->m_thread->loadWithCachedUnitAsync(blob, unit);
154 }
155};
156
157template<typename Loader>
158void QQmlTypeLoader::doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode)
159{
160#ifdef DATABLOB_DEBUG
161 qWarning("QQmlTypeLoader::doLoad(%s): %s thread", qPrintable(blob->urlString()),
162 m_thread->isThisThread()?"Compile":"Engine");
163#endif
164 blob->startLoading();
165
166 if (m_thread->isThisThread()) {
167 unlock();
168 loader.loadThread(this, blob);
169 lock();
170 } else if (mode == Asynchronous) {
171 blob->m_data.setIsAsync(true);
172 unlock();
173 loader.loadAsync(this, blob);
174 lock();
175 } else {
176 unlock();
177 loader.load(this, blob);
178 lock();
179 if (mode == PreferSynchronous) {
180 if (!blob->isCompleteOrError())
181 blob->m_data.setIsAsync(true);
182 } else {
184 while (!blob->isCompleteOrError()) {
185 m_thread->waitForNextMessage();
186 }
187 }
188 }
189}
190
197{
198 doLoad(PlainLoader(), blob, mode);
199}
200
207{
208 doLoad(StaticLoader(data), blob, mode);
209}
210
212{
213 doLoad(CachedLoader(unit), blob, mode);
214}
215
216void QQmlTypeLoader::loadWithStaticDataThread(const QQmlDataBlob::Ptr &blob, const QByteArray &data)
217{
219
220 setData(blob, data);
221}
222
223void QQmlTypeLoader::loadWithCachedUnitThread(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit)
224{
226
227 setCachedUnit(blob, unit);
228}
229
230void QQmlTypeLoader::loadThread(const QQmlDataBlob::Ptr &blob)
231{
233
234 // Don't continue loading if we've been shutdown
235 if (m_thread->isShutdown()) {
237 error.setDescription(QLatin1String("Interrupted by shutdown"));
238 blob->setError(error);
239 return;
240 }
241
242 if (blob->m_url.isEmpty()) {
244 error.setDescription(QLatin1String("Invalid null URL"));
245 blob->setError(error);
246 return;
247 }
248
249 if (QQmlFile::isSynchronous(blob->m_url)) {
252 blob->setError(QLatin1String("File name case mismatch"));
253 return;
254 }
255
256 blob->m_data.setProgress(1.f);
257 if (blob->m_data.isAsync())
258 m_thread->callDownloadProgressChanged(blob, 1.);
259
260 setData(blob, fileName);
261
262 } else {
263#if QT_CONFIG(qml_network)
264 QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url));
265 QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy();
266 m_networkReplies.insert(reply, blob);
267
268 if (reply->isFinished()) {
269 nrp->manualFinished(reply);
270 } else {
271 QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
272 nrp, SLOT(downloadProgress(qint64,qint64)));
273 QObject::connect(reply, SIGNAL(finished()),
274 nrp, SLOT(finished()));
275 }
276
277#ifdef DATABLOB_DEBUG
278 qWarning("QQmlDataBlob: requested %s", qPrintable(blob->urlString()));
279#endif // DATABLOB_DEBUG
280#endif // qml_network
281 }
282}
283
284#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
285
286#ifndef TYPELOADER_MINIMUM_TRIM_THRESHOLD
287#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64
288#endif
289
290#if QT_CONFIG(qml_network)
291void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
292{
293 Q_ASSERT(m_thread->isThisThread());
294
296
297 QQmlRefPointer<QQmlDataBlob> blob = m_networkReplies.take(reply);
298
299 Q_ASSERT(blob);
300
301 blob->m_redirectCount++;
302
303 if (blob->m_redirectCount < DATALOADER_MAXIMUM_REDIRECT_RECURSION) {
305 if (redirect.isValid()) {
306 QUrl url = reply->url().resolved(redirect.toUrl());
307 blob->m_finalUrl = url;
308 blob->m_finalUrlString.clear();
309
310 QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url));
311 QObject *nrp = m_thread->networkReplyProxy();
312 QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished()));
313 m_networkReplies.insert(reply, std::move(blob));
314#ifdef DATABLOB_DEBUG
315 qWarning("QQmlDataBlob: redirected to %s", qPrintable(blob->finalUrlString()));
316#endif
317 return;
318 }
319 }
320
321 if (reply->error()) {
322 blob->networkError(reply->error());
323 } else {
325 setData(blob, data);
326 }
327}
328
329void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply,
330 qint64 bytesReceived, qint64 bytesTotal)
331{
332 Q_ASSERT(m_thread->isThisThread());
333
334 const QQmlRefPointer<QQmlDataBlob> blob = m_networkReplies.value(reply);
335
336 Q_ASSERT(blob);
337
338 if (bytesTotal != 0) {
339 qreal progress = (qreal(bytesReceived) / qreal(bytesTotal));
340 blob->m_data.setProgress(progress);
341 if (blob->m_data.isAsync())
342 m_thread->callDownloadProgressChanged(blob, blob->m_data.progress());
343 }
344}
345#endif // qml_network
346
351{
352 return m_engine;
353}
354
359template<class Interface>
361 const char *uri)
362{
364
365 if (thread->isThisThread()) {
366 thread->initializeEngine(iface, uri);
367 } else {
369 iface->initializeEngine(engine, uri);
370 }
371}
372
374{
375 doInitializeEngine(iface, m_thread, engine(), uri);
376}
377
379{
380 doInitializeEngine(iface, m_thread, engine(), uri);
381}
382
383void QQmlTypeLoader::setData(const QQmlDataBlob::Ptr &blob, const QByteArray &data)
384{
386 d.inlineSourceCode = QString::fromUtf8(data);
387 d.hasInlineSourceCode = true;
388 setData(blob, d);
389}
390
391void QQmlTypeLoader::setData(const QQmlDataBlob::Ptr &blob, const QString &fileName)
392{
394 d.fileInfo = QFileInfo(fileName);
395 setData(blob, d);
396}
397
398void QQmlTypeLoader::setData(const QQmlDataBlob::Ptr &blob, const QQmlDataBlob::SourceCodeData &d)
399{
400 Q_TRACE_SCOPE(QQmlCompiling, blob->url());
401 QQmlCompilingProfiler prof(profiler(), blob.data());
402
403 blob->m_inCallback = true;
404
405 blob->dataReceived(d);
406
407 if (!blob->isError() && !blob->isWaiting())
408 blob->allDependenciesDone();
409
410 if (blob->status() != QQmlDataBlob::Error)
411 blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
412
413 blob->m_inCallback = false;
414
415 blob->tryDone();
416}
417
418void QQmlTypeLoader::setCachedUnit(const QQmlDataBlob::Ptr &blob, const QQmlPrivate::CachedQmlUnit *unit)
419{
420 Q_TRACE_SCOPE(QQmlCompiling, blob->url());
421 QQmlCompilingProfiler prof(profiler(), blob.data());
422
423 blob->m_inCallback = true;
424
425 blob->initializeFromCachedUnit(unit);
426
427 if (!blob->isError() && !blob->isWaiting())
428 blob->allDependenciesDone();
429
430 if (blob->status() != QQmlDataBlob::Error)
431 blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
432
433 blob->m_inCallback = false;
434
435 blob->tryDone();
436}
437
438void QQmlTypeLoader::shutdownThread()
439{
440 if (m_thread && !m_thread->isShutdown())
441 m_thread->shutdown();
442}
443
446 QQmlImports::ImportFlags flags)
447 : uri(blob->stringAt(import->uriIndex))
448 , qualifier(blob->stringAt(import->qualifierIndex))
449 , type(static_cast<QV4::CompiledData::Import::ImportType>(quint32(import->type)))
450 , location(import->location)
451 , flags(flags)
452 , version(import->version)
453{
454}
455
459{
460}
461
463{
464}
465
467{
468 QQmlRefPointer<QQmlQmldirData> data = typeLoader()->getQmldir(url);
469
470 data->setPriority(this, std::move(import), priority);
471
472 if (data->status() == Error) {
473 // This qmldir must not exist - which is not an error
474 return true;
475 } else if (data->status() == Complete) {
476 // This data is already available
477 return qmldirDataAvailable(data, errors);
478 }
479
480 // Wait for this data to become available
481 addDependency(data.data());
482 return true;
483}
484
492 const QQmlTypeLoaderQmldirContent &qmldir, const QUrl &qmldirUrl)
493{
494 const auto qmldirScripts = qmldir.scripts();
495 for (const QQmlDirParser::Script &script : qmldirScripts) {
496 const QUrl scriptUrl = qmldirUrl.resolved(QUrl(script.fileName));
497 QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
498 addDependency(blob.data());
499 scriptImported(blob, import->location, script.nameSpace, import->qualifier);
500 }
501}
502
503template<typename URL>
506 const QQmlTypeLoader::Blob::PendingImportPtr &import, const QString &qmldirFilePath,
507 const URL &qmldirUrl)
508{
509 const QQmlTypeLoaderQmldirContent qmldir = self->typeLoader()->qmldirContent(qmldirFilePath);
510 if (!import->qualifier.isEmpty())
511 self->importQmldirScripts(import, qmldir, QUrl(qmldirUrl));
512
513 if (qmldir.plugins().isEmpty()) {
514 // If the qmldir does not register a plugin, we might still have declaratively
515 // registered types (if we are dealing with an application instead of a library)
516 // We should use module name given in the qmldir rather than the one given by the
517 // import since the import may be a directory import.
518 auto module = QQmlMetaType::typeModule(qmldir.typeNamespace(), import->version);
519 if (!module)
521 // else: If the module already exists, the types must have been already registered
522 }
523}
524
526{
527 QString qmldirIdentifier = data->urlString();
528 QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1);
529
530 typeLoader()->setQmldirContent(qmldirIdentifier, data->content());
531
532 const QTypeRevision version = m_importCache->updateQmldirContent(
533 typeLoader()->importDatabase(), import->uri, import->qualifier, qmldirIdentifier,
534 qmldirUrl, errors);
535 if (!version.isValid())
536 return false;
537
538 // Use more specific version for dependencies if possible
539 if (version.hasMajorVersion())
540 import->version = version;
541
542 if (!loadImportDependencies(import, qmldirIdentifier, import->flags, errors))
543 return false;
544
545 import->priority = 0;
546
547 // Release this reference at destruction
548 m_qmldirs << data;
549
550 postProcessQmldir(this, import, qmldirIdentifier, qmldirUrl);
551 return true;
552}
553
554bool QQmlTypeLoader::Blob::addScriptImport(const QQmlTypeLoader::Blob::PendingImportPtr &import)
555{
556 const QUrl url(import->uri);
557 const auto module = m_typeLoader->engine()->handle()->moduleForUrl(url);
559 if (module.native) {
560 blob.adopt(new QQmlScriptBlob(url, m_typeLoader));
561 blob->initializeFromNative(*module.native);
562 blob->tryDone();
563 } else {
564 blob = typeLoader()->getScript(finalUrl().resolved(url));
565 }
566 addDependency(blob.data());
567 scriptImported(blob, import->location, import->qualifier, QString());
568 return true;
569}
570
571bool QQmlTypeLoader::Blob::addFileImport(const QQmlTypeLoader::Blob::PendingImportPtr &import, QList<QQmlError> *errors)
572{
573 QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
574 QQmlImports::ImportFlags flags;
575
576 QUrl importUrl(import->uri);
577 QString path = importUrl.path();
578 path.append(QLatin1String(path.endsWith(QLatin1Char('/')) ? "qmldir" : "/qmldir"));
579 importUrl.setPath(path);
580 QUrl qmldirUrl = finalUrl().resolved(importUrl);
581 if (!QQmlImports::isLocal(qmldirUrl)) {
582 // This is a remote file; the import is currently incomplete
584 }
585
586 const QTypeRevision version = m_importCache->addFileImport(
587 importDatabase, import->uri, import->qualifier, import->version, flags,
588 import->precedence, nullptr, errors);
589 if (!version.isValid())
590 return false;
591
592 // Use more specific version for the qmldir if possible
593 if (version.hasMajorVersion())
594 import->version = version;
595
597 if (!fetchQmldir(qmldirUrl, import, 1, errors))
598 return false;
599 } else {
601 if (!loadImportDependencies(import, qmldirFilePath, import->flags, errors))
602 return false;
603
604 postProcessQmldir(this, import, qmldirFilePath, qmldirUrl);
605 }
606
607 return true;
608}
609
610bool QQmlTypeLoader::Blob::addLibraryImport(const QQmlTypeLoader::Blob::PendingImportPtr &import, QList<QQmlError> *errors)
611{
612 QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
613
615 QQmlMetaType::isStronglyLockedModule(import->uri, import->version)
618
621 import->uri, import->version, searchMode,
622 [&](const QString &qmldirFilePath, const QString &qmldirUrl) {
623 // This is a local library import
624 const QTypeRevision actualVersion = m_importCache->addLibraryImport(
625 importDatabase, import->uri, import->qualifier,
626 import->version, qmldirFilePath, qmldirUrl, import->flags, import->precedence,
627 errors);
628 if (!actualVersion.isValid())
629 return false;
630
631 // Use more specific version for dependencies if possible
632 if (actualVersion.hasMajorVersion())
633 import->version = actualVersion;
634
635 if (!loadImportDependencies(import, qmldirFilePath, import->flags, errors)) {
636 QQmlError error;
637 QString reason = errors->front().description();
638 if (reason.size() > 512)
639 reason = reason.first(252) + QLatin1String("... ...") + reason.last(252);
640 if (import->version.hasMajorVersion()) {
641 error.setDescription(QQmlImportDatabase::tr(
642 "module \"%1\" version %2.%3 cannot be imported because:\n%4")
643 .arg(import->uri).arg(import->version.majorVersion())
644 .arg(import->version.hasMinorVersion()
645 ? QString::number(import->version.minorVersion())
646 : QLatin1String("x"))
647 .arg(reason));
648 } else {
649 error.setDescription(QQmlImportDatabase::tr("module \"%1\" cannot be imported because:\n%2")
650 .arg(import->uri, reason));
651 }
652 errors->prepend(error);
653 return false;
654 }
655
656 postProcessQmldir(this, import, qmldirFilePath, qmldirUrl);
657 return true;
658 });
659
660 switch (qmldirResult) {
662 return true;
665 break;
667 return false;
668 }
669
670 // If there is a qmldir we cannot see, yet, then we have to wait.
671 // The qmldir might contain import directives.
672 if (qmldirResult != QQmlImportDatabase::QmldirInterceptedToRemote && (
673 // Major version of module already registered:
674 // We believe that the registration is complete.
675 QQmlMetaType::typeModule(import->uri, import->version)
676
677 // Otherwise, try to register further module types.
679
680 // Otherwise, there is no way to register any further types.
681 // Try with any module of that name.
682 || QQmlMetaType::latestModuleVersion(import->uri).isValid())) {
683
684 if (!m_importCache->addLibraryImport(
685 importDatabase, import->uri, import->qualifier, import->version,
686 QString(), QString(), import->flags, import->precedence, errors).isValid()) {
687 return false;
688 }
689 } else {
690 // We haven't yet resolved this import
691 m_unresolvedImports << import;
692
693 const QQmlEngine *engine = typeLoader()->engine();
694 const bool hasInterceptors
696
697 // Query any network import paths for this library.
698 // Interceptor might redirect local paths.
699 QStringList remotePathList = importDatabase->importPathList(
700 hasInterceptors ? QQmlImportDatabase::LocalOrRemote
701 : QQmlImportDatabase::Remote);
702 if (!remotePathList.isEmpty()) {
703 // Add this library and request the possible locations for it
704 const QTypeRevision version = m_importCache->addLibraryImport(
705 importDatabase, import->uri, import->qualifier, import->version,
706 QString(), QString(), import->flags | QQmlImports::ImportIncomplete,
707 import->precedence, errors);
708
709 if (!version.isValid())
710 return false;
711
712 // Use more specific version for finding the qmldir if possible
713 if (version.hasMajorVersion())
714 import->version = version;
715
716 // Probe for all possible locations
717 int priority = 0;
719 import->uri, remotePathList, import->version);
720 for (const QString &qmldirPath : qmlDirPaths) {
721 if (hasInterceptors) {
726 && !fetchQmldir(url, import, ++priority, errors)) {
727 return false;
728 }
729 } else if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors)) {
730 return false;
731 }
732
733 }
734 }
735 }
736
737 return true;
738}
739
741 QQmlImports::ImportFlags flags, QList<QQmlError> *errors)
742{
743 return addImport(std::make_shared<PendingImport>(this, import, flags), errors);
744}
745
748{
749 Q_ASSERT(errors);
750
751 switch (import->type)
752 {
754 return addLibraryImport(import, errors);
756 return addFileImport(import ,errors);
758 return addScriptImport(import);
760 Q_UNREACHABLE_RETURN(false); // addImport is never called with an inline component import
761 }
762
763 Q_UNREACHABLE_RETURN(false);
764}
765
767{
768 if (blob->type() == QQmlDataBlob::QmldirFile) {
769 QQmlQmldirData *data = static_cast<QQmlQmldirData *>(blob);
770 QList<QQmlError> errors;
771 if (!qmldirDataAvailable(data, &errors)) {
772 Q_ASSERT(errors.size());
773 QQmlError error(errors.takeFirst());
774 error.setUrl(m_importCache->baseUrl());
775 const QV4::CompiledData::Location importLocation = data->importLocation(this);
776 error.setLine(qmlConvertSourceCoordinate<quint32, int>(importLocation.line()));
777 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(importLocation.column()));
778 errors.prepend(error); // put it back on the list after filling out information.
779 setError(errors);
780 }
781 }
782}
783
785 const QList<QQmlDirParser::Import> &imports, const QString &qualifier,
786 QTypeRevision version, quint16 precedence, QQmlImports::ImportFlags flags,
787 QList<QQmlError> *errors)
788{
789 for (const auto &import : imports) {
791 continue;
792 auto dependencyImport = std::make_shared<PendingImport>();
793 dependencyImport->uri = import.module;
794 dependencyImport->qualifier = qualifier;
795 dependencyImport->version = (import.flags & QQmlDirParser::Import::Auto)
796 ? version : import.version;
797 dependencyImport->flags = flags;
798 dependencyImport->precedence = precedence;
799
801 << "loading dependent import" << dependencyImport->uri << "version"
802 << dependencyImport->version << "as" << dependencyImport->qualifier;
803
804 if (!addImport(dependencyImport, errors)) {
806 error.setDescription(
808 "Failed to load dependent import \"%1\" version %2.%3")
809 .arg(dependencyImport->uri)
810 .arg(dependencyImport->version.majorVersion())
811 .arg(dependencyImport->version.minorVersion()));
812 errors->append(error);
813 return false;
814 }
815 }
816
817 return true;
818}
819
820bool QQmlTypeLoader::Blob::loadImportDependencies(
821 const QQmlTypeLoader::Blob::PendingImportPtr &currentImport, const QString &qmldirUri,
822 QQmlImports::ImportFlags flags, QList<QQmlError> *errors)
823{
824 const QQmlTypeLoaderQmldirContent qmldir = typeLoader()->qmldirContent(qmldirUri);
825 const QList<QQmlDirParser::Import> implicitImports
826 = QQmlMetaType::moduleImports(currentImport->uri, currentImport->version)
827 + qmldir.imports();
828
829 // Prevent overflow from one category of import into the other.
830 switch (currentImport->precedence) {
834 error.setDescription(
835 QString::fromLatin1("Too many dependent imports for %1 %2.%3")
836 .arg(currentImport->uri)
837 .arg(currentImport->version.majorVersion())
838 .arg(currentImport->version.minorVersion()));
839 errors->append(error);
840 return false;
841 }
842 default:
843 break;
844 }
845
846 if (!loadDependentImports(
847 implicitImports, currentImport->qualifier, currentImport->version,
848 currentImport->precedence + 1, flags, errors)) {
850 error.setDescription(
852 "Failed to load dependencies for module \"%1\" version %2.%3")
853 .arg(currentImport->uri)
854 .arg(currentImport->version.majorVersion())
855 .arg(currentImport->version.minorVersion()));
856 errors->append(error);
857 return false;
858 }
859
860 return true;
861}
862
864{
865 return typeLoader()->engine()->handle()->debugger() != nullptr;
866}
867
869{
870 return typeLoader()->engine()->handle()->diskCacheOptions()
872}
873
875{
876 return typeLoader()->engine()->handle()->diskCacheOptions()
878}
879
881{
882 const QV4::ExecutionEngine::DiskCacheOptions options
883 = typeLoader()->engine()->handle()->diskCacheOptions();
889}
890
892{
893 return data->processImports(this, [&](PendingImportPtr import) {
894 return updateQmldir(data, import, errors);
895 });
896}
897
902 : m_engine(engine)
903 , m_thread(new QQmlTypeLoaderThread(this))
904 , m_mutex(m_thread->mutex())
905 , m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
906{
907}
908
914{
915 // Stop the loader thread before releasing resources
916 shutdownThread();
917
918 clearCache();
919
920 invalidate();
921}
922
924{
926}
927
928QUrl QQmlTypeLoader::normalize(const QUrl &unNormalizedUrl)
929{
930 QUrl normalized(unNormalizedUrl);
931 if (normalized.scheme() == QLatin1String("qrc"))
932 normalized.setHost(QString()); // map qrc:///a.qml to qrc:/a.qml
933 return normalized;
934}
935
940{
941 Q_ASSERT(!unNormalizedUrl.isRelative() &&
942 (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
944
945 const QUrl url = normalize(unNormalizedUrl);
946
947 LockHolder<QQmlTypeLoader> holder(this);
948
949 QQmlTypeData *typeData = m_typeCache.value(url);
950
951 if (!typeData) {
952 // Trim before adding the new type, so that we don't immediately trim it away
953 if (m_typeCache.size() >= m_typeCacheTrimThreshold)
954 trimCache();
955
956 typeData = new QQmlTypeData(url, this);
957 // TODO: if (compiledData == 0), is it safe to omit this insertion?
958 m_typeCache.insert(url, typeData);
960
961 const QQmlMetaType::CacheMode cacheMode = typeData->aotCacheMode();
962 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
963 ? QQmlMetaType::findCachedCompilationUnit(typeData->url(), cacheMode, &error)
964 : nullptr) {
965 QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
966 } else {
967 typeData->setCachedUnitStatus(error);
968 QQmlTypeLoader::load(typeData, mode);
969 }
971 // this was started Asynchronous, but we need to force Synchronous
972 // completion now (if at all possible with this type of URL).
973
974 if (!m_thread->isThisThread()) {
975 // this only works when called directly from the UI thread, but not
976 // when recursively called on the QML thread via resolveTypes()
977
978 while (!typeData->isCompleteOrError()) {
979 m_thread->waitForNextMessage();
980 }
981 }
982 }
983
984 return typeData;
985}
986
992{
993 LockHolder<QQmlTypeLoader> holder(this);
994
995 QQmlTypeData *typeData = new QQmlTypeData(url, this);
997
999}
1000
1005{
1006 Q_ASSERT(!unNormalizedUrl.isRelative() &&
1007 (QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
1009
1010 const QUrl url = normalize(unNormalizedUrl);
1011
1012 LockHolder<QQmlTypeLoader> holder(this);
1013
1014 QQmlScriptBlob *scriptBlob = m_scriptCache.value(url);
1015
1016 if (!scriptBlob) {
1017 scriptBlob = new QQmlScriptBlob(url, this);
1018 m_scriptCache.insert(url, scriptBlob);
1019
1021 const QQmlMetaType::CacheMode cacheMode = scriptBlob->aotCacheMode();
1022 if (const QQmlPrivate::CachedQmlUnit *cachedUnit = (cacheMode != QQmlMetaType::RejectAll)
1023 ? QQmlMetaType::findCachedCompilationUnit(scriptBlob->url(), cacheMode, &error)
1024 : nullptr) {
1025 QQmlTypeLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
1026 } else {
1027 scriptBlob->setCachedUnitStatus(error);
1028 QQmlTypeLoader::load(scriptBlob);
1029 }
1030 }
1031
1032 return scriptBlob;
1033}
1034
1039{
1040 Q_ASSERT(!url.isRelative() &&
1043 LockHolder<QQmlTypeLoader> holder(this);
1044
1045 QQmlQmldirData *qmldirData = m_qmldirCache.value(url);
1046
1047 if (!qmldirData) {
1048 qmldirData = new QQmlQmldirData(url, this);
1049 m_qmldirCache.insert(url, qmldirData);
1050 QQmlTypeLoader::load(qmldirData);
1051 }
1052
1053 return qmldirData;
1054}
1055
1066{
1067 if (path.isEmpty())
1068 return QString();
1069 if (path.at(0) == QLatin1Char(':')) {
1070 // qrc resource
1071 QFileInfo fileInfo(path);
1072 return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
1073 } else if (path.size() > 3 && path.at(3) == QLatin1Char(':') &&
1074 path.startsWith(QLatin1String("qrc"), Qt::CaseInsensitive)) {
1075 // qrc resource url
1077 return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
1078 }
1079#if defined(Q_OS_ANDROID)
1080 else if (path.size() > 7 && path.at(6) == QLatin1Char(':') && path.at(7) == QLatin1Char('/') &&
1081 path.startsWith(QLatin1String("assets"), Qt::CaseInsensitive)) {
1082 // assets resource url
1084 return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
1085 } else if (path.size() > 8 && path.at(7) == QLatin1Char(':') && path.at(8) == QLatin1Char('/') &&
1086 path.startsWith(QLatin1String("content"), Qt::CaseInsensitive)) {
1087 // content url
1089 return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
1090 }
1091#endif
1092
1093 int lastSlash = path.lastIndexOf(QLatin1Char('/'));
1094 QString dirPath(path.left(lastSlash));
1095
1096 LockHolder<QQmlTypeLoader> holder(this);
1097 if (!m_importDirCache.contains(dirPath)) {
1098 bool exists = QDir(dirPath).exists();
1099 QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : nullptr;
1100 m_importDirCache.insert(dirPath, entry);
1101 }
1102 QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath);
1103 if (!fileSet)
1104 return QString();
1105
1107 QString fileName(path.mid(lastSlash+1, path.size()-lastSlash-1));
1108
1109 bool *value = fileSet->object(fileName);
1110 if (value) {
1111 if (*value)
1113 } else {
1114 bool exists = QFile::exists(path);
1115 fileSet->insert(fileName, new bool(exists));
1116 if (exists)
1118 }
1119
1120 if (absoluteFilePath.size() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':'))
1122
1123 return absoluteFilePath;
1124}
1125
1127{
1128 const QChar nullChar(QChar::Null);
1129 if (path.isEmpty() || path.contains(nullChar) || file.isEmpty() || file.contains(nullChar))
1130 return false;
1131
1132 Q_ASSERT(path.endsWith(QLatin1Char('/')));
1133
1134 LockHolder<QQmlTypeLoader> holder(this);
1135 QCache<QString, bool> *fileSet = m_importDirCache.object(path);
1136 if (fileSet) {
1137 if (bool *value = fileSet->object(file))
1138 return *value;
1139 } else if (m_importDirCache.contains(path)) {
1140 // explicit nullptr in cache
1141 return false;
1142 }
1143
1144 auto addToCache = [&](const QFileInfo &fileInfo) {
1145 if (!fileSet) {
1146 fileSet = fileInfo.dir().exists() ? new QCache<QString, bool> : nullptr;
1147 m_importDirCache.insert(path, fileSet);
1148 if (!fileSet)
1149 return false;
1150 }
1151
1152 const bool exists = fileInfo.exists();
1153 fileSet->insert(file, new bool(exists));
1154 return exists;
1155 };
1156
1157 if (path.at(0) == QLatin1Char(':')) {
1158 // qrc resource
1159 return addToCache(QFileInfo(path + file));
1160 }
1161
1162 if (path.size() > 3 && path.at(3) == QLatin1Char(':')
1163 && path.startsWith(QLatin1String("qrc"), Qt::CaseInsensitive)) {
1164 // qrc resource url
1165 return addToCache(QFileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)));
1166 }
1167
1168#if defined(Q_OS_ANDROID)
1169 if (path.size() > 7 && path.at(6) == QLatin1Char(':') && path.at(7) == QLatin1Char('/')
1170 && path.startsWith(QLatin1String("assets"), Qt::CaseInsensitive)) {
1171 // assets resource url
1172 return addToCache(QFileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)));
1173 }
1174
1175 if (path.size() > 8 && path.at(7) == QLatin1Char(':') && path.at(8) == QLatin1Char('/')
1176 && path.startsWith(QLatin1String("content"), Qt::CaseInsensitive)) {
1177 // content url
1178 return addToCache(QFileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)));
1179 }
1180#endif
1181
1182 return addToCache(QFileInfo(path + file));
1183}
1184
1185
1191{
1192 if (path.isEmpty())
1193 return false;
1194
1195 bool isResource = path.at(0) == QLatin1Char(':');
1196#if defined(Q_OS_ANDROID)
1197 isResource = isResource || path.startsWith(QLatin1String("assets:/")) || path.startsWith(QLatin1String("content:/"));
1198#endif
1199
1200 if (isResource) {
1201 // qrc resource
1202 QFileInfo fileInfo(path);
1203 return fileInfo.exists() && fileInfo.isDir();
1204 }
1205
1206 int length = path.size();
1207 if (path.endsWith(QLatin1Char('/')))
1208 --length;
1209 QString dirPath(path.left(length));
1210
1211 LockHolder<QQmlTypeLoader> holder(this);
1212 if (!m_importDirCache.contains(dirPath)) {
1213 bool exists = QDir(dirPath).exists();
1214 QCache<QString, bool> *files = exists ? new QCache<QString, bool> : nullptr;
1215 m_importDirCache.insert(dirPath, files);
1216 }
1217
1218 QCache<QString, bool> *fileSet = m_importDirCache.object(dirPath);
1219 return fileSet != nullptr;
1220}
1221
1222
1231{
1232 LockHolder<QQmlTypeLoader> holder(this);
1233
1234 QString filePath;
1235
1236 // Try to guess if filePathIn is already a URL. This is necessarily fragile, because
1237 // - paths can contain ':', which might make them appear as URLs with schemes.
1238 // - windows drive letters appear as schemes (thus "< 2" below).
1239 // - a "file:" URL is equivalent to the respective file, but will be treated differently.
1240 // Yet, this heuristic is the best we can do until we pass more structured information here,
1241 // for example a QUrl also for local files.
1242 QUrl url(filePathIn);
1243 if (url.scheme().size() < 2) {
1244 filePath = filePathIn;
1245 } else {
1247 if (filePath.isEmpty()) { // Can't load the remote here, but should be cached
1248 if (auto entry = m_importQmlDirCache.value(filePathIn))
1249 return **entry;
1250 else
1252 }
1253 }
1254
1255 QQmlTypeLoaderQmldirContent **val = m_importQmlDirCache.value(filePath);
1256 if (val)
1257 return **val;
1259
1260#define ERROR(description) { QQmlError e; e.setDescription(description); qmldir->setError(e); }
1261#define NOT_READABLE_ERROR QString(QLatin1String("module \"$$URI$$\" definition \"%1\" not readable"))
1262#define CASE_MISMATCH_ERROR QString(QLatin1String("cannot load module \"$$URI$$\": File name case mismatch for \"%1\""))
1263
1264 QFile file(filePath);
1265 if (!QQml_isFileCaseCorrect(filePath)) {
1266 ERROR(CASE_MISMATCH_ERROR.arg(filePath));
1267 } else if (file.open(QFile::ReadOnly)) {
1269 qmldir->setContent(filePath, QString::fromUtf8(data));
1270 } else {
1271 ERROR(NOT_READABLE_ERROR.arg(filePath));
1272 }
1273
1274#undef ERROR
1275#undef NOT_READABLE_ERROR
1276#undef CASE_MISMATCH_ERROR
1277
1278 m_importQmlDirCache.insert(filePath, qmldir);
1279 return *qmldir;
1280}
1281
1283{
1285 QQmlTypeLoaderQmldirContent **val = m_importQmlDirCache.value(url);
1286 if (val) {
1287 qmldir = *val;
1288 } else {
1289 qmldir = new QQmlTypeLoaderQmldirContent;
1290 m_importQmlDirCache.insert(url, qmldir);
1291 }
1292
1293 if (!qmldir->hasContent())
1294 qmldir->setContent(url, content);
1295}
1296
1302{
1303 for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter)
1304 (*iter)->release();
1305 for (ScriptCache::Iterator iter = m_scriptCache.begin(), end = m_scriptCache.end(); iter != end; ++iter)
1306 (*iter)->release();
1307 for (QmldirCache::Iterator iter = m_qmldirCache.begin(), end = m_qmldirCache.end(); iter != end; ++iter)
1308 (*iter)->release();
1309
1310 qDeleteAll(m_importQmlDirCache);
1311
1312 m_typeCache.clear();
1313 m_typeCacheTrimThreshold = TYPELOADER_MINIMUM_TRIM_THRESHOLD;
1314 m_scriptCache.clear();
1315 m_qmldirCache.clear();
1316 m_importDirCache.clear();
1317 m_importQmlDirCache.clear();
1318 m_checksumCache.clear();
1320}
1321
1322void QQmlTypeLoader::updateTypeCacheTrimThreshold()
1323{
1324 int size = m_typeCache.size();
1325 if (size > m_typeCacheTrimThreshold)
1326 m_typeCacheTrimThreshold = size * 2;
1327 if (size < m_typeCacheTrimThreshold / 2)
1328 m_typeCacheTrimThreshold = qMax(size * 2, TYPELOADER_MINIMUM_TRIM_THRESHOLD);
1329}
1330
1332{
1333 while (true) {
1334 bool deletedOneType = false;
1335 for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end;) {
1336 QQmlTypeData *typeData = iter.value();
1337
1338 // typeData->m_compiledData may be set early on in the proccess of loading a file, so
1339 // it's important to check the general loading status of the typeData before making any
1340 // other decisions.
1341 if (typeData->count() != 1 || (!typeData->isError() && !typeData->isComplete())) {
1342 ++iter;
1343 continue;
1344 }
1345
1347 = typeData->m_compiledData;
1348 if (compilationUnit) {
1349 if (compilationUnit->count()
1351 compilationUnit) + 1) {
1352 ++iter;
1353 continue;
1354 }
1355
1357 Q_ASSERT(compilationUnit->count() == 1);
1358 }
1359
1360 // There are no live objects of this type
1361 iter.value()->release();
1362 iter = m_typeCache.erase(iter);
1363 deletedOneType = true;
1364 }
1365
1366 if (!deletedOneType)
1367 break;
1368 }
1369
1370 updateTypeCacheTrimThreshold();
1371
1373
1374 // TODO: release any scripts which are no longer referenced by any types
1375}
1376
1378{
1379 LockHolder<QQmlTypeLoader> holder(const_cast<QQmlTypeLoader *>(this));
1380 return m_typeCache.contains(url);
1381}
1382
1384{
1385 LockHolder<QQmlTypeLoader> holder(const_cast<QQmlTypeLoader *>(this));
1386 return m_scriptCache.contains(url);
1387}
1388
\inmodule QtCore
Definition qbytearray.h:57
bool contains(const Key &key) const noexcept
Definition qcache.h:217
T * object(const Key &key) const noexcept
Definition qcache.h:209
void clear() noexcept(std::is_nothrow_destructible_v< Node >)
Definition qcache.h:176
bool insert(const Key &key, T *object, qsizetype cost=1)
Definition qcache.h:184
\inmodule QtCore
Definition qchar.h:48
@ Null
Definition qchar.h:51
\inmodule QtCore
Definition qdir.h:19
static bool isRelativePath(const QString &path)
Returns true if path is relative; returns false if it is absolute.
Definition qdir.cpp:2409
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qdir.cpp:1715
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString absoluteFilePath() const
Returns an absolute path including the file name.
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
bool exists() const
Returns true if the file exists; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1202
qsizetype size() const noexcept
Returns the number of items in the hash.
Definition qhash.h:925
iterator Iterator
Qt-style synonym for QHash::iterator.
Definition qhash.h:1255
iterator erase(const_iterator it)
Definition qhash.h:1223
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
value_type takeFirst()
Definition qlist.h:549
void prepend(rvalue_ref t)
Definition qlist.h:456
void append(parameter_type t)
Definition qlist.h:441
The QNetworkReply class contains the data and headers for a request sent with QNetworkAccessManager.
bool isFinished() const
QVariant attribute(QNetworkRequest::Attribute code) const
Returns the attribute associated with the code code.
NetworkError error() const
Returns the error that was found during the processing of this request.
QUrl url() const
Returns the URL of the content downloaded or uploaded.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QQmlDataBlob encapsulates a data request that can be issued to a QQmlTypeLoader.
bool isError() const
Returns true if the status is Error.
virtual void dataReceived(const SourceCodeData &)=0
Invoked when data for the blob is received.
bool isCompleteOrError() const
Returns true if the status is Complete or Error.
bool isComplete() const
Returns true if the status is Complete.
QUrl url() const
Returns the physical url of the data.
virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *)=0
Type
This enum describes the type of the data blob.
Status status() const
Returns the blob's status.
virtual void allDependenciesDone()
Called when all blobs waited for have completed.
bool isWaiting() const
Returns true if the status is WaitingForDependencies.
void startLoading()
Must be called before loading can occur.
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)
QQmlImportDatabase importDatabase
QList< QQmlAbstractUrlInterceptor * > urlInterceptors
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
Run the current URL interceptors on the given url of the given type and return the result.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
static bool isLocalFile(const QString &url)
Returns true if url is a local file that can be opened with QFile.
Definition qqmlfile.cpp:549
static bool isSynchronous(const QString &url)
Returns true if QQmlFile will open url synchronously.
Definition qqmlfile.cpp:415
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to QFile.
Definition qqmlfile.cpp:643
The QQmlImportDatabase class manages the QML imports for a QQmlEngine.
QStringList importPathList(PathType type=LocalOrRemote) const
LocalQmldirResult locateLocalQmldir(const QString &uri, QTypeRevision version, LocalQmldirSearchLocation location, const Callback &callback)
The QQmlImports class encapsulates one QML document's import statements.
static QUrl urlFromLocalFileOrQrcOrUrl(const QString &)
static bool isLocal(const QString &url)
static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, QTypeRevision version)
Forms complete paths to a qmldir file, from a base URL, a module URI and version specification.
static int countInternalCompositeTypeSelfReferences(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit)
static bool isStronglyLockedModule(const QString &uri, QTypeRevision version)
static QList< QQmlDirParser::Import > moduleImports(const QString &uri, QTypeRevision version)
static QTypeRevision latestModuleVersion(const QString &uri)
static QQmlTypeModule * typeModule(const QString &uri, QTypeRevision version)
static bool qmlRegisterModuleTypes(const QString &uri)
static const QQmlPrivate::CachedQmlUnit * findCachedCompilationUnit(const QUrl &uri, CacheMode mode, CachedUnitLookupError *status)
static void freeUnusedTypesAndCaches()
static void unregisterInternalCompositeType(QMetaType metaType, QMetaType listMetaType)
int count() const
T * data() const
QQmlRefPointer< T > & adopt(T *)
Takes ownership of other.
bool isThisThread() const
void shutdown()
void waitForNextMessage()
bool isShutdown() const
void callDownloadProgressChanged(const QQmlDataBlob::Ptr &b, qreal p)
void initializeEngine(QQmlExtensionInterface *, const char *)
std::shared_ptr< PendingImport > PendingImportPtr
Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader)
QQmlMetaType::CacheMode aotCacheMode() 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)
virtual bool qmldirDataAvailable(const QQmlRefPointer< QQmlQmldirData > &, QList< QQmlError > *)
void dependencyComplete(QQmlDataBlob *) override
Called if blob, which was previously waited for, has completed.
bool updateQmldir(const QQmlRefPointer< QQmlQmldirData > &data, const PendingImportPtr &import, QList< QQmlError > *errors)
void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status)
void importQmldirScripts(const PendingImportPtr &import, const QQmlTypeLoaderQmldirContent &qmldir, const QUrl &qmldirUrl)
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.
quintptr profiler() const
bool isTypeLoaded(const QUrl &url) const
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.
void load(QQmlDataBlob *, Mode=PreferSynchronous)
Load the provided blob from the network or filesystem.
bool isScriptLoaded(const QUrl &url) const
QString absoluteFilePath(const QString &path)
Returns the absolute filename of path via a directory cache.
~QQmlTypeLoader()
Destroys the type loader, first clearing the cache of any information about loaded files.
QQmlImportDatabase * importDatabase() const
friend struct StaticLoader
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode=PreferSynchronous)
void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode=PreferSynchronous)
Load the provided blob with data.
bool directoryExists(const QString &path)
Returns true if the path is a directory via a directory cache.
static QUrl normalize(const QUrl &unNormalizedUrl)
QQmlRefPointer< QQmlScriptBlob > getScript(const QUrl &unNormalizedUrl)
Return a QQmlScriptBlob for url.
QQmlTypeLoader(QQmlEngine *)
Constructs a new type loader that uses the given engine.
friend struct PlainLoader
void setProfiler(quintptr)
void initializeEngine(QQmlEngineExtensionInterface *, const char *)
QQmlRefPointer< QQmlQmldirData > getQmldir(const QUrl &)
Returns a QQmlQmldirData for url.
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath)
Return a QQmlTypeLoaderQmldirContent for absoluteFilePath.
void clearCache()
Clears cached information about loaded files, including any type data, scripts and qmldir information...
friend struct CachedLoader
void setQmldirContent(const QString &filePath, const QString &content)
bool fileExists(const QString &path, const QString &file)
void insert(const K &, const T &)
T * value(const K &) const
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString & append(QChar c)
Definition qstring.cpp:3227
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QThread * currentThread()
Definition qthread.cpp:966
\inmodule QtCore
constexpr bool hasMajorVersion() const
Returns true if the major version is known, otherwise false.
constexpr bool isValid() const
Returns true if the major version or the minor version is known, otherwise false.
\inmodule QtCore
Definition qurl.h:94
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2722
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition qurl.cpp:2797
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
#define this
Definition dialogs.cpp:9
qDeleteAll(list.begin(), list.end())
Path qmldirFilePath(QString path)
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
@ CaseInsensitive
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:162
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLint location
GLenum mode
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLfloat * val
GLuint entry
GLsizei const GLchar *const * path
GLint GLenum GLboolean normalized
Definition qopenglext.h:752
bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn)
Returns true if the case of fileName is equivalent to the file case of fileName on disk,...
const QLoggingCategory & lcQmlImport()
static void setError(QJsonObject *response, const QString &msg)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
#define ASSERT_LOADTHREAD()
#define CASE_MISMATCH_ERROR
void doInitializeEngine(Interface *iface, QQmlTypeLoaderThread *thread, QQmlEngine *engine, const char *uri)
#define ERROR(description)
#define NOT_READABLE_ERROR
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION
#define TYPELOADER_MINIMUM_TRIM_THRESHOLD
void postProcessQmldir(QQmlTypeLoader::Blob *self, const QQmlTypeLoader::Blob::PendingImportPtr &import, const QString &qmldirFilePath, const URL &qmldirUrl)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(*) void arg)
#define qPrintable(string)
Definition qstring.h:1391
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
QMutex mutex
[2]
QReadWriteLock lock
[0]
QStringList files
[8]
QNetworkReply * reply
QJSEngine engine
[0]
void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
CachedLoader(const QQmlPrivate::CachedQmlUnit *unit)
void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
const QQmlPrivate::CachedQmlUnit * unit
void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
\inmodule QtCore \reentrant
Definition qchar.h:17
const QByteArray & data
StaticLoader(const QByteArray &data)
void load(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
void loadAsync(QQmlTypeLoader *loader, QQmlDataBlob *blob) const
void loadThread(QQmlTypeLoader *loader, QQmlDataBlob *blob) const