1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QDECLARATIVEENGINE_P_H
43 #define QDECLARATIVEENGINE_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
56 #include "qdeclarativeengine.h"
58 #include "qdeclarativetypeloader_p.h"
59 #include "qdeclarativeimport_p.h"
60 #include <private/qpodvector_p.h>
61 #include "qdeclarative.h"
62 #include "qdeclarativevaluetype_p.h"
63 #include "qdeclarativecontext.h"
64 #include "qdeclarativecontext_p.h"
65 #include "qdeclarativeexpression.h"
66 #include "qdeclarativeimageprovider.h"
67 #include "qdeclarativeproperty_p.h"
68 #include "qdeclarativepropertycache_p.h"
69 #include "qdeclarativemetatype_p.h"
70 #include "qdeclarativedirparser_p.h"
71 #include <private/qintrusivelist_p.h>
72 #include <private/qrecyclepool_p.h>
74 #include <QtCore/qlist.h>
75 #include <QtCore/qpair.h>
76 #include <QtCore/qstack.h>
77 #include <QtCore/qmutex.h>
78 #include <QtCore/qstring.h>
79 #include <QtCore/qthread.h>
81 #include <private/qobject_p.h>
83 #include <private/qv8engine_p.h>
84 #include <private/qjsengine_p.h>
88 class QDeclarativeContext;
89 class QDeclarativeEngine;
90 class QDeclarativeContextPrivate;
91 class QDeclarativeExpression;
92 class QDeclarativeImportDatabase;
94 class QNetworkAccessManager;
95 class QDeclarativeNetworkAccessManagerFactory;
96 class QDeclarativeAbstractBinding;
97 class QDeclarativeTypeNameCache;
98 class QDeclarativeComponentAttached;
99 class QDeclarativeCleanup;
100 class QDeclarativeDelayedError;
101 class QDeclarativeWorkerScriptEngine;
102 class QDeclarativeVME;
104 class QDeclarativeIncubator;
106 // This needs to be declared here so that the pool for it can live in QDeclarativeEnginePrivate.
107 // The inline method definitions are in qdeclarativeexpression_p.h
108 class QDeclarativeJavaScriptExpressionGuard : public QDeclarativeNotifierEndpoint
111 inline QDeclarativeJavaScriptExpressionGuard(QDeclarativeJavaScriptExpression *);
113 static inline void endpointCallback(QDeclarativeNotifierEndpoint *);
114 static inline QDeclarativeJavaScriptExpressionGuard *New(QDeclarativeJavaScriptExpression *e);
115 inline void Delete();
117 QDeclarativeJavaScriptExpression *expression;
118 QDeclarativeJavaScriptExpressionGuard *next;
121 class Q_DECLARATIVE_EXPORT QDeclarativeEnginePrivate : public QJSEnginePrivate
123 Q_DECLARE_PUBLIC(QDeclarativeEngine)
125 QDeclarativeEnginePrivate(QDeclarativeEngine *);
126 ~QDeclarativeEnginePrivate();
130 class PropertyCapture {
132 inline virtual ~PropertyCapture() {}
133 virtual void captureProperty(QDeclarativeNotifier *) = 0;
134 virtual void captureProperty(QObject *, int, int) = 0;
137 PropertyCapture *propertyCapture;
138 inline void captureProperty(QDeclarativeNotifier *);
139 inline void captureProperty(QObject *, int, int);
141 QRecyclePool<QDeclarativeJavaScriptExpressionGuard> jsExpressionGuardPool;
143 QDeclarativeContext *rootContext;
146 bool outputWarningsToStdErr;
148 QDeclarativeContextData *sharedContext;
149 QObject *sharedScope;
151 // Registered cleanup handlers
152 QDeclarativeCleanup *cleanup;
154 // Bindings that have had errors during startup
155 QDeclarativeDelayedError *erroredBindings;
156 int inProgressCreations;
158 QV8Engine *v8engine() const { return q_func()->handle(); }
160 QDeclarativeWorkerScriptEngine *getWorkerScriptEngine();
161 QDeclarativeWorkerScriptEngine *workerScriptEngine;
165 typedef QPair<QDeclarativeGuard<QObject>,int> FinalizeCallback;
166 void registerFinalizeCallback(QObject *obj, int index);
168 QDeclarativeVME *activeVME;
170 QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
171 QNetworkAccessManager *getNetworkAccessManager() const;
172 mutable QNetworkAccessManager *networkAccessManager;
173 mutable QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory;
175 QHash<QString,QSharedPointer<QDeclarativeImageProvider> > imageProviders;
176 QDeclarativeImageProvider::ImageType getImageProviderType(const QUrl &url);
177 QDeclarativeTextureFactory *getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
178 QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
179 QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
181 // Scarce resources are "exceptionally high cost" QVariant types where allowing the
182 // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
183 // out-of-resource situations. When such a resource is passed into JavaScript we
184 // add it to the scarceResources list and it is destroyed when we return from the
185 // JavaScript execution that created it. The user can prevent this behavior by
186 // calling preserve() on the object which removes it from this scarceResource list.
187 class ScarceResourceData {
189 ScarceResourceData(const QVariant &data) : data(data) {}
191 QIntrusiveListNode node;
193 QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
194 int scarceResourcesRefCount;
195 void referenceScarceResources();
196 void dereferenceScarceResources();
198 QDeclarativeTypeLoader typeLoader;
199 QDeclarativeImportDatabase importDatabase;
201 QString offlineStoragePath;
203 mutable quint32 uniqueId;
204 inline quint32 getUniqueId() const {
208 QDeclarativeValueTypeFactory valueTypes;
210 // Unfortunate workaround to avoid a circular dependency between
211 // qdeclarativeengine_p.h and qdeclarativeincubator_p.h
213 QIntrusiveListNode next;
214 // Unfortunate workaround for MSVC
215 QIntrusiveListNode nextWaitingFor;
217 QIntrusiveList<Incubator, &Incubator::next> incubatorList;
218 unsigned int incubatorCount;
219 QDeclarativeIncubationController *incubationController;
220 void incubate(QDeclarativeIncubator &, QDeclarativeContextData *);
222 // These methods may be called from any thread
223 inline bool isEngineThread() const;
224 inline static bool isEngineThread(const QDeclarativeEngine *);
226 inline void deleteInEngineThread(T *);
228 inline static void deleteInEngineThread(QDeclarativeEngine *, T *);
230 // These methods may be called from the loader thread
231 QDeclarativeMetaType::ModuleApiInstance *moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module);
233 // These methods may be called from the loader thread
234 inline QDeclarativePropertyCache *cache(QObject *obj);
235 inline QDeclarativePropertyCache *cache(const QMetaObject *);
236 inline QDeclarativePropertyCache *cache(QDeclarativeType *, int, QDeclarativeError &error);
238 // These methods may be called from the loader thread
240 QObject *toQObject(const QVariant &, bool *ok = 0) const;
241 QDeclarativeMetaType::TypeCategory typeCategory(int) const;
242 bool isList(int) const;
243 int listType(int) const;
244 const QMetaObject *rawMetaObjectForType(int) const;
245 const QMetaObject *metaObjectForType(int) const;
246 void registerCompositeType(QDeclarativeCompiledData *);
249 void warning(const QDeclarativeError &);
250 void warning(const QList<QDeclarativeError> &);
251 static void warning(QDeclarativeEngine *, const QDeclarativeError &);
252 static void warning(QDeclarativeEngine *, const QList<QDeclarativeError> &);
253 static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &);
254 static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &);
256 inline static QV8Engine *getV8Engine(QDeclarativeEngine *e);
257 inline static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e);
258 inline static const QDeclarativeEnginePrivate *get(const QDeclarativeEngine *e);
259 inline static QDeclarativeEnginePrivate *get(QDeclarativeContext *c);
260 inline static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c);
261 inline static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p);
263 static QString urlToLocalFileOrQrc(const QUrl& url);
264 static QString urlToLocalFileOrQrc(const QString& url);
266 static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
267 static void defineModule();
269 static bool qml_debugging_enabled;
271 mutable QMutex mutex;
274 // Locker locks the QDeclarativeEnginePrivate data structures for read and write, if necessary.
275 // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
276 // either idle, or is running with the main thread blocked, no locking is necessary. This way
277 // we only pay for locking when we have to.
278 // Consequently, this class should only be used to protect simple accesses or modifications of the
279 // QDeclarativeEnginePrivate structures or operations that can be guarenteed not to start activity
280 // on the loader thread.
281 // The Locker API is identical to QMutexLocker. Locker reuses the QDeclarativeEnginePrivate::mutex
282 // QMutex instance and multiple Lockers are recursive in the same thread.
286 inline Locker(const QDeclarativeEngine *);
287 inline Locker(const QDeclarativeEnginePrivate *);
290 inline void unlock();
291 inline void relock();
294 const QDeclarativeEnginePrivate *m_ep;
298 // Must be called locked
299 QDeclarativePropertyCache *createCache(const QMetaObject *);
300 QDeclarativePropertyCache *createCache(QDeclarativeType *, int, QDeclarativeError &error);
302 // These members must be protected by a QDeclarativeEnginePrivate::Locker as they are required by
303 // the threaded loader. Only access them through their respective accessor methods.
304 QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *> moduleApiInstances;
305 QHash<const QMetaObject *, QDeclarativePropertyCache *> propertyCache;
306 QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *> typePropertyCache;
307 QHash<int, int> m_qmlLists;
308 QHash<int, QDeclarativeCompiledData *> m_compositeTypes;
310 // These members is protected by the full QDeclarativeEnginePrivate::mutex mutex
311 struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; };
312 QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread;
313 void doDeleteInEngineThread();
316 QDeclarativeEnginePrivate::Locker::Locker(const QDeclarativeEngine *e)
317 : m_ep(QDeclarativeEnginePrivate::get(e))
322 QDeclarativeEnginePrivate::Locker::Locker(const QDeclarativeEnginePrivate *e)
323 : m_ep(e), m_locked(false)
328 QDeclarativeEnginePrivate::Locker::~Locker()
333 void QDeclarativeEnginePrivate::Locker::unlock()
336 m_ep->mutex.unlock();
341 void QDeclarativeEnginePrivate::Locker::relock()
344 if (m_ep->typeLoader.isConcurrent()) {
351 Returns true if the calling thread is the QDeclarativeEngine thread.
353 bool QDeclarativeEnginePrivate::isEngineThread() const
355 Q_Q(const QDeclarativeEngine);
356 return QThread::currentThread() == q->thread();
360 Returns true if the calling thread is the QDeclarativeEngine \a engine thread.
362 bool QDeclarativeEnginePrivate::isEngineThread(const QDeclarativeEngine *engine)
365 return QDeclarativeEnginePrivate::get(engine)->isEngineThread();
369 Delete \a value in the engine thread. If the calling thread is the engine
370 thread, \a value will be deleted immediately.
372 This method should be used for *any* type that has resources that need to
373 be freed in the engine thread. This is generally types that use V8 handles.
374 As there is some small overhead in checking the current thread, it is best
375 practice to check if any V8 handles actually need to be freed and delete
376 the instance directly if not.
379 void QDeclarativeEnginePrivate::deleteInEngineThread(T *value)
381 Q_Q(QDeclarativeEngine);
384 if (isEngineThread()) {
387 struct I : public Deletable {
388 I(T *value) : value(value) {}
389 ~I() { delete value; }
394 bool wasEmpty = toDeleteInEngineThread.isEmpty();
395 toDeleteInEngineThread.append(i);
398 QCoreApplication::postEvent(q, new QEvent(QEvent::User));
403 Delete \a value in the \a engine thread. If the calling thread is the engine
404 thread, \a value will be deleted immediately.
407 void QDeclarativeEnginePrivate::deleteInEngineThread(QDeclarativeEngine *engine, T *value)
410 QDeclarativeEnginePrivate::get(engine)->deleteInEngineThread<T>(value);
414 Returns a QDeclarativePropertyCache for \a obj if one is available.
416 If \a obj is null, being deleted or contains a dynamic meta object 0
419 The returned cache is not referenced, so if it is to be stored, call addref().
421 XXX thread There is a potential future race condition in this and all the cache()
422 functions. As the QDeclarativePropertyCache is returned unreferenced, when called
423 from the loader thread, it is possible that the cache will have been dereferenced
424 and deleted before the loader thread has a chance to use or reference it. This
425 can't currently happen as the cache holds a reference to the
426 QDeclarativePropertyCache until the QDeclarativeEngine is destroyed.
428 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj)
430 if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
434 const QMetaObject *mo = obj->metaObject();
435 QDeclarativePropertyCache *rv = propertyCache.value(mo);
436 if (!rv) rv = createCache(mo);
441 Returns a QDeclarativePropertyCache for \a metaObject.
443 As the cache is persisted for the life of the engine, \a metaObject must be
444 a static "compile time" meta-object, or a meta-object that is otherwise known to
445 exist for the lifetime of the QDeclarativeEngine.
447 The returned cache is not referenced, so if it is to be stored, call addref().
449 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(const QMetaObject *metaObject)
451 Q_ASSERT(metaObject);
454 QDeclarativePropertyCache *rv = propertyCache.value(metaObject);
455 if (!rv) rv = createCache(metaObject);
460 Returns a QDeclarativePropertyCache for \a type with \a minorVersion.
462 The returned cache is not referenced, so if it is to be stored, call addref().
464 QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QDeclarativeType *type, int minorVersion, QDeclarativeError &error)
468 if (minorVersion == -1 || !type->containsRevisionedAttributes())
469 return cache(type->metaObject());
472 QDeclarativePropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
473 if (!rv) rv = createCache(type, minorVersion, error);
477 QV8Engine *QDeclarativeEnginePrivate::getV8Engine(QDeclarativeEngine *e)
479 return e->d_func()->v8engine();
482 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeEngine *e)
487 const QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(const QDeclarativeEngine *e)
492 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeContext *c)
494 return (c && c->engine()) ? QDeclarativeEnginePrivate::get(c->engine()) : 0;
497 QDeclarativeEnginePrivate *QDeclarativeEnginePrivate::get(QDeclarativeContextData *c)
499 return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0;
502 QDeclarativeEngine *QDeclarativeEnginePrivate::get(QDeclarativeEnginePrivate *p)
507 void QDeclarativeEnginePrivate::captureProperty(QDeclarativeNotifier *n)
510 propertyCapture->captureProperty(n);
513 void QDeclarativeEnginePrivate::captureProperty(QObject *o, int c, int n)
516 propertyCapture->captureProperty(o, c, n);
521 #endif // QDECLARATIVEENGINE_P_H