From 2791a13757912cfd0d5cc6a83f228fab5c1645ae Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 16 Aug 2012 12:16:38 +0200 Subject: [PATCH] Get rid of engine-wide state of visited objects for type conversion MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Pass the state through to internal conversion functions instead. Change-Id: Ifab9a9472d7271ee5da103ed915427dfd4f2b15b Reviewed-by: Michael Brasser Reviewed-by: Jędrzej Nowacki --- src/qml/qml/v8/qv8engine.cpp | 30 +++++++++++++++++------------- src/qml/qml/v8/qv8engine_p.h | 14 ++++++++++---- src/qml/qml/v8/qv8jsonwrapper.cpp | 34 +++++++++++++++++----------------- src/qml/qml/v8/qv8jsonwrapper_p.h | 22 ++++++++++++++-------- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index d86fc6b..96110ed 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -924,18 +924,19 @@ v8::Local QV8Engine::variantListToJS(const QVariantList &lst) // The result is a QVariantList with length equal to the length // of the JS Array, and elements being the JS Array's elements // converted to QVariants, recursively. -QVariantList QV8Engine::variantListFromJS(v8::Handle jsArray) +QVariantList QV8Engine::variantListFromJS(v8::Handle jsArray, + QSet &visitedObjects) { QVariantList result; int hash = jsArray->GetIdentityHash(); - if (visitedConversionObjects.contains(hash)) + if (visitedObjects.contains(hash)) return result; // Avoid recursion. v8::HandleScope handleScope; - visitedConversionObjects.insert(hash); + visitedObjects.insert(hash); uint32_t length = jsArray->Length(); for (uint32_t i = 0; i < length; ++i) - result.append(variantFromJS(jsArray->Get(i))); - visitedConversionObjects.remove(hash); + result.append(variantFromJS(jsArray->Get(i), visitedObjects)); + visitedObjects.remove(hash); return result; } @@ -956,7 +957,8 @@ v8::Local QV8Engine::variantMapToJS(const QVariantMap &vmap) // The result is a QVariantMap with keys being the property names // of the object, and values being the values of the JS object's // properties converted to QVariants, recursively. -QVariantMap QV8Engine::variantMapFromJS(v8::Handle jsObject) +QVariantMap QV8Engine::variantMapFromJS(v8::Handle jsObject, + QSet &visitedObjects) { QVariantMap result; @@ -967,16 +969,17 @@ QVariantMap QV8Engine::variantMapFromJS(v8::Handle jsObject) return result; int hash = jsObject->GetIdentityHash(); - if (visitedConversionObjects.contains(hash)) + if (visitedObjects.contains(hash)) return result; // Avoid recursion. - visitedConversionObjects.insert(hash); + visitedObjects.insert(hash); // TODO: Only object's own property names. Include non-enumerable properties. for (uint32_t i = 0; i < length; ++i) { v8::Handle name = propertyNames->Get(i); - result.insert(QJSConverter::toString(name->ToString()), variantFromJS(jsObject->Get(name))); + result.insert(QJSConverter::toString(name->ToString()), + variantFromJS(jsObject->Get(name), visitedObjects)); } - visitedConversionObjects.remove(hash); + visitedObjects.remove(hash); return result; } @@ -1261,7 +1264,8 @@ v8::Handle QV8Engine::variantToJS(const QVariant &value) // Date -> QVariant(QDateTime) // RegExp -> QVariant(QRegExp) // [Any other object] -> QVariantMap(...) -QVariant QV8Engine::variantFromJS(v8::Handle value) +QVariant QV8Engine::variantFromJS(v8::Handle value, + QSet &visitedObjects) { Q_ASSERT(!value.IsEmpty()); if (value->IsUndefined()) @@ -1278,7 +1282,7 @@ QVariant QV8Engine::variantFromJS(v8::Handle value) return QJSConverter::toString(value->ToString()); Q_ASSERT(value->IsObject()); if (value->IsArray()) - return variantListFromJS(v8::Handle::Cast(value)); + return variantListFromJS(v8::Handle::Cast(value), visitedObjects); if (value->IsDate()) return QJSConverter::toDateTime(v8::Handle::Cast(value)); if (value->IsRegExp()) @@ -1287,7 +1291,7 @@ QVariant QV8Engine::variantFromJS(v8::Handle value) return variantValue(value); if (isQObject(value)) return qVariantFromValue(qtObjectFromJS(value)); - return variantMapFromJS(value->ToObject()); + return variantMapFromJS(value->ToObject(), visitedObjects); } v8::Handle QV8Engine::jsonValueToJS(const QJsonValue &value) diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 7b0afaf..d885c77 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -371,13 +371,16 @@ public: v8::Local newVariant(const QVariant &variant); v8::Local variantListToJS(const QVariantList &lst); - QVariantList variantListFromJS(v8::Handle jsArray); + inline QVariantList variantListFromJS(v8::Handle jsArray) + { QSet visitedObjects; return variantListFromJS(jsArray, visitedObjects); } v8::Local variantMapToJS(const QVariantMap &vmap); - QVariantMap variantMapFromJS(v8::Handle jsObject); + inline QVariantMap variantMapFromJS(v8::Handle jsObject) + { QSet visitedObjects; return variantMapFromJS(jsObject, visitedObjects); } v8::Handle variantToJS(const QVariant &value); - QVariant variantFromJS(v8::Handle value); + inline QVariant variantFromJS(v8::Handle value) + { QSet visitedObjects; return variantFromJS(value, visitedObjects); } v8::Handle jsonValueToJS(const QJsonValue &value); QJsonValue jsonValueFromJS(v8::Handle value); @@ -405,7 +408,6 @@ public: int consoleCountHelper(const QString &file, quint16 line, quint16 column); QObject *qtObjectFromJS(v8::Handle value); - QSet visitedConversionObjects; static QDateTime qtDateTimeFromJsDate(double jsDate); @@ -472,6 +474,10 @@ protected: double qtDateTimeToJsDate(const QDateTime &dt); private: + QVariantList variantListFromJS(v8::Handle jsArray, QSet &visitedObjects); + QVariantMap variantMapFromJS(v8::Handle jsObject, QSet &visitedObjects); + QVariant variantFromJS(v8::Handle value, QSet &visitedObjects); + static v8::Persistent *findOwnerAndStrength(QObject *object, bool *shouldBeStrong); typedef QScriptIntrusiveList ValueList; diff --git a/src/qml/qml/v8/qv8jsonwrapper.cpp b/src/qml/qml/v8/qv8jsonwrapper.cpp index ff8cc4f..ff8b69f 100644 --- a/src/qml/qml/v8/qv8jsonwrapper.cpp +++ b/src/qml/qml/v8/qv8jsonwrapper.cpp @@ -43,10 +43,6 @@ #include "qv8engine_p.h" #include "qjsconverter_impl_p.h" -#include -#include -#include - QT_BEGIN_NAMESPACE QV8JsonWrapper::QV8JsonWrapper() @@ -85,7 +81,8 @@ v8::Handle QV8JsonWrapper::fromJsonValue(const QJsonValue &value) return v8::Undefined(); } -QJsonValue QV8JsonWrapper::toJsonValue(v8::Handle value) +QJsonValue QV8JsonWrapper::toJsonValue(v8::Handle value, + QSet &visitedObjects) { if (value->IsString()) return QJsonValue(QJSConverter::toString(value.As())); @@ -94,9 +91,9 @@ QJsonValue QV8JsonWrapper::toJsonValue(v8::Handle value) else if (value->IsBoolean()) return QJsonValue(value->BooleanValue()); else if (value->IsArray()) - return toJsonArray(value.As()); + return toJsonArray(value.As(), visitedObjects); else if (value->IsObject()) - return toJsonObject(value.As()); + return toJsonObject(value.As(), visitedObjects); else if (value->IsNull()) return QJsonValue(QJsonValue::Null); else @@ -111,7 +108,8 @@ v8::Local QV8JsonWrapper::fromJsonObject(const QJsonObject &object) return v8object; } -QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle value) +QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle value, + QSet &visitedObjects) { QJsonObject result; if (!value->IsObject() || value->IsArray() || value->IsFunction()) @@ -119,14 +117,14 @@ QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle value) v8::Handle v8object(value.As()); int hash = v8object->GetIdentityHash(); - if (m_visitedConversionObjects.contains(hash)) { + if (visitedObjects.contains(hash)) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty object (and no error is thrown). return result; } - m_visitedConversionObjects.insert(hash); + visitedObjects.insert(hash); v8::Local propertyNames = m_engine->getOwnPropertyNames(v8object); uint32_t length = propertyNames->Length(); @@ -134,10 +132,11 @@ QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle value) v8::Local name = propertyNames->Get(i); v8::Local propertyValue = v8object->Get(name); if (!propertyValue->IsFunction()) - result.insert(QJSConverter::toString(name->ToString()), toJsonValue(propertyValue)); + result.insert(QJSConverter::toString(name->ToString()), + toJsonValue(propertyValue, visitedObjects)); } - m_visitedConversionObjects.remove(hash); + visitedObjects.remove(hash); return result; } @@ -151,7 +150,8 @@ v8::Local QV8JsonWrapper::fromJsonArray(const QJsonArray &array) return v8array; } -QJsonArray QV8JsonWrapper::toJsonArray(v8::Handle value) +QJsonArray QV8JsonWrapper::toJsonArray(v8::Handle value, + QSet &visitedObjects) { QJsonArray result; if (!value->IsArray()) @@ -159,23 +159,23 @@ QJsonArray QV8JsonWrapper::toJsonArray(v8::Handle value) v8::Handle v8array(value.As()); int hash = v8array->GetIdentityHash(); - if (m_visitedConversionObjects.contains(hash)) { + if (visitedObjects.contains(hash)) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty array (and no error is thrown). return result; } - m_visitedConversionObjects.insert(hash); + visitedObjects.insert(hash); uint32_t length = v8array->Length(); for (uint32_t i = 0; i < length; ++i) { v8::Local element = v8array->Get(i); if (!element->IsFunction()) - result.append(toJsonValue(element)); + result.append(toJsonValue(element, visitedObjects)); } - m_visitedConversionObjects.remove(hash); + visitedObjects.remove(hash); return result; } diff --git a/src/qml/qml/v8/qv8jsonwrapper_p.h b/src/qml/qml/v8/qv8jsonwrapper_p.h index 842a3aa..887e106 100644 --- a/src/qml/qml/v8/qv8jsonwrapper_p.h +++ b/src/qml/qml/v8/qv8jsonwrapper_p.h @@ -57,11 +57,11 @@ #include #include -QT_BEGIN_NAMESPACE +#include +#include +#include -class QJsonValue; -class QJsonObject; -class QJsonArray; +QT_BEGIN_NAMESPACE class QV8Engine; class QV8JsonWrapper @@ -74,17 +74,23 @@ public: void destroy(); v8::Handle fromJsonValue(const QJsonValue &value); - QJsonValue toJsonValue(v8::Handle value); + inline QJsonValue toJsonValue(v8::Handle value) + { QSet visitedObjects; return toJsonValue(value, visitedObjects); } v8::Local fromJsonObject(const QJsonObject &object); - QJsonObject toJsonObject(v8::Handle value); + inline QJsonObject toJsonObject(v8::Handle value) + { QSet visitedObjects; return toJsonObject(value, visitedObjects); } v8::Local fromJsonArray(const QJsonArray &array); - QJsonArray toJsonArray(v8::Handle value); + inline QJsonArray toJsonArray(v8::Handle value) + { QSet visitedObjects; return toJsonArray(value, visitedObjects); } private: + QJsonValue toJsonValue(v8::Handle value, QSet &visitedObjects); + QJsonObject toJsonObject(v8::Handle value, QSet &visitedObjects); + QJsonArray toJsonArray(v8::Handle value, QSet &visitedObjects); + QV8Engine *m_engine; - QSet m_visitedConversionObjects; }; QT_END_NAMESPACE -- 2.7.4