~ubuntu-branches/debian/jessie/qtdeclarative-opensource-src/jessie

« back to all changes in this revision

Viewing changes to src/qml/qml/qqmltypeloader.cpp

  • Committer: Package Import Robot
  • Author(s): Lisandro Damián Nicanor Pérez Meyer
  • Date: 2014-06-05 23:53:56 UTC
  • mfrom: (8.1.11 experimental)
  • Revision ID: package-import@ubuntu.com-20140605235356-cf36ioh08oh2oow4
Tags: 5.3.0-5
* Upload to unstable.
* Backport v4_yarr_jit_push_pop_addressTempRegister.patch to fix a bug
  of the JIT compiler in arm. Thanks Scott Kitterman for pointing it out.
* Update symbols files with buildds' logs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
#include <private/qqmlthread_p.h>
50
50
#include <private/qqmlcompiler_p.h>
51
51
#include <private/qqmlcomponent_p.h>
52
 
#include <private/qqmlprofilerservice_p.h>
 
52
#include <private/qqmlprofiler_p.h>
53
53
#include <private/qqmlmemoryprofiler_p.h>
54
 
#include <private/qqmlcodegenerator_p.h>
 
54
#include <private/qqmltypecompiler_p.h>
55
55
 
56
56
#include <QtCore/qdir.h>
57
57
#include <QtCore/qfile.h>
93
93
 
94
94
#else
95
95
 
96
 
#define ASSERT_MAINTHREAD() 
 
96
#define ASSERT_MAINTHREAD()
97
97
#define ASSERT_LOADTHREAD()
98
98
#define ASSERT_CALLBACK()
99
99
 
115
115
}
116
116
 
117
117
// This is a lame object that we need to ensure that slots connected to
118
 
// QNetworkReply get called in the correct thread (the loader thread).  
 
118
// QNetworkReply get called in the correct thread (the loader thread).
119
119
// As QQmlDataLoader lives in the main thread, and we can't use
120
 
// Qt::DirectConnection connections from a QNetworkReply (because then 
 
120
// Qt::DirectConnection connections from a QNetworkReply (because then
121
121
// sender() wont work), we need to insert this object in the middle.
122
122
class QQmlDataLoaderNetworkReplyProxy : public QObject
123
123
{
147
147
    void loadAsync(QQmlDataBlob *b);
148
148
    void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
149
149
    void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &);
 
150
    void loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
150
151
    void callCompleted(QQmlDataBlob *b);
151
152
    void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
152
153
    void initializeEngine(QQmlExtensionInterface *, const char *);
157
158
private:
158
159
    void loadThread(QQmlDataBlob *b);
159
160
    void loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &);
 
161
    void loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
160
162
    void callCompletedMain(QQmlDataBlob *b);
161
163
    void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p);
162
164
    void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
167
169
};
168
170
 
169
171
 
170
 
QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l) 
171
 
: l(l) 
 
172
QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l)
 
173
: l(l)
172
174
{
173
175
}
174
176
 
240
242
Create a new QQmlDataBlob for \a url and of the provided \a type.
241
243
*/
242
244
QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type)
243
 
: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0), 
 
245
: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0),
244
246
  m_inCallback(false), m_isDone(false)
245
247
{
246
248
}
395
397
/*!
396
398
Mark this blob as having \a errors.
397
399
 
398
 
All outstanding dependencies will be cancelled.  Requests to add new dependencies 
 
400
All outstanding dependencies will be cancelled.  Requests to add new dependencies
399
401
will be ignored.  Entry into the Error state is irreversable.
400
402
 
401
403
The setError() method may only be called from within a QQmlDataBlob callback.
433
435
        tryDone();
434
436
}
435
437
 
436
 
/*! 
437
 
Wait for \a blob to become complete or to error.  If \a blob is already 
 
438
/*!
 
439
Wait for \a blob to become complete or to error.  If \a blob is already
438
440
complete or in error, or this blob is already complete, this has no effect.
439
441
 
440
442
The setError() method may only be called from within a QQmlDataBlob callback.
447
449
 
448
450
    if (!blob ||
449
451
        blob->status() == Error || blob->status() == Complete ||
450
 
        status() == Error || status() == Complete || m_isDone || 
 
452
        status() == Error || status() == Complete || m_isDone ||
451
453
        m_waitingFor.contains(blob))
452
454
        return;
453
455
 
468
470
*/
469
471
 
470
472
/*!
471
 
Invoked once data has either been received or a network error occurred, and all 
 
473
Invoked once data has either been received or a network error occurred, and all
472
474
dependencies are complete.
473
475
 
474
476
You can set an error in this method, but you cannot add new dependencies.  Implementors
536
538
    setError(error);
537
539
}
538
540
 
539
 
/*! 
 
541
/*!
540
542
Called if \a blob, which was previously waited for, has an error.
541
543
 
542
544
The default implementation does nothing.
556
558
    Q_UNUSED(blob);
557
559
}
558
560
 
559
 
/*! 
560
 
Called when all blobs waited for have completed.  This occurs regardless of 
561
 
whether they are in error, or complete state.  
 
561
/*!
 
562
Called when all blobs waited for have completed.  This occurs regardless of
 
563
whether they are in error, or complete state.
562
564
 
563
565
The default implementation does nothing.
564
566
*/
570
572
Called when the download progress of this blob changes.  \a progress goes
571
573
from 0 to 1.
572
574
 
573
 
This callback is only invoked if an asynchronous load for this blob is 
 
575
This callback is only invoked if an asynchronous load for this blob is
574
576
made.  An asynchronous load is one in which the Asynchronous mode is
575
 
specified explicitly, or one that is implicitly delayed due to a network 
 
577
specified explicitly, or one that is implicitly delayed due to a network
576
578
operation.
577
579
 
578
580
The default implementation does nothing.
586
588
Invoked on the main thread sometime after done() was called on the load thread.
587
589
 
588
590
You cannot modify the blobs state at all in this callback and cannot depend on the
589
 
order or timeliness of these callbacks.  Implementors should use this callback to notify 
 
591
order or timeliness of these callbacks.  Implementors should use this callback to notify
590
592
dependencies on the main thread that the blob is done and not a lot else.
591
593
 
592
 
This callback is only invoked if an asynchronous load for this blob is 
 
594
This callback is only invoked if an asynchronous load for this blob is
593
595
made.  An asynchronous load is one in which the Asynchronous mode is
594
 
specified explicitly, or one that is implicitly delayed due to a network 
 
596
specified explicitly, or one that is implicitly delayed due to a network
595
597
operation.
596
598
 
597
599
The default implementation does nothing.
669
671
 
670
672
    blob->release();
671
673
 
672
 
    if (!isError() && m_waitingFor.isEmpty()) 
 
674
    if (!isError() && m_waitingFor.isEmpty())
673
675
        allDependenciesDone();
674
676
 
675
677
    m_inCallback = false;
753
755
    return m_networkReplyProxy;
754
756
}
755
757
 
756
 
void QQmlDataLoaderThread::load(QQmlDataBlob *b) 
757
 
 
758
void QQmlDataLoaderThread::load(QQmlDataBlob *b)
 
759
{
758
760
    b->addref();
759
 
    callMethodInThread(&This::loadThread, b); 
 
761
    callMethodInThread(&This::loadThread, b);
760
762
}
761
763
 
762
764
void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b)
777
779
    postMethodToThread(&This::loadWithStaticDataThread, b, d);
778
780
}
779
781
 
780
 
void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b) 
781
 
782
 
    b->addref(); 
783
 
    postMethodToMain(&This::callCompletedMain, b); 
784
 
}
785
 
 
786
 
void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p) 
787
 
788
 
    b->addref(); 
789
 
    postMethodToMain(&This::callDownloadProgressChangedMain, b, p); 
790
 
}
791
 
 
792
 
void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface, 
 
782
void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
 
783
{
 
784
    b->addref();
 
785
    callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
 
786
}
 
787
 
 
788
void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
 
789
{
 
790
    b->addref();
 
791
    postMethodToMain(&This::callCompletedMain, b);
 
792
}
 
793
 
 
794
void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
 
795
{
 
796
    b->addref();
 
797
    postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
 
798
}
 
799
 
 
800
void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
793
801
                                                    const char *uri)
794
802
{
795
803
    callMethodInMain(&This::initializeEngineMain, iface, uri);
803
811
    m_networkReplyProxy = 0;
804
812
}
805
813
 
806
 
void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b) 
807
 
808
 
    m_loader->loadThread(b); 
 
814
void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b)
 
815
{
 
816
    m_loader->loadThread(b);
809
817
    b->release();
810
818
}
811
819
 
815
823
    b->release();
816
824
}
817
825
 
818
 
void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b) 
819
 
 
826
void QQmlDataLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
 
827
{
 
828
    m_loader->loadWithCachedUnitThread(b, unit);
 
829
    b->release();
 
830
}
 
831
 
 
832
void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b)
 
