From 00a07bcbd7a592072822b0e55ab2e75e90c3f9f5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 27 May 2013 20:23:13 +0200 Subject: [PATCH] Fix toString and destroy on QObject JS bindings The auto-tests requires these member functions to not rely on the thisObject at all. Also fixed lookup of QObject properties through the context wrapper to go through get() as the new interface (to catch destroy/toString). Change-Id: Iacbe8b5ce1895195a84a1224faba3f3bd34cd03b Reviewed-by: Lars Knoll --- src/qml/qml/v8/qv8contextwrapper.cpp | 10 ++- src/qml/qml/v8/qv8qobjectwrapper.cpp | 116 ++++++++++++++++++++--------------- src/qml/qml/v8/qv8qobjectwrapper_p.h | 13 ++-- src/qml/qml/v8/v8.pri | 2 - 4 files changed, 83 insertions(+), 58 deletions(-) diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp index 03cedf0..fec736b 100644 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ b/src/qml/qml/v8/qv8contextwrapper.cpp @@ -323,9 +323,13 @@ v8::Handle QV8ContextWrapper::Getter(v8::Handle property, // Search scope object if (scopeObject) { - v8::Handle result = qobjectWrapper->getProperty(scopeObject, propertystring, - context, QV8QObjectWrapper::CheckRevision); - if (!result.IsEmpty()) return result; + QV4::Value wrapper = qobjectWrapper->newQObject(scopeObject)->v4Value(); + if (QV4::Object *o = wrapper.asObject()) { + bool hasProperty = false; + QV4::Value result = o->get(o->engine()->current, propertystring.string().asString(), &hasProperty); + if (hasProperty) + return result; + } } scopeObject = 0; diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp index 18b2265..fdf0738 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -85,7 +85,9 @@ QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object) this->v8Engine = QV8Engine::get(engine->publicEngine); type = Type_QObject; vtbl = &static_vtbl; - initClass(engine); + + m_destroy = engine->newIdentifier(QStringLiteral("destroy")); + m_toString = engine->newIdentifier(QStringLiteral("toString")); } QObjectWrapper::~QObjectWrapper() @@ -104,50 +106,6 @@ QObjectWrapper::~QObjectWrapper() } } -QV4::Value QObjectWrapper::method_toString(QV4::SimpleCallContext *ctx) -{ - QString result; - if (object) { - QString objectName = object->objectName(); - - result += QString::fromUtf8(object->metaObject()->className()); - result += QLatin1String("(0x"); - result += QString::number((quintptr)object.object(),16); - - if (!objectName.isEmpty()) { - result += QLatin1String(", \""); - result += objectName; - result += QLatin1Char('\"'); - } - - result += QLatin1Char(')'); - } else { - result = QLatin1String("null"); - } - - return QV4::Value::fromString(ctx, result); -} - -QV4::Value QObjectWrapper::method_destroy(QV4::SimpleCallContext *ctx) -{ - if (!object) - return QV4::Value::undefinedValue(); - QQmlData *ddata = QQmlData::get(object, false); - if (!ddata || ddata->indestructible || ddata->rootObjectInCreation) - ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); - - int delay = 0; - if (ctx->argumentCount > 0) - delay = ctx->arguments[0].toUInt32(); - - if (delay > 0) - QTimer::singleShot(delay, object, SLOT(deleteLater())); - else - object->deleteLater(); - - return QV4::Value::undefinedValue(); -} - QV4::Value QObjectWrapper::get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty) { QObjectWrapper *that = static_cast(m); @@ -160,6 +118,22 @@ QV4::Value QObjectWrapper::get(Managed *m, ExecutionContext *ctx, String *name, QObject *object = that->object; + if (name->isEqualTo(that->m_destroy) || name->isEqualTo(that->m_toString)) { + bool hasProp = false; + QV4::Value method = QV4::Object::get(m, ctx, name, &hasProp); + + if (!hasProp) { + int index = name->isEqualTo(that->m_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod; + method = QV4::Value::fromObject(new (ctx->engine->memoryManager) QV4::QObjectMethod(ctx->engine->rootContext, object, index, QV4::Value::undefinedValue())); + QV4::Object::put(m, ctx, name, method); + } + + if (hasProperty) + *hasProperty = true; + + return method; + } + QHashedV4String propertystring(QV4::Value::fromString(name)); QV8Engine *v8engine = that->v8Engine; @@ -1962,6 +1936,50 @@ QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index subtype = WrappedQtMethod; } +QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx) +{ + QString result; + if (m_object) { + QString objectName = m_object->objectName(); + + result += QString::fromUtf8(m_object->metaObject()->className()); + result += QLatin1String("(0x"); + result += QString::number((quintptr)m_object.object(),16); + + if (!objectName.isEmpty()) { + result += QLatin1String(", \""); + result += objectName; + result += QLatin1Char('\"'); + } + + result += QLatin1Char(')'); + } else { + result = QLatin1String("null"); + } + + return QV4::Value::fromString(ctx, result); +} + +QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc) +{ + if (!m_object) + return QV4::Value::undefinedValue(); + QQmlData *ddata = QQmlData::get(m_object, false); + if (!ddata || ddata->indestructible || ddata->rootObjectInCreation) + ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); + + int delay = 0; + if (argc > 0) + delay = args[0].toUInt32(); + + if (delay > 0) + QTimer::singleShot(delay, m_object, SLOT(deleteLater())); + else + m_object->deleteLater(); + + return QV4::Value::undefinedValue(); +} + Value QObjectMethod::call(Managed *m, ExecutionContext *context, const Value &thisObject, Value *args, int argc) { QObjectMethod *This = static_cast(m); @@ -1970,7 +1988,11 @@ Value QObjectMethod::call(Managed *m, ExecutionContext *context, const Value &th Value QObjectMethod::callInternal(ExecutionContext *context, const Value &thisObject, Value *args, int argc) { - // object, index, qmlglobal, argCount, args + if (m_index == DestroyMethod) + return method_destroy(context, args, argc); + else if (m_index == ToStringMethod) + return method_toString(context); + QObject *object = m_object.data(); if (!object) return QV4::Value::undefinedValue(); @@ -2023,7 +2045,5 @@ Value QObjectMethod::callInternal(ExecutionContext *context, const Value &thisOb DEFINE_MANAGED_VTABLE(QObjectMethod); -#include "qv8qobjectwrapper_p_jsclass.cpp" - QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8qobjectwrapper_p.h b/src/qml/qml/v8/qv8qobjectwrapper_p.h index 5819000..b56e482 100644 --- a/src/qml/qml/v8/qv8qobjectwrapper_p.h +++ b/src/qml/qml/v8/qv8qobjectwrapper_p.h @@ -79,7 +79,7 @@ class QQmlPropertyCache; namespace QV4 { -struct Q_QML_EXPORT QV4_JS_CLASS(QObjectWrapper) : public QV4::Object +struct Q_QML_EXPORT QObjectWrapper : public QV4::Object { QObjectWrapper(ExecutionEngine *v8Engine, QObject *object); ~QObjectWrapper(); @@ -88,11 +88,9 @@ struct Q_QML_EXPORT QV4_JS_CLASS(QObjectWrapper) : public QV4::Object QQmlGuard object; QIntrusiveListNode weakResource; - QV4::Value method_toString(QV4::SimpleCallContext *ctx); - QV4::Value method_destroy(QV4::SimpleCallContext *ctx); - private: - void initClass(QV4::ExecutionEngine *engine); + String *m_destroy; + String *m_toString; static Value get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty); static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value); @@ -110,12 +108,17 @@ private: struct QObjectMethod : public QV4::FunctionObject { + enum { DestroyMethod = -1, ToStringMethod = -2 }; + QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal); int methodIndex() const { return m_index; } QObject *object() const { return m_object.data(); } private: + QV4::Value method_toString(QV4::ExecutionContext *ctx); + QV4::Value method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc); + QQmlGuard m_object; int m_index; QV4::PersistentValue m_qmlGlobal; diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri index 21e5623..73feebb 100644 --- a/src/qml/qml/v8/v8.pri +++ b/src/qml/qml/v8/v8.pri @@ -28,5 +28,3 @@ SOURCES += \ $$PWD/qv4sqlerrors.cpp \ $$PWD/qqmlbuiltinfunctions.cpp -JS_CLASS_SOURCES += \ - $$PWD/qv8qobjectwrapper_p.h -- 2.7.4