Get rid of QV8QObjectWrapper:setProperty and SetProperty
authorSimon Hausmann <simon.hausmann@digia.com>
Thu, 6 Jun 2013 14:11:23 +0000 (16:11 +0200)
committerLars Knoll <lars.knoll@digia.com>
Fri, 7 Jun 2013 16:33:09 +0000 (18:33 +0200)
Fold it all into QV4::QObjectWrapper::setQmlProperty and remove
a lot of otherwise unused code.

Change-Id: Ic28233fa7d4df898ff39ac065044319e01d47b88
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/qml/qqmlcontextwrapper.cpp
src/qml/qml/qqmltypewrapper.cpp
src/qml/qml/v8/qv8qobjectwrapper.cpp
src/qml/qml/v8/qv8qobjectwrapper_p.h

index ddeaead..a9ff7a2 100644 (file)
@@ -295,14 +295,13 @@ void QmlContextWrapper::put(Managed *m, ExecutionContext *ctx, String *name, con
 
         // Search scope object
         if (scopeObject &&
-            qobjectWrapper->setProperty(scopeObject, propertystring, context, value, QV4::QObjectWrapper::CheckRevision))
+            QV4::QObjectWrapper::setQmlProperty(ctx, context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
             return;
         scopeObject = 0;
 
         // Search context object
         if (context->contextObject &&
-            qobjectWrapper->setProperty(context->contextObject, propertystring, context, value,
-                                        QV4::QObjectWrapper::CheckRevision))
+            QV4::QObjectWrapper::setQmlProperty(ctx, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
             return;
 
         context = context->parent;
index b3b1ded..a41e3c4 100644 (file)
@@ -241,8 +241,7 @@ void QmlTypeWrapper::put(Managed *m, ExecutionContext *ctx, String *name, const
         QObject *object = w->object;
         QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
         if (ao) 
-            v8engine->qobjectWrapper()->setProperty(ao, propertystring, context, value,
-                                                    QV4::QObjectWrapper::IgnoreRevision);
+            QV4::QObjectWrapper::setQmlProperty(ctx, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
     } else if (type && type->isSingleton()) {
         QQmlEngine *e = v8engine->engine();
         QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
@@ -250,8 +249,7 @@ void QmlTypeWrapper::put(Managed *m, ExecutionContext *ctx, String *name, const
 
         QObject *qobjectSingleton = siinfo->qobjectApi(e);
         if (qobjectSingleton) {
-            v8engine->qobjectWrapper()->setProperty(qobjectSingleton, propertystring, context, value,
-                                                    QV4::QObjectWrapper::IgnoreRevision);
+            QV4::QObjectWrapper::setQmlProperty(ctx, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
         } else if (!siinfo->scriptApi(e).isUndefined()) {
             QV4::Object *apiprivate = QJSValuePrivate::get(siinfo->scriptApi(e))->value.asObject();
             if (!apiprivate) {
index 128fd25..29d3524 100644 (file)
@@ -435,6 +435,141 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
     return wrapper->getQmlProperty(ctx, qmlContext, name, revisionMode, hasProperty);
 }
 
+bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, const Value &value)
+{
+    if (QQmlData::wasDeleted(object))
+        return false;
+
+    QQmlPropertyData local;
+    QQmlPropertyData *result = 0;
+    {
+        QHashedV4String property(Value::fromString(name));
+        result = QQmlPropertyCache::property(ctx->engine->v8Engine->engine(), object, property, qmlContext, local);
+    }
+
+    if (!result)
+        return false;
+
+    if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) {
+        QQmlData *ddata = QQmlData::get(object);
+        if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
+            return false;
+    }
+
+    if (!result->isWritable() && !result->isQList()) {
+        QString error = QLatin1String("Cannot assign to read-only property \"") +
+                        name->toQString() + QLatin1Char('\"');
+        ctx->throwError(error);
+    }
+
+    QQmlBinding *newBinding = 0;
+    if (FunctionObject *f = value.asFunctionObject()) {
+        if (!f->bindingKeyFlag) {
+            if (!result->isVarProperty() && result->propType != qMetaTypeId<QJSValue>()) {
+                // assigning a JS function to a non var or QJSValue property or is not allowed.
+                QString error = QLatin1String("Cannot assign JavaScript function to ");
+                if (!QMetaType::typeName(result->propType))
+                    error += QLatin1String("[unknown property type]");
+                else
+                    error += QLatin1String(QMetaType::typeName(result->propType));
+                ctx->throwError(error);
+            }
+        } else {
+            // binding assignment.
+            QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
+
+            QV4::ExecutionEngine::StackFrame frame = ctx->engine->currentStackFrame();
+
+            newBinding = new QQmlBinding(value, object, callingQmlContext, frame.source,
+                                         qmlSourceCoordinate(frame.line), qmlSourceCoordinate(frame.column));
+            newBinding->setTarget(object, *result, callingQmlContext);
+            newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+                                         QQmlBinding::RequiresThisObject);
+        }
+    }
+
+    QQmlAbstractBinding *oldBinding =
+        QQmlPropertyPrivate::setBinding(object, result->coreIndex, -1, newBinding);
+    if (oldBinding)
+        oldBinding->destroy();
+
+    if (!newBinding && result->isVarProperty()) {
+        // allow assignment of "special" values (null, undefined, function) to var properties
+        QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
+        Q_ASSERT(vmemo);
+        vmemo->setVMEProperty(result->coreIndex, value);
+        return true;
+    }
+
+#define PROPERTY_STORE(cpptype, value) \
+    cpptype o = value; \
+    int status = -1; \
+    int flags = 0; \
+    void *argv[] = { &o, 0, &status, &flags }; \
+    QMetaObject::metacall(object, QMetaObject::WriteProperty, result->coreIndex, argv);
+
+    if (value.isNull() && result->isQObject()) {
+        PROPERTY_STORE(QObject*, 0);
+    } else if (value.isUndefined() && result->isResettable()) {
+        void *a[] = { 0 };
+        QMetaObject::metacall(object, QMetaObject::ResetProperty, result->coreIndex, a);
+    } else if (value.isUndefined() && result->propType == qMetaTypeId<QVariant>()) {
+        PROPERTY_STORE(QVariant, QVariant());
+    } else if (value.isUndefined() && result->propType == QMetaType::QJsonValue) {
+        PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
+    } else if (!newBinding && result->propType == qMetaTypeId<QJSValue>()) {
+        PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->engine, value));
+    } else if (value.isUndefined()) {
+        QString error = QLatin1String("Cannot assign [undefined] to ");
+        if (!QMetaType::typeName(result->propType))
+            error += QLatin1String("[unknown property type]");
+        else
+            error += QLatin1String(QMetaType::typeName(result->propType));
+        ctx->throwError(error);
+    } else if (value.asFunctionObject()) {
+        // this is handled by the binding creation above
+    } else if (result->propType == QMetaType::Int && value.isNumber()) {
+        PROPERTY_STORE(int, qRound(value.asDouble()));
+    } else if (result->propType == QMetaType::QReal && value.isNumber()) {
+        PROPERTY_STORE(qreal, qreal(value.asDouble()));
+    } else if (result->propType == QMetaType::Float && value.isNumber()) {
+        PROPERTY_STORE(float, float(value.asDouble()));
+    } else if (result->propType == QMetaType::Double && value.isNumber()) {
+        PROPERTY_STORE(double, double(value.asDouble()));
+    } else if (result->propType == QMetaType::QString && value.isString()) {
+        PROPERTY_STORE(QString, value.toQString());
+    } else if (result->isVarProperty()) {
+        QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
+        Q_ASSERT(vmemo);
+        vmemo->setVMEProperty(result->coreIndex, value);
+    } else {
+        QVariant v;
+        if (result->isQList())
+            v = ctx->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+        else
+            v = ctx->engine->v8Engine->toVariant(value, result->propType);
+
+        QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
+        if (!QQmlPropertyPrivate::write(object, *result, v, callingQmlContext)) {
+            const char *valueType = 0;
+            if (v.userType() == QVariant::Invalid) valueType = "null";
+            else valueType = QMetaType::typeName(v.userType());
+
+            const char *targetTypeName = QMetaType::typeName(result->propType);
+            if (!targetTypeName)
+                targetTypeName = "an unregistered type";
+
+            QString error = QLatin1String("Cannot assign ") +
+                            QLatin1String(valueType) +
+                            QLatin1String(" to ") +
+                            QLatin1String(targetTypeName);
+            ctx->throwError(error);
+        }
+    }
+
+    return true;
+}
+
 Value QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
 {
     if (QQmlData::wasDeleted(object))
@@ -510,15 +645,8 @@ void QObjectWrapper::put(Managed *m, ExecutionContext *ctx, String *name, const
     if (QQmlData::wasDeleted(that->m_object))
         return;
 
-    QObject *object = that->m_object;
-
-    QHashedV4String propertystring(QV4::Value::fromString(name));
-
-    QQmlContextData *context = QV4::QmlContextWrapper::callingContext(ctx->engine);
-    QV8Engine *v8engine = ctx->engine->v8Engine;
-    bool result = QV8QObjectWrapper::SetProperty(v8engine, object, propertystring, context, value, QV4::QObjectWrapper::IgnoreRevision);
-
-    if (!result) {
+    QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
+    if (!setQmlProperty(ctx, qmlContext, that->m_object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
         QString error = QLatin1String("Cannot assign to non-existent property \"") +
                         name->toQString() + QLatin1Char('\"');
         ctx->throwError(error);
@@ -853,212 +981,6 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
     m_engine = engine;
 }
 
-// Setter for writable properties.  Shared between the interceptor and fast property accessor
-static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropertyData *property,
-                                 v8::Handle<v8::Value> value)
-{
-    QQmlBinding *newBinding = 0;
-    if (value->IsFunction()) {
-        QV4::FunctionObject *f = value->v4Value().asFunctionObject();
-        if (!f->bindingKeyFlag) {
-            if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
-                // assigning a JS function to a non var or QJSValue property or is not allowed.
-                QString error = QLatin1String("Cannot assign JavaScript function to ");
-                if (!QMetaType::typeName(property->propType))
-                    error += QLatin1String("[unknown property type]");
-                else
-                    error += QLatin1String(QMetaType::typeName(property->propType));
-                v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-                return;
-            }
-        } else {
-            // binding assignment.
-            QQmlContextData *context = engine->callingContext();
-            v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
-
-            QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
-            QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame();
-
-            newBinding = new QQmlBinding(function->v4Value(), object, context, frame.source,
-                                         qmlSourceCoordinate(frame.line), qmlSourceCoordinate(frame.column));
-            newBinding->setTarget(object, *property, context);
-            newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
-                                         QQmlBinding::RequiresThisObject);
-        }
-    }
-
-    QQmlAbstractBinding *oldBinding = 
-        QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
-    if (oldBinding)
-        oldBinding->destroy();
-
-    if (!newBinding && property->isVarProperty()) {
-        // allow assignment of "special" values (null, undefined, function) to var properties
-        QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
-        Q_ASSERT(vmemo);
-        vmemo->setVMEProperty(property->coreIndex, value->v4Value());
-        return;
-    }
-
-#define PROPERTY_STORE(cpptype, value) \
-    cpptype o = value; \
-    int status = -1; \
-    int flags = 0; \
-    void *argv[] = { &o, 0, &status, &flags }; \
-    QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
-
-    if (value->IsNull() && property->isQObject()) {
-        PROPERTY_STORE(QObject*, 0);
-    } else if (value->IsUndefined() && property->isResettable()) {
-        void *a[] = { 0 };
-        QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
-    } else if (value->IsUndefined() && property->propType == qMetaTypeId<QVariant>()) {
-        PROPERTY_STORE(QVariant, QVariant());
-    } else if (value->IsUndefined() && property->propType == QMetaType::QJsonValue) {
-        PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
-    } else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
-        PROPERTY_STORE(QJSValue, new QJSValuePrivate(QV8Engine::getV4(engine), value->v4Value()));
-    } else if (value->IsUndefined()) {
-        QString error = QLatin1String("Cannot assign [undefined] to ");
-        if (!QMetaType::typeName(property->propType))
-            error += QLatin1String("[unknown property type]");
-        else
-            error += QLatin1String(QMetaType::typeName(property->propType));
-        v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-    } else if (value->IsFunction()) {
-        // this is handled by the binding creation above
-    } else if (property->propType == QMetaType::Int && value->IsNumber()) {
-        PROPERTY_STORE(int, qRound(value->v4Value().asDouble()));
-    } else if (property->propType == QMetaType::QReal && value->IsNumber()) {
-        PROPERTY_STORE(qreal, qreal(value->v4Value().asDouble()));
-    } else if (property->propType == QMetaType::Float && value->IsNumber()) {
-        PROPERTY_STORE(float, float(value->v4Value().asDouble()));
-    } else if (property->propType == QMetaType::Double && value->IsNumber()) {
-        PROPERTY_STORE(double, double(value->v4Value().asDouble()));
-    } else if (property->propType == QMetaType::QString && value->IsString()) {
-        PROPERTY_STORE(QString, value->v4Value().toQString());
-    } else if (property->isVarProperty()) {
-        QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
-        Q_ASSERT(vmemo);
-        vmemo->setVMEProperty(property->coreIndex, value->v4Value());
-    } else {
-        QVariant v;
-        if (property->isQList()) 
-            v = engine->toVariant(value->v4Value(), qMetaTypeId<QList<QObject *> >());
-        else
-            v = engine->toVariant(value->v4Value(), property->propType);
-
-        QQmlContextData *context = engine->callingContext();
-        if (!QQmlPropertyPrivate::write(object, *property, v, context)) {
-            const char *valueType = 0;
-            if (v.userType() == QVariant::Invalid) valueType = "null";
-            else valueType = QMetaType::typeName(v.userType());
-
-            const char *targetTypeName = QMetaType::typeName(property->propType);
-            if (!targetTypeName)
-                targetTypeName = "an unregistered type";
-
-            QString error = QLatin1String("Cannot assign ") +
-                            QLatin1String(valueType) +
-                            QLatin1String(" to ") +
-                            QLatin1String(targetTypeName);
-            v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-        }
-    }
-}
-
-bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV4String &property, QQmlContextData *context,
-                                    v8::Handle<v8::Value> value, QV4::QObjectWrapper::RevisionMode revisionMode)
-{
-    if (QQmlData::wasDeleted(object))
-        return false;
-
-    QQmlPropertyData local;
-    QQmlPropertyData *result = 0;
-    result = QQmlPropertyCache::property(engine->engine(), object, property, context, local);
-
-    if (!result)
-        return false;
-
-    if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) {
-        QQmlData *ddata = QQmlData::get(object);
-        if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
-            return false;
-    }
-
-    if (!result->isWritable() && !result->isQList()) {
-        QString error = QLatin1String("Cannot assign to read-only property \"") +
-                        property.toString() + QLatin1Char('\"');
-        v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-        return true;
-    }
-
-    StoreProperty(engine, object, result, value);
-
-    return true;
-}
-
-static void FastValueSetter(v8::Handle<v8::String>, v8::Handle<v8::Value> value,
-                            const v8::AccessorInfo& info)
-{
-    QV4::QObjectWrapper *wrapper = info.This()->v4Value().as<QObjectWrapper>();
-
-    if (QQmlData::wasDeleted(wrapper->object()))
-        return; 
-
-    QObject *object = wrapper->object();
-
-    QQmlPropertyData *property =
-            (QQmlPropertyData *)v8::External::Cast(info.Data().get())->Value();
-
-    int index = property->coreIndex;
-
-    QQmlData *ddata = QQmlData::get(object, false);
-    Q_ASSERT(ddata);
-    Q_ASSERT(ddata->propertyCache);
-
-    QQmlPropertyData *pdata = ddata->propertyCache->property(index);
-    Q_ASSERT(pdata);
-
-    Q_ASSERT(pdata->isWritable() || pdata->isQList());
-
-    StoreProperty(wrapper->engine()->v8Engine, object, pdata, value);
-}
-
-static void FastValueSetterReadOnly(v8::Handle<v8::String> property, v8::Handle<v8::Value>,
-                                    const v8::AccessorInfo& info)
-{
-    QV4::QObjectWrapper *wrapper = info.This()->v4Value().as<QObjectWrapper>();
-
-    if (QQmlData::wasDeleted(wrapper->object()))
-        return; 
-
-    QV8Engine *v8engine = wrapper->engine()->v8Engine;
-
-    QString error = QLatin1String("Cannot assign to read-only property \"") +
-                    property->v4Value().toQString() + QLatin1Char('\"');
-    v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
-}
-
-/*!
-    \fn v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode)
-
-    Get the \a property of \a object.  Returns an empty handle if the property doesn't exist.
-
-    Only searches for real properties of \a object (including methods), not attached properties etc.
-*/
-
-/*
-    \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle<v8::Value> value, RevisionMode revisionMode)
-
-    Set the \a property of \a object to \a value.
-
-    Returns true if the property was "set" - even if this results in an exception being thrown -
-    and false if the object has no such property.
-
-    Only searches for real properties of \a object (including methods), not attached properties etc.
-*/
-
 namespace {
 struct CallArgs
 {
index 5c423b7..979def3 100644 (file)
@@ -95,6 +95,8 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
     Value getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
     static Value getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
 
+    static bool setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
+
     static Value wrap(ExecutionEngine *engine, QObject *object);
 
 private:
@@ -204,31 +206,14 @@ public:
     void init(QV8Engine *);
     void destroy();
 
-    inline bool setProperty(QObject *, const QHashedV4String &, QQmlContextData *, v8::Handle<v8::Value>, QV4::QObjectWrapper::RevisionMode);
-
 private:
     friend class QQmlPropertyCache;
     friend struct QV4::QObjectWrapper;
     friend struct QV4::QObjectSlotDispatcher;
 
-    static bool SetProperty(QV8Engine *, QObject *, const QHashedV4String &, QQmlContextData *,
-                            v8::Handle<v8::Value>, QV4::QObjectWrapper::RevisionMode);
-
     QV8Engine *m_engine;
 };
 
-bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV4String &string,
-                                    QQmlContextData *context, v8::Handle<v8::Value> value, QV4::QObjectWrapper::RevisionMode mode)
-{
-    QQmlData *dd = QQmlData::get(object, false);
-    if (!dd || !dd->propertyCache ||
-        dd->propertyCache->property(string, object, context)) {
-        return SetProperty(m_engine, object, string, context, value, mode);
-    } else {
-        return false;
-    }
-}
-
 QT_END_NAMESPACE
 
 #endif // QV8QOBJECTWRAPPER_P_H