aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-06-09 12:34:59 +1000
committerAaron Kennedy <aaron.kennedy@nokia.com>2011-06-09 12:34:59 +1000
commitd9d952d3c0475b1e7f7b8df2b062f85f24387aca (patch)
treeacaca0f2bfb6a1d20110f8a952e18c6f6e04f3f4
parent0ad1d429820aae65d1b69813bf354455de3a1669 (diff)
Allow extensions to register with the QV8Engine
This means we don't have to modify the QV8Engine class every time a new JS API is added.
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp33
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h43
2 files changed, 74 insertions, 2 deletions
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
index 530c9b0ef3..c7f05f0473 100644
--- a/src/declarative/qml/v8/qv8engine.cpp
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -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();
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
index ee0b9115a3..1843460f76 100644
--- a/src/declarative/qml/v8/qv8engine_p.h
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -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