833
{
820
834
    QML_MEMORY_SCOPE_URL(b->url());
821
835
#ifdef DATABLOB_DEBUG
822
 
    qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString())); 
 
836
    qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
823
837
#endif
824
 
    b->completed(); 
825
 
    b->release(); 
 
838
    b->completed();
 
839
    b->release();
826
840
}
827
841
 
828
 
void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p) 
829
 
 
842
void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
 
843
{
830
844
#ifdef DATABLOB_DEBUG
831
 
    qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback", 
832
 
             qPrintable(b->url().toString()), p); 
 
845
    qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback",
 
846
             qPrintable(b->url().toString()), p);
833
847
#endif
834
 
    b->downloadProgressChanged(p); 
835
 
    b->release(); 
 
848
    b->downloadProgressChanged(p);
 
849
    b->release();
836
850
}
837
851
 
838
 
void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, 
 
852
void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
839
853
                                                        const char *uri)
840
854
{
841
855
    Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
855
869
QQmlDataBlob is an abstract class, so should always be specialized.
856
870
 
857
871
Once data is received, the QQmlDataBlob::dataReceived() method is invoked on the blob.  The
858
 
derived class should use this callback to process the received data.  Processing of the data can 
 
872
derived class should use this callback to process the received data.  Processing of the data can
859
873
result in an error being set (QQmlDataBlob::setError()), or one or more dependencies being
860
874
created (QQmlDataBlob::addDependency()).  Dependencies are other QQmlDataBlob's that
861
875
are required before processing can fully complete.
883
897
/*! \internal */
884
898
QQmlDataLoader::~QQmlDataLoader()
885
899
{
886
 
    for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) 
 
900
    for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
887
901
        (*iter)->release();
888
902
 
889
903
    shutdownThread();
908
922
void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode)
909
923
{
910
924
#ifdef DATABLOB_DEBUG
911
 
    qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), 
 
925
    qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
912
926
             m_thread->isThisThread()?"Compile":"Engine");
913
927
#endif
914
928
    blob->startLoading(this);
940
954
void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
941
955
{
942
956
#ifdef DATABLOB_DEBUG
943
 
    qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), 
 
957
    qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
944
958
             m_thread->isThisThread()?"Compile":"Engine");
945
959
#endif
946
960
 
965
979
    }
966
980
}
967
981
 
 
982
void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
 
983
{
 
984
#ifdef DATABLOB_DEBUG
 
985
    qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
 
986
             m_thread->isThisThread()?"Compile":"Engine");
 
987
#endif
 
988
 
 
989
    blob->startLoading(this);
 
990
 
 
991
    if (m_thread->isThisThread()) {
 
992
        unlock();
 
993
        loadWithCachedUnitThread(blob, unit);
 
994
        lock();
 
995
    } else {
 
996
        unlock();
 
997
        m_thread->loadWithCachedUnit(blob, unit);
 
998
        lock();
 
999
        if (!blob->isCompleteOrError())
 
1000
            blob->m_data.setIsAsync(true);
 
1001
    }
 
1002
}
 
1003
 
968
1004
void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
969
1005
{
970
1006
    ASSERT_LOADTHREAD();
972
1008
    setData(blob, data);
973
1009
}
974
1010
 
 
1011
void QQmlDataLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
 
1012
{
 
1013
    ASSERT_LOADTHREAD();
 
1014
 
 
1015
    setCachedUnit(blob, unit);
 
1016
}
 
1017
 
975
1018
void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
976
1019
{
977
1020
    ASSERT_LOADTHREAD();
1117
1160
Call the initializeEngine() method on \a iface.  Used by QQmlImportDatabase to ensure it
1118
1161
gets called in the correct thread.
1119
1162
*/
1120
 
void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface, 
 
1163
void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface,
1121
1164
                                              const char *uri)
1122
1165
{
1123
1166
    Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread());
1157
1200
    if (!blob->isError() && !blob->isWaiting())
1158
1201
        blob->allDependenciesDone();
1159
1202
 
1160
 
    if (blob->status() != QQmlDataBlob::Error) 
 
1203
    if (blob->status() != QQmlDataBlob::Error)
 
1204
        blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
 
1205
 
 
1206
    blob->m_inCallback = false;
 
1207
 
 
1208
    blob->tryDone();
 
1209
}
 
1210
 
 
1211
void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
 
1212
{
 
1213
    QML_MEMORY_SCOPE_URL(blob->url());
 
1214
    blob->m_inCallback = true;
 
1215
 
 
1216
    blob->initializeFromCachedUnit(unit);
 
1217
 
 
1218
    if (!blob->isError() && !blob->isWaiting())
 
1219
        blob->allDependenciesDone();
 
1220
 
 
1221
    if (blob->status() != QQmlDataBlob::Error)
1161
1222
        blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
1162
1223
 
1163
1224
    blob->m_inCallback = false;
1172
1233
}
1173
1234
 
1174
1235
QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader)
1175
 
  : QQmlDataBlob(url, type), m_typeLoader(loader), m_imports(loader), m_isSingleton(false)
 
1236
  : QQmlDataBlob(url, type), m_typeLoader(loader), m_importCache(loader), m_isSingleton(false)
1176
1237
{
1177
1238
}
1178
1239
 
1182
1243
        m_qmldirs.at(ii)->release();
1183
1244
}
1184
1245
 
1185
 
bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QQmlScript::Import *import, int priority, QList<QQmlError> *errors)
 
1246
bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors)
1186
1247
{
1187
1248
    QQmlQmldirData *data = typeLoader()->getQmldir(url);
1188
1249
 
1203
1264
    return true;
1204
1265
}
1205
1266
 
1206
 
bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QQmlScript::Import *import, QList<QQmlError> *errors)
 
1267
bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
1207
1268
{
1208
1269
    QString qmldirIdentifier = data->url().toString();
1209
1270
    QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1);
1210
1271
 
1211
1272
    typeLoader()->setQmldirContent(qmldirIdentifier, data->content());
1212
1273
 
1213
 
    if (!m_imports.updateQmldirContent(typeLoader()->importDatabase(), import->uri, import->qualifier, qmldirIdentifier, qmldirUrl, errors))
 
1274
    if (!m_importCache.updateQmldirContent(typeLoader()->importDatabase(), stringAt(import->uriIndex), stringAt(import->qualifierIndex), qmldirIdentifier, qmldirUrl, errors))
1214
1275
        return false;
1215
1276
 
1216
 
    QHash<const QQmlScript::Import *, int>::iterator it = m_unresolvedImports.find(import);
 
1277
    QHash<const QV4::CompiledData::Import *, int>::iterator it = m_unresolvedImports.find(import);
1217
1278
    if (it != m_unresolvedImports.end()) {
1218
1279
        *it = data->priority();
1219
1280
    }
1221
1282
    // Release this reference at destruction
1222
1283
    m_qmldirs << data;
1223
1284
 
1224
 
    if (!import->qualifier.isEmpty()) {
 
1285
    const QString &importQualifier = stringAt(import->qualifierIndex);
 
1286
    if (!importQualifier.isEmpty()) {
1225
1287
        // Does this library contain any qualified scripts?
1226
1288
        QUrl libraryUrl(qmldirUrl);
1227
1289
        const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier, qmldirUrl);
1230
1292
            QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
1231
1293
            addDependency(blob);
1232
1294
 
1233
 
            scriptImported(blob, import->location.start, script.nameSpace, import->qualifier);
 
1295
            scriptImported(blob, import->location, script.nameSpace, importQualifier);
1234
1296
        }
1235
1297
    }
1236
1298
 
1237
1299
    return true;
1238
1300
}
1239
1301
 
1240
 
bool QQmlTypeLoader::Blob::addImport(const QQmlScript::Import &import, QList<QQmlError> *errors)
 
1302
bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
1241
1303
{
1242
1304
    Q_ASSERT(errors);
1243
1305
 
1244
1306
    QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
1245
1307
 
1246
 
    if (import.type == QQmlScript::Import::Script) {
1247
 
        QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri));
 
1308
    const QString &importUri = stringAt(import->uriIndex);
 
1309
    const QString &importQualifier = stringAt(import->qualifierIndex);
 
1310
    if (import->type == QV4::CompiledData::Import::ImportScript) {
 
1311
        QUrl scriptUrl = finalUrl().resolved(QUrl(importUri));
1248
1312
        QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
1249
1313
        addDependency(blob);
1250
1314
 
1251
 
        scriptImported(blob, import.location.start, import.qualifier, QString());
1252
 
    } else if (import.type == QQmlScript::Import::Library) {
 
1315
        scriptImported(blob, import->location, importQualifier, QString());
 
1316
    } else if (import->type == QV4::CompiledData::Import::ImportLibrary) {
1253
1317
        QString qmldirFilePath;
1254
1318
        QString qmldirUrl;
1255
1319
 
1256
 
        if (QQmlMetaType::isLockedModule(import.uri, import.majorVersion)) {
 
1320
        if (QQmlMetaType::isLockedModule(importUri, import->majorVersion)) {
1257
1321
            //Locked modules are checked first, to save on filesystem checks
1258
 
            if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
1259
 
                                          import.minorVersion, QString(), QString(), false, errors))
 
1322
            if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
 
1323
                                          import->minorVersion, QString(), QString(), false, errors))
