diff options
Diffstat (limited to 'src/qml/jsapi')
| -rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 6 | ||||
| -rw-r--r-- | src/qml/jsapi/qjsengine.h | 22 | ||||
| -rw-r--r-- | src/qml/jsapi/qjsmanagedvalue.cpp | 13 | ||||
| -rw-r--r-- | src/qml/jsapi/qjsprimitivevalue.h | 6 | ||||
| -rw-r--r-- | src/qml/jsapi/qjsvalue.cpp | 30 | ||||
| -rw-r--r-- | src/qml/jsapi/qjsvalue_p.h | 2 |
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; } |
