Update obsolete contact address.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativetypeloader_p.h
index 7f487a0..36e8d93 100644 (file)
@@ -1,35 +1,35 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
 ** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file.  Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional
-** rights.  These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
 **
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
 **
 **
 **
 //
 
 #include <QtCore/qobject.h>
+#include <QtCore/qatomic.h>
 #include <QtNetwork/qnetworkreply.h>
 #include <QtDeclarative/qdeclarativeerror.h>
 #include <QtDeclarative/qdeclarativeengine.h>
-#include <private/qdeclarativescriptparser_p.h>
-#include <private/qdeclarativedirparser_p.h>
+
+#include <private/qv8_p.h>
+#include <private/qhashedstring_p.h>
+#include <private/qdeclarativescript_p.h>
 #include <private/qdeclarativeimport_p.h>
+#include <private/qdeclarativecleanup_p.h>
+#include <private/qdeclarativedirparser_p.h>
 
 QT_BEGIN_NAMESPACE
 
 class QDeclarativeScriptData;
+class QDeclarativeScriptBlob;
 class QDeclarativeQmldirData;
 class QDeclarativeTypeLoader;
 class QDeclarativeCompiledData;
 class QDeclarativeComponentPrivate;
 class QDeclarativeTypeData;
 class QDeclarativeDataLoader;
+class QDeclarativeExtensionInterface;
 
-class Q_AUTOTEST_EXPORT QDeclarativeDataBlob : public QDeclarativeRefCount
+// Exported for QtQuick1
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDataBlob : public QDeclarativeRefCount
 {
 public:
     enum Status {
@@ -108,39 +116,59 @@ public:
 
     QList<QDeclarativeError> errors() const;
 
+protected:
+    // Can be called from within callbacks
     void setError(const QDeclarativeError &);
     void setError(const QList<QDeclarativeError> &errors);
-
     void addDependency(QDeclarativeDataBlob *);
 
-protected:
+    // Callbacks made in load thread
     virtual void dataReceived(const QByteArray &) = 0;
-
     virtual void done();
     virtual void networkError(QNetworkReply::NetworkError);
-
     virtual void dependencyError(QDeclarativeDataBlob *);
     virtual void dependencyComplete(QDeclarativeDataBlob *);
     virtual void allDependenciesDone();
-    
-    virtual void downloadProgressChanged(qreal);
 
+    // Callbacks made in main thread
+    virtual void downloadProgressChanged(qreal);
+    virtual void completed();
 private:
     friend class QDeclarativeDataLoader;
+    friend class QDeclarativeDataLoaderThread;
+
     void tryDone();
     void cancelAllWaitingFor();
     void notifyAllWaitingOnMe();
     void notifyComplete(QDeclarativeDataBlob *);
 
+    struct ThreadData {
+        inline ThreadData();
+        inline QDeclarativeDataBlob::Status status() const;
+        inline void setStatus(QDeclarativeDataBlob::Status);
+        inline bool isAsync() const;
+        inline void setIsAsync(bool);
+        inline quint8 progress() const;
+        inline void setProgress(quint8);
+
+    private:
+        QAtomicInt _p;
+    };
+    ThreadData m_data;
+
+    // m_errors should *always* be written before the status is set to Error.
+    // We use the status change as a memory fence around m_errors so that locking
+    // isn't required.  Once the status is set to Error (or Complete), m_errors 
+    // cannot be changed.
+    QList<QDeclarativeError> m_errors;
+
     Type m_type;
-    Status m_status;
-    qreal m_progress;
 
     QUrl m_url;
     QUrl m_finalUrl;
 
     // List of QDeclarativeDataBlob's that are waiting for me to complete.
-    QList<QDeclarativeDataBlob *> m_waitingOnMe;     
+    QList<QDeclarativeDataBlob *> m_waitingOnMe;
 
     // List of QDeclarativeDataBlob's that I am waiting for to complete.
     QList<QDeclarativeDataBlob *> m_waitingFor;
@@ -150,38 +178,52 @@ private:
     int m_redirectCount:30;
     bool m_inCallback:1;
     bool m_isDone:1;
-
-    QList<QDeclarativeError> m_errors;
 };
 
-class Q_AUTOTEST_EXPORT QDeclarativeDataLoader : public QObject
+class QDeclarativeDataLoaderThread;
+// Exported for QtQuick1
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDataLoader 
 {
-    Q_OBJECT
 public:
     QDeclarativeDataLoader(QDeclarativeEngine *);
     ~QDeclarativeDataLoader();
 
-    void load(QDeclarativeDataBlob *);
-    void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &);
+    void lock();
+    void unlock();
 
-    QDeclarativeEngine *engine() const;
+    bool isConcurrent() const { return true; }
+
+    enum Mode { PreferSynchronous, Asynchronous };
 
-private slots:
-    void networkReplyFinished();
-    void networkReplyProgress(qint64,qint64);
+    void load(QDeclarativeDataBlob *, Mode = PreferSynchronous);
+    void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &, Mode = PreferSynchronous);
+
+    QDeclarativeEngine *engine() const;
+    void initializeEngine(QDeclarativeExtensionInterface *, const char *);
 
 private:
