1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #ifndef QDECLARATIVEV8ENGINE_P_H
43 #define QDECLARATIVEV8ENGINE_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 <QtCore/qglobal.h>
57 #include <QtCore/qvariant.h>
58 #include <QtCore/qset.h>
59 #include <QtCore/qmutex.h>
60 #include <private/qv8_p.h>
62 #include <private/qdeclarativepropertycache_p.h>
64 #include "qv8contextwrapper_p.h"
65 #include "qv8qobjectwrapper_p.h"
66 #include "qv8stringwrapper_p.h"
67 #include "qv8typewrapper_p.h"
68 #include "qv8listwrapper_p.h"
69 #include "qv8variantwrapper_p.h"
70 #include "qv8valuetypewrapper_p.h"
75 // Uncomment the following line to enable global handle debugging. When enabled, all the persistent
76 // handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
77 // with qPersistentDispose() are tracked. If you try and do something illegal, like double disposing
78 // a handle, qFatal() is called.
79 // #define QML_GLOBAL_HANDLE_DEBUGGING
81 #define V8_RESOURCE_TYPE(resourcetype) \
83 enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
84 virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
87 #define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
88 #define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
89 #define V8THROW_ERROR(string) { \
90 v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
91 return v8::Handle<v8::Value>(); \
93 #define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data()));
94 #define V8THROW_ERROR_SETTER(string) { \
95 v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
99 #define V8_DEFINE_EXTENSION(dataclass, datafunction) \
100 inline dataclass *datafunction(QV8Engine *engine) \
102 static int extensionId = -1; \
103 if (extensionId == -1) { \
104 QV8Engine::registrationMutex()->lock(); \
105 if (extensionId == -1) \
106 extensionId = QV8Engine::registerExtension(); \
107 QV8Engine::registrationMutex()->unlock(); \
109 dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
111 rv = new dataclass(engine); \
112 engine->setExtensionData(extensionId, rv); \
118 class QV8ObjectResource : public v8::Object::ExternalResource
121 QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
122 enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
123 ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
124 ListModelType, Context2DType };
125 virtual ResourceType resourceType() const = 0;
131 T *v8_resource_cast(v8::Handle<v8::Object> object) {
132 QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
133 return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
136 // Used to allow a QObject method take and return raw V8 handles without having to expose
137 // v8 in the public API.
139 // class MyClass : public QObject {
142 // Q_INVOKABLE void myMethod(QDeclarativeV8Function*);
144 // The QDeclarativeV8Function - and consequently the arguments and return value - only remains
145 // valid during the call. If the return value isn't set within myMethod(), the will return
148 class QDeclarativeV8Function
151 int Length() const { return _ac; }
152 v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
153 QDeclarativeContextData *context() { return _c; }
154 v8::Handle<v8::Object> qmlGlobal() { return *_g; }
155 void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
156 QV8Engine *engine() const { return _e; }
158 friend class QV8QObjectWrapper;
159 QDeclarativeV8Function();
160 QDeclarativeV8Function(const QDeclarativeV8Function &);
161 QDeclarativeV8Function &operator=(const QDeclarativeV8Function &);
163 QDeclarativeV8Function(int length, v8::Handle<v8::Object> &args,
164 v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
165 QDeclarativeContextData *c, QV8Engine *e)
166 : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
169 v8::Handle<v8::Object> *_a;
170 v8::Handle<v8::Value> *_r;
171 v8::Handle<v8::Object> *_g;
172 QDeclarativeContextData *_c;
176 class QDeclarativeV8Handle
179 QDeclarativeV8Handle() : d(0) {}
180 QDeclarativeV8Handle(const QDeclarativeV8Handle &other) : d(other.d) {}
181 QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; }
183 static QDeclarativeV8Handle fromHandle(v8::Handle<v8::Value> h) {
184 return reinterpret_cast<QDeclarativeV8Handle &>(h);
186 v8::Handle<v8::Value> toHandle() const {
187 return reinterpret_cast<const v8::Handle<v8::Value> &>(*this);
194 class QDeclarativeEngine;
195 class QDeclarativeValueType;
196 class QNetworkAccessManager;
197 class QDeclarativeContextData;
198 class Q_AUTOTEST_EXPORT QV8Engine
208 void init(QDeclarativeEngine *);
210 QDeclarativeEngine *engine() { return m_engine; }
211 v8::Local<v8::Object> global() { return m_context->Global(); }
212 v8::Handle<v8::Context> context() { return m_context; }
213 QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
214 QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
215 QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
216 QV8ListWrapper *listWrapper() { return &m_listWrapper; }
217 QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
219 void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
220 void *sqlDatabaseData() { return m_sqlDatabaseData; }
222 Deletable *listModelData() { return m_listModelData; }
223 void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
225 QDeclarativeContextData *callingContext();
227 v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
228 void freezeObject(v8::Handle<v8::Value>);
230 inline QString toString(v8::Handle<v8::Value> string);
231 inline QString toString(v8::Handle<v8::String> string);
232 static QString toStringStatic(v8::Handle<v8::Value>);
233 static QString toStringStatic(v8::Handle<v8::String>);
234 static inline bool startsWithUpper(v8::Handle<v8::String>);
236 QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
237 v8::Handle<v8::Value> fromVariant(const QVariant &);
238 inline bool isVariant(v8::Handle<v8::Value>);
240 // Compile \a source (from \a fileName at \a lineNumber) in QML mode
241 v8::Local<v8::Script> qmlModeCompile(const QString &source,
242 const QString &fileName = QString(),
245 // Return the QML global "scope" object for the \a ctxt context and \a scope object.
246 inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
248 // Return a JS wrapper for the given QObject \a object
249 inline v8::Handle<v8::Value> newQObject(QObject *object);
250 inline bool isQObject(v8::Handle<v8::Value>);
251 inline QObject *toQObject(v8::Handle<v8::Value>);
253 // Return a JS string for the given QString \a string
254 inline v8::Local<v8::String> toString(const QString &string);
256 // Create a new value type object
257 inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
258 inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
260 // Create a new QVariant object. This doesn't examine the type of the variant, but always returns
261 // a QVariant wrapper
262 inline v8::Handle<v8::Value> newQVariant(const QVariant &);
264 // Return the network access manager for this engine. By default this returns the network
265 // access manager of the QDeclarativeEngine. It is overridden in the case of a threaded v8
266 // instance (like in WorkerScript).
267 virtual QNetworkAccessManager *networkAccessManager();
269 // Return the list of illegal id names (the names of the properties on the global object)
270 const QSet<QString> &illegalNames() const;
274 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
275 // Used for handle debugging
276 static void registerHandle(void *);
277 static void releaseHandle(void *);
280 static QMutex *registrationMutex();
281 static int registerExtension();
283 inline Deletable *extensionData(int) const;
284 void setExtensionData(int, Deletable *);
287 QDeclarativeEngine *m_engine;
288 v8::Persistent<v8::Context> m_context;
290 QV8StringWrapper m_stringWrapper;
291 QV8ContextWrapper m_contextWrapper;
292 QV8QObjectWrapper m_qobjectWrapper;
293 QV8TypeWrapper m_typeWrapper;
294 QV8ListWrapper m_listWrapper;
295 QV8VariantWrapper m_variantWrapper;
296 QV8ValueTypeWrapper m_valueTypeWrapper;
298 v8::Persistent<v8::Function> m_getOwnPropertyNames;
299 v8::Persistent<v8::Function> m_freezeObject;
301 void *m_xmlHttpRequestData;
302 void *m_sqlDatabaseData;
304 QVector<Deletable *> m_extensionData;
305 Deletable *m_listModelData;
307 QSet<QString> m_illegalNames;
309 QVariant toBasicVariant(v8::Handle<v8::Value>);
311 void initializeGlobal(v8::Handle<v8::Object>);
313 static v8::Handle<v8::Value> gc(const v8::Arguments &args);
314 static v8::Handle<v8::Value> print(const v8::Arguments &args);
315 static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
316 static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
317 static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
318 static v8::Handle<v8::Value> rect(const v8::Arguments &args);
319 static v8::Handle<v8::Value> point(const v8::Arguments &args);
320 static v8::Handle<v8::Value> size(const v8::Arguments &args);
321 static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
322 static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
323 static v8::Handle<v8::Value> darker(const v8::Arguments &args);
324 static v8::Handle<v8::Value> tint(const v8::Arguments &args);
325 static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
326 static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
327 static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
328 static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
329 static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
330 static v8::Handle<v8::Value> md5(const v8::Arguments &args);
331 static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
332 static v8::Handle<v8::Value> atob(const v8::Arguments &args);
333 static v8::Handle<v8::Value> quit(const v8::Arguments &args);
334 static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
335 static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
336 static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
338 double qtDateTimeToJsDate(const QDateTime &dt);
339 QDateTime qtDateTimeFromJsDate(double jsDate);
342 // Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated
343 // using this method.
345 v8::Persistent<T> qPersistentNew(v8::Handle<T> that)
347 v8::Persistent<T> rv = v8::Persistent<T>::New(that);
348 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
349 QV8Engine::registerHandle(*rv);
354 // Register a Persistent handle that was returned to you by V8 (such as by
355 // v8::Context::New). This allows us to do handle tracking on these handles too.
357 void qPersistentRegister(v8::Persistent<T> handle)
359 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
360 QV8Engine::registerHandle(*handle);
366 // Dispose and clear a persistent handle. *ALL* persistent handles in QML must be
367 // disposed using this method.
369 void qPersistentDispose(v8::Persistent<T> &that)
371 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
372 QV8Engine::releaseHandle(*that);
378 QString QV8Engine::toString(v8::Handle<v8::Value> string)
380 return m_stringWrapper.toString(string->ToString());
383 QString QV8Engine::toString(v8::Handle<v8::String> string)
385 return m_stringWrapper.toString(string);
388 bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
390 return m_variantWrapper.isVariant(value);
393 v8::Local<v8::Object> QV8Engine::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
395 return m_contextWrapper.qmlScope(ctxt, scope);
398 bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
400 return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
403 QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
405 return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
408 v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
410 return m_qobjectWrapper.newQObject(object);
413 v8::Local<v8::String> QV8Engine::toString(const QString &string)
415 return m_stringWrapper.toString(string);
418 v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QDeclarativeValueType *type)
420 return m_valueTypeWrapper.newValueType(object, property, type);
423 v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QDeclarativeValueType *type)
425 return m_valueTypeWrapper.newValueType(value, type);
428 // XXX Can this be made more optimal? It is called prior to resolving each and every
429 // unqualified name in QV8ContextWrapper.
430 bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
432 uint16_t c = string->GetCharacter(0);
433 return (c >= 'A' && c <= 'Z') ||
434 (c > 127 && QChar::category(c) == QChar::Letter_Uppercase);
437 QV8Engine::Deletable *QV8Engine::extensionData(int index) const
439 if (index < m_extensionData.count())
440 return m_extensionData[index];
447 #endif // QDECLARATIVEV8ENGINE_P_H