diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-10-19 15:49:32 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-10-21 09:47:01 +0200 |
commit | 9021f46cc0ce1d89d5d62ccb622085437c8350a8 (patch) | |
tree | 0f205a21ca3282d62c71ada8babcb83da3e334da /src/qml/jsruntime/qv4qobjectwrapper.cpp | |
parent | e37809ec62927f33de2d6ae07e2610d6382b5466 (diff) |
QV4::QObjectWrapper: Improve overload resolution
QQmlV4Function should be used as the last fallback if there are other
options available. Also, take QVariantMap into account.
Change-Id: I9ebf39f4f860cf3bf44c6cbc80efbac7ea30c70b
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4qobjectwrapper.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 98 |
1 files changed, 59 insertions, 39 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 517fbab6f1..40398cb648 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1585,17 +1585,17 @@ static int MatchScore(const QV4::Value &actual, QMetaType conversionMetaType) else if (v.canConvert(conversionMetaType)) return 5; return 10; - } else if (conversionType == QMetaType::QJsonObject) { - return 5; - } else if (conversionType == qMetaTypeId<QJSValue>()) { - return 0; - } else { - return 10; } - } else { - return 10; + if (conversionType == QMetaType::QJsonObject) + return 5; + if (conversionType == qMetaTypeId<QJSValue>()) + return 0; + if (conversionType == QMetaType::QVariantMap) + return 5; } + + return 10; } static int numDefinedArguments(QV4::CallData *callArgs) @@ -1708,46 +1708,66 @@ static const QQmlPropertyData *ResolveOverloaded( const QQmlPropertyData *best = nullptr; int bestParameterScore = INT_MAX; - int bestMatchScore = INT_MAX; + int bestMaxMatchScore = INT_MAX; + int bestSumMatchScore = INT_MAX; QV4::Scope scope(engine); QV4::ScopedValue v(scope); for (int i = 0; i < methodCount; ++i) { const QQmlPropertyData *attempt = methods + i; - QQmlMetaObject::ArgTypeStorage storage; - int methodArgumentCount = 0; - if (attempt->hasArguments()) { - if (attempt->isConstructor()) { - if (!object.constructorParameterTypes(attempt->coreIndex(), &storage, nullptr)) - continue; - } else { - if (!object.methodParameterTypes(attempt->coreIndex(), &storage, nullptr)) - continue; - } - methodArgumentCount = storage.size(); - } - if (methodArgumentCount > argumentCount) - continue; // We don't have sufficient arguments to call this method + // QQmlV4Function overrides anything that doesn't provide the exact number of arguments + int methodParameterScore = 1; + // QQmlV4Function overrides the "no idea" option, which is 10 + int maxMethodMatchScore = 9; + // QQmlV4Function cannot provide a best sum of match scores as we don't match the arguments + int sumMethodMatchScore = bestSumMatchScore; - int methodParameterScore = definedArgumentCount - methodArgumentCount; - if (methodParameterScore > bestParameterScore) - continue; // We already have a better option + if (!attempt->isV4Function()) { + QQmlMetaObject::ArgTypeStorage storage; + int methodArgumentCount = 0; + if (attempt->hasArguments()) { + if (attempt->isConstructor()) { + if (!object.constructorParameterTypes(attempt->coreIndex(), &storage, nullptr)) + continue; + } else { + if (!object.methodParameterTypes(attempt->coreIndex(), &storage, nullptr)) + continue; + } + methodArgumentCount = storage.size(); + } - int methodMatchScore = 0; - for (int ii = 0; ii < methodArgumentCount; ++ii) { - methodMatchScore += MatchScore((v = QV4::Value::fromStaticValue(callArgs->args[ii])), - storage[ii]); + if (methodArgumentCount > argumentCount) + continue; // We don't have sufficient arguments to call this method + + methodParameterScore = (definedArgumentCount == methodArgumentCount) + ? 0 + : (definedArgumentCount - methodArgumentCount + 1); + if (methodParameterScore > bestParameterScore) + continue; // We already have a better option + + maxMethodMatchScore = 0; + sumMethodMatchScore = 0; + for (int ii = 0; ii < methodArgumentCount; ++ii) { + const int score = MatchScore((v = QV4::Value::fromStaticValue(callArgs->args[ii])), + storage[ii]); + maxMethodMatchScore = qMax(maxMethodMatchScore, score); + sumMethodMatchScore += score; + } } - if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) { + if (bestParameterScore > methodParameterScore || bestMaxMatchScore > maxMethodMatchScore + || (bestParameterScore == methodParameterScore + && bestMaxMatchScore == maxMethodMatchScore + && bestSumMatchScore > sumMethodMatchScore)) { best = attempt; bestParameterScore = methodParameterScore; - bestMatchScore = methodMatchScore; + bestMaxMatchScore = maxMethodMatchScore; + bestSumMatchScore = sumMethodMatchScore; } - if (bestParameterScore == 0 && bestMatchScore == 0) + if (bestParameterScore == 0 && bestMaxMatchScore == 0) break; // We can't get better than that }; @@ -2259,6 +2279,12 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value * return call(); }; + if (d()->methodCount != 1) { + method = ResolveOverloaded(object, d()->methods, d()->methodCount, v4, callData); + if (method == nullptr) + return Encode::undefined(); + } + if (method->isV4Function()) { return doCall([&]() { QV4::ScopedValue rv(scope, QV4::Value::undefinedValue()); @@ -2272,12 +2298,6 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value * }); } - if (d()->methodCount != 1) { - method = ResolveOverloaded(object, d()->methods, d()->methodCount, v4, callData); - if (method == nullptr) - return Encode::undefined(); - } - return doCall([&]() { return CallPrecise(object, *method, v4, callData); }); } |