Allow extensions to register with the QV8Engine
authorAaron Kennedy <aaron.kennedy@nokia.com>
Thu, 9 Jun 2011 02:34:59 +0000 (12:34 +1000)
committerAaron Kennedy <aaron.kennedy@nokia.com>
Thu, 9 Jun 2011 02:34:59 +0000 (12:34 +1000)
This means we don't have to modify the QV8Engine class every time
a new JS API is added.

src/declarative/qml/v8/qv8engine.cpp
src/declarative/qml/v8/qv8engine_p.h

index 530c9b0..c7f05f0 100644 (file)
@@ -73,6 +73,10 @@ QV8Engine::QV8Engine()
 
 QV8Engine::~QV8Engine()
 {
+    for (int ii = 0; ii < m_extensionData.count(); ++ii) 
+        delete m_extensionData[ii];
+    m_extensionData.clear();
+
     qt_rem_qmlsqldatabase(this, m_sqlDatabaseData); 
     m_sqlDatabaseData = 0;
     qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData); 
@@ -149,6 +153,7 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
             case QV8ObjectResource::DOMNodeType:
             case QV8ObjectResource::SQLDatabaseType:
             case QV8ObjectResource::ListModelType:
+            case QV8ObjectResource::Context2DType:
                 return QVariant();
             case QV8ObjectResource::QObjectType:
                 return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
@@ -651,6 +656,34 @@ void QV8Engine::releaseHandle(void *handle)
 }
 #endif
 
+struct QV8EngineRegistrationData
+{
+    QMutex mutex;
+    int extensionCount;
+};
+Q_GLOBAL_STATIC(QV8EngineRegistrationData, registrationData);
+
+QMutex *QV8Engine::registrationMutex()
+{
+    return &registrationData()->mutex;
+}
+
+int QV8Engine::registerExtension()
+{
+    return registrationData()->extensionCount++;
+}
+
+void QV8Engine::setExtensionData(int index, Deletable *data)
+{
+    if (m_extensionData.count() <= index) 
+        m_extensionData.resize(index);
+
+    if (m_extensionData.at(index)) 
+        delete m_extensionData.at(index);
+
+    m_extensionData[index] = data;
+}
+
 v8::Handle<v8::Value> QV8Engine::gc(const v8::Arguments &args)
 {
     gc();
index ee0b911..1843460 100644 (file)
@@ -56,6 +56,7 @@
 #include <QtCore/qglobal.h>
 #include <QtCore/qvariant.h>
 #include <QtCore/qset.h>
+#include <QtCore/qmutex.h>
 #include <private/qv8_p.h>
 
 #include <private/qdeclarativepropertycache_p.h>
@@ -85,11 +86,33 @@ private:
 
 #define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
 #define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
-// XXX Are we mean to return a value here, or is an empty handle ok?
 #define V8THROW_ERROR(string) { \
     v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
     return v8::Handle<v8::Value>(); \
 }
+#define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data()));
+#define V8THROW_ERROR_SETTER(string) { \
+    v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
+    return; \
+}
+
+#define V8_DEFINE_EXTENSION(dataclass, datafunction) \
+    inline dataclass *datafunction(QV8Engine *engine) \
+    { \
+        static int extensionId = -1; \
+        if (extensionId == -1) { \
+            QV8Engine::registrationMutex()->lock(); \
+            if (extensionId == -1) \
+                extensionId = QV8Engine::registerExtension(); \
+            QV8Engine::registrationMutex()->unlock(); \
+        } \
+        dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
+        if (!rv) { \
+            rv = new dataclass(engine); \
+            engine->setExtensionData(extensionId, rv); \
+        } \
+        return rv; \
+    } \
 
 class QV8Engine;
 class QV8ObjectResource : public v8::Object::ExternalResource
@@ -98,7 +121,7 @@ public:
     QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
     enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, 
                         ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
-                        ListModelType };
+                        ListModelType, Context2DType };
     virtual ResourceType resourceType() const = 0;
 
     QV8Engine *engine;
@@ -253,6 +276,12 @@ public:
     static void releaseHandle(void *);
 #endif
 
+    static QMutex *registrationMutex();
+    static int registerExtension();
+
+    inline Deletable *extensionData(int) const;
+    void setExtensionData(int, Deletable *);
+
 private:
     QDeclarativeEngine *m_engine;
     v8::Persistent<v8::Context> m_context;
@@ -269,6 +298,8 @@ private:
 
     void *m_xmlHttpRequestData;
     void *m_sqlDatabaseData;
+
+    QVector<Deletable *> m_extensionData;
     Deletable *m_listModelData;
 
     QSet<QString> m_illegalNames;
@@ -404,6 +435,14 @@ bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
            ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
 }
 
+QV8Engine::Deletable *QV8Engine::extensionData(int index) const
+{
+    if (index < m_extensionData.count())
+        return m_extensionData[index];
+    else
+        return 0;
+}
+
 QT_END_NAMESPACE
 
 #endif // QDECLARATIVEV8ENGINE_P_H