aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4jscall_p.h
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2023-10-03 17:44:20 +0200
committerUlf Hermann <ulf.hermann@qt.io>2023-10-07 19:00:16 +0200
commit1d8859ce3a3d161ffa2ccd74f195b276795a5af5 (patch)
tree590e495e60841a9cabe3783800771be82be541a5 /src/qml/jsruntime/qv4jscall_p.h
parentbb698b7f2e974a23b688dd15393f6a550448a5a8 (diff)
QtQml: Fix return type constructions when calling methods
We now expect the return type to be initialized in all cases. This is in line with what the various metacall() methods expect. Unifying this behavior makes it much easier to reason about and avoids complicated bugs and memory leaks. The code generated by QmlCompiler always passes initialized values for the return type anyway. Amends commit 4f1b9156a48e44cf1f127a4563d0ac69ab436f12 Amends commit 02c4c817fe1cfa4766c56759be99fb081382a586 Change-Id: I26c016676dd82c91d6ef81762b5c4b599f6f7f72 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/qml/jsruntime/qv4jscall_p.h')
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h26
1 files changed, 17 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index 82a83fd06f..06a8e62761 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -125,7 +125,8 @@ ReturnedValue convertAndCall(
types[i + 1] = argumentType;
if (const qsizetype argumentSize = argumentType.sizeOf()) {
Q_ALLOCA_VAR(void, argument, argumentSize);
- argumentType.construct(argument);
+ if (argumentType.flags() & QMetaType::NeedsConstruction)
+ argumentType.construct(argument);
if (i < argc)
ExecutionEngine::metaTypeFromJS(argv[i], argumentType, argument);
values[i + 1] = argument;
@@ -139,6 +140,8 @@ ReturnedValue convertAndCall(
if (const qsizetype returnSize = types[0].sizeOf()) {
Q_ALLOCA_ASSIGN(void, returnValue, returnSize);
values[0] = returnValue;
+ if (types[0].flags() & QMetaType::NeedsConstruction)
+ types[0].construct(returnValue);
} else {
values[0] = nullptr;
}
@@ -151,13 +154,16 @@ ReturnedValue convertAndCall(
ReturnedValue result;
if (values[0]) {
result = engine->metaTypeToJS(types[0], values[0]);
- types[0].destruct(values[0]);
+ if (types[0].flags() & QMetaType::NeedsDestruction)
+ types[0].destruct(values[0]);
} else {
result = Encode::undefined();
}
- for (qsizetype i = 1, end = numFunctionArguments + 1; i < end; ++i)
- types[i].destruct(values[i]);
+ for (qsizetype i = 1, end = numFunctionArguments + 1; i < end; ++i) {
+ if (types[i].flags() & QMetaType::NeedsDestruction)
+ types[i].destruct(values[i]);
+ }
return result;
}
@@ -477,10 +483,9 @@ void coerceAndCall(
memcpy(transformedArguments, argv, (argc + 1) * sizeof(void *));
if (frameReturn == QMetaType::fromType<QVariant>()) {
- void *returnValue = argv[0];
- new (returnValue) QVariant(returnType);
- transformedResult = transformedArguments[0]
- = static_cast<QVariant *>(returnValue)->data();
+ QVariant *returnValue = static_cast<QVariant *>(argv[0]);
+ *returnValue = QVariant(returnType);
+ transformedResult = transformedArguments[0] = returnValue->data();
returnsQVariantWrapper = true;
} else if (returnType.sizeOf() > 0) {
Q_ALLOCA_ASSIGN(void, transformedResult, returnType.sizeOf());
@@ -545,8 +550,11 @@ void coerceAndCall(
call(transformedArguments, numFunctionArguments);
if (transformedResult && !returnsQVariantWrapper) {
- if (frameReturn.sizeOf() > 0)
+ if (frameReturn.sizeOf() > 0) {
+ if (frameReturn.flags() & QMetaType::NeedsDestruction)
+ frameReturn.destruct(argv[0]);
coerce(engine, returnType, transformedResult, frameReturn, argv[0]);
+ }
if (returnType.flags() & QMetaType::NeedsDestruction)
returnType.destruct(transformedResult);
}