1260
1324
                return false;
1261
1325
 
1262
 
        } else if (m_imports.locateQmldir(importDatabase, import.uri, import.majorVersion, import.minorVersion,
 
1326
        } else if (m_importCache.locateQmldir(importDatabase, importUri, import->majorVersion, import->minorVersion,
1263
1327
                                 &qmldirFilePath, &qmldirUrl)) {
1264
1328
            // This is a local library import
1265
 
            if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
1266
 
                                          import.minorVersion, qmldirFilePath, qmldirUrl, false, errors))
 
1329
            if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
 
1330
                                          import->minorVersion, qmldirFilePath, qmldirUrl, false, errors))
1267
1331
                return false;
1268
1332
 
1269
 
            if (!import.qualifier.isEmpty()) {
 
1333
            if (!importQualifier.isEmpty()) {
1270
1334
                // Does this library contain any qualified scripts?
1271
1335
                QUrl libraryUrl(qmldirUrl);
1272
1336
                const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath, qmldirUrl);
1275
1339
                    QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
1276
1340
                    addDependency(blob);
1277
1341
 
1278
 
                    scriptImported(blob, import.location.start, script.nameSpace, import.qualifier);
 
1342
                    scriptImported(blob, import->location, script.nameSpace, importQualifier);
1279
1343
                }
1280
1344
            }
1281
1345
        } else {
1282
1346
            // Is this a module?
1283
 
            if (QQmlMetaType::isAnyModule(import.uri)) {
1284
 
                if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
1285
 
                                              import.minorVersion, QString(), QString(), false, errors))
 
1347
            if (QQmlMetaType::isAnyModule(importUri)) {
 
1348
                if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
 
1349
                                              import->minorVersion, QString(), QString(), false, errors))
1286
1350
                    return false;
1287
1351
            } else {
1288
1352
                // We haven't yet resolved this import
1289
 
                m_unresolvedImports.insert(&import, 0);
 
1353
                m_unresolvedImports.insert(import, 0);
1290
1354
 
1291
1355
                // Query any network import paths for this library
1292
1356
                QStringList remotePathList = importDatabase->importPathList(QQmlImportDatabase::Remote);
1293
1357
                if (!remotePathList.isEmpty()) {
1294
1358
                    // Add this library and request the possible locations for it
1295
 
                    if (!m_imports.addLibraryImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
1296
 
                                                  import.minorVersion, QString(), QString(), true, errors))
 
1359
                    if (!m_importCache.addLibraryImport(importDatabase, importUri, importQualifier, import->majorVersion,
 
1360
                                                  import->minorVersion, QString(), QString(), true, errors))
1297
1361
                        return false;
1298
1362
 
1299
1363
                    // Probe for all possible locations
1300
1364
                    int priority = 0;
1301
1365
                    for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
1302
1366
                        foreach (const QString &path, remotePathList) {
1303
 
                            QString qmldirUrl = QQmlImports::completeQmldirPath(import.uri, path, import.majorVersion, import.minorVersion,
 
1367
                            QString qmldirUrl = QQmlImports::completeQmldirPath(importUri, path, import->majorVersion, import->minorVersion,
1304
1368
                                                                                static_cast<QQmlImports::ImportVersion>(version));
1305
 
                            if (!fetchQmldir(QUrl(qmldirUrl), &import, ++priority, errors))
 
1369
                            if (!fetchQmldir(QUrl(qmldirUrl), import, ++priority, errors))
1306
1370
                                return false;
1307
1371
                        }
1308
1372
                    }
1310
1374
            }
1311
1375
        }
1312
1376
    } else {
1313
 
        Q_ASSERT(import.type == QQmlScript::Import::File);
 
1377
        Q_ASSERT(import->type == QV4::CompiledData::Import::ImportFile);
1314
1378
 
1315
1379
        bool incomplete = false;
1316
1380
 
1317
1381
        QUrl qmldirUrl;
1318
 
        if (import.qualifier.isEmpty()) {
1319
 
            qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir")));
 
1382
        if (importQualifier.isEmpty()) {
 
1383
            qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir")));
1320
1384
            if (!QQmlImports::isLocal(qmldirUrl)) {
1321
1385
                // This is a remote file; the import is currently incomplete
1322
1386
                incomplete = true;
1323
1387
            }
1324
1388
        }
1325
1389
 
1326
 
        if (!m_imports.addFileImport(importDatabase, import.uri, import.qualifier, import.majorVersion,
1327
 
                                   import.minorVersion, incomplete, errors))
 
1390
        if (!m_importCache.addFileImport(importDatabase, importUri, importQualifier, import->majorVersion,
 
1391
                                   import->minorVersion, incomplete, errors))
1328
1392
            return false;
1329
1393
 
1330
1394
        if (incomplete) {
1331
 
            if (!fetchQmldir(qmldirUrl, &import, 1, errors))
 
1395
            if (!fetchQmldir(qmldirUrl, import, 1, errors))
1332
1396
                return false;
1333
1397
        }
1334
1398
    }
1336
1400
    return true;
1337
1401
}
1338
1402
 
1339
 
bool QQmlTypeLoader::Blob::addPragma(const QQmlScript::Pragma &pragma, QList<QQmlError> *errors)
 
1403
bool QQmlTypeLoader::Blob::addPragma(const QmlIR::Pragma &pragma, QList<QQmlError> *errors)
1340
1404
{
1341
1405
    Q_ASSERT(errors);
1342
1406
 
1343
 
    if (pragma.type == QQmlScript::Pragma::Singleton) {
 
1407
    if (pragma.type == QmlIR::Pragma::PragmaSingleton) {
1344
1408
        QUrl myUrl = finalUrl();
1345
1409
 
1346
1410
        QQmlType *ret = QQmlMetaType::qmlType(myUrl, true);
1348
1412
            QQmlError error;
1349
1413
            error.setDescription(QQmlTypeLoader::tr("No matching type found, pragma Singleton files cannot be used by QQmlComponent."));
1350
1414
            error.setUrl(myUrl);
1351
 
            error.setLine(pragma.location.start.line);
1352
 
            error.setColumn(pragma.location.start.column);
 
1415
            error.setLine(pragma.location.line);
 
1416
            error.setColumn(pragma.location.column);
1353
1417
            errors->prepend(error);
1354
1418
            return false;
1355
1419
        }
1358
1422
            QQmlError error;
1359
1423
            error.setDescription(QQmlTypeLoader::tr("pragma Singleton used with a non composite singleton type %1").arg(ret->qmlTypeName()));
1360
1424
            error.setUrl(myUrl);
1361
 
            error.setLine(pragma.location.start.line);
1362
 
            error.setColumn(pragma.location.start.column);
 
1425
            error.setLine(pragma.location.line);
 
1426
            error.setColumn(pragma.location.column);
1363
1427
            errors->prepend(error);
1364
1428
            return false;
1365
1429
        }
1370
1434
        QQmlError error;
1371
1435
        error.setDescription(QLatin1String("Invalid pragma"));
1372
1436
        error.setUrl(finalUrl());
1373
 
        error.setLine(pragma.location.start.line);
1374
 
        error.setColumn(pragma.location.start.column);
 
1437
        error.setLine(pragma.location.line);
 
1438
        error.setColumn(pragma.location.column);
1375
1439
        errors->prepend(error);
1376
1440
        return false;
1377
1441
    }
