summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-09-21 10:56:11 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-09-21 14:29:16 (GMT)
commit65b4ce3c51283adb76dcb73cc654b06359b1ae00 (patch)
treec71e10c6da5f986cc83ab520efce3a5952114efe
parent1b34feacef7a2d3ac005449a7cfbcb08a6bbf947 (diff)
downloadQt-65b4ce3c51283adb76dcb73cc654b06359b1ae00.zip
Qt-65b4ce3c51283adb76dcb73cc654b06359b1ae00.tar.gz
Qt-65b4ce3c51283adb76dcb73cc654b06359b1ae00.tar.bz2
QtScript: Fix comparing QVariant and QObject.
This add a hook inside JSC to be able to implement our own comparison function when comparing objects. Reviewed-by: Kent Hansen
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h3
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h6
-rw-r--r--src/script/bridge/qscriptobject.cpp14
-rw-r--r--src/script/bridge/qscriptobject_p.h4
-rw-r--r--src/script/bridge/qscriptqobject.cpp12
-rw-r--r--src/script/bridge/qscriptqobject_p.h2
-rw-r--r--src/script/bridge/qscriptvariant.cpp8
-rw-r--r--src/script/bridge/qscriptvariant_p.h2
-rw-r--r--tests/auto/qscriptvalue/tst_qscriptvalue.cpp42
9 files changed, 90 insertions, 3 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h
index 15b7957..35f7832 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h
@@ -189,6 +189,9 @@ namespace JSC {
virtual bool isActivationObject() const { return false; }
virtual bool isWatchdogException() const { return false; }
virtual bool isNotAnObjectErrorStub() const { return false; }
+#ifdef QT_BUILD_SCRIPT_LIB
+ virtual bool compareToObject(ExecState*, JSObject *other) { return other == this; }
+#endif
void allocatePropertyStorage(size_t oldSize, size_t newSize);
void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h
index acfc6c2..a0caff4 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h
@@ -73,7 +73,11 @@ namespace JSC {
if (v1.isObject()) {
if (v2.isObject())
- return v1 == v2;
+ return v1 == v2
+#ifdef QT_BUILD_SCRIPT_LIB
+ || asObject(v1)->compareToObject(exec, asObject(v2))
+#endif
+ ;
JSValue p1 = v1.toPrimitive(exec);
if (exec->hadException())
return false;
diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp
index d46765a..0807dc2 100644
--- a/src/script/bridge/qscriptobject.cpp
+++ b/src/script/bridge/qscriptobject.cpp
@@ -145,6 +145,15 @@ void QScriptObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArra
d->delegate->getPropertyNames(this, exec, propertyNames, listedAttributes);
}
+bool QScriptObject::compareToObject(JSC::ExecState* exec, JSC::JSObject *other)
+{
+ if (!d || !d->delegate) {
+ return JSC::JSObject::compareToObject(exec, other);
+ }
+ return d->delegate->compareToObject(this, exec, other);
+}
+
+
void QScriptObject::mark()
{
Q_ASSERT(!marked());
@@ -255,4 +264,9 @@ bool QScriptObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState* e
return object->JSC::JSObject::hasInstance(exec, value, proto);
}
+bool QScriptObjectDelegate::compareToObject(QScriptObject* object, JSC::ExecState* exec, JSC::JSObject* o)
+{
+ return object->JSC::JSObject::compareToObject(exec, o);
+}
+
QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h
index 8f4113f..8060914 100644
--- a/src/script/bridge/qscriptobject_p.h
+++ b/src/script/bridge/qscriptobject_p.h
@@ -108,6 +108,8 @@ public:
QScriptObjectDelegate *delegate() const;
void setDelegate(QScriptObjectDelegate *delegate);
+ virtual bool compareToObject(JSC::ExecState*, JSC::JSObject*);
+
protected:
Data *d;
};
@@ -151,6 +153,8 @@ public:
virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
JSC::JSValue value, JSC::JSValue proto);
+ virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
private:
Q_DISABLE_COPY(QScriptObjectDelegate)
};
diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp
index b7df781..236f899 100644
--- a/src/script/bridge/qscriptqobject.cpp
+++ b/src/script/bridge/qscriptqobject.cpp
@@ -1572,6 +1572,18 @@ void QObjectDelegate::mark(QScriptObject *object)
QScriptObjectDelegate::mark(object);
}
+bool QObjectDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2)
+{
+ if(!o2->inherits(&QScriptObject::info))
+ return false;
+ QScriptObject *object = static_cast<QScriptObject*>(o2);
+ QScriptObjectDelegate *delegate = object->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject))
+ return false;
+ return value() == static_cast<QObjectDelegate *>(delegate)->value();
+}
+
+
static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*,
JSC::JSValue thisValue, const JSC::ArgList &args)
{
diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h
index ef26c7d..72d066d 100644
--- a/src/script/bridge/qscriptqobject_p.h
+++ b/src/script/bridge/qscriptqobject_p.h
@@ -122,6 +122,8 @@ public:
inline void setOptions(QScriptEngine::QObjectWrapOptions options)
{ data->options = options; }
+ virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
protected:
Data *data;
};
diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp
index 583b61c..aa7ad94 100644
--- a/src/script/bridge/qscriptvariant.cpp
+++ b/src/script/bridge/qscriptvariant.cpp
@@ -148,6 +148,13 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec,
return JSC::jsString(exec, result);
}
+bool QVariantDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2)
+{
+ const QVariant &variant1 = value();
+ return variant1 == scriptEngineFromExec(exec)->scriptValueFromJSCValue(o2).toVariant();
+}
+
+
QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure,
JSC::Structure* prototypeFunctionStructure)
: QScriptObject(structure)
@@ -158,6 +165,7 @@ QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::
putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, variantProtoFuncValueOf), JSC::DontEnum);
}
+
} // namespace QScript
QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptvariant_p.h b/src/script/bridge/qscriptvariant_p.h
index 9325396..4ce0aa6 100644
--- a/src/script/bridge/qscriptvariant_p.h
+++ b/src/script/bridge/qscriptvariant_p.h
@@ -73,6 +73,8 @@ public:
Type type() const;
+ bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*);
+
private:
QVariant m_value;
};
diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
index 92b7c90..742f765 100644
--- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
+++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp
@@ -2875,15 +2875,27 @@ void tst_QScriptValue::equals()
QScriptValue qobj1 = eng.newQObject(this);
QScriptValue qobj2 = eng.newQObject(this);
+ QScriptValue qobj3 = eng.newQObject(0);
+ QScriptValue qobj4 = eng.newQObject(new QObject());
QVERIFY(qobj1.equals(qobj2)); // compares the QObject pointers
+ QVERIFY(!qobj2.equals(qobj4)); // compares the QObject pointers
+ QVERIFY(!qobj2.equals(obj2)); // compares the QObject pointers
QScriptValue compareFun = eng.evaluate("(function(a, b) { return a == b; })");
QVERIFY(compareFun.isFunction());
{
QScriptValue ret = compareFun.call(QScriptValue(), QScriptValueList() << qobj1 << qobj2);
QVERIFY(ret.isBool());
- QEXPECT_FAIL("", "In JSC back-end, == on QObject wrappers doesn't work", Continue);
QVERIFY(ret.toBool());
+ ret = compareFun.call(QScriptValue(), QScriptValueList() << qobj1 << qobj3);
+ QVERIFY(ret.isBool());
+ QVERIFY(!ret.toBool());
+ ret = compareFun.call(QScriptValue(), QScriptValueList() << qobj1 << qobj4);
+ QVERIFY(ret.isBool());
+ QVERIFY(!ret.toBool());
+ ret = compareFun.call(QScriptValue(), QScriptValueList() << qobj1 << obj1);
+ QVERIFY(ret.isBool());
+ QVERIFY(!ret.toBool());
}
{
@@ -2893,7 +2905,6 @@ void tst_QScriptValue::equals()
{
QScriptValue ret = compareFun.call(QScriptValue(), QScriptValueList() << var1 << var2);
QVERIFY(ret.isBool());
- QEXPECT_FAIL("", "In JSC back-end, == on QVariant wrappers doesn't work", Continue);
QVERIFY(ret.toBool());
}
}
@@ -2929,6 +2940,33 @@ void tst_QScriptValue::equals()
// QVariant::operator==() performs type conversion
QVERIFY(var1.equals(var2));
}
+ {
+ QScriptValue var1 = eng.newVariant(QVariant(QString::fromLatin1("123")));
+ QScriptValue var2 = eng.newVariant(QVariant(double(123)));
+ QScriptValue var3(QString::fromLatin1("123"));
+ QScriptValue var4(123);
+ QScriptValue var4(123.0);
+
+ QVERIFY(var1.equals(var1));
+ QVERIFY(var1.equals(var2));
+ QVERIFY(var1.equals(var3));
+ QVERIFY(var1.equals(var4));
+
+ QVERIFY(var2.equals(var1));
+ QVERIFY(var2.equals(var2));
+ QVERIFY(var2.equals(var3));
+ QVERIFY(var2.equals(var4));
+
+ QVERIFY(var3.equals(var1));
+ QVERIFY(var3.equals(var2));
+ QVERIFY(var3.equals(var3));
+ QVERIFY(var3.equals(var4));
+
+ QVERIFY(var4.equals(var1));
+ QVERIFY(var4.equals(var2));
+ QVERIFY(var4.equals(var3));
+ QVERIFY(var4.equals(var4));
+ }
QScriptEngine otherEngine;
QTest::ignoreMessage(QtWarningMsg, "QScriptValue::equals: "