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