1394
1458
    if (blob->type() == QQmlDataBlob::QmldirFile) {
1395
1459
        QQmlQmldirData *data = static_cast<QQmlQmldirData *>(blob);
1396
1460
 
1397
 
        const QQmlScript::Import *import = data->import();
 
1461
        const QV4::CompiledData::Import *import = data->import();
1398
1462
 
1399
1463
        QList<QQmlError> errors;
1400
1464
        if (!qmldirDataAvailable(data, &errors)) {
1401
1465
            Q_ASSERT(errors.size());
1402
1466
            QQmlError error(errors.takeFirst());
1403
 
            error.setUrl(m_imports.baseUrl());
1404
 
            error.setLine(import->location.start.line);
1405
 
            error.setColumn(import->location.start.column);
 
1467
            error.setUrl(m_importCache.baseUrl());
 
1468
            error.setLine(import->location.line);
 
1469
            error.setColumn(import->location.column);
1406
1470
            errors.prepend(error); // put it back on the list after filling out information.
1407
1471
            setError(errors);
1408
1472
        }
1413
1477
{
1414
1478
    bool resolve = true;
1415
1479
 
1416
 
    const QQmlScript::Import *import = data->import();
 
1480
    const QV4::CompiledData::Import *import = data->import();
1417
1481
    data->setImport(0);
1418
1482
 
1419
1483
    int priority = data->priority();
1421
1485
 
1422
1486
    if (import) {
1423
1487
        // Do we need to resolve this import?
1424
 
        QHash<const QQmlScript::Import *, int>::iterator it = m_unresolvedImports.find(import);
 
1488
        QHash<const QV4::CompiledData::Import *, int>::iterator it = m_unresolvedImports.find(import);
1425
1489
        if (it != m_unresolvedImports.end()) {
1426
1490
            resolve = (*it == 0) || (*it > priority);
1427
1491
        }
1524
1588
*/
1525
1589
QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
1526
1590
{
1527
 
    Q_ASSERT(!url.isRelative() && 
 
1591
    Q_ASSERT(!url.isRelative() &&
1528
1592
            (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
1529
1593
             !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
1530
1594
 
1531
1595
    LockHolder<QQmlTypeLoader> holder(this);
1532
 
    
 
1596
 
1533
1597
    QQmlTypeData *typeData = m_typeCache.value(url);
1534
1598
 
1535
1599
    if (!typeData) {
1536
1600
        typeData = new QQmlTypeData(url, this);
1537
1601
        // TODO: if (compiledData == 0), is it safe to omit this insertion?
1538
1602
        m_typeCache.insert(url, typeData);
1539
 
        QQmlDataLoader::load(typeData, mode);
 
1603
        if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
 
1604
            QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit);
 
1605
        } else {
 
1606
            QQmlDataLoader::load(typeData, mode);
 
1607
        }
1540
1608
    }
1541
1609
 
1542
1610
    typeData->addref();
1545
1613
}
1546
1614
 
1547
1615
/*!
1548
 
Returns a QQmlTypeData for the given \a data with the provided base \a url.  The 
 
1616
Returns a QQmlTypeData for the given \a data with the provided base \a url.  The
1549
1617
QQmlTypeData will not be cached.
1550
1618
*/
1551
1619
QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url)
1563
1631
*/
1564
1632
QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
1565
1633
{
1566
 
    Q_ASSERT(!url.isRelative() && 
 
1634
    Q_ASSERT(!url.isRelative() &&
1567
1635
            (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
1568
1636
             !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
1569
1637
 
1574
1642
    if (!scriptBlob) {
1575
1643
        scriptBlob = new QQmlScriptBlob(url, this);
1576
1644
        m_scriptCache.insert(url, scriptBlob);
1577
 
        QQmlDataLoader::load(scriptBlob);
 
1645
 
 
1646
        if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
 
1647
            QQmlDataLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
 
1648
        } else {
 
1649
            QQmlDataLoader::load(scriptBlob);
 
1650
        }
1578
1651
    }
1579
1652
 
1580
1653
    scriptBlob->addref();
1587
1660
*/
1588
1661
QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
1589
1662
{
1590
 
    Q_ASSERT(!url.isRelative() && 
 
1663
    Q_ASSERT(!url.isRelative() &&
1591
1664
            (QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
1592
1665
             !QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
1593
1666
 
1904
1977
{
1905
1978
    for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter)
1906
1979
        (*iter)->release();
1907
 
    for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter) 
 
1980
    for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter)
1908
1981
        (*iter)->release();
1909
1982
    for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter)
1910
1983
        (*iter)->release();
1965
2038
: QQmlTypeLoader::Blob(url, QmlFile, manager),
1966
2039
   m_typesResolved(false), m_compiledData(0), m_implicitImport(0), m_implicitImportLoaded(false)
1967
2040
{
1968
 
    m_useNewCompiler = QQmlEnginePrivate::get(manager->engine())->useNewCompiler;
 
2041
 
1969
2042
}
1970
2043
 
1971
2044
QQmlTypeData::~QQmlTypeData()
1972
2045
{
1973
 
    for (int ii = 0; ii < m_scripts.count(); ++ii) 
 
2046
    for (int ii = 0; ii < m_scripts.count(); ++ii)
1974
2047
        m_scripts.at(ii).script->release();
1975
 
    for (int ii = 0; ii < m_types.count(); ++ii) 
1976
 
        if (m_types.at(ii).typeData) m_types.at(ii).typeData->release();
 
2048
    for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
 
2049
        if (QQmlTypeData *tdata = m_compositeSingletons.at(ii).typeData)
 
2050
            tdata->release();
 
2051
    }
 
2052
    for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
 
2053
         it != end; ++it) {
 
2054
        if (QQmlTypeData *tdata = it->typeData)
 
2055
            tdata->release();
 
2056
    }
 
2057
 
1977
2058
    if (m_compiledData)
1978
2059
        m_compiledData->release();
1979
 
    delete m_implicitImport;
1980
 
}
1981
 
 
1982
 
const QQmlScript::Parser &QQmlTypeData::parser() const
1983
 
{
1984
 
    return scriptParser;
1985
 
}
1986
 
 
1987
 
const QList<QQmlTypeData::TypeReference> &QQmlTypeData::resolvedTypes() const
1988
 
{
1989
 
    return m_types;
1990
2060
}
1991
2061
 
1992
2062
const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
2041
2111
    }
2042
2112
 
2043
2113
    // Check all type dependencies for errors
2044
 
    // --- old compiler:
2045
 
    for (int ii = 0; !isError() && ii < m_types.count(); ++ii) {
2046
 
        const TypeReference &type = m_types.at(ii);
2047
 
        Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
2048
 
        if (type.typeData && type.typeData->isError()) {
2049
 
            QString typeName = scriptParser.referencedTypes().at(ii)->name;
2050
 
 
2051
 
            QList<QQmlError> errors = type.typeData->errors();
2052
 
            QQmlError error;
2053
 
            error.setUrl(finalUrl());
2054
 
            error.setLine(type.location.line);
2055
 
            error.setColumn(type.location.column);
2056
 
            error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
2057
 
            errors.prepend(error);
2058
 
            setError(errors);
2059
 
        }
2060
 
    }
2061
 
    // --- new compiler:
2062
2114
    for (QHash<int, TypeReference>::ConstIterator it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
2063
2115
         !isError() && it != end; ++it) {
2064
2116
        const TypeReference &type = *it;
2065
2117
        Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
2066
2118
        if (type.typeData && type.typeData->isError()) {
2067
 
            QString typeName = parsedQML->jsGenerator.strings.at(it.key());
 
2119
            QString typeName = m_document->stringAt(it.key());
2068
2120
 
2069
2121
            QList<QQmlError> errors = type.typeData->errors();
2070
2122
            QQmlError error;
2076
2128
            setError(errors);
2077
2129
        }
2078
2130
    }
2079
 
    // ---
2080
2131
 
2081
2132
    // Check all composite singleton type dependencies for errors
2082
2133
    for (int ii = 0; !isError() && ii < m_compositeSingletons.count(); ++ii) {
2109
2160
    }
2110
2161
 
2111
2162
    // Compile component
2112
 
    if (!isError()) 
 
2163
    if (!isError())
2113
2164
        compile();
2114
2165
 
2115
 
    scriptParser.clear();
2116
 
    parsedQML.reset();
 
2166
    m_document.reset();
 
2167
    m_implicitImport = 0;
2117
2168
}
2118
2169
 
2119
2170
void QQmlTypeData::completed()
2129
2180
{
2130
2181
    m_implicitImportLoaded = true; // Even if we hit an error, count as loaded (we'd just keep hitting the error)
2131
2182
 
2132
 
    m_imports.setBaseUrl(finalUrl(), finalUrlString());
 
2183
    m_importCache.setBaseUrl(finalUrl(), finalUrlString());
2133
2184
 
2134
2185
    QQmlImportDatabase *importDatabase = typeLoader()->importDatabase();
2135
2186
    // For local urls, add an implicit import "." as most overridden lookup.
2136
2187
    // This will also trigger the loading of the qmldir and the import of any native
2137
2188
    // types from available plugins.
2138
2189
    QList<QQmlError> implicitImportErrors;
2139
 
    m_imports.addImplicitImport(importDatabase, &implicitImportErrors);
 
2190
    m_importCache.addImplicitImport(importDatabase, &implicitImportErrors);
2140
2191
 
2141
2192
    if (!implicitImportErrors.isEmpty()) {
2142
2193
        setError(implicitImportErrors);
2153
2204
 
2154
2205
    if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
2155
2206
 
2156
 
    if (m_useNewCompiler) {
2157
 
        parsedQML.reset(new QtQml::ParsedQML(QV8Engine::getV4(typeLoader()->engine())->debugger != 0));
2158
 
        QQmlCodeGenerator compiler;
2159
 
        if (!compiler.generateFromQml(code, finalUrl(), finalUrlString(), parsedQML.data())) {
2160
 
            setError(compiler.errors);
2161
 
            return;
2162
 
        }
2163
 
    } else {
2164
 
        if (!scriptParser.parse(code, preparseData, finalUrl(), finalUrlString())) {
2165
 
            setError(scriptParser.errors());
2166
 
            return;
2167
 
        }
 
2207
    QQmlEngine *qmlEngine = typeLoader()->engine();
 
2208
    m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
 
2209
    QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
 
2210
    if (!compiler.generateFromQml(code, finalUrlString(), finalUrlString(), m_document.data())) {
 
2211
        QList<QQmlError> errors;
 
2212
        foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
 
2213
            QQmlError e;
 
2214
            e.setUrl(finalUrl());
 
2215
            e.setLine(msg.loc.startLine);
 
2216
            e.setColumn(msg.loc.startColumn);
 
2217
            e.setDescription(msg.message);
 
2218
            errors << e;
 
2219
        }
 
2220
        setError(errors);
 
2221
        return;
2168
2222
    }
2169
2223
 
2170
 
    m_imports.setBaseUrl(finalUrl(), finalUrlString());
 
2224
    continueLoadFromIR();
 
2225
}
 
2226
 
 
2227
void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
 
2228
{
 
2229
    QQmlEngine *qmlEngine = typeLoader()->engine();
 
2230
    m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
 
2231
    unit->loadIR(m_document.data(), unit);
 
2232
    continueLoadFromIR();
 
2233
}
 
2234
 
 
2235
void QQmlTypeData::continueLoadFromIR()
 
2236
{
 
2237
    m_document->collectTypeReferences();
 
2238
    m_importCache.setBaseUrl(finalUrl(), finalUrlString());
2171
2239
 
2172
2240
    // For remote URLs, we don't delay the loading of the implicit import
2173
2241
    // because the loading probably requires an asynchronous fetch of the
2178
2246
            if (!loadImplicitImport())
2179
2247
                return;
2180
2248
            // This qmldir is for the implicit import
2181
 
            m_implicitImport = new QQmlScript::Import;
2182
 
            m_implicitImport->uri = QLatin1String(".");
2183
 
            m_implicitImport->qualifier = QString();
 
2249
            QQmlJS::MemoryPool *pool = m_document->jsParserEngine.pool();
 
2250
            m_implicitImport = pool->New<QV4::CompiledData::Import>();
 
2251
            m_implicitImport->uriIndex = m_document->registerString(QLatin1String("."));
 
2252
            m_implicitImport->qualifierIndex = 0; // empty string
2184
2253
            m_implicitImport->majorVersion = -1;
2185
2254
            m_implicitImport->minorVersion = -1;
2186
2255
            QList<QQmlError> errors;
2194
2263
 
2195
2264
    QList<QQmlError> errors;
2196
2265
 
2197
 
    // ### convert to use new data structure once old compiler is gone.
2198
 
    if (m_useNewCompiler && m_newImports.isEmpty()) {
2199
 
        m_newImports.reserve(parsedQML->imports.size());
2200
 
        foreach (QV4::CompiledData::Import *i, parsedQML->imports) {
2201
 
            QQmlScript::Import import;
2202
 
            import.uri = parsedQML->stringAt(i->uriIndex);
2203
 
            import.qualifier = parsedQML->stringAt(i->qualifierIndex);
2204
 
            import.majorVersion = i->majorVersion;
2205
 
            import.minorVersion = i->minorVersion;
2206
 
            import.location.start.line = i->location.line;
2207
 
            import.location.start.column = i->location.column;
2208
 
 
2209
 
            switch (i->type) {
2210
 
            case QV4::CompiledData::Import::ImportFile: import.type = QQmlScript::Import::File; break;
2211
 
            case QV4::CompiledData::Import::ImportLibrary: import.type = QQmlScript::Import::Library; break;
2212
 
            case QV4::CompiledData::Import::ImportScript: import.type = QQmlScript::Import::Script; break;
2213
 
            default: break;
2214
 
            }
2215
 
 
2216
 
 
2217
 
            m_newImports << import;
2218
 
        }
2219
 
    }
2220
 
 
2221
 
    foreach (const QQmlScript::Import &import, m_useNewCompiler ? m_newImports : scriptParser.imports()) {
 
2266
    foreach (const QV4::CompiledData::Import *import, m_document->imports) {
2222
2267
        if (!addImport(import, &errors)) {
2223
2268
            Q_ASSERT(errors.size());
2224
2269
            QQmlError error(errors.takeFirst());
2225
 
            error.setUrl(m_imports.baseUrl());
2226
 
            error.setLine(import.location.start.line);
2227
 
            error.setColumn(import.location.start.column);
 
2270
            error.setUrl(m_importCache.baseUrl());
 
2271
            error.setLine(import->location.line);
 
2272
            error.setColumn(import->location.column);
2228
2273
            errors.prepend(error); // put it back on the list after filling out information.
2229
2274
            setError(errors);
2230
2275
            return;
2231
2276
        }
2232
2277
    }
2233
2278
 
2234
 
    // ### convert to use new data structure once old compiler is gone.
2235
 
    if (m_useNewCompiler && m_newPragmas.isEmpty()) {
2236
 
        m_newPragmas.reserve(parsedQML->pragmas.size());
2237
 
        foreach (QtQml::Pragma *p, parsedQML->pragmas) {
2238
 
            QQmlScript::Pragma pragma;
2239
 
            pragma.location.start.line = p->location.line;
2240
 
            pragma.location.start.column = p->location.column;
2241
 
 
2242
 
            switch (p->type) {
2243
 
            case QtQml::Pragma::PragmaSingleton: pragma.type = QQmlScript::Pragma::Singleton; break;
2244
 
            default: break;
2245
 
            }
2246
 
 
2247
 
            m_newPragmas << pragma;
2248
 
        }
2249
 
    }
2250
 
 
2251
 
    foreach (const QQmlScript::Pragma &pragma, m_useNewCompiler ? m_newPragmas : scriptParser.pragmas()) {
2252
 
        if (!addPragma(pragma, &errors)) {
 
2279
    foreach (QmlIR::Pragma *pragma, m_document->pragmas) {
 
2280
        if (!addPragma(*pragma, &errors)) {
2253
2281
            Q_ASSERT(errors.size());
2254
2282
            setError(errors);
2255
2283
            return;
2262
2290
    if (!m_typesResolved) {
2263
2291
        // Check that all imports were resolved
2264
2292
        QList<QQmlError> errors;
2265
 
        QHash<const QQmlScript::Import *, int>::const_iterator it = m_unresolvedImports.constBegin(), end = m_unresolvedImports.constEnd();
 
2293
        QHash<const QV4::CompiledData::Import *, int>::const_iterator it = m_unresolvedImports.constBegin(), end = m_unresolvedImports.constEnd();
2266
2294
        for ( ; it != end; ++it) {
2267
2295
            if (*it == 0) {
2268
2296
                // This import was not resolved
2269
 
                foreach (const QQmlScript::Import *import, m_unresolvedImports.keys()) {
 
2297
                foreach (const QV4::CompiledData::Import *import, m_unresolvedImports.keys()) {
2270
2298
                    QQmlError error;
2271
 
                    error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(import->uri));
2272
 
                    error.setUrl(m_imports.baseUrl());
2273
 
                    error.setLine(import->location.start.line);
2274
 
                    error.setColumn(import->location.start.column);
 
2299
                    error.setDescription(QQmlTypeLoader::tr("module \"%1\" is not installed").arg(stringAt(import->uriIndex)));
 
2300
                    error.setUrl(m_importCache.baseUrl());
 
2301
                    error.setLine(import->location.line);
 
2302
                    error.setColumn(import->location.column);
2275
2303
                    errors.prepend(error);
2276
2304
                }
2277
2305
            }
2294
2322
    }
2295
2323
}
2296
2324
 
 
2325
QString QQmlTypeData::stringAt(int index) const
 
2326
{
 
2327
    return m_document->jsGenerator.stringTable.stringForIndex(index);
 
2328
}
 
2329
 
2297
2330
void QQmlTypeData::compile()
2298
2331
{
2299
2332
    Q_ASSERT(m_compiledData == 0);
2302
2335
    m_compiledData->url = finalUrl();
2303
2336
    m_compiledData->name = finalUrlString();
2304
2337
 
2305
 
    QQmlCompilingProfiler prof(m_compiledData->name);
2306
 
 
2307
 
    if (m_useNewCompiler) {
2308
 
        m_compiledData->importCache = new QQmlTypeNameCache;
2309
 
 
2310
 
        foreach (const QString &ns, m_namespaces)
2311
 
            m_compiledData->importCache->add(ns);
2312
 
 
2313
 
        // Add any Composite Singletons that were used to the import cache
2314
 
        for (int i = 0; i < compositeSingletons().count(); ++i) {
2315
 
            m_compiledData->importCache->add(compositeSingletons().at(i).type->qmlTypeName(),
2316
 
                compositeSingletons().at(i).type->sourceUrl(), compositeSingletons().at(i).prefix);
2317
 
        }
2318
 
 
2319
 
        m_imports.populateCache(m_compiledData->importCache);
2320
 
        m_compiledData->importCache->addref();
2321
 
 
2322
 
        QQmlEngine *engine = typeLoader()->engine();
2323
 
        QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
2324
 
 
2325
 
        for (QHash<int, TypeReference>::ConstIterator resolvedType = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
2326
 
             resolvedType != end; ++resolvedType) {
2327
 
            QQmlCompiledData::TypeReference ref;
2328
 
            if (resolvedType->typeData) {
2329
 
                ref.component = resolvedType->typeData->compiledData();
2330
 
                ref.component->addref();
2331
 
            } else {
2332
 
                ref.type = resolvedType->type;
2333
 
                Q_ASSERT(ref.type);
2334
 
            }
2335
 
            ref.majorVersion = resolvedType->majorVersion;
2336
 
            ref.minorVersion = resolvedType->minorVersion;
2337
 
            m_compiledData->resolvedTypes.insert(resolvedType.key(), ref);
2338
 
        }
2339
 
 
2340
 
        {
2341
 
            SignalHandlerConverter converter(QQmlEnginePrivate::get(engine),
2342
 
                                             parsedQML.data(),
2343
 
                                             m_compiledData);
2344
 
            if (!converter.convertSignalHandlerExpressionsToFunctionDeclarations()) {
2345
 
                setError(converter.errors);
2346
 
                m_compiledData->release();
2347
 
                m_compiledData = 0;
2348
 
                return;
2349
 
            }
2350
 
        }
2351
 
 
2352
 
        // Collect imported scripts
2353
 
        m_compiledData->scripts.reserve(m_scripts.count());
2354
 
        for (int scriptIndex = 0; scriptIndex < m_scripts.count(); ++scriptIndex) {
2355
 
            const ScriptReference &script = m_scripts.at(scriptIndex);
2356
 
 
2357
 
            QString qualifier = script.qualifier;
2358
 
            QString enclosingNamespace;
2359
 
 
2360
 
            const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
2361
 
            if (lastDotIndex != -1) {
2362
 
                enclosingNamespace = qualifier.left(lastDotIndex);
2363
 
                qualifier = qualifier.mid(lastDotIndex+1);
2364
 
            }
2365
 
 
2366
 
            m_compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
2367
 
            QQmlScriptData *scriptData = script.script->scriptData();
2368
 
            scriptData->addref();
2369
 
            m_compiledData->scripts << scriptData;
2370
 
        }
2371
 
 
2372
 
        // Compile JS binding expressions and signal handlers
2373
 
 
2374
 
        JSCodeGen jsCodeGen(finalUrlString(), parsedQML->code, &parsedQML->jsModule, &parsedQML->jsParserEngine, parsedQML->program, m_compiledData->importCache);
2375
 
        const QVector<int> runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(parsedQML->functions);
2376
 
 
2377
 
        QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
2378
 
 
2379
 
        QScopedPointer<QQmlJS::EvalInstructionSelection> isel(v4->iselFactory->create(enginePrivate, v4->executableAllocator, &parsedQML->jsModule, &parsedQML->jsGenerator));
2380
 
        isel->setUseFastLookups(false);
2381
 
        QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false);
2382
 
 
2383
 
        // Generate QML compiled type data structures
2384
 
 
2385
 
        QmlUnitGenerator qmlGenerator;
2386
 
        QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*parsedQML.data(), runtimeFunctionIndices);
2387
 
 
2388
 
        if (jsUnit) {
2389
 
            Q_ASSERT(!jsUnit->data);
2390
 
            jsUnit->ownsData = false;
2391
 
            jsUnit->data = &qmlUnit->header;
2392
 
        }
2393
 
 
2394
 
        m_compiledData->compilationUnit = jsUnit;
2395
 
        if (m_compiledData->compilationUnit)
2396
 
            m_compiledData->compilationUnit->ref();
2397
 
        m_compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData
2398
 
 
2399
 
        QList<QQmlError> errors;
2400
 
 
2401
 
        // Build property caches and VME meta object data
2402
 
 
2403
 
        m_compiledData->datas.reserve(qmlUnit->nObjects);
2404
 
        m_compiledData->propertyCaches.reserve(qmlUnit->nObjects);
2405
 
 
2406
 
        QQmlPropertyCacheCreator propertyCacheBuilder(enginePrivate,
2407
 
                                                      qmlUnit, m_compiledData->url,
2408
 
                                                      &m_imports, &m_compiledData->resolvedTypes);
2409
 
 
2410
 
        for (quint32 i = 0; i < qmlUnit->nObjects; ++i) {
2411
 
            const QV4::CompiledData::Object *obj = qmlUnit->objectAt(i);
2412
 
 
2413
 
            QByteArray vmeMetaObjectData;
2414
 
            QQmlPropertyCache *propertyCache = 0;
2415
 
 
2416
 
            // If the object has no type, then it's probably a nested object definition as part
2417
 
            // of a group property.
2418
 
            const bool objectHasType = !parsedQML->jsGenerator.strings.at(obj->inheritedTypeNameIndex).isEmpty();
2419
 
            if (objectHasType) {
2420
 
                if (!propertyCacheBuilder.create(obj, &propertyCache, &vmeMetaObjectData)) {
2421
 
                    errors << propertyCacheBuilder.errors;
2422
 
                    break;
2423
 
                }
2424
 
            }
2425
 
 
2426
 
            m_compiledData->datas << vmeMetaObjectData;
2427
 
            if (propertyCache)
2428
 
                propertyCache->addref();
2429
 
            m_compiledData->propertyCaches << propertyCache;
2430
 
 
2431
 
            if (i == qmlUnit->indexOfRootObject) {
2432
 
                Q_ASSERT(propertyCache);
2433
 
                m_compiledData->rootPropertyCache = propertyCache;
2434
 
                propertyCache->addref();
2435
 
            }
2436
 
        }
2437
 
 
2438
 
        // Resolve component boundaries and aliases
2439
 
 
2440
 
        if (errors.isEmpty()) {
2441
 
            // Scan for components, determine their scopes and resolve aliases within the scope.
2442
 
            QQmlComponentAndAliasResolver resolver(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes, m_compiledData->propertyCaches,
2443
 
                                                   &m_compiledData->datas, &m_compiledData->objectIndexToIdForRoot, &m_compiledData->objectIndexToIdPerComponent);
2444
 
            if (!resolver.resolve())
2445
 
                errors << resolver.errors;
2446
 
        }
2447
 
 
2448
 
        if (errors.isEmpty()) {
2449
 
            // Add to type registry of composites
2450
 
            if (m_compiledData->isCompositeType())
2451
 
                QQmlEnginePrivate::get(engine)->registerInternalCompositeType(m_compiledData);
2452
 
            else {
2453
 
                const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
2454
 
                QQmlCompiledData::TypeReference typeRef = m_compiledData->resolvedTypes.value(obj->inheritedTypeNameIndex);
2455
 
                if (typeRef.component) {
2456
 
                    m_compiledData->metaTypeId = typeRef.component->metaTypeId;
2457
 
                    m_compiledData->listMetaTypeId = typeRef.component->listMetaTypeId;
2458
 
                } else {
2459
 
                    m_compiledData->metaTypeId = typeRef.type->typeId();
2460
 
                    m_compiledData->listMetaTypeId = typeRef.type->qListTypeId();
2461
 
                }
2462
 
            }
2463
 
        }
2464
 
 
2465
 
        // Sanity check property bindings
2466
 
        if (errors.isEmpty()) {
2467
 
            QQmlPropertyValidator validator(m_compiledData->url, m_compiledData->qmlUnit, m_compiledData->resolvedTypes,
2468
 
                                            m_compiledData->propertyCaches, m_compiledData->objectIndexToIdPerComponent);
2469
 
            if (!validator.validate())
2470
 
                errors << validator.errors;
2471
 
        }
2472
 
 
2473
 
        if (!errors.isEmpty()) {
2474
 
            setError(errors);
2475
 
            m_compiledData->release();
2476
 
            m_compiledData = 0;
2477
 
        }
2478
 
    } else {
2479
 
        QQmlCompiler compiler(&scriptParser._pool);
2480
 
        if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) {
2481
 
            setError(compiler.errors());
2482
 
            m_compiledData->release();
2483
 
            m_compiledData = 0;
2484
 
        }
 
2338
    QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name);
 
2339
 
 
2340
    QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, m_document.data());
 
2341
    if (!compiler.compile()) {
 
2342
        setError(compiler.compilationErrors());
 
2343
        m_compiledData->release();
 
2344
        m_compiledData = 0;
2485
2345
    }
2486
2346
}
2487
2347
 
2488
2348
void QQmlTypeData::resolveTypes()
2489
2349
{
2490
2350
    // Add any imported scripts to our resolved set
2491
 
    foreach (const QQmlImports::ScriptReference &script, m_imports.resolvedScripts())
 
2351
    foreach (const QQmlImports::ScriptReference &script, m_importCache.resolvedScripts())
2492
2352
    {
2493
2353
        QQmlScriptBlob *blob = typeLoader()->getScript(script.location);
2494
2354
        addDependency(blob);
2509
2369
    }
2510
2370
 
2511
2371
    // Lets handle resolved composite singleton types
2512
 
    foreach (const QQmlImports::CompositeSingletonReference &csRef, m_imports.resolvedCompositeSingletons()) {
 
2372
    foreach (const QQmlImports::CompositeSingletonReference &csRef, m_importCache.resolvedCompositeSingletons()) {
2513
2373
        TypeReference ref;
2514
 
        QQmlScript::TypeReference parserRef;
2515
 
        parserRef.name = csRef.typeName;
2516
 
        // we are basing our type on the information from qmldir and therefore
2517
 
        // do not have a proper location.
2518
 
        parserRef.firstUse = NULL;
 
2374
        QString typeName = csRef.typeName;
2519
2375
 
2520
2376
        if (!csRef.prefix.isEmpty()) {
2521
 
            parserRef.name.prepend(csRef.prefix + QLatin1Char('.'));
 
2377
            typeName.prepend(csRef.prefix + QLatin1Char('.'));
2522
2378
            // Add a reference to the enclosing namespace
2523
2379
            m_namespaces.insert(csRef.prefix);
2524
2380
        }
2526
2382
        int majorVersion = -1;
2527
2383
        int minorVersion = -1;
2528
2384
 
2529
 
        if (!resolveType(&parserRef, majorVersion, minorVersion, ref))
 
2385
        if (!resolveType(typeName, majorVersion, minorVersion, ref))
2530
2386
            return;
2531
2387
 
2532
2388
        if (ref.type->isCompositeSingleton()) {
2538
2394
        }
2539
2395
    }
2540
2396
 
2541
 
    // --- old compiler:
2542
 
    foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
2543
 
        TypeReference ref;
2544
 
 
2545
 
        int majorVersion = -1;
2546
 
        int minorVersion = -1;
2547
 
 
2548
 
        if (!resolveType(parserRef, majorVersion, minorVersion, ref))
2549
 
            return;
2550
 
 
2551
 
        if (ref.type->isComposite()) {
2552
 
            ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
2553
 
            addDependency(ref.typeData);
2554
 
        }
2555
 
 
2556
 
        ref.majorVersion = majorVersion;
2557
 
        ref.minorVersion = minorVersion;
2558
 
 
2559
 
        Q_ASSERT(parserRef->firstUse);
2560
 
        ref.location = parserRef->firstUse->location.start;
2561
 
 
2562
 
        m_types << ref;
2563
 
    }
2564
 
 
2565
 
    // --- new compiler:
2566
 
    QV4::CompiledData::TypeReferenceMap typeReferences;
2567
 
    QStringList names;
2568
 
    if (parsedQML) {
2569
 
        typeReferences = parsedQML->typeReferences;
2570
 
        names = parsedQML->jsGenerator.strings;
2571
 
    } else {
2572
 
        // ### collect from available QV4::CompiledData::QmlUnit
2573
 
    }
2574
 
    for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = typeReferences.constBegin(), end = typeReferences.constEnd();
 
2397
    for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_document->typeReferences.constBegin(), end = m_document->typeReferences.constEnd();
2575
2398
         unresolvedRef != end; ++unresolvedRef) {
2576
2399
 
2577
2400
        TypeReference ref; // resolved reference
2578
2401
 
 
2402
        const bool reportErrors = unresolvedRef->errorWhenNotFound;
 
2403
 
2579
2404
        int majorVersion = -1;
2580
2405
        int minorVersion = -1;
2581
2406
        QQmlImportNamespace *typeNamespace = 0;
2582
2407
        QList<QQmlError> errors;
2583
2408
 
2584
 
        const QString name = names.at(unresolvedRef.key());
2585
 
        bool typeFound = m_imports.resolveType(name, &ref.type,
 
2409
        const QString name = stringAt(unresolvedRef.key());
 
2410
        bool typeFound = m_importCache.resolveType(name, &ref.type,
2586
2411
                &majorVersion, &minorVersion, &typeNamespace, &errors);
2587
2412
        if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
2588
2413
            // Lazy loading of implicit import
2589
2414
            if (loadImplicitImport()) {
2590
2415
                // Try again to find the type
2591
2416
                errors.clear();
2592
 
                typeFound = m_imports.resolveType(name, &ref.type,
 
2417
                typeFound = m_importCache.resolveType(name, &ref.type,
2593
2418
                    &majorVersion, &minorVersion, &typeNamespace, &errors);
2594
2419
            } else {
2595
2420
                return; //loadImplicitImport() hit an error, and called setError already
2596
2421
            }
2597
2422
        }
2598
2423
 
2599
 
        if (!typeFound || typeNamespace) {
 
2424
        if ((!typeFound || typeNamespace) && reportErrors) {
2600
2425
            // Known to not be a type:
2601
2426
            //  - known to be a namespace (Namespace {})
2602
2427
            //  - type with unknown namespace (UnknownNamespace.SomeType {})
2611
2436
                    // Description should come from error provided by addImport() function.
2612
2437
                    error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
2613
2438
                }
2614
 
                error.setUrl(m_imports.baseUrl());
 
2439
                error.setUrl(m_importCache.baseUrl());
2615
2440
                error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(name).arg(error.description()));
2616
2441
            }
2617
2442
 
2618
 
            error.setLine(unresolvedRef->line);
2619
 
            error.setColumn(unresolvedRef->column);
 
2443
            error.setLine(unresolvedRef->location.line);
 
2444
            error.setColumn(unresolvedRef->location.column);
2620
2445
 
2621
2446
            errors.prepend(error);
2622
2447
            setError(errors);
2623
2448
            return;
2624
2449
        }
2625
2450
 
2626
 
        if (ref.type->isComposite()) {
 
2451
        if (ref.type && ref.type->isComposite()) {
2627
2452
            ref.typeData = typeLoader()->getType(ref.type->sourceUrl());
2628
2453
            addDependency(ref.typeData);
2629
2454
        }
2630
2455
        ref.majorVersion = majorVersion;
2631
2456
        ref.minorVersion = minorVersion;
2632
2457
 
2633
 
        ref.location.line = unresolvedRef->line;
2634
 
        ref.location.column = unresolvedRef->column;
 
2458
        ref.location.line = unresolvedRef->location.line;
 
2459
        ref.location.column = unresolvedRef->location.column;
 
2460
 
 
2461
        ref.needsCreation = unresolvedRef->needsCreation;
2635
2462
 
2636
2463
        m_resolvedTypes.insert(unresolvedRef.key(), ref);
2637
2464
    }
2638
2465
}
2639
2466
 
2640
 
bool QQmlTypeData::resolveType(const QQmlScript::TypeReference *parserRef, int &majorVersion, int &minorVersion, TypeReference &ref)
 
2467
bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion, TypeReference &ref)
2641
2468
{
2642
2469
    QQmlImportNamespace *typeNamespace = 0;
2643
2470
    QList<QQmlError> errors;
2644
2471
 
2645
 
    bool typeFound = m_imports.resolveType(parserRef->name, &ref.type,
 
2472
    bool typeFound = m_importCache.resolveType(typeName, &ref.type,
2646
2473
                                          &majorVersion, &minorVersion, &typeNamespace, &errors);
2647
2474
    if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
2648
2475
        // Lazy loading of implicit import
2649
2476
        if (loadImplicitImport()) {
2650
2477
            // Try again to find the type
2651
2478
            errors.clear();
2652
 
            typeFound = m_imports.resolveType(parserRef->name, &ref.type,
 
2479
            typeFound = m_importCache.resolveType(typeName, &ref.type,
2653
2480
                                              &majorVersion, &minorVersion, &typeNamespace, &errors);
2654
2481
        } else {
2655
2482
            return false; //loadImplicitImport() hit an error, and called setError already
2662
2489
        //  - type with unknown namespace (UnknownNamespace.SomeType {})
2663
2490
        QQmlError error;
2664
2491
        if (typeNamespace) {
2665
 
            error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(parserRef->name));
 
2492
            error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(typeName));
2666
2493
        } else {
2667
2494
            if (errors.size()) {
2668
2495
                error = errors.takeFirst();
2671
2498
                // Description should come from error provided by addImport() function.
2672
2499
                error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
2673
2500
            }
2674
 
            error.setUrl(m_imports.baseUrl());
2675
 
            error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(parserRef->name).arg(error.description()));
2676
 
        }
2677
 
 
2678
 
        if (parserRef->firstUse)
2679
 
        {
2680
 
            error.setLine(parserRef->firstUse->location.start.line);
2681
 
            error.setColumn(parserRef->firstUse->location.start.column);
 
2501
            error.setUrl(m_importCache.baseUrl());
 
2502
            error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(typeName).arg(error.description()));
2682
2503
        }
2683
2504
 
2684
2505
        errors.prepend(error);
2689
2510
    return true;
2690
2511
}
2691
2512
 
2692
 
void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
 
2513
void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
2693
2514
{
2694
2515
    ScriptReference ref;
2695
2516
    ref.script = blob;
2701
2522
 
2702
2523
QQmlScriptData::QQmlScriptData()
2703
2524
    : importCache(0)
2704
 
    , pragmas(QQmlScript::Object::ScriptBlock::None)
2705
2525
    , m_loaded(false)
2706
2526
    , m_precompiledScript(0)
2707
2527
    , m_program(0)
2747
2567
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine);
2748
2568
    QV4::Scope scope(v4);
2749
2569
 
2750
 
    bool shared = pragmas & QQmlScript::Object::ScriptBlock::Shared;
 
2570
    bool shared = m_precompiledScript->data->flags & QV4::CompiledData::Unit::IsSharedLibrary;
2751
2571
 
2752
2572
    QQmlContextData *effectiveCtxt = parentCtxt;
2753
2573
    if (shared)
2851
2671
    }
2852
2672
}
2853
2673
 
2854
 
QQmlScript::Object::ScriptBlock::Pragmas QQmlScriptBlob::pragmas() const
2855
 
{
2856
 
    return m_metadata.pragmas;
2857
 
}
2858
 
 
2859
2674
QQmlScriptData *QQmlScriptBlob::scriptData() const
2860
2675
{
2861
2676
    return m_scriptData;
2863
2678
 
2864
2679
void QQmlScriptBlob::dataReceived(const Data &data)
2865
2680
{
2866
 
    m_source = QString::fromUtf8(data.data(), data.size());
2867
 
 
2868
 
    m_scriptData = new QQmlScriptData();
2869
 
    m_scriptData->url = finalUrl();
2870
 
    m_scriptData->urlString = finalUrlString();
2871
 
 
2872
 
    QQmlError metaDataError;
2873
 
    m_metadata = QQmlScript::Parser::extractMetaData(m_source, &metaDataError);
2874
 
    if (metaDataError.isValid()) {
2875
 
        metaDataError.setUrl(finalUrl());
2876
 
        setError(metaDataError);
 
2681
    QString source = QString::fromUtf8(data.data(), data.size());
 
2682
 
 
2683
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
 
2684
    QmlIR::Document irUnit(v4->debugger != 0);
 
2685
    QQmlJS::DiagnosticMessage metaDataError;
 
2686
    irUnit.extractScriptMetaData(source, &metaDataError);
 
2687
    if (!metaDataError.message.isEmpty()) {
 
2688
        QQmlError e;
 
2689
        e.setUrl(finalUrl());
 
2690
        e.setLine(metaDataError.loc.startLine);
 
2691
        e.setColumn(metaDataError.loc.startColumn);
 
2692
        e.setDescription(metaDataError.message);
 
2693
        setError(e);
2877
2694
        return;
2878
2695
    }
2879
2696
 
2880
 
    m_imports.setBaseUrl(finalUrl(), finalUrlString());
2881
 
 
2882
2697
    QList<QQmlError> errors;
2883
 
 
2884
 
    foreach (const QQmlScript::Import &import, m_metadata.imports) {
2885
 
        if (!addImport(import, &errors)) {
2886
 
            Q_ASSERT(errors.size());
2887
 
            QQmlError error(errors.takeFirst());
2888
 
            error.setUrl(m_imports.baseUrl());
2889
 
            error.setLine(import.location.start.line);
2890
 
            error.setColumn(import.location.start.column);
2891
 
            errors.prepend(error); // put it back on the list after filling out information.
2892
 
            setError(errors);
2893
 
            return;
2894
 
        }
 
2698
    QV4::CompiledData::CompilationUnit *unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors);
 
2699
    if (unit)
 
2700
        unit->ref();
 
2701
    source.clear();
 
2702
    if (!errors.isEmpty()) {
 
2703
        if (unit)
 
2704
            unit->deref();
 
2705
        setError(errors);
 
2706
        return;
2895
2707
    }
 
2708
    irUnit.javaScriptCompilationUnit = unit;
 
2709
 
 
2710
    QmlIR::QmlUnitGenerator qmlGenerator;
 
2711
    QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(irUnit);
 
2712
    Q_ASSERT(!unit->data);
 
2713
    Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header);
 
2714
    // The js unit owns the data and will free the qml unit.
 
2715
    unit->data = &qmlUnit->header;
 
2716
 
 
2717
    initializeFromCompilationUnit(unit);
 
2718
    unit->deref();
 
2719
}
 
2720
 
 
2721
void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
 
2722
{
 
2723
    initializeFromCompilationUnit(unit->createCompilationUnit());
2896
2724
}
2897
2725
 
2898
2726
void QQmlScriptBlob::done()
2934
2762
        m_scriptData->importCache->add(script.qualifier, scriptIndex, script.nameSpace);
2935
2763
    }
2936
2764
 
2937
 
    m_imports.populateCache(m_scriptData->importCache);
2938
 
 
2939
 
    m_scriptData->pragmas = m_metadata.pragmas;
2940
 
 
2941
 
    QList<QQmlError> errors;
2942
 
    QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
2943
 
    m_scriptData->m_precompiledScript = QV4::Script::precompile(v4, m_scriptData->url, m_source, &errors);
 
2765
    m_importCache.populateCache(m_scriptData->importCache);
 
2766
}
 
2767
 
 
2768
QString QQmlScriptBlob::stringAt(int index) const
 
2769
{
 
2770
    return m_scriptData->m_precompiledScript->data->stringAt(index);
 
2771
}
 
2772
 
 
2773
void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace)
 
2774
{
 
2775
    ScriptReference ref;
 
2776
    ref.script = blob;
 
2777
    ref.location = location;
 
2778
    ref.qualifier = qualifier;
 
2779
    ref.nameSpace = nameSpace;
 
2780
 
 
2781
    m_scripts << ref;
 
2782
}
 
2783
 
 
2784
void QQmlScriptBlob::initializeFromCompilationUnit(QV4::CompiledData::CompilationUnit *unit)
 
2785
{
 
2786
    Q_ASSERT(!m_scriptData);
 
2787
    m_scriptData = new QQmlScriptData();
 
2788
    m_scriptData->url = finalUrl();
 
2789
    m_scriptData->urlString = finalUrlString();
 
2790
    m_scriptData->m_precompiledScript = unit;
2944
2791
    if (m_scriptData->m_precompiledScript)
2945
2792
        m_scriptData->m_precompiledScript->ref();
2946
 
    m_source.clear();
2947
 
    if (!errors.isEmpty()) {
2948
 
        setError(errors);
2949
 
        return;
 
2793
 
 
2794
    m_importCache.setBaseUrl(finalUrl(), finalUrlString());
 
2795
 
 
2796
    Q_ASSERT(m_scriptData->m_precompiledScript->data->flags & QV4::CompiledData::Unit::IsQml);
 
2797
    const QV4::CompiledData::QmlUnit *qmlUnit = reinterpret_cast<const QV4::CompiledData::QmlUnit*>(m_scriptData->m_precompiledScript->data);
 
2798
 
 
2799
    QList<QQmlError> errors;
 
2800
    for (quint32 i = 0; i < qmlUnit->nImports; ++i) {
 
2801
        const QV4::CompiledData::Import *import = qmlUnit->importAt(i);
 
2802
        if (!addImport(import, &errors)) {
 
2803
           Q_ASSERT(errors.size());
 
2804
            QQmlError error(errors.takeFirst());
 
2805
            error.setUrl(m_importCache.baseUrl());
 
2806
            error.setLine(import->location.line);
 
2807
            error.setColumn(import->location.column);
 
2808
            errors.prepend(error); // put it back on the list after filling out information.
 
2809
            setError(errors);
 
2810
            return;
 
2811
        }
2950
2812
    }
2951
2813
}
2952
2814
 
2953
 
void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QQmlScript::Location &location, const QString &qualifier, const QString &nameSpace)
2954
 
