Improve QJSValueIterator implementation.
[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 <QtCore/qmutex.h>
60 #include <QtCore/qstack.h>
61 #include <QtCore/qstringlist.h>
62
63 #include <private/qv8_p.h>
64 #include <qjsengine.h>
65 #include <qjsvalue.h>
66 #include "qscriptoriginalglobalobject_p.h"
67 #include "qscripttools_p.h"
68
69 #include <private/qdeclarativepropertycache_p.h>
70
71 #include "qv8contextwrapper_p.h"
72 #include "qv8qobjectwrapper_p.h"
73 #include "qv8stringwrapper_p.h"
74 #include "qv8typewrapper_p.h"
75 #include "qv8listwrapper_p.h"
76 #include "qv8variantwrapper_p.h"
77 #include "qv8valuetypewrapper_p.h"
78
79 QT_BEGIN_NAMESPACE
80
81
82 // Uncomment the following line to enable global handle debugging.  When enabled, all the persistent
83 // handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
84 // with qPersistentDispose() are tracked.  If you try and do something illegal, like double disposing
85 // a handle, qFatal() is called.
86 // #define QML_GLOBAL_HANDLE_DEBUGGING
87
88 #define V8_RESOURCE_TYPE(resourcetype) \
89 public: \
90     enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
91     virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
92 private: 
93
94 #define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
95 #define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
96 #define V8THROW_ERROR(string) { \
97     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
98     return v8::Handle<v8::Value>(); \
99 }
100 #define V8THROW_TYPE(string) { \
101     v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \
102     return v8::Handle<v8::Value>(); \
103 }
104 #define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data()));
105 #define V8THROW_ERROR_SETTER(string) { \
106     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
107     return; \
108 }
109
110 #define V8_DEFINE_EXTENSION(dataclass, datafunction) \
111     inline dataclass *datafunction(QV8Engine *engine) \
112     { \
113         static int extensionId = -1; \
114         if (extensionId == -1) { \
115             QV8Engine::registrationMutex()->lock(); \
116             if (extensionId == -1) \
117                 extensionId = QV8Engine::registerExtension(); \
118             QV8Engine::registrationMutex()->unlock(); \
119         } \
120         dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
121         if (!rv) { \
122             rv = new dataclass(engine); \
123             engine->setExtensionData(extensionId, rv); \
124         } \
125         return rv; \
126     } \
127
128 class QV8Engine;
129 class QV8ObjectResource : public v8::Object::ExternalResource
130 {
131 public:
132     QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
133     enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, 
134                         ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
135                         ListModelType, Context2DType, ParticleDataType };
136     virtual ResourceType resourceType() const = 0;
137
138     QV8Engine *engine;
139 };
140
141 template<class T>
142 inline T *v8_resource_cast(v8::Handle<v8::Object> object) {
143     QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
144     return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
145 }
146
147 template<class T>
148 inline T *v8_resource_check(v8::Handle<v8::Object> object) {
149     T *resource = static_cast<T *>(object->GetExternalResource());
150     Q_ASSERT(resource && resource->resourceType() == (quint32)T::V8ResourceType);
151     return resource;
152 }
153
154 // Used to allow a QObject method take and return raw V8 handles without having to expose
155 // v8 in the public API.
156 // Use like this:
157 //     class MyClass : public QObject {
158 //         Q_OBJECT
159 //         ...
160 //         Q_INVOKABLE void myMethod(QDeclarativeV8Function*);
161 //     };
162 // The QDeclarativeV8Function - and consequently the arguments and return value - only remains 
163 // valid during the call.  If the return value isn't set within myMethod(), the will return
164 // undefined.
165 class QV8Engine;
166 class QDeclarativeV8Function
167 {
168 public:
169     int Length() const { return _ac; }
170     v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
171     QDeclarativeContextData *context() { return _c; }
172     v8::Handle<v8::Object> qmlGlobal() { return *_g; }
173     void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
174     QV8Engine *engine() const { return _e; }
175 private:
176     friend class QV8QObjectWrapper;
177     QDeclarativeV8Function();
178     QDeclarativeV8Function(const QDeclarativeV8Function &);
179     QDeclarativeV8Function &operator=(const QDeclarativeV8Function &);
180
181     QDeclarativeV8Function(int length, v8::Handle<v8::Object> &args, 
182                            v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
183                            QDeclarativeContextData *c, QV8Engine *e)
184     : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
185
186     int _ac;
187     v8::Handle<v8::Object> *_a;
188     v8::Handle<v8::Value> *_r;
189     v8::Handle<v8::Object> *_g;
190     QDeclarativeContextData *_c;
191     QV8Engine *_e;
192 };
193
194 class QDeclarativeV8Handle
195 {
196 public:
197     QDeclarativeV8Handle() : d(0) {}
198     QDeclarativeV8Handle(const QDeclarativeV8Handle &other) : d(other.d) {}
199     QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; }
200
201     static QDeclarativeV8Handle fromHandle(v8::Handle<v8::Value> h) {
202         return QDeclarativeV8Handle(*h);
203     }
204     v8::Handle<v8::Value> toHandle() const {
205         return v8::Handle<v8::Value>((v8::Value *)d);
206     }
207 private:
208     QDeclarativeV8Handle(void *d) : d(d) {}
209     void *d;
210 };
211
212 class QObject;
213 class QDeclarativeEngine;
214 class QDeclarativeValueType;
215 class QNetworkAccessManager;
216 class QDeclarativeContextData;
217 class QJSValueIteratorPrivate;
218
219 class Q_DECLARATIVE_EXPORT QV8Engine
220 {
221 public:
222     static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
223     static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
224
225     QV8Engine(QJSEngine* qq,QJSEngine::ContextOwnership ownership = QJSEngine::CreateNewContext);
226     ~QV8Engine();
227
228     struct Deletable {
229         virtual ~Deletable() {}
230     };
231
232     class Exception
233     {
234         typedef QPair<v8::Persistent<v8::Value>, v8::Persistent<v8::Message> > ValueMessagePair;
235
236         v8::Persistent<v8::Value> m_value;
237         v8::Persistent<v8::Message> m_message;
238         QStack<ValueMessagePair> m_stack;
239
240         Q_DISABLE_COPY(Exception)
241     public:
242         inline Exception();
243         inline ~Exception();
244         inline void set(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message);
245         inline void clear();
246         inline operator bool() const;
247         inline operator v8::Handle<v8::Value>() const;
248         inline int lineNumber() const;
249         inline QStringList backtrace() const;
250
251         inline void push();
252         inline void pop();
253     };
254
255     void initDeclarativeGlobalObject();
256     void setEngine(QDeclarativeEngine *engine);
257     QDeclarativeEngine *engine() { return m_engine; }
258     v8::Local<v8::Object> global() { return m_context->Global(); }
259     v8::Handle<v8::Context> context() const { return m_context; }
260
261     inline void registerValue(QJSValuePrivate *data);
262     inline void unregisterValue(QJSValuePrivate *data);
263     inline void invalidateAllValues();
264
265     inline void registerValueIterator(QJSValueIteratorPrivate *data);
266     inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
267     inline void invalidateAllIterators();
268
269     QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
270     QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
271     QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
272     QV8ListWrapper *listWrapper() { return &m_listWrapper; }
273     QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
274     QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
275
276     void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
277     void *sqlDatabaseData() { return m_sqlDatabaseData; }
278
279     Deletable *listModelData() { return m_listModelData; }
280     void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
281
282     QDeclarativeContextData *callingContext();
283
284     v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
285     inline QJSValue::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
286     void freezeObject(v8::Handle<v8::Value>);
287
288     inline QString toString(v8::Handle<v8::Value> string);
289     inline QString toString(v8::Handle<v8::String> string);
290     static QString toStringStatic(v8::Handle<v8::Value>);
291     static QString toStringStatic(v8::Handle<v8::String>);
292     static inline bool startsWithUpper(v8::Handle<v8::String>);
293
294     QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
295     v8::Handle<v8::Value> fromVariant(const QVariant &);
296     inline bool isVariant(v8::Handle<v8::Value>);
297
298     // Compile \a source (from \a fileName at \a lineNumber) in QML mode
299     v8::Local<v8::Script> qmlModeCompile(const QString &source, 
300                                          const QString &fileName = QString(), 
301                                          int lineNumber = 1);
302
303     // Return the QML global "scope" object for the \a ctxt context and \a scope object.
304     inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
305
306     QScriptPassPointer<QJSValuePrivate> newRegExp(const QRegExp &regexp);
307     QScriptPassPointer<QJSValuePrivate> newRegExp(const QString &pattern, const QString &flags);
308
309     // Return a JS wrapper for the given QObject \a object
310     inline v8::Handle<v8::Value> newQObject(QObject *object);
311     inline bool isQObject(v8::Handle<v8::Value>);
312     inline QObject *toQObject(v8::Handle<v8::Value>);
313
314     // Return a JS string for the given QString \a string
315     inline v8::Local<v8::String> toString(const QString &string);
316
317     // Create a new value type object
318     inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
319     inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
320
321     // Create a new QVariant object.  This doesn't examine the type of the variant, but always returns
322     // a QVariant wrapper
323     inline v8::Handle<v8::Value> newQVariant(const QVariant &);
324
325     // Return the network access manager for this engine.  By default this returns the network
326     // access manager of the QDeclarativeEngine.  It is overridden in the case of a threaded v8
327     // instance (like in WorkerScript).
328     virtual QNetworkAccessManager *networkAccessManager();
329
330     // Return the list of illegal id names (the names of the properties on the global object)
331     const QSet<QString> &illegalNames() const;
332
333     inline void collectGarbage() { gc(); }
334     static void gc();
335
336     void clearExceptions();
337     void setException(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message = v8::Handle<v8::Message>());
338     v8::Handle<v8::Value> throwException(v8::Handle<v8::Value> value);
339     bool hasUncaughtException() const;
340     int uncaughtExceptionLineNumber() const;
341     QStringList uncaughtExceptionBacktrace() const;
342     v8::Handle<v8::Value> uncaughtException() const;
343     void saveException();
344     void restoreException();
345
346 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
347     // Used for handle debugging
348     static void registerHandle(void *);
349     static void releaseHandle(void *);
350 #endif
351
352     static QMutex *registrationMutex();
353     static int registerExtension();
354
355     inline Deletable *extensionData(int) const;
356     void setExtensionData(int, Deletable *);
357
358     inline v8::Handle<v8::Value> makeJSValue(bool value);
359     inline v8::Handle<v8::Value> makeJSValue(int value);
360     inline v8::Handle<v8::Value> makeJSValue(uint value);
361     inline v8::Handle<v8::Value> makeJSValue(double value);
362     inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
363     inline v8::Handle<v8::Value> makeJSValue(const QString& value);
364
365     inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
366     QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
367
368     QScriptPassPointer<QJSValuePrivate> newArray(uint length);
369     v8::Handle<v8::Object> newVariant(const QVariant &variant);
370     QScriptPassPointer<QJSValuePrivate> newVariant(QJSValuePrivate* value, const QVariant &variant);
371
372     v8::Handle<v8::Array> variantListToJS(const QVariantList &lst);
373     QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray);
374
375     v8::Handle<v8::Object> variantMapToJS(const QVariantMap &vmap);
376     QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject);
377
378     v8::Handle<v8::Value> variantToJS(const QVariant &value);
379     QVariant variantFromJS(v8::Handle<v8::Value> value);
380
381     v8::Handle<v8::Value> metaTypeToJS(int type, const void *data);
382     bool metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data);
383
384     bool convertToNativeQObject(v8::Handle<v8::Value> value,
385                                 const QByteArray &targetType,
386                                 void **result);
387
388     QVariant variantValue(v8::Handle<v8::Value> value);
389
390     QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const;
391
392     void emitSignalHandlerException();
393
394     QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
395     QSet<int> visitedConversionObjects;
396 protected:
397     QJSEngine* q;
398     QDeclarativeEngine *m_engine;
399     bool m_ownsV8Context;
400     v8::Persistent<v8::Context> m_context;
401     QScriptOriginalGlobalObject m_originalGlobalObject;
402
403     QV8StringWrapper m_stringWrapper;
404     QV8ContextWrapper m_contextWrapper;
405     QV8QObjectWrapper m_qobjectWrapper;
406     QV8TypeWrapper m_typeWrapper;
407     QV8ListWrapper m_listWrapper;
408     QV8VariantWrapper m_variantWrapper;
409     QV8ValueTypeWrapper m_valueTypeWrapper;
410
411     v8::Persistent<v8::Function> m_getOwnPropertyNames;
412     v8::Persistent<v8::Function> m_freezeObject;
413
414     void *m_xmlHttpRequestData;
415     void *m_sqlDatabaseData;
416
417     QVector<Deletable *> m_extensionData;
418     Deletable *m_listModelData;
419
420     QSet<QString> m_illegalNames;
421
422     Exception m_exception;
423
424     QVariant toBasicVariant(v8::Handle<v8::Value>);
425
426     void initializeGlobal(v8::Handle<v8::Object>);
427
428     static v8::Handle<v8::Value> gc(const v8::Arguments &args);
429     static v8::Handle<v8::Value> print(const v8::Arguments &args);
430     static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
431     static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
432     static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
433     static v8::Handle<v8::Value> rect(const v8::Arguments &args);
434     static v8::Handle<v8::Value> point(const v8::Arguments &args);
435     static v8::Handle<v8::Value> size(const v8::Arguments &args);
436     static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
437     static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
438     static v8::Handle<v8::Value> darker(const v8::Arguments &args);
439     static v8::Handle<v8::Value> tint(const v8::Arguments &args);
440     static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
441     static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
442     static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
443     static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
444     static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
445     static v8::Handle<v8::Value> md5(const v8::Arguments &args);
446     static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
447     static v8::Handle<v8::Value> atob(const v8::Arguments &args);
448     static v8::Handle<v8::Value> quit(const v8::Arguments &args);
449     static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
450     static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
451     static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
452     static v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args);
453     static v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args);
454     static v8::Handle<v8::Value> qsTr(const v8::Arguments &args);
455     static v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args);
456     static v8::Handle<v8::Value> qsTrId(const v8::Arguments &args);
457     static v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args);
458     static v8::Handle<v8::Value> stringArg(const v8::Arguments &args);
459
460     double qtDateTimeToJsDate(const QDateTime &dt);
461     QDateTime qtDateTimeFromJsDate(double jsDate);
462 private:
463     QScriptBagContainer<QJSValuePrivate> m_values;
464     QScriptBagContainer<QJSValueIteratorPrivate> m_valueIterators;
465
466     Q_DISABLE_COPY(QV8Engine)
467 };
468
469 // Allocate a new Persistent handle.  *ALL* persistent handles in QML must be allocated
470 // using this method.
471 template<class T>
472 v8::Persistent<T> qPersistentNew(v8::Handle<T> that)
473 {
474     v8::Persistent<T> rv = v8::Persistent<T>::New(that);
475 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
476     QV8Engine::registerHandle(*rv);
477 #endif
478     return rv;
479 }
480
481 // Register a Persistent handle that was returned to you by V8 (such as by
482 // v8::Context::New). This allows us to do handle tracking on these handles too.
483 template<class T>
484 void qPersistentRegister(v8::Persistent<T> handle)
485 {
486 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
487     QV8Engine::registerHandle(*handle);
488 #else
489     Q_UNUSED(handle);
490 #endif
491 }
492
493 // Dispose and clear a persistent handle.  *ALL* persistent handles in QML must be
494 // disposed using this method.
495 template<class T>
496 void qPersistentDispose(v8::Persistent<T> &that)
497 {
498 #ifdef QML_GLOBAL_HANDLE_DEBUGGING
499     QV8Engine::releaseHandle(*that);
500 #endif
501     that.Dispose();
502     that.Clear();
503 }
504
505 QString QV8Engine::toString(v8::Handle<v8::Value> string)
506 {
507     return m_stringWrapper.toString(string->ToString());
508 }
509
510 QString QV8Engine::toString(v8::Handle<v8::String> string)
511 {
512     return m_stringWrapper.toString(string);
513 }
514
515 bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
516 {
517     return m_variantWrapper.isVariant(value);
518 }
519
520 v8::Local<v8::Object> QV8Engine::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
521 {
522     return m_contextWrapper.qmlScope(ctxt, scope);
523 }
524
525 bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
526 {
527     return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
528 }
529
530 QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
531 {
532     return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
533 }
534
535 v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
536 {
537     return m_qobjectWrapper.newQObject(object);
538 }
539
540 v8::Local<v8::String> QV8Engine::toString(const QString &string)
541 {
542     return m_stringWrapper.toString(string);
543 }
544
545 v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QDeclarativeValueType *type)
546 {
547     return m_valueTypeWrapper.newValueType(object, property, type);
548 }
549
550 v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QDeclarativeValueType *type)
551 {
552     return m_valueTypeWrapper.newValueType(value, type);
553 }
554
555 // XXX Can this be made more optimal?  It is called prior to resolving each and every 
556 // unqualified name in QV8ContextWrapper.
557 bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
558 {
559     uint16_t c = string->GetCharacter(0);
560     return (c >= 'A' && c <= 'Z') || 
561            (c > 127 && QChar::category(c) == QChar::Letter_Uppercase);
562 }
563
564 QV8Engine::Deletable *QV8Engine::extensionData(int index) const
565 {
566     if (index < m_extensionData.count())
567         return m_extensionData[index];
568     else
569         return 0;
570 }
571
572 QT_END_NAMESPACE
573
574 #endif // QDECLARATIVEV8ENGINE_P_H