aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsapi')
-rw-r--r--src/qml/jsapi/qjsengine.cpp6
-rw-r--r--src/qml/jsapi/qjsengine.h22
-rw-r--r--src/qml/jsapi/qjsmanagedvalue.cpp13
-rw-r--r--src/qml/jsapi/qjsprimitivevalue.h6
-rw-r--r--src/qml/jsapi/qjsvalue.cpp30
-rw-r--r--src/qml/jsapi/qjsvalue_p.h2
6 files changed, 64 insertions, 15 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 374d170019..45990f6996 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -928,7 +928,8 @@ bool QJSEngine::convertV2(const QJSValue &value, QMetaType metaType, void *ptr)
return convertString(*string, metaType, ptr);
// Does not need scoping since QJSValue still holds on to the value.
- return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), metaType, ptr);
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&value)),
+ metaType, ptr);
}
bool QJSEngine::convertVariant(const QVariant &value, QMetaType metaType, void *ptr)
@@ -1155,7 +1156,8 @@ void QJSEngine::throwError(QJSValue::ErrorType errorType, const QString &message
*/
void QJSEngine::throwError(const QJSValue &error)
{
- m_v4Engine->throwError(QJSValuePrivate::asReturnedValue(&error));
+ // safe, QJSValue holds a persistent reference
+ m_v4Engine->throwError(QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&error)));
}
/*!
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index dbeecb45ae..a16ac60603 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -145,6 +145,18 @@ public:
}
}
+ if constexpr (std::is_same_v<T, double>) {
+ if (sourceType == QMetaType::fromType<int>())
+ return double(*static_cast<const int *>(value.constData()));
+ }
+
+ if constexpr (std::is_same_v<T, int>) {
+ if (sourceType == QMetaType::fromType<double>()) {
+ return QJSNumberCoercion::toInteger(
+ *static_cast<const double *>(value.constData()));
+ }
+ }
+
if constexpr (std::is_same_v<QObject, std::remove_const_t<std::remove_pointer_t<T>>>) {
if (sourceType.flags() & QMetaType::PointerToQObject) {
return *static_cast<QObject *const *>(value.constData());
@@ -254,6 +266,16 @@ public:
return from;
}
+ if constexpr (std::is_same_v<To, double>) {
+ if constexpr (std::is_same_v<From, int>)
+ return double(from);
+ }
+
+ if constexpr (std::is_same_v<To, int>) {
+ if constexpr (std::is_same_v<From, double>)
+ return QJSNumberCoercion::toInteger(from);
+ }
+
{
const QMetaType sourceType = QMetaType::fromType<From>();
const QMetaType targetType = QMetaType::fromType<To>();
diff --git a/src/qml/jsapi/qjsmanagedvalue.cpp b/src/qml/jsapi/qjsmanagedvalue.cpp
index a4f2f97432..b429784a96 100644
--- a/src/qml/jsapi/qjsmanagedvalue.cpp
+++ b/src/qml/jsapi/qjsmanagedvalue.cpp
@@ -787,7 +787,8 @@ void QJSManagedValue::setProperty(const QString &name, const QJSValue &value)
return;
}
QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
- obj->put(key, QJSValuePrivate::convertToReturnedValue(scope.engine, value));
+ QV4::ScopedValue val(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, value));
+ obj->put(key, val);
}
}
@@ -905,7 +906,10 @@ void QJSManagedValue::setProperty(quint32 arrayIndex, const QJSValue &value)
"Value was created in different engine.");
return;
}
- obj->put(arrayIndex, QJSValuePrivate::convertToReturnedValue(v4, value));
+ v4 = obj->engine(); // in case value was primitive
+ QV4::Scope scope(v4);
+ QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(v4, value));
+ obj->put(arrayIndex, v);
}
}
@@ -1120,6 +1124,8 @@ QJSManagedValue QJSManagedValue::jsMetaInstantiate(const QJSValueList &values) c
*result.d = c->engine()->newObject(c->d());
QV4::Object *o = result.d->as<QV4::Object>();
+ QV4::Scope scope(engine);
+ QV4::ScopedValue val(scope);
for (uint i = 0, end = qMin(qsizetype(c->d()->size), values.size()); i < end; ++i) {
const QJSValue &arg = values[i];
if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
@@ -1127,7 +1133,8 @@ QJSManagedValue QJSManagedValue::jsMetaInstantiate(const QJSValueList &values) c
"Argument was created in different engine.");
return QJSManagedValue();
}
- o->setProperty(i, QJSValuePrivate::convertToReturnedValue(engine, arg));
+ val = QJSValuePrivate::convertToReturnedValue(engine, arg);
+ o->setProperty(i, val);
}
return result;
diff --git a/src/qml/jsapi/qjsprimitivevalue.h b/src/qml/jsapi/qjsprimitivevalue.h
index 49a00ed180..ea65aa5610 100644
--- a/src/qml/jsapi/qjsprimitivevalue.h
+++ b/src/qml/jsapi/qjsprimitivevalue.h
@@ -777,10 +777,14 @@ private:
}
union {
- bool m_bool = false;
+ bool m_bool;
int m_int;
double m_double;
QString m_string;
+
+ // Dummy value to trigger initialization of the whole storage.
+ // We don't want to see maybe-uninitialized warnings every time we access m_string.
+ std::byte m_zeroInitialize[sizeof(QString)] = {};
};
Type m_type = Undefined;
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 8717462729..943808b322 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -902,7 +902,10 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
if (const QString *string = QJSValuePrivate::asQString(&other))
QJSValuePrivate::setString(this, *string);
else
- QJSValuePrivate::setValue(this, QJSValuePrivate::asReturnedValue(&other));
+ // fomReturnedValue is safe, as the QJSValue still has a persistent reference
+ QJSValuePrivate::setValue(
+ this,
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
return *this;
}
@@ -990,17 +993,25 @@ static bool js_equal(const QString &string, const QV4::Value &value)
*/
bool QJSValue::equals(const QJSValue& other) const
{
+ // QJSValue stores heap items in persistent values, which already ensures marking
+ // therefore, fromReturnedValue below is safe
if (const QString *string = QJSValuePrivate::asQString(this)) {
if (const QString *otherString = QJSValuePrivate::asQString(&other))
return *string == *otherString;
- return js_equal(*string, QJSValuePrivate::asReturnedValue(&other));
+ return js_equal(
+ *string,
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
}
- if (const QString *otherString = QJSValuePrivate::asQString(&other))
- return js_equal(*otherString, QJSValuePrivate::asReturnedValue(this));
+ if (const QString *otherString = QJSValuePrivate::asQString(&other)) {
+ return js_equal(
+ *otherString,
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)));
+ }
- return Runtime::CompareEqual::call(QJSValuePrivate::asReturnedValue(this),
- QJSValuePrivate::asReturnedValue(&other));
+ return Runtime::CompareEqual::call(
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)),
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
}
/*!
@@ -1041,8 +1052,11 @@ bool QJSValue::strictlyEquals(const QJSValue& other) const
return false;
}
- return RuntimeHelpers::strictEqual(QJSValuePrivate::asReturnedValue(this),
- QJSValuePrivate::asReturnedValue(&other));
+ // QJSValue stores heap objects persistently, so we can be sure that they'll be marked
+ // thus we can safely use fromReturnedValue
+ return RuntimeHelpers::strictEqual(
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)),
+ QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&other)));
}
/*!
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index b95e76e76e..6bc731aace 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -189,7 +189,7 @@ public:
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
{
QJSValue result;
- setValue(&result, d);
+ setValue(&result, QV4::Value::fromReturnedValue(d));
return result;
}