Merge branch 'master' of git://gitorious.org/qt/qtdeclarative into api_changes
[profile/ivi/qtdeclarative.git] / src / qml / qml / v8 / qv8qobjectwrapper.cpp
index b84ae33..4be93d1 100644 (file)
@@ -513,13 +513,13 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
     if (!result)
         return v8::Handle<v8::Value>();
 
-    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) {
         QQmlData *ddata = QQmlData::get(object);
         if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
             return v8::Handle<v8::Value>();
     }
 
-    if (result->isFunction()) {
+    if (result->isFunction() && !result->isVMEProperty()) {
         if (result->isVMEFunction()) {
             return ((QQmlVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
         } else if (result->isV8Function()) {
@@ -579,24 +579,55 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
                                  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 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);
+        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();
+                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.
+            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);
+        }
     }
 
     QQmlAbstractBinding *oldBinding = 
@@ -604,6 +635,12 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropert
     if (oldBinding)
         oldBinding->destroy();
 
+    if (!newBinding && property->isVMEProperty()) {
+        // allow assignment of "special" values (null, undefined, function) to var properties
+        static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(object->metaObject()))->setVMEProperty(property->coreIndex, value);
+        return;
+    }
+
 #define PROPERTY_STORE(cpptype, value) \
     cpptype o = value; \
     int status = -1; \
@@ -673,7 +710,7 @@ bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QH
     if (!result)
         return false;
 
-    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) {
         QQmlData *ddata = QQmlData::get(object);
         if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
             return false;