v8::Handle<v8::Value> value)
{
QQmlBinding *newBinding = 0;
-
if (value->IsFunction()) {
- 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 columnNumber = frame->GetColumn();
- QString url = engine->toString(frame->GetScriptName());
-
- newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
- newBinding->setTarget(object, *property, context);
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
- QQmlBinding::RequiresThisObject);
+ 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;
+ // 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();
++ int columnNumber = frame->GetColumn();
+ QString url = engine->toString(frame->GetScriptName());
+
- newBinding = new QQmlBinding(&function, object, context);
- newBinding->setSourceLocation(url, lineNumber, columNumber);
++ newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
+ 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.
+ 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();
++ int columnNumber = frame->GetColumn();
+ QString url = engine->toString(frame->GetScriptName());
+
- newBinding = new QQmlBinding(&function, object, context);
- newBinding->setSourceLocation(url, lineNumber, columNumber);
++ newBinding = new QQmlBinding(&function, object, context, url, lineNumber, columnNumber);
+ newBinding->setTarget(object, *property, context);
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+ QQmlBinding::RequiresThisObject);
+ }
}
QQmlAbstractBinding *oldBinding =
QQmlComponent component(&engine, testFileUrl("functionAssignment.1.qml"));
QString url = component.url().toString();
- QString w1 = url + ":4: Unable to assign a function to a property of any type other than var.";
- QString w2 = url + ":5: Invalid use of Qt.binding() in a binding declaration.";
- QString w3 = url + ":6: Invalid use of Qt.binding() in a binding declaration.";
- QString warning = url + ":4:25: Unable to assign a function to a property.";
- QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
-
++ QString w1 = url + ":4:25: Unable to assign a function to a property of any type other than var.";
++ QString w2 = url + ":5:25: Invalid use of Qt.binding() in a binding declaration.";
++ QString w3 = url + ":6:21: Invalid use of Qt.binding() in a binding declaration.";
+ QTest::ignoreMessage(QtWarningMsg, w1.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, w2.toLatin1().constData());
+ QTest::ignoreMessage(QtWarningMsg, w3.toLatin1().constData());
-
++
MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(o != 0);
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect().x(), 92);
+ QCOMPARE(object->rect().y(), 97);
delete object;
+ }
+
+ // function assignment should fail without crashing
+ {
- QString warning1 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":6: Invalid use of Qt.binding() in a binding declaration.");
++ QString warning1 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":6:13: Invalid use of Qt.binding() in a binding declaration.");
+ QString warning2 = testFileUrl("bindingAssignment.2.qml").toString() + QLatin1String(":10: Error: Cannot assign JavaScript function to value-type property");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QQmlComponent component(&engine, testFileUrl("bindingAssignment.2.qml"));
+ MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ QVERIFY(object != 0);
+ QCOMPARE(object->rect().x(), 5);
+ object->setProperty("value", QVariant(92));
+ QCOMPARE(object->rect().x(), 5);
+ delete object;
+ }
}
// Test bindings can read from value types