From 628a5cd0669dbfb6a4f2b60f5b59b044f8ca2bbb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 1 Jul 2011 16:31:05 +1000 Subject: [PATCH] Variants should compare as equal We need to implement an object comparison callback to ensure that two variants with identical values (although different JS objects) compare as equal. We also add a v8 autotest for this callback. Change-Id: Idd1ab602d31b398a937d4df4a7bd091aa205de24 Reviewed-on: http://codereview.qt.nokia.com/989 Reviewed-by: Aaron Kennedy --- src/declarative/qml/v8/qv8engine.cpp | 31 +++++ src/declarative/qml/v8/qv8variantwrapper.cpp | 2 + tests/auto/declarative/v8/tst_v8.cpp | 6 + tests/auto/declarative/v8/v8main.cpp | 1 + tests/auto/declarative/v8/v8test.cpp | 176 +++++++++++++++++++++++++- tests/auto/declarative/v8/v8test.h | 1 + 6 files changed, 215 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index cb89d0f..67679b9 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -66,6 +66,34 @@ // QDeclarativeEngine is not available QT_BEGIN_NAMESPACE +static bool ObjectComparisonCallback(v8::Local lhs, v8::Local rhs) +{ + if (lhs == rhs) + return true; + + QV8ObjectResource *lhsr = static_cast(lhs->GetExternalResource()); + QV8ObjectResource *rhsr = static_cast(rhs->GetExternalResource()); + + Q_ASSERT(lhsr->engine == rhsr->engine); + + if (lhsr && rhsr) { + QV8ObjectResource::ResourceType lhst = lhsr->resourceType(); + QV8ObjectResource::ResourceType rhst = rhsr->resourceType(); + + switch (lhst) { + case QV8ObjectResource::VariantType: + if (rhst == QV8ObjectResource::VariantType) + return lhsr->engine->variantWrapper()->toVariant(lhsr) == + lhsr->engine->variantWrapper()->toVariant(rhsr); + break; + default: + break; + } + } + + return false; +} + QV8Engine::QV8Engine() : m_xmlHttpRequestData(0), m_sqlDatabaseData(0), m_listModelData(0) { @@ -109,6 +137,8 @@ void QV8Engine::init(QDeclarativeEngine *engine) qPersistentRegister(m_context); v8::Context::Scope context_scope(m_context); + v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback); + m_stringWrapper.init(); m_contextWrapper.init(this); m_qobjectWrapper.init(this); @@ -658,6 +688,7 @@ void QV8Engine::setExtensionData(int index, Deletable *data) v8::Handle QV8Engine::gc(const v8::Arguments &args) { + Q_UNUSED(args); gc(); return v8::Undefined(); } diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp index 9d486d0..a5602fb 100644 --- a/src/declarative/qml/v8/qv8variantwrapper.cpp +++ b/src/declarative/qml/v8/qv8variantwrapper.cpp @@ -76,6 +76,7 @@ void QV8VariantWrapper::init(QV8Engine *engine) v8::Local ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); + ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, m_toString, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); @@ -87,6 +88,7 @@ void QV8VariantWrapper::init(QV8Engine *engine) v8::Local ft = v8::FunctionTemplate::New(); ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); ft->InstanceTemplate()->SetHasExternalResource(true); + ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0, m_preserve, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); diff --git a/tests/auto/declarative/v8/tst_v8.cpp b/tests/auto/declarative/v8/tst_v8.cpp index 4749da0..32d100e 100644 --- a/tests/auto/declarative/v8/tst_v8.cpp +++ b/tests/auto/declarative/v8/tst_v8.cpp @@ -54,6 +54,7 @@ private slots: void cleanupTestCase() {} void eval(); + void userobjectcompare(); }; void tst_v8::eval() @@ -61,6 +62,11 @@ void tst_v8::eval() QVERIFY(v8test_eval()); } +void tst_v8::userobjectcompare() +{ + QVERIFY(v8test_userobjectcompare()); +} + int main(int argc, char *argv[]) { V8::SetFlagsFromCommandLine(&argc, argv, true); diff --git a/tests/auto/declarative/v8/v8main.cpp b/tests/auto/declarative/v8/v8main.cpp index bf37e2d..5930f53 100644 --- a/tests/auto/declarative/v8/v8main.cpp +++ b/tests/auto/declarative/v8/v8main.cpp @@ -11,6 +11,7 @@ int main(int argc, char *argv[]) v8::V8::SetFlagsFromCommandLine(&argc, argv, true); RUN_TEST(eval); + RUN_TEST(userobjectcompare); return -1; } diff --git a/tests/auto/declarative/v8/v8test.cpp b/tests/auto/declarative/v8/v8test.cpp index 9b80b08..27d39c5 100644 --- a/tests/auto/declarative/v8/v8test.cpp +++ b/tests/auto/declarative/v8/v8test.cpp @@ -48,6 +48,7 @@ using namespace v8; #define VERIFY(expr) { \ if (!(expr)) { \ + fprintf(stderr, "FAIL: %s:%d %s\n", __FILE__, __LINE__, # expr); \ _testPassed = false; \ goto cleanup; \ } \ @@ -59,11 +60,11 @@ bool v8test_eval() BEGINTEST(); HandleScope handle_scope; - v8::Persistent context = Context::New(); + Persistent context = Context::New(); Context::Scope context_scope(context); Local qmlglobal = Object::New(); - qmlglobal->Set(String::New("a"), v8::Integer::New(1922)); + qmlglobal->Set(String::New("a"), Integer::New(1922)); Local