Change copyrights from Nokia to Digia
[profile/ivi/qtdeclarative.git] / src / qml / qml / v8 / qv8engine_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QQMLV8ENGINE_P_H
43 #define QQMLV8ENGINE_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 <QtCore/qmutex.h>
60 #include <QtCore/qstack.h>
61 #include <QtCore/qstringlist.h>
62 #include <QtCore/QElapsedTimer>
63 #include <QtCore/QThreadStorage>
64
65 #include <private/qv8_p.h>
66 #include <qjsengine.h>
67 #include <qjsvalue.h>
68 #include "qjsvalue_p.h"
69 #include "qjsvalueiterator_p.h"
70 #include "qscriptoriginalglobalobject_p.h"
71 #include "qscripttools_p.h"
72
73 #include <private/qqmlpropertycache_p.h>
74
75 #include "qv8objectresource_p.h"
76 #include "qv8contextwrapper_p.h"
77 #include "qv8qobjectwrapper_p.h"
78 #include "qv8stringwrapper_p.h"
79 #include "qv8typewrapper_p.h"
80 #include "qv8listwrapper_p.h"
81 #include "qv8variantwrapper_p.h"
82 #include "qv8valuetypewrapper_p.h"
83 #include "qv8sequencewrapper_p.h"
84 #include "qv8jsonwrapper_p.h"
85
86 namespace v8 {
87
88 // Needed for V8ObjectSet
89 inline uint qHash(const v8::Handle<v8::Object> &object, uint seed)
90 {
91     return (object->GetIdentityHash() ^ seed);
92 }
93
94 }
95
96 QT_BEGIN_NAMESPACE
97
98
99 // Uncomment the following line to enable global handle debugging.  When enabled, all the persistent
100 // handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
101 // with qPersistentDispose() are tracked.  If you try and do something illegal, like double disposing
102 // a handle, qFatal() is called.
103 // #define QML_GLOBAL_HANDLE_DEBUGGING
104
105 #define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
106 #define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
107 #define V8THROW_ERROR(string) { \
108     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
109     return v8::Handle<v8::Value>(); \
110 }
111 #define V8THROW_TYPE(string) { \
112     v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \
113     return v8::Handle<v8::Value>(); \
114 }
115 #define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data()));
116 #define V8THROW_ERROR_SETTER(string) { \
117     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
118     return; \
119 }
120
121 #define V8ASSERT_TYPE(condition, string) \
122     if (!(condition)) { \
123         v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \
124         return v8::Handle<v8::Value>(); \
125     }
126 #define V8ASSERT_TYPE_SETTER(condition, string) \
127     if (!(condition)) { \
128         v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \
129         return; \
130     }
131
132 #define V8_DEFINE_EXTENSION(dataclass, datafunction) \
133     static inline dataclass *datafunction(QV8Engine *engine) \
134     { \
135         static int extensionId = -1; \
136         if (extensionId == -1) { \
137             QV8Engine::registrationMutex()->lock(); \
138             if (extensionId == -1) \
139                 extensionId = QV8Engine::registerExtension(); \
140             QV8Engine::registrationMutex()->unlock(); \
141         } \
142         dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
143         if (!rv) { \
144             rv = new dataclass(engine); \
145             engine->setExtensionData(extensionId, rv); \
146         } \
147         return rv; \
148     } \
149
150 template<class T>
151 inline T *v8_resource_cast(v8::Handle<v8::Object> object) {
152     QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
153     return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
154 }
155
156 template<class T>
157 inline T *v8_resource_check(v8::Handle<v8::Object> object) {
158     T *resource = static_cast<T *>(object->GetExternalResource());
159     Q_ASSERT(resource && resource->resourceType() == (quint32)T::V8ResourceType);
160     return resource;
161 }
162
163 // Used to allow a QObject method take and return raw V8 handles without having to expose
164 // v8 in the public API.
165 // Use like this:
166 //     class MyClass : public QObject {
167 //         Q_OBJECT
168 //         ...
169 //         Q_INVOKABLE void myMethod(QQmlV8Function*);
170 //     };
171 // The QQmlV8Function - and consequently the arguments and return value - only remains 
172 // valid during the call.  If the return value isn't set within myMethod(), the will return
173 // undefined.
174 class QV8Engine;
175 class QQmlV8Function
176 {
177 public:
178     int Length() const { return _ac; }
179     v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
180     QQmlContextData *context() { return _c; }
181     v8::Handle<v8::Object> qmlGlobal() { return *_g; }
182     void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
183     QV8Engine *engine() const { return _e; }
184 private:
185     friend class QV8QObjectWrapper;
186     QQmlV8Function();
187     QQmlV8Function(const QQmlV8Function &);
188     QQmlV8Function &operator=(const QQmlV8Function &);
189
190     QQmlV8Function(int length, v8::Handle<v8::Object> &args, 
191                            v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
192                            QQmlContextData *c, QV8Engine *e)
193     : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
194
195     int _ac;
196     v8::Handle<v8::Object> *_a;
197     v8::Handle<v8::Value> *_r;
198     v8::Handle<v8::Object> *_g;
199     QQmlContextData *_c;
200     QV8Engine *_e;
201 };
202
203 class QQmlV8Handle
204 {
205 public:
206     QQmlV8Handle() : d(0) {}
207     QQmlV8Handle(const QQmlV8Handle &other) : d(other.d) {}
208     QQmlV8Handle &operator=(const QQmlV8Handle &other) { d = other.d; return *this; }
209
210     static QQmlV8Handle fromHandle(v8::Handle<v8::Value> h) {
211         return QQmlV8Handle(*h);
212     }
213     v8::Handle<v8::Value> toHandle() const {
214         return v8::Handle<v8::Value>((v8::Value *)d);
215     }
216 private:
217     QQmlV8Handle(void *d) : d(d) {}
218     void *d;
219 };
220
221 class QObject;
222 class QQmlEngine;
223 class QQmlValueType;
224 class QNetworkAccessManager;
225 class QQmlContextData;
226
227 class Q_AUTOTEST_EXPORT QV8GCCallback
228 {
229 private:
230     class ThreadData;
231 public:
232     static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags);
233     static void registerGcPrologueCallback();
234
235     class Q_AUTOTEST_EXPORT Node {
236     public:
237         typedef void (*PrologueCallback)(Node *node);
238         Node(PrologueCallback callback);
239         ~Node();
240
241         QIntrusiveListNode node;
242         PrologueCallback prologueCallback;
243     };
244
245     static void addGcCallbackNode(Node *node);
246 };
247
248 class Q_QML_PRIVATE_EXPORT QV8Engine
249 {
250     typedef QSet<v8::Handle<v8::Object> > V8ObjectSet;
251 public:
252     static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
253     static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
254
255     enum ContextOwnership {
256         AdoptCurrentContext,
257         CreateNewContext
258     };
259     QV8Engine(QJSEngine* qq, ContextOwnership ownership = CreateNewContext);
260     virtual ~QV8Engine();
261
262     // This enum should be in sync with QQmlEngine::ObjectOwnership
263     enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
264
265     struct Deletable {
266         virtual ~Deletable() {}
267     };
268
269     void initQmlGlobalObject();
270     void setEngine(QQmlEngine *engine);
271     QQmlEngine *engine() { return m_engine; }
272     v8::Local<v8::Object> global() { return m_context->Global(); }
273     v8::Handle<v8::Context> context() const { return m_context; }
274
275     inline void registerValue(QJSValuePrivate *data);
276     inline void unregisterValue(QJSValuePrivate *data);
277     inline void invalidateAllValues();
278
279     inline void registerValueIterator(QJSValueIteratorPrivate *data);
280     inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
281     inline void invalidateAllIterators();
282
283     QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
284     QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
285     QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
286     QV8ListWrapper *listWrapper() { return &m_listWrapper; }
287     QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
288     QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
289     QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; }
290
291     void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
292
293     Deletable *listModelData() { return m_listModelData; }
294     void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
295
296     QQmlContextData *callingContext();
297
298     v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
299     inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
300     void freezeObject(v8::Handle<v8::Value>);
301
302     inline QString toString(v8::Handle<v8::Value> string);
303     inline QString toString(v8::Handle<v8::String> string);
304     static QString toStringStatic(v8::Handle<v8::Value>);
305     static QString toStringStatic(v8::Handle<v8::String>);
306     static inline bool startsWithUpper(v8::Handle<v8::String>);
307
308     QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
309     v8::Handle<v8::Value> fromVariant(const QVariant &);
310     inline bool isVariant(v8::Handle<v8::Value>);
311
312     // Compile \a source (from \a fileName at \a lineNumber) in QML mode
313     v8::Local<v8::Script> qmlModeCompile(const QString &source, 
314                                          const QString &fileName = QString(), 
315                                          quint16 lineNumber = 1);
316     v8::Local<v8::Script> qmlModeCompile(const char *source, int sourceLength = -1,
317                                          const QString &fileName = QString(),
318                                          quint16 lineNumber = 1);
319
320     // Return the QML global "scope" object for the \a ctxt context and \a scope object.
321     inline v8::Local<v8::Object> qmlScope(QQmlContextData *ctxt, QObject *scope);
322
323     // Return a JS wrapper for the given QObject \a object
324     inline v8::Handle<v8::Value> newQObject(QObject *object);
325     inline v8::Handle<v8::Value> newQObject(QObject *object, const ObjectOwnership ownership);
326     inline bool isQObject(v8::Handle<v8::Value>);
327     inline QObject *toQObject(v8::Handle<v8::Value>);
328
329     // Return a JS string for the given QString \a string
330     inline v8::Local<v8::String> toString(const QString &string);
331
332     // Create a new value type object
333     inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QQmlValueType *);
334     inline v8::Handle<v8::Value> newValueType(const QVariant &, QQmlValueType *);
335     inline bool isValueType(v8::Handle<v8::Value>) const;
336     inline QVariant toValueType(v8::Handle<v8::Value> obj);
337
338     // Create a new sequence type object
339     inline v8::Handle<v8::Value> newSequence(int sequenceType, QObject *, int coreIndex, bool *succeeded);
340
341     // Create a new QVariant object.  This doesn't examine the type of the variant, but always returns
342     // a QVariant wrapper
343     inline v8::Handle<v8::Value> newQVariant(const QVariant &);
344
345     // Return the JS string key for the "function is a binding" flag
346     inline v8::Handle<v8::String> bindingFlagKey() const;
347
348     // Return the network access manager for this engine.  By default this returns the network
349     // access manager of the QQmlEngine.  It is overridden in the case of a threaded v8
350     // instance (like in WorkerScript).
351     virtual QNetworkAccessManager *networkAccessManager();
352
353     // Return the list of illegal id names (the names of the properties on the global object)
354     const QStringHash<bool> &illegalNames() const;
355
356     inline void collectGarbage() { gc(); }
357     static void gc();
358
359     v8::Handle<v8::Value> throwException(v8::Handle<v8::Value> value);
360
361 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
362     // Used for handle debugging
363     static void registerHandle(void *);
364     static void releaseHandle(void *);
365 #endif
366
367     static QMutex *registrationMutex();
368     static int registerExtension();
369
370     inline Deletable *extensionData(int) const;
371     void setExtensionData(int, Deletable *);
372
373     inline v8::Handle<v8::Value> makeJSValue(bool value);
374     inline v8::Local<v8::Value> makeJSValue(int value);
375     inline v8::Local<v8::Value> makeJSValue(uint value);
376     inline v8::Local<v8::Value> makeJSValue(double value);
377     inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
378     inline v8::Local<v8::Value> makeJSValue(const QString &value);
379
380     inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), quint16 lineNumber = 1);
381     QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
382
383     QScriptPassPointer<QJSValuePrivate> newArray(uint length);
384     v8::Local<v8::Object> newVariant(const QVariant &variant);
385
386     v8::Local<v8::Array> variantListToJS(const QVariantList &lst);
387     inline QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray)
388     { V8ObjectSet visitedObjects; return variantListFromJS(jsArray, visitedObjects); }
389
390     v8::Local<v8::Object> variantMapToJS(const QVariantMap &vmap);
391     inline QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject)
392     { V8ObjectSet visitedObjects; return variantMapFromJS(jsObject, visitedObjects); }
393
394     v8::Handle<v8::Value> variantToJS(const QVariant &value);
395     inline QVariant variantFromJS(v8::Handle<v8::Value> value)
396     { V8ObjectSet visitedObjects; return variantFromJS(value, visitedObjects); }
397
398     v8::Handle<v8::Value> jsonValueToJS(const QJsonValue &value);
399     QJsonValue jsonValueFromJS(v8::Handle<v8::Value> value);
400     v8::Local<v8::Object> jsonObjectToJS(const QJsonObject &object);
401     QJsonObject jsonObjectFromJS(v8::Handle<v8::Value> value);
402     v8::Local<v8::Array> jsonArrayToJS(const QJsonArray &array);
403     QJsonArray jsonArrayFromJS(v8::Handle<v8::Value> value);
404
405     v8::Handle<v8::Value> metaTypeToJS(int type, const void *data);
406     bool metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data);
407
408     bool convertToNativeQObject(v8::Handle<v8::Value> value,
409                                 const QByteArray &targetType,
410                                 void **result);
411
412     QVariant &variantValue(v8::Handle<v8::Value> value);
413
414     QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const;
415
416     // used for console.time(), console.timeEnd()
417     void startTimer(const QString &timerName);
418     qint64 stopTimer(const QString &timerName, bool *wasRunning);
419
420     // used for console.count()
421     int consoleCountHelper(const QString &file, quint16 line, quint16 column);
422
423     QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
424
425     static QDateTime qtDateTimeFromJsDate(double jsDate);
426
427     void addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle);
428     void addRelationshipForGC(QObject *object, QObject *other);
429
430     static v8::Handle<v8::Value> getApplication(v8::Local<v8::String> property, const v8::AccessorInfo &info);
431     static v8::Handle<v8::Value> getInputMethod(v8::Local<v8::String> property, const v8::AccessorInfo &info);
432
433     struct ThreadData {
434         ThreadData();
435         ~ThreadData();
436         v8::Isolate* isolate;
437         bool gcPrologueCallbackRegistered;
438         QIntrusiveList<QV8GCCallback::Node, &QV8GCCallback::Node::node> gcCallbackNodes;
439     };
440
441     static bool hasThreadData();
442     static ThreadData* threadData();
443     static void ensurePerThreadIsolate();
444
445     v8::Persistent<v8::Object> m_strongReferencer;
446
447 protected:
448     QJSEngine* q;
449     QQmlEngine *m_engine;
450     bool m_ownsV8Context;
451     v8::Persistent<v8::Context> m_context;
452     QScriptOriginalGlobalObject m_originalGlobalObject;
453
454     v8::Persistent<v8::String> m_bindingFlagKey;
455
456     QV8StringWrapper m_stringWrapper;
457     QV8ContextWrapper m_contextWrapper;
458     QV8QObjectWrapper m_qobjectWrapper;
459     QV8TypeWrapper m_typeWrapper;
460     QV8ListWrapper m_listWrapper;
461     QV8VariantWrapper m_variantWrapper;
462     QV8ValueTypeWrapper m_valueTypeWrapper;
463     QV8SequenceWrapper m_sequenceWrapper;
464     QV8JsonWrapper m_jsonWrapper;
465
466     v8::Persistent<v8::Function> m_getOwnPropertyNames;
467     v8::Persistent<v8::Function> m_freezeObject;
468
469     void *m_xmlHttpRequestData;
470
471     QVector<Deletable *> m_extensionData;
472     Deletable *m_listModelData;
473
474     QStringHash<bool> m_illegalNames;
475
476     QElapsedTimer m_time;
477     QHash<QString, qint64> m_startedTimers;
478
479     QHash<QString, quint32> m_consoleCount;
480
481     QObject *m_application;
482
483     QVariant toBasicVariant(v8::Handle<v8::Value>);
484
485     void initializeGlobal(v8::Handle<v8::Object>);
486
487     double qtDateTimeToJsDate(const QDateTime &dt);
488
489 private:
490     QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray, V8ObjectSet &visitedObjects);
491     QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject, V8ObjectSet &visitedObjects);
492     QVariant variantFromJS(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects);
493
494     static v8::Persistent<v8::Object> *findOwnerAndStrength(QObject *object, bool *shouldBeStrong);
495
496     typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
497     ValueList m_values;
498     typedef QScriptIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList;
499     ValueIteratorList m_valueIterators;
500
501     Q_DISABLE_COPY(QV8Engine)
502 };
503
504 // Allocate a new Persistent handle.  *ALL* persistent handles in QML must be allocated
505 // using this method.
506 template<class T>
507 v8::Persistent<T> qPersistentNew(v8::Handle<T> that)
508 {
509     v8::Persistent<T> rv = v8::Persistent<T>::New(that);
510 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
511     QV8Engine::registerHandle(*rv);
512 #endif
513     return rv;
514 }
515
516 // Register a Persistent handle that was returned to you by V8 (such as by
517 // v8::Context::New). This allows us to do handle tracking on these handles too.
518 template<class T>
519 void qPersistentRegister(v8::Persistent<T> handle)
520 {
521 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
522     QV8Engine::registerHandle(*handle);
523 #else
524     Q_UNUSED(handle);
525 #endif
526 }
527
528 // Dispose and clear a persistent handle.  *ALL* persistent handles in QML must be
529 // disposed using this method.
530 template<class T>
531 void qPersistentDispose(v8::Persistent<T> &that)
532 {
533 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
534     QV8Engine::releaseHandle(*that);
535 #endif
536     that.Dispose();
537     that.Clear();
538 }
539
540 QString QV8Engine::toString(v8::Handle<v8::Value> string)
541 {
542     return m_stringWrapper.toString(string->ToString());
543 }
544
545 QString QV8Engine::toString(v8::Handle<v8::String> string)
546 {
547     return m_stringWrapper.toString(string);
548 }
549
550 bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
551 {
552     return m_variantWrapper.isVariant(value);
553 }
554
555 v8::Local<v8::Object> QV8Engine::qmlScope(QQmlContextData *ctxt, QObject *scope)
556 {
557     return m_contextWrapper.qmlScope(ctxt, scope);
558 }
559
560 bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
561 {
562     return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
563 }
564
565 QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
566 {
567     return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
568 }
569
570 v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
571 {
572     return m_qobjectWrapper.newQObject(object);
573 }
574
575 v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership)
576 {
577     if (!object)
578         return v8::Null();
579
580     v8::Handle<v8::Value> result = newQObject(object);
581     QQmlData *ddata = QQmlData::get(object, true);
582     if (ownership == JavaScriptOwnership && ddata) {
583         ddata->indestructible = false;
584         ddata->explicitIndestructibleSet = true;
585     }
586     return result;
587 }
588
589 v8::Local<v8::String> QV8Engine::toString(const QString &string)
590 {
591     return m_stringWrapper.toString(string);
592 }
593
594 v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QQmlValueType *type)
595 {
596     return m_valueTypeWrapper.newValueType(object, property, type);
597 }
598
599 v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QQmlValueType *type)
600 {
601     return m_valueTypeWrapper.newValueType(value, type);
602 }
603
604 bool QV8Engine::isValueType(v8::Handle<v8::Value> obj) const
605 {
606     return obj->IsObject()?m_valueTypeWrapper.isValueType(v8::Handle<v8::Object>::Cast(obj)):false;
607 }
608
609 QVariant QV8Engine::toValueType(v8::Handle<v8::Value> obj)
610 {
611     return obj->IsObject()?m_valueTypeWrapper.toVariant(v8::Handle<v8::Object>::Cast(obj)):QVariant();
612 }
613
614 v8::Handle<v8::Value> QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded)
615 {
616     return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded);
617 }
618
619 v8::Handle<v8::String> QV8Engine::bindingFlagKey() const
620 {
621     return m_bindingFlagKey;
622 }
623
624 // XXX Can this be made more optimal?  It is called prior to resolving each and every 
625 // unqualified name in QV8ContextWrapper.
626 bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
627 {
628     uint16_t c = string->GetCharacter(0);
629     return (c >= 'A' && c <= 'Z') || 
630            (c > 127 && QChar::category(c) == QChar::Letter_Uppercase);
631 }
632
633 QV8Engine::Deletable *QV8Engine::extensionData(int index) const
634 {
635     if (index < m_extensionData.count())
636         return m_extensionData[index];
637     else
638         return 0;
639 }
640
641 QT_END_NAMESPACE
642
643 #endif // QQMLV8ENGINE_P_H