diff options
| author | Fabian Kosmale <fabian.kosmale@qt.io> | 2024-12-12 14:39:37 +0100 |
|---|---|---|
| committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2024-12-18 11:55:52 +0100 |
| commit | a5feec81934ab0b074d6a8c7621b591851f6b544 (patch) | |
| tree | ca409667609e35a3a5dec64ee2cdd14cf59f634f /src/qml/jsapi/qjsengine.cpp | |
| parent | ac2d9bf0f2c32bdd6a64b8421c414a28369cbe2e (diff) | |
QtQml: Avoid potential gc issues
Implicitly constructing a value from a ReturnedValue muddies the
responsibility for ensuring that the gc can find the object.
With this change, we disable the implicit conversion. The expectation
for lifetime management is now:
- If a ReturnedValue is stored on the C++ stack, it must be put into a
QV4::Scoped class (or there should be a comment why not doing so is
safe). Passing a ReturnedValue to a function should no longer be
possible, unless the function takes a ReturnedValue, in which case the
expectation is that it stores the value in a place where it can be
seen by the gc, before doing anything that could trigger a gc run.
Using Value::fromReturnedValue can still be used to pass a Value on,
but in that case, the expectation is that there is a comment which
explains why this is safe.
- If a QV4::Value is obtained from a function call, it ought to be
stored in a ScopedValue, too. We currently can't enforce this easily,
so this should be checked during code review. A possible way forward
would be to disallow returning Values, but that would be a larger
change, and is deferred to the future.
- If a functions has a QV4::Value parameter, it's the callers'
responsibilty to ensure that the gc can find it.
Pick-to: 6.9 6.8 6.5
Fixes: QTBUG-131961
Change-Id: Iea055589d35a5f1ac36fe376d4389eb81de87961
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/jsapi/qjsengine.cpp')
| -rw-r--r-- | src/qml/jsapi/qjsengine.cpp | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index 25a72cb7a2..e6ed87dab9 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -934,7 +934,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) @@ -1166,7 +1167,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))); } /*! |
