diff options
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 405 |
1 files changed, 143 insertions, 262 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0ac1d7fabd..ea9b83cee3 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -79,8 +79,8 @@ #ifdef DATABLOB_DEBUG -#define ASSERT_MAINTHREAD() do { if(m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in main thread"); } while(false) -#define ASSERT_LOADTHREAD() do { if(!m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in load thread"); } while(false) +#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false) +#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false) #define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false) #else @@ -108,14 +108,14 @@ namespace { // This is a lame object that we need to ensure that slots connected to // QNetworkReply get called in the correct thread (the loader thread). -// As QQmlDataLoader lives in the main thread, and we can't use +// As QQmlTypeLoader lives in the main thread, and we can't use // Qt::DirectConnection connections from a QNetworkReply (because then // sender() wont work), we need to insert this object in the middle. -class QQmlDataLoaderNetworkReplyProxy : public QObject +class QQmlTypeLoaderNetworkReplyProxy : public QObject { Q_OBJECT public: - QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l); + QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l); public slots: void finished(); @@ -123,17 +123,17 @@ public slots: void manualFinished(QNetworkReply*); private: - QQmlDataLoader *l; + QQmlTypeLoader *l; }; -class QQmlDataLoaderThread : public QQmlThread +class QQmlTypeLoaderThread : public QQmlThread { - typedef QQmlDataLoaderThread This; + typedef QQmlTypeLoaderThread This; public: - QQmlDataLoaderThread(QQmlDataLoader *loader); + QQmlTypeLoaderThread(QQmlTypeLoader *loader); QNetworkAccessManager *networkAccessManager() const; - QQmlDataLoaderNetworkReplyProxy *networkReplyProxy() const; + QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const; void load(QQmlDataBlob *b); void loadAsync(QQmlDataBlob *b); @@ -156,18 +156,18 @@ private: void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p); void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri); - QQmlDataLoader *m_loader; + QQmlTypeLoader *m_loader; mutable QNetworkAccessManager *m_networkAccessManager; - mutable QQmlDataLoaderNetworkReplyProxy *m_networkReplyProxy; + mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy; }; -QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l) +QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l) : l(l) { } -void QQmlDataLoaderNetworkReplyProxy::finished() +void QQmlTypeLoaderNetworkReplyProxy::finished() { Q_ASSERT(sender()); Q_ASSERT(qobject_cast<QNetworkReply *>(sender())); @@ -175,7 +175,7 @@ void QQmlDataLoaderNetworkReplyProxy::finished() l->networkReplyFinished(reply); } -void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +void QQmlTypeLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { Q_ASSERT(sender()); Q_ASSERT(qobject_cast<QNetworkReply *>(sender())); @@ -184,7 +184,7 @@ void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qin } // This function is for when you want to shortcut the signals and call directly -void QQmlDataLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply) +void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply) { qint64 replySize = reply->size(); l->networkReplyProgress(reply, replySize, replySize); @@ -194,12 +194,12 @@ void QQmlDataLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply) /*! \class QQmlDataBlob -\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlDataLoader. +\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlTypeLoader. \internal -QQmlDataBlob's are loaded by a QQmlDataLoader. The user creates the QQmlDataBlob -and then calls QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() to load it. -The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes available. +QQmlDataBlob's are loaded by a QQmlTypeLoader. The user creates the QQmlDataBlob +and then calls QQmlTypeLoader::load() or QQmlTypeLoader::loadWithStaticData() to load it. +The QQmlTypeLoader invokes callbacks on the QQmlDataBlob as data becomes available. */ /*! @@ -208,7 +208,7 @@ The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes availab This enum describes the status of the data blob. \list -\li Null The blob has not yet been loaded by a QQmlDataLoader +\li Null The blob has not yet been loaded by a QQmlTypeLoader \li Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been invoked or has not yet returned. \li WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status @@ -234,10 +234,14 @@ This enum describes the type of the data blob. /*! Create a new QQmlDataBlob for \a url and of the provided \a type. */ -QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type) -: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0), +QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type, QQmlTypeLoader *manager) +: m_typeLoader(manager), m_type(type), m_url(url), m_finalUrl(url), m_redirectCount(0), m_inCallback(false), m_isDone(false) { + //Set here because we need to get the engine from the manager + if (m_typeLoader->engine() && m_typeLoader->engine()->urlInterceptor()) + m_url = m_typeLoader->engine()->urlInterceptor()->intercept(m_url, + (QQmlAbstractUrlInterceptor::DataType)m_type); } /*! \internal */ @@ -249,20 +253,12 @@ QQmlDataBlob::~QQmlDataBlob() } /*! - Sets the manager, and does stuff like selection which needs access to the manager. Must be called before loading can occur. */ -void QQmlDataBlob::startLoading(QQmlDataLoader *manager) +void QQmlDataBlob::startLoading() { Q_ASSERT(status() == QQmlDataBlob::Null); - Q_ASSERT(m_manager == 0); m_data.setStatus(QQmlDataBlob::Loading); - m_manager = manager; - - //Set here because we need to get the engine from the manager - if (manager && manager->engine() && manager->engine()->urlInterceptor()) - m_url = manager->engine()->urlInterceptor()->intercept(m_url, - (QQmlAbstractUrlInterceptor::DataType)m_type); } /*! @@ -360,7 +356,7 @@ May only be called from the load thread, or after the blob isCompleteOrError(). */ QUrl QQmlDataBlob::finalUrl() const { - Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread())); return m_finalUrl; } @@ -369,7 +365,7 @@ Returns the finalUrl() as a string. */ QString QQmlDataBlob::finalUrlString() const { - Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread())); if (m_finalUrlString.isEmpty()) m_finalUrlString = m_finalUrl.toString(); @@ -383,7 +379,7 @@ May only be called from the load thread, or after the blob isCompleteOrError(). */ QList<QQmlError> QQmlDataBlob::errors() const { - Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread())); + Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread())); return m_errors; } @@ -617,7 +613,7 @@ void QQmlDataBlob::tryDone() #ifdef DATABLOB_DEBUG qWarning("QQmlDataBlob: Dispatching completed"); #endif - m_manager->m_thread->callCompleted(this); + m_typeLoader->m_thread->callCompleted(this); release(); } @@ -725,86 +721,86 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v) } } -QQmlDataLoaderThread::QQmlDataLoaderThread(QQmlDataLoader *loader) +QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader) : m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0) { // Do that after initializing all the members. startup(); } -QNetworkAccessManager *QQmlDataLoaderThread::networkAccessManager() const +QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const { Q_ASSERT(isThisThread()); if (!m_networkAccessManager) { m_networkAccessManager = QQmlEnginePrivate::get(m_loader->engine())->createNetworkAccessManager(0); - m_networkReplyProxy = new QQmlDataLoaderNetworkReplyProxy(m_loader); + m_networkReplyProxy = new QQmlTypeLoaderNetworkReplyProxy(m_loader); } return m_networkAccessManager; } -QQmlDataLoaderNetworkReplyProxy *QQmlDataLoaderThread::networkReplyProxy() const +QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const { Q_ASSERT(isThisThread()); Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first return m_networkReplyProxy; } -void QQmlDataLoaderThread::load(QQmlDataBlob *b) +void QQmlTypeLoaderThread::load(QQmlDataBlob *b) { b->addref(); callMethodInThread(&This::loadThread, b); } -void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b) +void QQmlTypeLoaderThread::loadAsync(QQmlDataBlob *b) { b->addref(); postMethodToThread(&This::loadThread, b); } -void QQmlDataLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d) +void QQmlTypeLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d) { b->addref(); callMethodInThread(&This::loadWithStaticDataThread, b, d); } -void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d) +void QQmlTypeLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d) { b->addref(); postMethodToThread(&This::loadWithStaticDataThread, b, d); } -void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) +void QQmlTypeLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) { b->addref(); callMethodInThread(&This::loadWithCachedUnitThread, b, unit); } -void QQmlDataLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) +void QQmlTypeLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) { b->addref(); postMethodToThread(&This::loadWithCachedUnitThread, b, unit); } -void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b) +void QQmlTypeLoaderThread::callCompleted(QQmlDataBlob *b) { b->addref(); postMethodToMain(&This::callCompletedMain, b); } -void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p) +void QQmlTypeLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p) { b->addref(); postMethodToMain(&This::callDownloadProgressChangedMain, b, p); } -void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface, +void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface, const char *uri) { callMethodInMain(&This::initializeEngineMain, iface, uri); } -void QQmlDataLoaderThread::shutdownThread() +void QQmlTypeLoaderThread::shutdownThread() { delete m_networkAccessManager; m_networkAccessManager = 0; @@ -812,45 +808,45 @@ void QQmlDataLoaderThread::shutdownThread() m_networkReplyProxy = 0; } -void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b) +void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b) { m_loader->loadThread(b); b->release(); } -void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d) +void QQmlTypeLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d) { m_loader->loadWithStaticDataThread(b, d); b->release(); } -void QQmlDataLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) +void QQmlTypeLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit) { m_loader->loadWithCachedUnitThread(b, unit); b->release(); } -void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b) +void QQmlTypeLoaderThread::callCompletedMain(QQmlDataBlob *b) { QML_MEMORY_SCOPE_URL(b->url()); #ifdef DATABLOB_DEBUG - qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString())); + qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->url().toString())); #endif b->completed(); b->release(); } -void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p) +void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p) { #ifdef DATABLOB_DEBUG - qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback", + qWarning("QQmlTypeLoaderThread: %s downloadProgressChanged(%f) callback", qPrintable(b->url().toString()), p); #endif b->downloadProgressChanged(p); b->release(); } -void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, +void QQmlTypeLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, const char *uri) { Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread()); @@ -858,14 +854,14 @@ void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, } /*! -\class QQmlDataLoader -\brief The QQmlDataLoader class abstracts loading files and their dependencies over the network. +\class QQmlTypeLoader +\brief The QQmlTypeLoader class abstracts loading files and their dependencies over the network. \internal -The QQmlDataLoader class is provided for the exclusive use of the QQmlTypeLoader class. +The QQmlTypeLoader class is provided for the exclusive use of the QQmlTypeLoader class. -Clients create QQmlDataBlob instances and submit them to the QQmlDataLoader class -through the QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() methods. +Clients create QQmlDataBlob instances and submit them to the QQmlTypeLoader class +through the QQmlTypeLoader::load() or QQmlTypeLoader::loadWithStaticData() methods. The loader then fetches the data over the network or from the local file system in an efficient way. QQmlDataBlob is an abstract class, so should always be specialized. @@ -887,21 +883,7 @@ one of these three preconditions are met. Thus QQmlDataBlob::done() will always eventually be called, even if the blob has an error set. */ -/*! -Create a new QQmlDataLoader for \a engine. -*/ -QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine) -: m_engine(engine), m_thread(new QQmlDataLoaderThread(this)) -{ -} - -/*! \internal */ -QQmlDataLoader::~QQmlDataLoader() -{ - invalidate(); -} - -void QQmlDataLoader::invalidate() +void QQmlTypeLoader::invalidate() { if (m_thread) { shutdownThread(); @@ -917,12 +899,12 @@ void QQmlDataLoader::invalidate() m_networkReplies.clear(); } -void QQmlDataLoader::lock() +void QQmlTypeLoader::lock() { m_thread->lock(); } -void QQmlDataLoader::unlock() +void QQmlTypeLoader::unlock() { m_thread->unlock(); } @@ -932,13 +914,13 @@ Load the provided \a blob from the network or filesystem. The loader must be locked. */ -void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode) +void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode) { #ifdef DATABLOB_DEBUG - qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), + qWarning("QQmlTypeLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), m_thread->isThisThread()?"Compile":"Engine"); #endif - blob->startLoading(this); + blob->startLoading(); if (m_thread->isThisThread()) { unlock(); @@ -964,14 +946,14 @@ Load the provided \a blob with \a data. The blob's URL is not used by the data The loader must be locked. */ -void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode) +void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode) { #ifdef DATABLOB_DEBUG - qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), + qWarning("QQmlTypeLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), m_thread->isThisThread()?"Compile":"Engine"); #endif - blob->startLoading(this); + blob->startLoading(); if (m_thread->isThisThread()) { unlock(); @@ -992,14 +974,14 @@ void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &da } } -void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode) +void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode) { #ifdef DATABLOB_DEBUG - qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()), + qWarning("QQmlTypeLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()), m_thread->isThisThread()?"Compile":"Engine"); #endif - blob->startLoading(this); + blob->startLoading(); if (m_thread->isThisThread()) { unlock(); @@ -1020,21 +1002,21 @@ void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::C } } -void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data) +void QQmlTypeLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data) { ASSERT_LOADTHREAD(); setData(blob, data); } -void QQmlDataLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) +void QQmlTypeLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) { ASSERT_LOADTHREAD(); setCachedUnit(blob, unit); } -void QQmlDataLoader::loadThread(QQmlDataBlob *blob) +void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) { ASSERT_LOADTHREAD(); @@ -1089,7 +1071,7 @@ void QQmlDataLoader::loadThread(QQmlDataBlob *blob) } else { QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url)); - QQmlDataLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy(); + QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy(); blob->addref(); m_networkReplies.insert(reply, blob); @@ -1111,7 +1093,7 @@ void QQmlDataLoader::loadThread(QQmlDataBlob *blob) #define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 -void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply) +void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) { Q_ASSERT(m_thread->isThisThread()); @@ -1150,7 +1132,7 @@ void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply) blob->release(); } -void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply, +void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply, qint64 bytesReceived, qint64 bytesTotal) { Q_ASSERT(m_thread->isThisThread()); @@ -1170,7 +1152,7 @@ void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply, /*! Return the QQmlEngine associated with this loader */ -QQmlEngine *QQmlDataLoader::engine() const +QQmlEngine *QQmlTypeLoader::engine() const { return m_engine; } @@ -1179,7 +1161,7 @@ QQmlEngine *QQmlDataLoader::engine() const Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it gets called in the correct thread. */ -void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface, +void QQmlTypeLoader::initializeEngine(QQmlExtensionInterface *iface, const char *uri) { Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread()); @@ -1193,7 +1175,7 @@ void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface, } -void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data) +void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data) { QML_MEMORY_SCOPE_URL(blob->url()); QQmlDataBlob::Data d; @@ -1201,7 +1183,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data) setData(blob, d); } -void QQmlDataLoader::setData(QQmlDataBlob *blob, QQmlFile *file) +void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file) { QML_MEMORY_SCOPE_URL(blob->url()); QQmlDataBlob::Data d; @@ -1209,7 +1191,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, QQmlFile *file) setData(blob, d); } -void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d) +void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d) { QML_MEMORY_SCOPE_URL(blob->url()); blob->m_inCallback = true; @@ -1227,7 +1209,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d) blob->tryDone(); } -void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) +void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit) { QML_MEMORY_SCOPE_URL(blob->url()); blob->m_inCallback = true; @@ -1245,14 +1227,14 @@ void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::Cached blob->tryDone(); } -void QQmlDataLoader::shutdownThread() +void QQmlTypeLoader::shutdownThread() { if (m_thread && !m_thread->isShutdown()) m_thread->shutdown(); } QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader) - : QQmlDataBlob(url, type), m_typeLoader(loader), m_importCache(loader), m_isSingleton(false) + : QQmlDataBlob(url, type, loader), m_importCache(loader), m_isSingleton(false) { } @@ -1305,7 +1287,7 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile if (!importQualifier.isEmpty()) { // Does this library contain any qualified scripts? QUrl libraryUrl(qmldirUrl); - const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier, qmldirUrl); + const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier); foreach (const QQmlDirParser::Script &script, qmldir->scripts()) { QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName)); QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl); @@ -1352,7 +1334,7 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL if (!importQualifier.isEmpty()) { // Does this library contain any qualified scripts? QUrl libraryUrl(qmldirUrl); - const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath, qmldirUrl); + const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath); foreach (const QQmlDirParser::Script &script, qmldir->scripts()) { QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName)); QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl); @@ -1585,7 +1567,7 @@ bool QQmlTypeLoader::QmldirContent::designerSupported() const Constructs a new type loader that uses the given \a engine. */ QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) -: QQmlDataLoader(engine) + : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)) { } @@ -1599,6 +1581,8 @@ QQmlTypeLoader::~QQmlTypeLoader() shutdownThread(); clearCache(); + + invalidate(); } QQmlImportDatabase *QQmlTypeLoader::importDatabase() @@ -1623,10 +1607,10 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode) typeData = new QQmlTypeData(url, this); // TODO: if (compiledData == 0), is it safe to omit this insertion? m_typeCache.insert(url, typeData); - if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) { - QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit, mode); + if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(typeData->url())) { + QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode); } else { - QQmlDataLoader::load(typeData, mode); + QQmlTypeLoader::load(typeData, mode); } } @@ -1644,7 +1628,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url) LockHolder<QQmlTypeLoader> holder(this); QQmlTypeData *typeData = new QQmlTypeData(url, this); - QQmlDataLoader::loadWithStaticData(typeData, data); + QQmlTypeLoader::loadWithStaticData(typeData, data); return typeData; } @@ -1666,10 +1650,10 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url) scriptBlob = new QQmlScriptBlob(url, this); m_scriptCache.insert(url, scriptBlob); - if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) { - QQmlDataLoader::loadWithCachedUnit(scriptBlob, cachedUnit); + if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(scriptBlob->url())) { + QQmlTypeLoader::loadWithCachedUnit(scriptBlob, cachedUnit); } else { - QQmlDataLoader::load(scriptBlob); + QQmlTypeLoader::load(scriptBlob); } } @@ -1694,7 +1678,7 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url) if (!qmldirData) { qmldirData = new QQmlQmldirData(url, this); m_qmldirCache.insert(url, qmldirData); - QQmlDataLoader::load(qmldirData); + QQmlTypeLoader::load(qmldirData); } qmldirData->addref(); @@ -1702,82 +1686,15 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url) return qmldirData; } +// #### Qt 6: Remove this function, it exists only for binary compatibility. /*! -Returns a QQmlBundleData for \a identifier. -*/ -QQmlBundleData *QQmlTypeLoader::getBundle(const QString &identifier) -{ - return getBundle(QHashedStringRef(identifier)); -} - -QQmlBundleData *QQmlTypeLoader::getBundle(const QHashedStringRef &identifier) -{ - lock(); - - QQmlBundleData *rv = 0; - QQmlBundleData **bundle = m_bundleCache.value(identifier); - if (bundle) { - rv = *bundle; - rv->addref(); - } - - unlock(); - - return rv; -} - -QQmlBundleData::QQmlBundleData(const QString &file) -: QQmlBundle(file), fileName(file) -{ -} - -// XXX check for errors etc. -void QQmlTypeLoader::addBundle(const QString &identifier, const QString &fileName) -{ - lock(); - addBundleNoLock(identifier, fileName); - unlock(); -} - -void QQmlTypeLoader::addBundleNoLock(const QString &identifier, const QString &fileName) -{ - QQmlBundleData *data = new QQmlBundleData(fileName); - if (data->open()) { - - m_bundleCache.insert(identifier, data); - - } else { - data->release(); - } -} - -QString QQmlTypeLoader::bundleIdForQmldir(const QString &name, const QString &uriHint) -{ - lock(); - QString *bundleId = m_qmldirBundleIdCache.value(name); - if (!bundleId) { - QString newBundleId = QLatin1String("qml.") + uriHint.toLower() /* XXX toLower()? */; - if (m_qmldirBundleIdCache.contains(newBundleId)) - newBundleId += QString::number(m_qmldirBundleIdCache.count()); - m_qmldirBundleIdCache.insert(name, newBundleId); - addBundleNoLock(newBundleId, name); - unlock(); - return newBundleId; - } else { - unlock(); - return *bundleId; - } -} - + * \internal + */ bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName) { - Q_D(QQmlEngine); - - if (name.startsWith(QLatin1String("qml."))) // reserved - return false; - - d->typeLoader.addBundle(name, fileName); - return true; + Q_UNUSED(name) + Q_UNUSED(fileName) + return false; } /*! @@ -1896,20 +1813,20 @@ bool QQmlTypeLoader::directoryExists(const QString &path) /*! Return a QmldirContent for absoluteFilePath. The QmldirContent may be cached. -\a filePath is either a bundle URL, or a local file path. +\a filePath is a local file path. It can also be a remote path for a remote directory import, but it will have been cached by now in this case. */ -const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn, const QString &uriHint) +const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn) { - QUrl url(filePathIn); //May already contain bundle or http scheme + QUrl url(filePathIn); //May already contain http scheme if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) return *(m_importQmlDirCache.value(filePathIn)); //Can't load the remote here, but should be cached - else if (!QQmlFile::isBundle(filePathIn)) + else url = QUrl::fromLocalFile(filePathIn); if (engine() && engine()->urlInterceptor()) url = engine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::QmldirFile); - Q_ASSERT(url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("bundle")); + Q_ASSERT(url.scheme() == QLatin1String("file")); QString filePath; if (url.scheme() == QLatin1String("file")) filePath = url.toLocalFile(); @@ -1925,45 +1842,14 @@ const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString #define NOT_READABLE_ERROR QString(QLatin1String("module \"$$URI$$\" definition \"%1\" not readable")) #define CASE_MISMATCH_ERROR QString(QLatin1String("cannot load module \"$$URI$$\": File name case mismatch for \"%1\"")) - if (QQmlFile::isBundle(url.toString())) { - QQmlFile file(engine(), url); - if (file.isError()) { - ERROR(NOT_READABLE_ERROR.arg(url.toString())); - } else { - QString content(QString::fromUtf8(file.data(), file.size())); - qmldir->setContent(filePath, content); - } - + QFile file(filePath); + if (!QQml_isFileCaseCorrect(filePath)) { + ERROR(CASE_MISMATCH_ERROR.arg(filePath)); + } else if (file.open(QFile::ReadOnly)) { + QByteArray data = file.readAll(); + qmldir->setContent(filePath, QString::fromUtf8(data)); } else { - - QFile file(filePath); - if (!QQml_isFileCaseCorrect(filePath)) { - ERROR(CASE_MISMATCH_ERROR.arg(filePath)); - } else if (file.open(QFile::ReadOnly)) { - QByteArray data = file.read(QQmlBundle::bundleHeaderLength()); - - if (QQmlBundle::isBundleHeader(data.constData(), data.length())) { - QString id = bundleIdForQmldir(filePath, uriHint); - - QString bundleUrl = QLatin1String("bundle://") + id + QLatin1Char('/'); - - QUrl url(bundleUrl + QLatin1String("qmldir")); - - QQmlFile file(engine(), url); - if (file.isError()) { - ERROR(NOT_READABLE_ERROR.arg(filePath)); - } else { - QString content(QString::fromUtf8(file.data(), file.size())); - qmldir->setContent(QQmlFile::bundleFileName(bundleUrl, engine()), content); - } - } else { - data += file.readAll(); - qmldir->setContent(filePath, QString::fromUtf8(data)); - } - } else { - ERROR(NOT_READABLE_ERROR.arg(filePath)); - } - + ERROR(NOT_READABLE_ERROR.arg(filePath)); } #undef ERROR @@ -2223,10 +2109,6 @@ bool QQmlTypeData::loadImplicitImport() void QQmlTypeData::dataReceived(const Data &data) { QString code = QString::fromUtf8(data.data(), data.size()); - QByteArray preparseData; - - if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse")); - QQmlEngine *qmlEngine = typeLoader()->engine(); m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0)); QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames()); @@ -2579,7 +2461,6 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare Q_ASSERT(parentCtxt && parentCtxt->engine); QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine); - QV8Engine *v8engine = ep->v8engine(); QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine); QV4::Scope scope(v4); @@ -2622,12 +2503,12 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare QV4::ScopedObject scriptsArray(scope); if (ctxt->importedScripts.isNullOrUndefined()) { scriptsArray = v4->newArrayObject(scripts.count()); - ctxt->importedScripts = scriptsArray; + ctxt->importedScripts.set(v4, scriptsArray); } else { - scriptsArray = ctxt->importedScripts; + scriptsArray = ctxt->importedScripts.valueRef(); } for (int ii = 0; ii < scripts.count(); ++ii) - scriptsArray->putIndexed(ii, scripts.at(ii)->scriptData()->scriptValueForContext(ctxt)); + scriptsArray->putIndexed(ii, *scripts.at(ii)->scriptData()->scriptValueForContext(ctxt).valueRef()); if (!hasEngine()) initialize(parentCtxt->engine); @@ -2638,19 +2519,18 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare return QV4::PersistentValue(); } - QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v8engine, ctxt, 0)); + QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0)); QV4::QmlContextWrapper::takeContextOwnership(qmlglobal); - QV4::ExecutionContext *ctx = QV8Engine::getV4(v8engine)->currentContext(); - m_program->qml = qmlglobal; + m_program->qml.set(scope.engine, qmlglobal); m_program->run(); if (scope.engine->hasException) { - QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx); + QQmlError error = scope.engine->catchExceptionAsQmlError(); if (error.isValid()) ep->warning(error); } - rv = qmlglobal; + rv.set(scope.engine, qmlglobal); if (shared) { m_value = rv; m_loaded = true; @@ -2692,33 +2572,34 @@ QQmlScriptData *QQmlScriptBlob::scriptData() const return m_scriptData; } +struct EmptyCompilationUnit : public QV4::CompiledData::CompilationUnit +{ + virtual void linkBackendToEngine(QV4::ExecutionEngine *) {} +}; + void QQmlScriptBlob::dataReceived(const Data &data) { QString source = QString::fromUtf8(data.data(), data.size()); QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); QmlIR::Document irUnit(v4->debugger != 0); - QQmlJS::DiagnosticMessage metaDataError; - irUnit.extractScriptMetaData(source, &metaDataError); - if (!metaDataError.message.isEmpty()) { - QQmlError e; - e.setUrl(finalUrl()); - e.setLine(metaDataError.loc.startLine); - e.setColumn(metaDataError.loc.startColumn); - e.setDescription(metaDataError.message); - setError(e); - return; - } + QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator); QList<QQmlError> errors; - QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors); + QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors, &collector); // No need to addref on unit, it's initial refcount is 1 source.clear(); if (!errors.isEmpty()) { setError(errors); return; } + if (!unit) { + unit.take(new EmptyCompilationUnit); + } irUnit.javaScriptCompilationUnit = unit; + irUnit.imports = collector.imports; + if (collector.hasPragmaLibrary) + irUnit.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary; QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit); |