{
2955
 
    ScriptReference ref;
2956
 
    ref.script = blob;
2957
 
    ref.location = location;
2958
 
    ref.qualifier = qualifier;
2959
 
    ref.nameSpace = nameSpace;
2960
 
 
2961
 
    m_scripts << ref;
2962
 
}
2963
 
 
2964
2815
QQmlQmldirData::QQmlQmldirData(const QUrl &url, QQmlTypeLoader *loader)
2965
2816
: QQmlTypeLoader::Blob(url, QmldirFile, loader), m_import(0), m_priority(0)
2966
2817
{
2971
2822
    return m_content;
2972
2823
}
2973
2824
 
2974
 
const QQmlScript::Import *QQmlQmldirData::import() const
 
2825
const QV4::CompiledData::Import *QQmlQmldirData::import() const
2975
2826
{
2976
2827
    return m_import;
2977
2828
}
2978
2829
 
2979
 
void QQmlQmldirData::setImport(const QQmlScript::Import *import)
 
2830
void QQmlQmldirData::setImport(const QV4::CompiledData::Import *import)
2980
2831
{
2981
2832
    m_import = import;
2982
2833
}
2996
2847
    m_content = QString::fromUtf8(data.data(), data.size());
2997
2848
}
2998
2849
 
 
2850
void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *)
 
2851
{
 
2852
    Q_UNIMPLEMENTED();
 
2853
}
 
2854
 
2999
2855
QT_END_NAMESPACE
3000
2856
 
3001
2857
#include "qqmltypeloader.moc"