+    friend class QDeclarativeDataBlob;
+    friend class QDeclarativeDataLoaderThread;
+    friend class QDeclarativeDataLoaderNetworkReplyProxy;
+
+    void loadThread(QDeclarativeDataBlob *);
+    void loadWithStaticDataThread(QDeclarativeDataBlob *, const QByteArray &);
+    void networkReplyFinished(QNetworkReply *);
+    void networkReplyProgress(QNetworkReply *, qint64, qint64);
+    
+    typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies;
+
     void setData(QDeclarativeDataBlob *, const QByteArray &);
 
     QDeclarativeEngine *m_engine;
-    typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies;
+    QDeclarativeDataLoaderThread *m_thread;
     NetworkReplies m_networkReplies;
 };
 
-
-class Q_AUTOTEST_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader
+// Exported for QtQuick1
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader
 {
-    Q_OBJECT
+    Q_DECLARE_TR_FUNCTIONS(QDeclarativeTypeLoader)
 public:
     QDeclarativeTypeLoader(QDeclarativeEngine *);
     ~QDeclarativeTypeLoader();
@@ -196,16 +238,25 @@ public:
     QDeclarativeTypeData *get(const QByteArray &, const QUrl &url, Options = None);
     void clearCache();
 
-    QDeclarativeScriptData *getScript(const QUrl &);
+    QDeclarativeScriptBlob *getScript(const QUrl &);
     QDeclarativeQmldirData *getQmldir(const QUrl &);
+
+    QString absoluteFilePath(const QString &path);
+    bool directoryExists(const QString &path);
+    const QDeclarativeDirParser *qmlDirParser(const QString &absoluteFilePath);
 private:
     typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache;
-    typedef QHash<QUrl, QDeclarativeScriptData *> ScriptCache;
+    typedef QHash<QUrl, QDeclarativeScriptBlob *> ScriptCache;
     typedef QHash<QUrl, QDeclarativeQmldirData *> QmldirCache;
+    typedef QStringHash<bool> StringSet;
+    typedef QStringHash<StringSet*> ImportDirCache;
+    typedef QStringHash<QDeclarativeDirParser*> ImportQmlDirCache;
 
     TypeCache m_typeCache;
     ScriptCache m_scriptCache;
     QmldirCache m_qmldirCache;
+    ImportDirCache m_importDirCache;
+    ImportQmlDirCache m_importQmlDirCache;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options)
@@ -217,7 +268,7 @@ public:
     {
         TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {}
 
-        QDeclarativeParser::Location location;
+        QDeclarativeScript::Location location;
         QDeclarativeType *type;
         int majorVersion;
         int minorVersion;
@@ -228,9 +279,9 @@ public:
     {
         ScriptReference() : script(0) {}
 
-        QDeclarativeParser::Location location;
+        QDeclarativeScript::Location location;
         QString qualifier;
-        QDeclarativeScriptData *script;
+        QDeclarativeScriptBlob *script;
     };
 
     QDeclarativeTypeData(const QUrl &, QDeclarativeTypeLoader::Options, QDeclarativeTypeLoader *);
@@ -239,7 +290,7 @@ public:
     QDeclarativeTypeLoader *typeLoader() const;
 
     const QDeclarativeImports &imports() const;
-    const QDeclarativeScriptParser &parser() const;
+    const QDeclarativeScript::Parser &parser() const;
 
     const QList<TypeReference> &resolvedTypes() const;
     const QList<ScriptReference> &resolvedScripts() const;
@@ -257,6 +308,7 @@ public:
 
 protected:
     virtual void done();
+    virtual void completed();
     virtual void dataReceived(const QByteArray &);
     virtual void allDependenciesDone();
     virtual void downloadProgressChanged(qreal);
@@ -269,7 +321,7 @@ private:
 
     QDeclarativeQmldirData *qmldirForUrl(const QUrl &);
 
-    QDeclarativeScriptParser scriptParser;
+    QDeclarativeScript::Parser scriptParser;
     QDeclarativeImports m_imports;
 
     QList<ScriptReference> m_scripts;
@@ -285,20 +337,77 @@ private:
     QDeclarativeTypeLoader *m_typeLoader;
 };
 
