5#include <private/qqmldatablob_p.h>
6#include <private/qqmlglobal_p.h>
7#include <private/qqmlprofiler_p.h>
8#include <private/qqmlsourcecoordinate_p.h>
9#include <private/qqmltypedata_p.h>
10#include <private/qqmltypeloader_p.h>
11#include <private/qqmltypeloaderthread_p.h>
13#include <QtQml/qqmlengine.h>
15#include <qtqml_tracepoints_p.h>
22
23
24
25
26
27
28
29
32
33
34
35
36
37
38
39
40
41
42
43
44
47
48
49
50
51
52
53
54
57
58
59QQmlDataBlob::QQmlDataBlob(
const QUrl &url, Type type, QQmlTypeLoader *manager)
60 : m_typeLoader(manager)
62 , m_url(manager->interceptUrl(url, (QQmlAbstractUrlInterceptor::DataType)type))
71QQmlDataBlob::~QQmlDataBlob()
73 Q_ASSERT(m_waitingOnMe.isEmpty());
90 cancelAllWaitingFor();
94
95
96void QQmlDataBlob::startLoading()
100 Q_ASSERT(status() == QQmlDataBlob::Null);
101 setStatus(QQmlDataBlob::Loading);
105
106
107QQmlDataBlob::Type QQmlDataBlob::type()
const
113
114
115QQmlDataBlob::Status QQmlDataBlob::status()
const
117 return m_data.status();
121
122
123bool QQmlDataBlob::isNull()
const
125 return status() == Null;
129
130
131bool QQmlDataBlob::isLoading()
const
133 return status() == Loading;
137
138
139bool QQmlDataBlob::isWaiting()
const
141 return status() == WaitingForDependencies ||
142 status() == ResolvingDependencies;
146
147
148bool QQmlDataBlob::isComplete()
const
150 return status() == Complete;
154
155
156bool QQmlDataBlob::isError()
const
158 return status() == Error;
162
163
164bool QQmlDataBlob::isCompleteOrError()
const
167 return s == Error || s == Complete;
170bool QQmlDataBlob::isAsync()
const
172 return m_data.isAsync();
176
177
178qreal QQmlDataBlob::progress()
const
180 return m_data.progress();
184
185
186
187
188
189
190QUrl QQmlDataBlob::url()
const
195QString QQmlDataBlob::urlString()
const
198 if (m_urlString.isEmpty())
199 m_urlString = m_url.toString();
205
206
207
208
209
210
211
212
213
214
215
216
217QUrl QQmlDataBlob::finalUrl()
const
223
224
225QString QQmlDataBlob::finalUrlString()
const
229 if (m_finalUrlString.isEmpty())
230 m_finalUrlString = m_finalUrl.toString();
232 return m_finalUrlString;
236
237
238
239
240QList<QQmlError> QQmlDataBlob::errors()
const
242 Q_ASSERT(isCompleteOrError()
244 || !m_typeLoader->thread()
245 || m_typeLoader->thread()->isThisThread());
250
251
252
253
254
255
256
257void QQmlDataBlob::setError(
const QQmlError &errors)
259 assertTypeLoaderThread();
267
268
269void QQmlDataBlob::setError(
const QList<QQmlError> &errors)
271 assertTypeLoaderThread();
273 Q_ASSERT(status() != Error);
274 Q_ASSERT(m_errors.isEmpty());
277 m_errors.reserve(errors.size());
278 for (
const QQmlError &error : errors) {
279 if (error.url().isEmpty()) {
280 QQmlError mutableError = error;
281 mutableError.setUrl(url());
282 m_errors.append(mutableError);
284 m_errors.append(error);
288 cancelAllWaitingFor();
292 qWarning().nospace() <<
"Errors for " << urlString();
293 for (
int ii = 0; ii < errors.size(); ++ii)
294 qWarning().nospace() <<
" " << qPrintable(errors.at(ii).toString());
301void QQmlDataBlob::setError(
const QQmlJS::DiagnosticMessage &error)
303 assertTypeLoaderThread();
305 e.setColumn(qmlConvertSourceCoordinate<quint32,
int>(error.loc.startColumn));
306 e.setLine(qmlConvertSourceCoordinate<quint32,
int>(error.loc.startLine));
307 e.setDescription(error.message);
312void QQmlDataBlob::setError(
const QString &description)
314 assertTypeLoaderThread();
316 e.setDescription(description);
322
323
324
325
326
327void QQmlDataBlob::addDependency(
const QQmlDataBlob::Ptr &blob)
329 assertTypeLoaderThread();
331 Q_ASSERT(status() != Null);
334 blob->status() == Error || blob->status() == Complete ||
335 status() == Error || status() == Complete || m_isDone)
338 for (
const auto &existingDep: std::as_const(m_waitingFor)) {
339 if (existingDep.data() == blob)
343 m_waitingFor.append(blob);
344 blob->m_waitingOnMe.append(
this);
346 setStatus(WaitingForDependencies);
349 if (m_waitingOnMe.indexOf(blob.data()) >= 0) {
350 qCWarning(lcCycle) <<
"Cyclic dependency detected between" <<
this->url().toString()
351 <<
"and" << blob->url().toString();
354 error.setDescription(QString::fromLatin1(
"Cyclic dependency detected between \"%1\" and \"%2\"")
355 .arg(url().toString(), blob->url().toString()));
361
362
363
364
365
366
369
370
371
372
373
374
375
376
377
378
379
380void QQmlDataBlob::done()
382 assertTypeLoaderThread();
385#if QT_CONFIG(qml_network)
387
388
389
390
391void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
393 assertTypeLoaderThread();
395 Q_UNUSED(networkError);
400 const char *errorString =
nullptr;
401 switch (networkError) {
403 errorString =
"Network error";
405 case QNetworkReply::ConnectionRefusedError:
406 errorString =
"Connection refused";
408 case QNetworkReply::RemoteHostClosedError:
409 errorString =
"Remote host closed the connection";
411 case QNetworkReply::HostNotFoundError:
412 errorString =
"Host not found";
414 case QNetworkReply::TimeoutError:
415 errorString =
"Timeout";
417 case QNetworkReply::ProxyConnectionRefusedError:
418 case QNetworkReply::ProxyConnectionClosedError:
419 case QNetworkReply::ProxyNotFoundError:
420 case QNetworkReply::ProxyTimeoutError:
421 case QNetworkReply::ProxyAuthenticationRequiredError:
422 case QNetworkReply::UnknownProxyError:
423 errorString =
"Proxy error";
425 case QNetworkReply::ContentAccessDenied:
426 errorString =
"Access denied";
428 case QNetworkReply::ContentNotFoundError:
429 errorString =
"File not found";
431 case QNetworkReply::AuthenticationRequiredError:
432 errorString =
"Authentication required";
436 error.setDescription(QLatin1String(errorString));
443
444
445
446
447void QQmlDataBlob::dependencyError(
const QQmlDataBlob::Ptr &blob)
449 assertTypeLoaderThread();
454
455
456
457
458void QQmlDataBlob::dependencyComplete(
const QQmlDataBlob::Ptr &blob)
460 assertTypeLoaderThread();
465
466
467
468
469
470void QQmlDataBlob::allDependenciesDone()
472 assertTypeLoaderThread();
473 setStatus(QQmlDataBlob::ResolvingDependencies);
477
478
479
480
481
482
483
484
485
486
487void QQmlDataBlob::downloadProgressChanged(qreal progress)
490 assertEngineThread();
494
495
496
497
498
499
500
501
502
503
504
505
506
507void QQmlDataBlob::completed()
509 assertEngineThread();
512void QQmlDataBlob::tryDone()
514 assertTypeLoaderThread();
516 if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
521 qWarning(
"QQmlDataBlob::done() %s", qPrintable(urlString()));
525 if (status() != Error)
528 notifyAllWaitingOnMe();
533 qWarning(
"QQmlDataBlob: Dispatching completed");
535 m_typeLoader->thread()->callCompleted(
this);
541void QQmlDataBlob::cancelAllWaitingFor()
543 while (m_waitingFor.size()) {
548 assertTypeLoaderThreadIfRunning();
550 QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
552 Q_ASSERT(blob->m_waitingOnMe.contains(
this));
554 blob->m_waitingOnMe.removeOne(
this);
558void QQmlDataBlob::notifyAllWaitingOnMe()
560 assertTypeLoaderThread();
562 while (m_waitingOnMe.size()) {
563 QQmlDataBlob::Ptr blob = m_waitingOnMe.takeLast();
565 Q_ASSERT(std::any_of(blob->m_waitingFor.constBegin(), blob->m_waitingFor.constEnd(),
566 [
this](
const QQmlRefPointer<QQmlDataBlob> &waiting) {
return waiting.data() ==
this; }));
568 blob->notifyComplete(
this);
572void QQmlDataBlob::notifyComplete(
const QQmlDataBlob::Ptr &blob)
574 assertTypeLoaderThread();
576 Q_ASSERT(blob->status() == Error || blob->status() == Complete);
577 Q_TRACE_SCOPE(QQmlCompiling, blob->url());
578 QQmlCompilingProfiler prof(typeLoader()->profiler(), blob.data());
582 QQmlRefPointer<QQmlDataBlob> blobRef;
583 for (
int i = 0; i < m_waitingFor.size(); ++i) {
584 if (m_waitingFor.at(i).data() == blob) {
585 blobRef = m_waitingFor.takeAt(i);
591 if (blob->status() == Error) {
592 dependencyError(blob);
593 }
else if (blob->status() == Complete) {
594 dependencyComplete(blob);
597 if (!isError() && m_waitingFor.isEmpty())
598 allDependenciesDone();
600 m_inCallback =
false;
605QString QQmlDataBlob::SourceCodeData::readAll(QString *error)
const
608 if (hasInlineSourceCode)
609 return inlineSourceCode;
611 QFile f(fileInfo.absoluteFilePath());
612 if (!f.open(QIODevice::ReadOnly)) {
613 *error = f.errorString();
617 const qint64 fileSize = fileInfo.size();
619 if (uchar *mappedData = f.map(0, fileSize)) {
620 QString source = QString::fromUtf8(
reinterpret_cast<
const char *>(mappedData), fileSize);
625 QByteArray data(fileSize, Qt::Uninitialized);
626 if (f.read(data.data(), data.size()) != data.size()) {
627 *error = f.errorString();
630 return QString::fromUtf8(data);
633QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp()
const
635 if (hasInlineSourceCode)
638 return fileInfo.lastModified();
641bool QQmlDataBlob::SourceCodeData::exists()
const
643 if (hasInlineSourceCode)
645 return fileInfo.exists();
648bool QQmlDataBlob::SourceCodeData::isEmpty()
const
650 if (hasInlineSourceCode)
651 return inlineSourceCode.isEmpty();
652 return fileInfo.size() == 0;
655bool QQmlDataBlob::setStatus(Status status)
660 case WaitingForDependencies:
661 Q_ASSERT(!m_waitingFor.isEmpty());
664 case ResolvingDependencies:
667 Q_ASSERT(m_waitingFor.isEmpty());
671 return m_data.setStatus(status);
DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE)