1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QQMLTYPELOADER_P_H
41#define QQMLTYPELOADER_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <private/qqmldatablob_p.h>
55#include <private/qqmlimport_p.h>
56#include <private/qqmlmetatype_p.h>
57
58#include <QtQml/qtqmlglobal.h>
59#include <QtQml/qqmlerror.h>
60
61#include <QtCore/qcache.h>
62#include <QtCore/qmutex.h>
63
64#include <memory>
65
66QT_BEGIN_NAMESPACE
67
68class QQmlScriptBlob;
69class QQmlQmldirData;
70class QQmlTypeData;
71class QQmlExtensionInterface;
72class QQmlProfiler;
73class QQmlTypeLoaderThread;
74class QQmlEngine;
75
76class Q_QML_PRIVATE_EXPORT QQmlTypeLoader
77{
78 Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
79public:
80 enum Mode { PreferSynchronous, Asynchronous, Synchronous };
81
82 class Q_QML_PRIVATE_EXPORT Blob : public QQmlDataBlob
83 {
84 public:
85 Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader);
86 ~Blob() override;
87
88 const QQmlImports &imports() const { return m_importCache; }
89
90 void setCachedUnitStatus(QQmlMetaType::CachedUnitLookupError status) { m_cachedUnitStatus = status; }
91
92 struct PendingImport
93 {
94 QV4::CompiledData::Import::ImportType type = QV4::CompiledData::Import::ImportType::ImportLibrary;
95
96 QString uri;
97 QString qualifier;
98
99 int majorVersion = -1;
100 int minorVersion = -1;
101
102 QV4::CompiledData::Location location;
103
104 int priority = 0;
105
106 PendingImport() = default;
107 PendingImport(Blob *blob, const QV4::CompiledData::Import *import);
108 };
109 using PendingImportPtr = std::shared_ptr<PendingImport>;
110
111 protected:
112 bool addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
113 bool addImport(PendingImportPtr import, QList<QQmlError> *errors);
114
115 bool fetchQmldir(const QUrl &url, PendingImportPtr import, int priority, QList<QQmlError> *errors);
116 bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, PendingImportPtr import, QList<QQmlError> *errors);
117
118 private:
119 virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
120
121 virtual void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &, const QString &, const QString &) {}
122
123 void dependencyComplete(QQmlDataBlob *) override;
124
125 bool loadImportDependencies(PendingImportPtr currentImport, const QString &qmldirUri, QList<QQmlError> *errors);
126
127 protected:
128 virtual QString stringAt(int) const { return QString(); }
129
130 bool isDebugging() const;
131
132 static bool diskCacheDisabled();
133 static bool diskCacheForced();
134
135 QQmlImports m_importCache;
136 QVector<PendingImportPtr> m_unresolvedImports;
137 QVector<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
138 QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
139 };
140
141 QQmlTypeLoader(QQmlEngine *);
142 ~QQmlTypeLoader();
143
144 QQmlImportDatabase *importDatabase() const;
145
146 static QUrl normalize(const QUrl &unNormalizedUrl);
147
148 QQmlRefPointer<QQmlTypeData> getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
149 QQmlRefPointer<QQmlTypeData> getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
150
151 QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl);
152 QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &);
153
154 QString absoluteFilePath(const QString &path);
155 bool fileExists(const QString &path, const QString &file);
156 bool directoryExists(const QString &path);
157
158 const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath);
159 void setQmldirContent(const QString &filePath, const QString &content);
160
161 void clearCache();
162 void trimCache();
163
164 bool isTypeLoaded(const QUrl &url) const;
165 bool isScriptLoaded(const QUrl &url) const;
166
167 void lock() { m_mutex.lock(); }
168 void unlock() { m_mutex.unlock(); }
169
170 void load(QQmlDataBlob *, Mode = PreferSynchronous);
171 void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
172 void loadWithCachedUnit(QQmlDataBlob *blob, const QV4::CompiledData::Unit *unit, Mode mode = PreferSynchronous);
173
174 QQmlEngine *engine() const;
175 void initializeEngine(QQmlExtensionInterface *, const char *);
176 void invalidate();
177
178#if !QT_CONFIG(qml_debug)
179 quintptr profiler() const { return 0; }
180 void setProfiler(quintptr) {}
181#else
182 QQmlProfiler *profiler() const { return m_profiler.data(); }
183 void setProfiler(QQmlProfiler *profiler);
184#endif // QT_CONFIG(qml_debug)
185
186
187private:
188 friend class QQmlDataBlob;
189 friend class QQmlTypeLoaderThread;
190#if QT_CONFIG(qml_network)
191 friend class QQmlTypeLoaderNetworkReplyProxy;
192#endif // qml_network
193
194 void shutdownThread();
195
196 void loadThread(QQmlDataBlob *);
197 void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
198 void loadWithCachedUnitThread(QQmlDataBlob *blob, const QV4::CompiledData::Unit *unit);
199#if QT_CONFIG(qml_network)
200 void networkReplyFinished(QNetworkReply *);
201 void networkReplyProgress(QNetworkReply *, qint64, qint64);
202
203 typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
204#endif
205
206 void setData(QQmlDataBlob *, const QByteArray &);
207 void setData(QQmlDataBlob *, const QString &fileName);
208 void setData(QQmlDataBlob *, const QQmlDataBlob::SourceCodeData &);
209 void setCachedUnit(QQmlDataBlob *blob, const QV4::CompiledData::Unit *unit);
210
211 template<typename T>
212 struct TypedCallback
213 {
214 TypedCallback(T *object, void (T::*func)(QQmlTypeData *)) : o(object), mf(func) {}
215
216 static void redirect(void *arg, QQmlTypeData *type)
217 {
218 TypedCallback<T> *self = reinterpret_cast<TypedCallback<T> *>(arg);
219 ((self->o)->*(self->mf))(type);
220 }
221
222 private:
223 T *o;
224 void (T::*mf)(QQmlTypeData *);
225 };
226
227 typedef QHash<QUrl, QQmlTypeData *> TypeCache;
228 typedef QHash<QUrl, QQmlScriptBlob *> ScriptCache;
229 typedef QHash<QUrl, QQmlQmldirData *> QmldirCache;
230 typedef QCache<QString, QCache<QString, bool> > ImportDirCache;
231 typedef QStringHash<QQmlTypeLoaderQmldirContent *> ImportQmlDirCache;
232
233 QQmlEngine *m_engine;
234 QQmlTypeLoaderThread *m_thread;
235 QMutex &m_mutex;
236
237#if QT_CONFIG(qml_debug)
238 QScopedPointer<QQmlProfiler> m_profiler;
239#endif
240
241#if QT_CONFIG(qml_network)
242 NetworkReplies m_networkReplies;
243#endif
244 TypeCache m_typeCache;
245 int m_typeCacheTrimThreshold;
246 ScriptCache m_scriptCache;
247 QmldirCache m_qmldirCache;
248 ImportDirCache m_importDirCache;
249 ImportQmlDirCache m_importQmlDirCache;
250
251 template<typename Loader>
252 void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode);
253 void updateTypeCacheTrimThreshold();
254
255 friend struct PlainLoader;
256 friend struct CachedLoader;
257 friend struct StaticLoader;
258};
259
260QT_END_NAMESPACE
261
262#endif // QQMLTYPELOADER_P_H
263