-class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeDataBlob
+// QDeclarativeScriptData instances are created, uninitialized, by the loader in the 
+// load thread.  The first time they are used by the VME, they are initialized which
+// creates their v8 objects and they are referenced and added to the  engine's cleanup
+// list.  During QDeclarativeCleanup::clear() all v8 resources are destroyed, and the 
+// reference that was created is released but final deletion only occurs once all the
+// references as released.  This is all intended to ensure that the v8 resources are
+// only created and destroyed in the main thread :)
+class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeCleanup, 
+                                                 public QDeclarativeRefCount
 {
 public:
-    QDeclarativeScriptData(const QUrl &);
+    QDeclarativeScriptData();
+    ~QDeclarativeScriptData();
+
+    QUrl url;
+    QDeclarativeTypeNameCache *importCache;
+    QList<QDeclarativeScriptBlob *> scripts;
+    QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas;
+
+    bool isInitialized() const { return hasEngine(); }
+    void initialize(QDeclarativeEngine *);
+
+protected:
+    virtual void clear(); // From QDeclarativeCleanup
+
+private:
+    friend class QDeclarativeVME;
+    friend class QDeclarativeScriptBlob;
 
-    QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas() const;
+    bool m_loaded;
+    QString m_programSource;
+    v8::Persistent<v8::Script> m_program;
+    v8::Persistent<v8::Object> m_value;
+};
+
+class Q_AUTOTEST_EXPORT QDeclarativeScriptBlob : public QDeclarativeDataBlob
+{
+public:
+    QDeclarativeScriptBlob(const QUrl &, QDeclarativeTypeLoader *);
+    ~QDeclarativeScriptBlob();
+
+    struct ScriptReference
+    {
+        ScriptReference() : script(0) {}
+
+        QDeclarativeScript::Location location;
+        QString qualifier;
+        QDeclarativeScriptBlob *script;
+    };
+
+    QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas() const;
     QString scriptSource() const;
 
+    QDeclarativeTypeLoader *typeLoader() const;
+    const QDeclarativeImports &imports() const;
+
+    QDeclarativeScriptData *scriptData() const;
+
 protected:
     virtual void dataReceived(const QByteArray &);
+    virtual void done();
 
 private:
-    QDeclarativeParser::Object::ScriptBlock::Pragmas m_pragmas;
+    QDeclarativeScript::Object::ScriptBlock::Pragmas m_pragmas;
     QString m_source;
+
+    QDeclarativeImports m_imports;
+    QList<ScriptReference> m_scripts;
+    QDeclarativeScriptData *m_scriptData;
+
+    QDeclarativeTypeLoader *m_typeLoader;
 };
 
 class Q_AUTOTEST_EXPORT QDeclarativeQmldirData : public QDeclarativeDataBlob