4#include <private/qqmldatablob_p.h>
5#include <private/qqmlglobal_p.h>
6#include <private/qqmlprofiler_p.h>
7#include <private/qqmlsourcecoordinate_p.h>
8#include <private/qqmltypedata_p.h>
9#include <private/qqmltypeloader_p.h>
10#include <private/qqmltypeloaderthread_p.h>
12#include <QtQml/qqmlengine.h>
14#include <qtqml_tracepoints_p.h>
21
22
23
24
25
26
27
28
31
32
33
34
35
36
37
38
39
40
41
42
43
46
47
48
49
50
51
52
53
56
57
58QQmlDataBlob::QQmlDataBlob(
const QUrl &url, Type type, QQmlTypeLoader *manager)
59 : m_typeLoader(manager)
61 , m_url(manager->interceptUrl(url, (QQmlAbstractUrlInterceptor::DataType)type))
70QQmlDataBlob::~QQmlDataBlob()
72 Q_ASSERT(m_waitingOnMe.isEmpty());
89 cancelAllWaitingFor();
93
94
95void QQmlDataBlob::startLoading()
99 Q_ASSERT(status() == QQmlDataBlob::Null);
100 setStatus(QQmlDataBlob::Loading);
104
105
106QQmlDataBlob::Type QQmlDataBlob::type()
const
112
113
114QQmlDataBlob::Status QQmlDataBlob::status()
const
116 return m_data.status();
120
121
122bool QQmlDataBlob::isNull()
const
124 return status() == Null;
128
129
130bool QQmlDataBlob::isLoading()
const
132 return status() == Loading;
136
137
138bool QQmlDataBlob::isWaiting()
const
140 return status() == WaitingForDependencies ||
141 status() == ResolvingDependencies;
145
146
147bool QQmlDataBlob::isComplete()
const
149 return status() == Complete;
153
154
155bool QQmlDataBlob::isError()
const
157 return status() == Error;
161
162
163bool QQmlDataBlob::isCompleteOrError()
const
166 return s == Error || s == Complete;
169bool QQmlDataBlob::isAsync()
const
171 return m_data.isAsync();
175
176
177qreal QQmlDataBlob::progress()
const
179 return m_data.progress();
183
184
185
186
187
188
189QUrl QQmlDataBlob::url()
const
194QString QQmlDataBlob::urlString()
const
197 if (m_urlString.isEmpty())
198 m_urlString = m_url.toString();
204
205
206
207
208
209
210
211
212
213
214
215
216QUrl QQmlDataBlob::finalUrl()
const
222
223
224QString QQmlDataBlob::finalUrlString()
const
228 if (m_finalUrlString.isEmpty())
229 m_finalUrlString = m_finalUrl.toString();
231 return m_finalUrlString;
235
236
237
238
239QList<QQmlError> QQmlDataBlob::errors()
const
241 Q_ASSERT(isCompleteOrError()
243 || !m_typeLoader->thread()
244 || m_typeLoader->thread()->isThisThread());
249
250
251
252
253
254
255
256void QQmlDataBlob::setError(
const QQmlError &errors)
258 assertTypeLoaderThread();
266
267
268void QQmlDataBlob::setError(
const QList<QQmlError> &errors)
270 assertTypeLoaderThread();
272 Q_ASSERT(status() != Error);
273 Q_ASSERT(m_errors.isEmpty());
276 m_errors.reserve(errors.size());
277 for (
const QQmlError &error : errors) {
278 if (error.url().isEmpty()) {
279 QQmlError mutableError = error;
280 mutableError.setUrl(url());
281 m_errors.append(mutableError);
283 m_errors.append(error);
287 cancelAllWaitingFor();
291 qWarning().nospace() <<
"Errors for " << urlString();
292 for (
int ii = 0; ii < errors.size(); ++ii)
293 qWarning().nospace() <<
" " << qPrintable(errors.at(ii).toString());
300void QQmlDataBlob::setError(
const QQmlJS::DiagnosticMessage &error)
302 assertTypeLoaderThread();
304 e.setColumn(qmlConvertSourceCoordinate<quint32,
int>(error.loc.startColumn));
305 e.setLine(qmlConvertSourceCoordinate<quint32,
int>(error.loc.startLine));
306 e.setDescription(error.message);
311void QQmlDataBlob::setError(
const QString &description)
313 assertTypeLoaderThread();
315 e.setDescription(description);
321
322
323
324
325
326void QQmlDataBlob::addDependency(
const QQmlDataBlob::Ptr &blob)
328 assertTypeLoaderThread();
330 Q_ASSERT(status() != Null);
333 blob->status() == Error || blob->status() == Complete ||
334 status() == Error || status() == Complete || m_isDone)
337 for (
const auto &existingDep: std::as_const(m_waitingFor)) {
338 if (existingDep.data() == blob)
342 m_waitingFor.append(blob);
343 blob->m_waitingOnMe.append(
this);
345 setStatus(WaitingForDependencies);
348 if (m_waitingOnMe.indexOf(blob.data()) >= 0) {
349 qCWarning(lcCycle) <<
"Cyclic dependency detected between" <<
this->url().toString()
350 <<
"and" << blob->url().toString();
351 cancelAllWaitingFor();
357
358
359
360
361
362
365
366
367
368
369
370
371
372
373
374
375
376void QQmlDataBlob::done()
378 assertTypeLoaderThread();
381#if QT_CONFIG(qml_network)
383
384
385
386
387void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
389 assertTypeLoaderThread();
391 Q_UNUSED(networkError);
396 const char *errorString =
nullptr;
397 switch (networkError) {
399 errorString =
"Network error";
401 case QNetworkReply::ConnectionRefusedError:
402 errorString =
"Connection refused";
404 case QNetworkReply::RemoteHostClosedError:
405 errorString =
"Remote host closed the connection";
407 case QNetworkReply::HostNotFoundError:
408 errorString =
"Host not found";
410 case QNetworkReply::TimeoutError:
411 errorString =
"Timeout";
413 case QNetworkReply::ProxyConnectionRefusedError:
414 case QNetworkReply::ProxyConnectionClosedError:
415 case QNetworkReply::ProxyNotFoundError:
416 case QNetworkReply::ProxyTimeoutError:
417 case QNetworkReply::ProxyAuthenticationRequiredError:
418 case QNetworkReply::UnknownProxyError:
419 errorString =
"Proxy error";
421 case QNetworkReply::ContentAccessDenied:
422 errorString =
"Access denied";
424 case QNetworkReply::ContentNotFoundError:
425 errorString =
"File not found";
427 case QNetworkReply::AuthenticationRequiredError:
428 errorString =
"Authentication required";
432 error.setDescription(QLatin1String(errorString));
439
440
441
442
443void QQmlDataBlob::dependencyError(
const QQmlDataBlob::Ptr &blob)
445 assertTypeLoaderThread();
450
451
452
453
454void QQmlDataBlob::dependencyComplete(
const QQmlDataBlob::Ptr &blob)
456 assertTypeLoaderThread();
461
462
463
464
465
466void QQmlDataBlob::allDependenciesDone()
468 assertTypeLoaderThread();
469 setStatus(QQmlDataBlob::ResolvingDependencies);
473
474
475
476
477
478
479
480
481
482
483void QQmlDataBlob::downloadProgressChanged(qreal progress)
486 assertEngineThread();
490
491
492
493
494
495
496
497
498
499
500
501
502
503void QQmlDataBlob::completed()
505 assertEngineThread();
508void QQmlDataBlob::tryDone()
510 assertTypeLoaderThread();
512 if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
517 qWarning(
"QQmlDataBlob::done() %s", qPrintable(urlString()));
521 if (status() != Error)
524 notifyAllWaitingOnMe();
529 qWarning(
"QQmlDataBlob: Dispatching completed");
531 m_typeLoader->thread()->callCompleted(
this);
537void QQmlDataBlob::cancelAllWaitingFor()
539 while (m_waitingFor.size()) {
544 assertTypeLoaderThreadIfRunning();
546 QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
548 Q_ASSERT(blob->m_waitingOnMe.contains(
this));
550 blob->m_waitingOnMe.removeOne(
this);
554void QQmlDataBlob::notifyAllWaitingOnMe()
556 assertTypeLoaderThread();
558 while (m_waitingOnMe.size()) {
559 QQmlDataBlob::Ptr blob = m_waitingOnMe.takeLast();
561 Q_ASSERT(std::any_of(blob->m_waitingFor.constBegin(), blob->m_waitingFor.constEnd(),
562 [
this](
const QQmlRefPointer<QQmlDataBlob> &waiting) {
return waiting.data() ==
this; }));
564 blob->notifyComplete(
this);
568void QQmlDataBlob::notifyComplete(
const QQmlDataBlob::Ptr &blob)
570 assertTypeLoaderThread();
572 Q_ASSERT(blob->status() == Error || blob->status() == Complete);
573 Q_TRACE_SCOPE(QQmlCompiling, blob->url());
574 QQmlCompilingProfiler prof(typeLoader()->profiler(), blob.data());
578 QQmlRefPointer<QQmlDataBlob> blobRef;
579 for (
int i = 0; i < m_waitingFor.size(); ++i) {
580 if (m_waitingFor.at(i).data() == blob) {
581 blobRef = m_waitingFor.takeAt(i);
587 if (blob->status() == Error) {
588 dependencyError(blob);
589 }
else if (blob->status() == Complete) {
590 dependencyComplete(blob);
593 if (!isError() && m_waitingFor.isEmpty())
594 allDependenciesDone();
596 m_inCallback =
false;
601QString QQmlDataBlob::SourceCodeData::readAll(QString *error)
const
604 if (hasInlineSourceCode)
605 return inlineSourceCode;
607 QFile f(fileInfo.absoluteFilePath());
608 if (!f.open(QIODevice::ReadOnly)) {
609 *error = f.errorString();
613 const qint64 fileSize = fileInfo.size();
615 if (uchar *mappedData = f.map(0, fileSize)) {
616 QString source = QString::fromUtf8(
reinterpret_cast<
const char *>(mappedData), fileSize);
621 QByteArray data(fileSize, Qt::Uninitialized);
622 if (f.read(data.data(), data.size()) != data.size()) {
623 *error = f.errorString();
626 return QString::fromUtf8(data);
629QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp()
const
631 if (hasInlineSourceCode)
634 return fileInfo.lastModified();
637bool QQmlDataBlob::SourceCodeData::exists()
const
639 if (hasInlineSourceCode)
641 return fileInfo.exists();
644bool QQmlDataBlob::SourceCodeData::isEmpty()
const
646 if (hasInlineSourceCode)
647 return inlineSourceCode.isEmpty();
648 return fileInfo.size() == 0;
651bool QQmlDataBlob::setStatus(Status status)
656 case WaitingForDependencies:
657 Q_ASSERT(!m_waitingFor.isEmpty());
660 case ResolvingDependencies:
663 Q_ASSERT(m_waitingFor.isEmpty());
667 return m_data.setStatus(status);
DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE)