Allow function assignment to cause binding for non-var props
authorChris Adams <christopher.adams@nokia.com>
Mon, 27 Feb 2012 00:51:57 +0000 (10:51 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 5 Mar 2012 09:06:48 +0000 (10:06 +0100)
This patch maintains the old function-assignment behaviour for non-var
properties, and will be reverted soon.

Change-Id: I523e464501106616c51ff7478f7eb7171c1ca350
Reviewed-by: Matthew Vogt <matthew.vogt@nokia.com>

src/qml/qml/v8/qv8qobjectwrapper.cpp
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp

index 59b58ca..4be93d1 100644 (file)
@@ -582,11 +582,32 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
     if (value->IsFunction()) {
         if (value->ToObject()->GetHiddenValue(engine->bindingFlagKey()).IsEmpty()) {
             if (!property->isVMEProperty()) {
+                // XXX TODO: uncomment the following lines
                 // assigning a JS function to a non-var-property is not allowed.
-                QString error = QLatin1String("Cannot assign JavaScript function to ") +
-                                QLatin1String(QMetaType::typeName(property->propType));
-                v8::ThrowException(v8::Exception::Error(engine->toString(error)));
-                return;
+                //QString error = QLatin1String("Cannot assign JavaScript function to ") +
+                //                QLatin1String(QMetaType::typeName(property->propType));
+                //v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+                //return;
+                // XXX TODO: remove the following transition behaviour
+                // Temporarily allow assignment of functions to non-var properties
+                // to mean binding assignment (as per old behaviour).
+                QQmlContextData *context = engine->callingContext();
+                v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+                v8::Local<v8::StackTrace> trace =
+                    v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+                                                                                             v8::StackTrace::kScriptName));
+                v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+                int lineNumber = frame->GetLineNumber();
+                int columNumber = frame->GetColumn();
+                QString url = engine->toString(frame->GetScriptName());
+
+                newBinding = new QQmlBinding(&function, object, context);
+                newBinding->setSourceLocation(url, lineNumber, columNumber);
+                newBinding->setTarget(object, *property, context);
+                newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+                                             QQmlBinding::RequiresThisObject);
+                qWarning("WARNING: function assignment is DEPRECATED and will be removed!  Wrap RHS in Qt.binding(): %s:%d", qPrintable(engine->toString(frame->GetScriptName())), frame->GetLineNumber());
             }
         } else {
             // binding assignment.
index 9c8d1e7..4540639 100644 (file)
@@ -5109,13 +5109,15 @@ void tst_qqmlecmascript::functionAssignment_afterBinding()
     QQmlComponent component(&engine, testFileUrl("functionAssignment.3.qml"));
 
     QString url = component.url().toString();
-    QString w1 = url + ":16: Error: Cannot assign JavaScript function to int";
+    //QString w1 = url + ":16: Error: Cannot assign JavaScript function to int"; // for now, function assignment = binding assignment
+    QString w1 = QLatin1String("WARNING: function assignment is DEPRECATED and will be removed!  Wrap RHS in Qt.binding(): ") + url + QLatin1String(":16");
     QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData());
 
     QObject *o = component.create();
     QVERIFY(o != 0);
     QCOMPARE(o->property("t1"), QVariant::fromValue<int>(4)); // should have bound
-    QCOMPARE(o->property("t2"), QVariant::fromValue<int>(2)); // should not have changed
+    //QCOMPARE(o->property("t2"), QVariant::fromValue<int>(2)); // should not have changed
+    QCOMPARE(o->property("t2"), QVariant::fromValue<int>(4)); // for now, function assignment = binding assignment
 
     delete o;
 }