Merge branch 'master' into v8
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qv8engine_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
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
14 ** this package.
15 **
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.
23 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QDECLARATIVEV8ENGINE_P_H
43 #define QDECLARATIVEV8ENGINE_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
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.
52 //
53 // We mean it.
54 //
55
56 #include <QtCore/qglobal.h>
57 #include <QtCore/qvariant.h>
58 #include <QtCore/qset.h>
59 #include <private/qv8_p.h>
60
61 #include <private/qdeclarativepropertycache_p.h>
62
63 #include "qv8contextwrapper_p.h"
64 #include "qv8qobjectwrapper_p.h"
65 #include "qv8stringwrapper_p.h"
66 #include "qv8typewrapper_p.h"
67 #include "qv8listwrapper_p.h"
68 #include "qv8variantwrapper_p.h"
69 #include "qv8valuetypewrapper_p.h"
70
71 QT_BEGIN_NAMESPACE
72
73 #define V8_RESOURCE_TYPE(resourcetype) \
74 public: \
75     enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
76     virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
77 private: 
78
79 #define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
80 #define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
81 // XXX Are we mean to return a value here, or is an empty handle ok?
82 #define V8THROW_ERROR(string) { \
83     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
84     return v8::Handle<v8::Value>(); \
85 }
86
87 class QV8Engine;
88 class QV8ObjectResource : public v8::Object::ExternalResource
89 {
90 public:
91     QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
92     enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, 
93                         ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType };
94     virtual ResourceType resourceType() const = 0;
95
96     QV8Engine *engine;
97 };
98
99 template<class T>
100 T *v8_resource_cast(v8::Handle<v8::Object> object) {
101     QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
102     return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
103 }
104
105 // Used to allow a QObject method take and return raw V8 handles without having to expose
106 // v8 in the public API.
107 // Use like this:
108 //     class MyClass : public QObject {
109 //         Q_OBJECT
110 //         ...
111 //         Q_INVOKABLE void myMethod(QDeclarativeV8Function*);
112 //     };
113 // The QDeclarativeV8Function - and consequently the arguments and return value - only remains 
114 // valid during the call.  If the return value isn't set within myMethod(), the will return
115 // undefined.
116 class QV8Engine;
117 class QDeclarativeV8Function
118 {
119 public:
120     int Length() const { return _ac; }
121     v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
122     QDeclarativeContextData *context() { return _c; }
123     v8::Handle<v8::Object> qmlGlobal() { return *_g; }
124     void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
125     QV8Engine *engine() const { return _e; }
126 private:
127     friend class QV8QObjectWrapper;
128     QDeclarativeV8Function();
129     QDeclarativeV8Function(const QDeclarativeV8Function &);
130     QDeclarativeV8Function &operator=(const QDeclarativeV8Function &);
131
132     QDeclarativeV8Function(int length, v8::Handle<v8::Object> &args, 
133                            v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
134                            QDeclarativeContextData *c, QV8Engine *e)
135     : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
136
137     int _ac;
138     v8::Handle<v8::Object> *_a;
139     v8::Handle<v8::Value> *_r;
140     v8::Handle<v8::Object> *_g;
141     QDeclarativeContextData *_c;
142     QV8Engine *_e;
143 };
144
145 class QDeclarativeV8Handle
146 {
147 public:
148     QDeclarativeV8Handle() : d(0) {}
149     QDeclarativeV8Handle(const QDeclarativeV8Handle &other) : d(other.d) {}
150     QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; }
151
152     static QDeclarativeV8Handle fromHandle(v8::Handle<v8::Value> h) {
153         return reinterpret_cast<QDeclarativeV8Handle &>(h);
154     }
155     v8::Handle<v8::Value> toHandle() const {
156         return reinterpret_cast<const v8::Handle<v8::Value> &>(*this);
157     }
158 private:
159     void *d;
160 };
161
162 class QObject;
163 class QDeclarativeEngine;
164 class QDeclarativeValueType;
165 class QNetworkAccessManager;
166 class QDeclarativeContextData;
167 class Q_AUTOTEST_EXPORT QV8Engine 
168 {
169 public:
170     QV8Engine();
171     ~QV8Engine();
172
173     void init(QDeclarativeEngine *);
174
175     QDeclarativeEngine *engine() { return m_engine; }
176     v8::Local<v8::Object> global() { return m_context->Global(); }
177     v8::Handle<v8::Context> context() { return m_context; }
178     QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
179     QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
180     QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
181     QV8ListWrapper *listWrapper() { return &m_listWrapper; }
182     QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
183
184     void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
185     void *sqlDatabaseData() { return m_sqlDatabaseData; }
186
187     QDeclarativeContextData *callingContext();
188
189     v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
190
191     inline QString toString(v8::Handle<v8::Value> string);
192     inline QString toString(v8::Handle<v8::String> string);
193     static QString toStringStatic(v8::Handle<v8::Value>);
194     static QString toStringStatic(v8::Handle<v8::String>);
195     static inline bool startsWithUpper(v8::Handle<v8::String>);
196
197     QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
198     v8::Handle<v8::Value> fromVariant(const QVariant &);
199     inline bool isVariant(v8::Handle<v8::Value>);
200
201     // Compile \a source (from \a fileName at \a lineNumber) in QML mode
202     v8::Local<v8::Script> qmlModeCompile(const QString &source, 
203                                          const QString &fileName = QString(), 
204                                          int lineNumber = 1);
205
206     // Return the QML global "scope" object for the \a ctxt context and \a scope object.
207     inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
208
209     // Return a JS wrapper for the given QObject \a object
210     inline v8::Handle<v8::Value> newQObject(QObject *object);
211     inline bool isQObject(v8::Handle<v8::Value>);
212     inline QObject *toQObject(v8::Handle<v8::Value>);
213
214     // Return a JS string for the given QString \a string
215     inline v8::Local<v8::String> toString(const QString &string);
216
217     // Create a new value type object
218     inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
219     inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
220
221     // Create a new QVariant object.  This doesn't examine the type of the variant, but always returns
222     // a QVariant wrapper
223     inline v8::Handle<v8::Value> newQVariant(const QVariant &);
224
225     // Return the network access manager for this engine.  By default this returns the network
226     // access manager of the QDeclarativeEngine.  It is overridden in the case of a threaded v8
227     // instance (like in WorkerScript).
228     virtual QNetworkAccessManager *networkAccessManager();
229
230     // Return the list of illegal id names (the names of the properties on the global object)
231     const QSet<QString> &illegalNames() const;
232
233 private:
234     QDeclarativeEngine *m_engine;
235     v8::Persistent<v8::Context> m_context;
236
237     QV8StringWrapper m_stringWrapper;
238     QV8ContextWrapper m_contextWrapper;
239     QV8QObjectWrapper m_qobjectWrapper;
240     QV8TypeWrapper m_typeWrapper;
241     QV8ListWrapper m_listWrapper;
242     QV8VariantWrapper m_variantWrapper;
243     QV8ValueTypeWrapper m_valueTypeWrapper;
244
245     v8::Persistent<v8::Function> m_getOwnPropertyNames;
246
247     void *m_xmlHttpRequestData;
248     void *m_sqlDatabaseData;
249
250     QSet<QString> m_illegalNames;
251
252     QVariant toBasicVariant(v8::Handle<v8::Value>);
253
254     void initializeGlobal(v8::Handle<v8::Object>);
255     void freezeGlobal();
256
257     static v8::Handle<v8::Value> print(const v8::Arguments &args);
258     static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
259     static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
260     static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
261     static v8::Handle<v8::Value> rect(const v8::Arguments &args);
262     static v8::Handle<v8::Value> point(const v8::Arguments &args);
263     static v8::Handle<v8::Value> size(const v8::Arguments &args);
264     static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
265     static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
266     static v8::Handle<v8::Value> darker(const v8::Arguments &args);
267     static v8::Handle<v8::Value> tint(const v8::Arguments &args);
268     static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
269     static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
270     static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
271     static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
272     static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
273     static v8::Handle<v8::Value> md5(const v8::Arguments &args);
274     static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
275     static v8::Handle<v8::Value> atob(const v8::Arguments &args);
276     static v8::Handle<v8::Value> quit(const v8::Arguments &args);
277     static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
278     static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
279     static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
280
281     double qtDateTimeToJsDate(const QDateTime &dt);
282     QDateTime qtDateTimeFromJsDate(double jsDate);
283 };
284
285 QString QV8Engine::toString(v8::Handle<v8::Value> string)
286 {
287     return m_stringWrapper.toString(string->ToString());
288 }
289
290 QString QV8Engine::toString(v8::Handle<v8::String> string)
291 {
292     return m_stringWrapper.toString(string);
293 }
294
295 bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
296 {
297     return m_variantWrapper.isVariant(value);
298 }
299
300 v8::Local<v8::Object> QV8Engine::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
301 {
302     return m_contextWrapper.qmlScope(ctxt, scope);
303 }
304
305 bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
306 {
307     return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
308 }
309
310 QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
311 {
312     return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
313 }
314
315 v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
316 {
317     return m_qobjectWrapper.newQObject(object);
318 }
319
320 v8::Local<v8::String> QV8Engine::toString(const QString &string)
321 {
322     return m_stringWrapper.toString(string);
323 }
324
325 v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QDeclarativeValueType *type)
326 {
327     return m_valueTypeWrapper.newValueType(object, property, type);
328 }
329
330 v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QDeclarativeValueType *type)
331 {
332     return m_valueTypeWrapper.newValueType(value, type);
333 }
334
335 // XXX perf?
336 bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
337 {
338     uint16_t buffer[2];
339     int written = string->Write(buffer, 0, 1);
340     if (written == 0) return false;
341     uint16_t c = buffer[0];
342     return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
343            ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
344 }
345
346 QT_END_NAMESPACE
347
348 #endif // QDECLARATIVEV8ENGINE_P_H