aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-09-10 17:13:10 +0200
committerLars Knoll <lars.knoll@digia.com>2014-09-17 08:13:11 +0200
commit3dbe05f6bf3fd51ce8097c35f6c7f12b39acb0f6 (patch)
tree444ed433aa02085357b589b19b28f4bc1c243320 /src/qml/jsapi
parentcfe1a8152c948a4586ffa1fe79b47f9a0e88beb5 (diff)
Fix mapping of JS objects/arrays to C++
[ChangeLog][QtQml][Important Behavior Changes] When a JavaScript object/array is passed to C++ through a QVariant, the engine no longer immediately converts the object recursively into a QVariantMap or QVariantList but instead stores a QJSValue in the QVariant. This prevents a loss of data when the JS object contains non-primitive types such as function objects for example. Code that expects the variant type to be exactly QVariant::Map or QVariant::List may need to be adapted. Registered conversion functions however ensure that code that merely calls toMap() or toList() continues to work. Task-number: QTBUG-40431 Change-Id: I1dbc1d5f8e78ad28bb62db3681b9a0b34557e7f5 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r--src/qml/jsapi/qjsengine.cpp27
-rw-r--r--src/qml/jsapi/qjsvalue.cpp69
-rw-r--r--src/qml/jsapi/qjsvalue_p.h7
3 files changed, 72 insertions, 31 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 58251fac96..0d2b394cd6 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -420,17 +420,19 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
QV4::ScopedValue v(scope, vp->getValue(engine->m_v4Engine));
return engine->metaTypeFromJS(v, type, ptr);
} else if (vp->value.isEmpty()) {
- // have a string based value without engine. Do conversion manually
- if (type == QMetaType::Bool) {
- *reinterpret_cast<bool*>(ptr) = vp->string.length() != 0;
- return true;
- }
- if (type == QMetaType::QString) {
- *reinterpret_cast<QString*>(ptr) = vp->string;
- return true;
- }
- double d = QV4::RuntimeHelpers::stringToNumber(vp->string);
- switch (type) {
+ if (vp->unboundData.userType() == QMetaType::QString) {
+ QString string = vp->unboundData.toString();
+ // have a string based value without engine. Do conversion manually
+ if (type == QMetaType::Bool) {
+ *reinterpret_cast<bool*>(ptr) = string.length() != 0;
+ return true;
+ }
+ if (type == QMetaType::QString) {
+ *reinterpret_cast<QString*>(ptr) = string;
+ return true;
+ }
+ double d = QV4::RuntimeHelpers::stringToNumber(string);
+ switch (type) {
case QMetaType::Int:
*reinterpret_cast<int*>(ptr) = QV4::Primitive::toInt32(d);
return true;
@@ -466,6 +468,9 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
return true;
default:
return false;
+ }
+ } else {
+ return QMetaType::convert(&vp->unboundData.data_ptr(), vp->unboundData.userType(), ptr, type);
}
} else {
switch (type) {
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 891f17762c..47a764e641 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -58,14 +58,14 @@ QV4::ReturnedValue QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
}
if (value.isEmpty()) {
- value = QV4::Encode(engine->newString(string));
+ value = QV4::Encode(engine->v8Engine->fromVariant(unboundData));
PersistentValuePrivate **listRoot = &engine->memoryManager->m_persistentValues;
prev = listRoot;
next = *listRoot;
*prev = this;
if (next)
next->prev = &this->next;
- string = QString();
+ unboundData.clear();
}
return value.asReturnedValue();
}
@@ -353,8 +353,21 @@ bool QJSValue::isVariant() const
*/
QString QJSValue::toString() const
{
- if (d->value.isEmpty())
- return d->string;
+ if (d->value.isEmpty()) {
+ if (d->unboundData.type() == QVariant::Map)
+ return QStringLiteral("[object Object]");
+ else if (d->unboundData.type() == QVariant::List) {
+ const QVariantList list = d->unboundData.toList();
+ QString result;
+ for (int i = 0; i < list.count(); ++i) {
+ if (i > 0)
+ result.append(QLatin1Char(','));
+ result.append(list.at(i).toString());
+ }
+ return result;
+ }
+ return d->unboundData.toString();
+ }
return d->value.toQStringNoThrow();
}
@@ -372,8 +385,14 @@ QString QJSValue::toString() const
*/
double QJSValue::toNumber() const
{
- if (d->value.isEmpty())
- return RuntimeHelpers::stringToNumber(d->string);
+ if (d->value.isEmpty()) {
+ if (d->unboundData.type() == QVariant::String)
+ return RuntimeHelpers::stringToNumber(d->unboundData.toString());
+ else if (d->unboundData.canConvert<double>())
+ return d->unboundData.value<double>();
+ else
+ return std::numeric_limits<double>::quiet_NaN();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
double dbl = d->value.toNumber();
@@ -398,8 +417,12 @@ double QJSValue::toNumber() const
*/
bool QJSValue::toBool() const
{
- if (d->value.isEmpty())
- return d->string.length() > 0;
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return d->unboundData.toString().length() > 0;
+ else
+ return d->unboundData.toBool();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
bool b = d->value.toBoolean();
@@ -424,8 +447,12 @@ bool QJSValue::toBool() const
*/
qint32 QJSValue::toInt() const
{
- if (d->value.isEmpty())
- return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(d->string));
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ else
+ return d->unboundData.toInt();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
qint32 i = d->value.toInt32();
@@ -450,8 +477,12 @@ qint32 QJSValue::toInt() const
*/
quint32 QJSValue::toUInt() const
{
- if (d->value.isEmpty())
- return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(d->string));
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ else
+ return d->unboundData.toUInt();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
quint32 u = d->value.toUInt32();
@@ -487,7 +518,7 @@ quint32 QJSValue::toUInt() const
QVariant QJSValue::toVariant() const
{
if (d->value.isEmpty())
- return QVariant(d->string);
+ return d->unboundData;
return QV4::VariantObject::toVariant(d->value);
}
@@ -775,8 +806,10 @@ bool QJSValue::equals(const QJSValue& other) const
{
if (d->value.isEmpty()) {
if (other.d->value.isEmpty())
- return d->string == other.d->string;
- return js_equal(d->string, QV4::ValueRef(other.d->value));
+ return d->unboundData == other.d->unboundData;
+ if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return false;
+ return js_equal(d->unboundData.toString(), QV4::ValueRef(other.d->value));
}
if (other.d->value.isEmpty())
return other.equals(*this);
@@ -810,9 +843,11 @@ bool QJSValue::strictlyEquals(const QJSValue& other) const
{
if (d->value.isEmpty()) {
if (other.d->value.isEmpty())
- return d->string == other.d->string;
+ return d->unboundData == other.d->unboundData;
+ if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return false;
if (other.d->value.isString())
- return d->string == other.d->value.stringValue()->toQString();
+ return d->unboundData.toString() == other.d->value.stringValue()->toQString();
return false;
}
if (other.d->value.isEmpty())
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index e66c1bcde4..43a3a74e38 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -51,6 +51,7 @@
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
+#include <private/qflagpointer_p.h>
QT_BEGIN_NAMESPACE
@@ -72,8 +73,8 @@ public:
Q_ASSERT(!value.isEmpty());
}
QJSValuePrivate(const QString &s)
- : PersistentValuePrivate(QV4::Primitive::emptyValue().asReturnedValue())
- , string(s)
+ : PersistentValuePrivate(QV4::Primitive::emptyValue().asReturnedValue()),
+ unboundData(s)
{
}
@@ -81,7 +82,7 @@ public:
static QJSValuePrivate *get(const QJSValue &v) { return v.d; }
- QString string;
+ QVariant unboundData;
};
QT_END_NAMESPACE