aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-06-03 14:41:17 +0200
committerLars Knoll <lars.knoll@digia.com>2013-06-03 14:53:52 +0200
commit10def71cf4b13b55b421b740b1dc22f1084a8185 (patch)
treeb3d523d04febd6d06abef2e9b478ab7048ebb644
parent2e391fec759c2075f95509c5dbda6fb21e88f3ee (diff)
Initial port of connect/disconnect from V8 to V4
Change-Id: I289a49ab60cce33bf03724e93df9a9cac2b2aa1a Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r--src/qml/qml/v8/qv8engine.cpp1
-rw-r--r--src/qml/qml/v8/qv8objectresource_p.h2
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp151
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper_p.h30
4 files changed, 93 insertions, 91 deletions
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 260f6098a5..d0478a22b4 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -145,7 +145,6 @@ QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint)
switch (r->resourceType()) {
case QV8ObjectResource::Context2DStyleType:
case QV8ObjectResource::Context2DPixelArrayType:
- case QV8ObjectResource::SignalHandlerType:
case QV8ObjectResource::VisualDataItemType:
case QV8ObjectResource::XMLHttpRequestType:
case QV8ObjectResource::DOMNodeType:
diff --git a/src/qml/qml/v8/qv8objectresource_p.h b/src/qml/qml/v8/qv8objectresource_p.h
index 382259700c..1dc72d10d5 100644
--- a/src/qml/qml/v8/qv8objectresource_p.h
+++ b/src/qml/qml/v8/qv8objectresource_p.h
@@ -71,7 +71,7 @@ public:
QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
enum ResourceType { XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
ListModelType, Context2DStyleType, Context2DPixelArrayType,
- ParticleDataType, SignalHandlerType, VisualDataItemType,
+ ParticleDataType, VisualDataItemType,
ChangeSetArrayType };
virtual ResourceType resourceType() const = 0;
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 110bec4f9c..86bbcf3d80 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -277,16 +277,6 @@ public:
QV8QObjectWrapper *wrapper;
};
-class QV8SignalHandlerResource : public QV8ObjectResource
-{
- V8_RESOURCE_TYPE(SignalHandlerType)
-public:
- QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index);
-
- QQmlGuard<QObject> object;
- int index;
-};
-
namespace {
template<typename A, typename B, typename C, typename D, typename E,
@@ -348,11 +338,6 @@ private:
};
}
-QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index)
-: QV8ObjectResource(engine), object(object), index(index)
-{
-}
-
static QAtomicInt objectIdCounter(1);
QV8QObjectWrapper::QV8QObjectWrapper()
@@ -428,23 +413,8 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- v8::Handle<v8::Function> connect = V8FUNCTION(Connect, engine);
- v8::Handle<v8::Function> disconnect = V8FUNCTION(Disconnect, engine);
-
- {
- v8::Handle<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
- ft->InstanceTemplate()->SetHasExternalResource(true);
- ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum);
- ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
- m_signalHandlerConstructor = ft->GetFunction()->v4Value();
- }
-
- {
- v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>(engine->global())
- ->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
- prototype->Set(v8::String::New("connect"), connect, v8::DontEnum);
- prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
- }
+ v4->functionPrototype->defineDefaultProperty(v4, QStringLiteral("connect"), Connect);
+ v4->functionPrototype->defineDefaultProperty(v4, QStringLiteral("disconnect"), Disconnect);
}
bool QV8QObjectWrapper::isQObject(v8::Handle<v8::Object> obj)
@@ -598,10 +568,15 @@ QV4::Value QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object,
} else if (result->isV4Function()) {
return MethodClosure::createWithGlobal(engine, object, result->coreIndex);
} else if (result->isSignalHandler()) {
- v8::Handle<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor.value().asFunctionObject()->newInstance();
- QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex);
- handler->SetExternalResource(r);
- return handler->v4Value();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::QmlSignalHandler *handler = new (v4->memoryManager) QV4::QmlSignalHandler(v4, object, result->coreIndex);
+
+ QV4::String *connect = v4->newIdentifier(QStringLiteral("connect"));
+ QV4::String *disconnect = v4->newIdentifier(QStringLiteral("disconnect"));
+ handler->put(connect, v4->functionPrototype->get(connect));
+ handler->put(disconnect, v4->functionPrototype->get(disconnect));
+
+ return QV4::Value::fromObject(handler);
} else {
return MethodClosure::create(engine, object, result->coreIndex);
}
@@ -913,23 +888,21 @@ v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
}
}
-QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, const Value &value)
{
- if (object->IsFunction())
- return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object));
+ if (QV4::FunctionObject *function = value.asFunctionObject())
+ return ExtractQtMethod(engine, function);
- if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object))
- return qMakePair(resource->object.data(), resource->index);
+ if (QV4::QmlSignalHandler *handler = value.as<QV4::QmlSignalHandler>())
+ return qMakePair(handler->object(), handler->signalIndex());
return qMakePair((QObject *)0, -1);
}
-QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, QV4::FunctionObject *function)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::FunctionObject *v4Function = function->v4Value().asFunctionObject();
- if (v4Function->subtype == QV4::FunctionObject::WrappedQtMethod) {
- QObjectMethod *method = static_cast<QObjectMethod*>(v4Function);
+ if (function && function->subtype == QV4::FunctionObject::WrappedQtMethod) {
+ QObjectMethod *method = static_cast<QObjectMethod*>(function);
return qMakePair(method->object(), method->methodIndex());
}
@@ -1075,14 +1048,15 @@ int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, v
return -1;
}
-QV4::Value QV8QObjectWrapper::Connect(const v8::Arguments &args)
+QV4::Value QV8QObjectWrapper::Connect(SimpleCallContext *ctx)
{
- if (args.Length() == 0)
+ if (ctx->argumentCount == 0)
V4THROW_ERROR("Function.prototype.connect: no arguments given");
- QV8Engine *engine = V8ENGINE();
+ // ### Eliminate, won't work within worker scripts
+ QV8Engine *engine = QV8Engine::get(ctx->engine->publicEngine);
- QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, ctx->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
@@ -1095,20 +1069,20 @@ QV4::Value QV8QObjectWrapper::Connect(const v8::Arguments &args)
if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
V4THROW_ERROR("Function.prototype.connect: this object is not a signal");
- v8::Handle<v8::Value> functionValue;
- v8::Handle<v8::Value> functionThisValue;
+ QV4::Value functionValue = QV4::Value::emptyValue();
+ QV4::Value functionThisValue = QV4::Value::emptyValue();
- if (args.Length() == 1) {
- functionValue = args[0];
- } else {
- functionThisValue = args[0];
- functionValue = args[1];
+ if (ctx->argumentCount == 1) {
+ functionValue = ctx->arguments[0];
+ } else if (ctx->argumentCount >= 2) {
+ functionThisValue = ctx->arguments[0];
+ functionValue = ctx->arguments[1];
}
- if (!functionValue->IsFunction())
+ if (!functionValue.asFunctionObject())
V4THROW_ERROR("Function.prototype.connect: target is not a function");
- if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ if (!functionThisValue.isEmpty() && !functionThisValue.isObject())
V4THROW_ERROR("Function.prototype.connect: target this is not an object");
QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
@@ -1125,23 +1099,24 @@ QV4::Value QV8QObjectWrapper::Connect(const v8::Arguments &args)
}
QV8QObjectConnectionList::Connection connection;
- if (!functionThisValue.IsEmpty())
- connection.thisObject = functionThisValue->ToObject()->v4Value();
- connection.function = functionValue->v4Value();
+ if (!functionThisValue.isEmpty())
+ connection.thisObject = functionThisValue;
+ connection.function = functionValue;
slotIter->append(connection);
return QV4::Value::undefinedValue();
}
-QV4::Value QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
+QV4::Value QV8QObjectWrapper::Disconnect(SimpleCallContext *ctx)
{
- if (args.Length() == 0)
+ if (ctx->argumentCount == 0)
V4THROW_ERROR("Function.prototype.disconnect: no arguments given");
- QV8Engine *engine = V8ENGINE();
+ // ### Eliminate, won't work within worker scripts
+ QV8Engine *engine = QV8Engine::get(ctx->engine->publicEngine);
- QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
+ QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, ctx->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
@@ -1154,20 +1129,20 @@ QV4::Value QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
V4THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
- v8::Handle<v8::Value> functionValue;
- v8::Handle<v8::Value> functionThisValue;
+ QV4::Value functionValue = QV4::Value::emptyValue();
+ QV4::Value functionThisValue = QV4::Value::emptyValue();
- if (args.Length() == 1) {
- functionValue = args[0];
- } else {
- functionThisValue = args[0];
- functionValue = args[1];
+ if (ctx->argumentCount == 1) {
+ functionValue = ctx->arguments[0];
+ } else if (ctx->argumentCount >= 2) {
+ functionThisValue = ctx->arguments[0];
+ functionValue = ctx->arguments[1];
}
- if (!functionValue->IsFunction())
+ if (!functionValue.asFunctionObject())
V4THROW_ERROR("Function.prototype.disconnect: target is not a function");
- if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ if (!functionThisValue.isEmpty() && !functionThisValue.isObject())
V4THROW_ERROR("Function.prototype.disconnect: target this is not an object");
QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
@@ -1183,18 +1158,17 @@ QV4::Value QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
QV8QObjectConnectionList::ConnectionList &connections = *slotIter;
- v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionValue);
- QPair<QObject *, int> functionData = ExtractQtMethod(engine, function);
+ QPair<QObject *, int> functionData = ExtractQtMethod(engine, functionValue.asFunctionObject());
if (functionData.second != -1) {
// This is a QObject function wrapper
for (int ii = 0; ii < connections.count(); ++ii) {
QV8QObjectConnectionList::Connection &connection = connections[ii];
- if (connection.thisObject.isEmpty() == functionThisValue.IsEmpty() &&
- (connection.thisObject.isEmpty() || __qmljs_strict_equal(connection.thisObject, functionThisValue->v4Value()))) {
+ if (connection.thisObject.isEmpty() == functionThisValue.isEmpty() &&
+ (connection.thisObject.isEmpty() || __qmljs_strict_equal(connection.thisObject, functionThisValue))) {
- QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function.value());
+ QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function.value().asFunctionObject());
if (connectedFunctionData == functionData) {
// Match!
if (connections.connectionsInUse) {
@@ -1213,9 +1187,9 @@ QV4::Value QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
// This is a normal JS function
for (int ii = 0; ii < connections.count(); ++ii) {
QV8QObjectConnectionList::Connection &connection = connections[ii];
- if (__qmljs_strict_equal(connection.function, function->v4Value()) &&
- connection.thisObject.isEmpty() == functionThisValue.IsEmpty() &&
- (connection.thisObject.isEmpty() || __qmljs_strict_equal(connection.thisObject, functionThisValue->v4Value()))) {
+ if (__qmljs_strict_equal(connection.function, functionValue) &&
+ connection.thisObject.isEmpty() == functionThisValue.isEmpty() &&
+ (connection.thisObject.isEmpty() || __qmljs_strict_equal(connection.thisObject, functionThisValue))) {
// Match!
if (connections.connectionsInUse) {
connection.needsDestroy = true;
@@ -1980,5 +1954,16 @@ Value QObjectMethod::callInternal(ExecutionContext *context, const Value &thisOb
DEFINE_MANAGED_VTABLE(QObjectMethod);
+QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex)
+ : Object(engine)
+ , m_object(object)
+ , m_signalIndex(signalIndex)
+{
+ vtbl = &static_vtbl;
+ prototype = engine->objectPrototype;
+}
+
+DEFINE_MANAGED_VTABLE(QmlSignalHandler);
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8qobjectwrapper_p.h b/src/qml/qml/v8/qv8qobjectwrapper_p.h
index 44a402a6f3..af84afba3d 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper_p.h
+++ b/src/qml/qml/v8/qv8qobjectwrapper_p.h
@@ -109,6 +109,8 @@ private:
struct QObjectMethod : public QV4::FunctionObject
{
+ Q_MANAGED
+
enum { DestroyMethod = -1, ToStringMethod = -2 };
QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal);
@@ -132,8 +134,25 @@ private:
{
static_cast<QObjectMethod *>(that)->~QObjectMethod();
}
+};
+
+struct QmlSignalHandler : public QV4::Object
+{
+ Q_MANAGED
- static const QV4::ManagedVTable static_vtbl;
+ QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex);
+
+ int signalIndex() const { return m_signalIndex; }
+ QObject *object() const { return m_object.data(); }
+
+private:
+ QQmlGuard<QObject> m_object;
+ int m_signalIndex;
+
+ static void destroy(Managed *that)
+ {
+ static_cast<QmlSignalHandler *>(that)->~QmlSignalHandler();
+ }
};
}
@@ -166,14 +185,13 @@ private:
const QHashedV4String &, QQmlContextData *, QV8QObjectWrapper::RevisionMode);
static bool SetProperty(QV8Engine *, QObject *, const QHashedV4String &, QQmlContextData *,
v8::Handle<v8::Value>, QV8QObjectWrapper::RevisionMode);
- static QV4::Value Connect(const v8::Arguments &args);
- static QV4::Value Disconnect(const v8::Arguments &args);
- static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, v8::Handle<v8::Function>);
- static QPair<QObject *, int> ExtractQtSignal(QV8Engine *, v8::Handle<v8::Object>);
+ static QV4::Value Connect(QV4::SimpleCallContext *ctx);
+ static QV4::Value Disconnect(QV4::SimpleCallContext *ctx);
+ static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, QV4::FunctionObject *);
+ static QPair<QObject *, int> ExtractQtSignal(QV8Engine *, const QV4::Value &value);
QV8Engine *m_engine;
quint32 m_id;
- QV4::PersistentValue m_signalHandlerConstructor;
QHash<QObject *, QV8QObjectConnectionList *> m_connections;
typedef QHash<QObject *, QV8QObjectInstance *> TaintedHash;
TaintedHash m_taintedObjects;