Fix tst_qqmlecmascript::functionAssignment_afterBinding
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 18 Jun 2013 13:07:24 +0000 (15:07 +0200)
committerLars Knoll <lars.knoll@digia.com>
Tue, 18 Jun 2013 14:47:32 +0000 (16:47 +0200)
When calling Qt.binding(f), don't modify f and set the bindingKeyFlag
there, but instead we must return a _new_ function that acts as proxy
and has the bindingKeyFlag set to true, similar to how the V8 based
implementation created a clone.

Change-Id: I4998359869c02e32c89e929793bf74a4adafcb72
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/qml/v8/qqmlbuiltinfunctions.cpp

index cf51a87..c8f7a64 100644 (file)
@@ -1170,6 +1170,39 @@ Value QtObject::method_locale(SimpleCallContext *ctx)
     return QQmlLocale::locale(v8engine, code);
 }
 
+namespace {
+
+struct BindingFunction : public QV4::FunctionObject
+{
+    Q_MANAGED
+    BindingFunction(FunctionObject *originalFunction)
+        : QV4::FunctionObject(originalFunction->scope, originalFunction->name)
+        , originalFunction(originalFunction)
+    {
+        vtbl = &static_vtbl;
+        bindingKeyFlag = true;
+    }
+
+    static Value call(Managed *that, ExecutionContext *ctx, const Value &thisObject, Value *argv, int argc)
+    {
+        BindingFunction *This = static_cast<BindingFunction*>(that);
+        return This->originalFunction->call(ctx, thisObject, argv, argc);
+    }
+
+    static void markObjects(Managed *that)
+    {
+        BindingFunction *This = static_cast<BindingFunction*>(that);
+        This->originalFunction->mark();
+        QV4::FunctionObject::markObjects(that);
+    }
+
+    QV4::FunctionObject *originalFunction;
+};
+
+DEFINE_MANAGED_VTABLE(BindingFunction);
+
+}
+
 /*!
     \qmlmethod Qt::binding(function)
 
@@ -1218,17 +1251,13 @@ Value QtObject::method_locale(SimpleCallContext *ctx)
 */
 Value QtObject::method_binding(SimpleCallContext *ctx)
 {
-    QString code;
     if (ctx->argumentCount != 1)
         V4THROW_ERROR("binding() requires 1 argument");
     QV4::FunctionObject *f = ctx->arguments[0].asFunctionObject();
     if (!f)
         V4THROW_TYPE("binding(): argument (binding expression) must be a function");
 
-    if (f->bindingKeyFlag)
-        V4THROW_ERROR("function passed to binding() can only be bound once"); // FIXME: With v8 we cloned the binding argument
-    f->bindingKeyFlag = true;
-    return QV4::Value::fromObject(f);
+    return QV4::Value::fromObject(new (ctx->engine->memoryManager) BindingFunction(f));
 }