Showing the changes to libraries/script-engine/src/qtscript/ScriptObjectQtProxy.cpp (1 of 3 files). Show all
Unified · Split
| @@ -462,38 +462,51 @@ QVariant ScriptMethodQtProxy::extension(Extension extension, const QVariant& arg · 461 unmodified lines | ||
| 462 | 462 | int parameterConversionFailureId = 0; |
| 463 | 463 | int parameterConversionFailureCount = 0; |
| 464 | 464 | |
| 465 | − for (auto iter = _metas.cbegin(); iter != _metas.end(); ++iter) { | |
| 466 | − const QMetaMethod& meta = *iter; | |
| 465 | + int num_metas = _metas.size(); | |
| 466 | + QVector< QList<ScriptValue> > qScriptArgLists; | |
| 467 | + QVector< QVector <QGenericArgument> > qGenArgsVectors; | |
| 468 | + QVector< QList<QVariant> > qVarArgLists; | |
| 469 | + int conversionPenaltyScore[num_metas]; | |
| 470 | + bool isMetaRejected[num_metas]; | |
| 471 | + qScriptArgLists.resize(num_metas); | |
| 472 | + qGenArgsVectors.resize(num_metas); | |
| 473 | + qVarArgLists.resize(num_metas); | |
| 474 | + | |
| 475 | + for (int i = 0; i < num_metas; i++) { | |
| 476 | + const QMetaMethod& meta = _metas[i]; | |
| 477 | + isMetaRejected[i] = false; | |
| 467 | 478 | int methodNumArgs = meta.parameterCount(); |
| 468 | 479 | if (methodNumArgs != numArgs) { |
| 480 | + isMetaRejected[i] = true; | |
| 469 | 481 | continue; |
| 470 | 482 | } |
| 471 | 483 | |
| 472 | − QList<ScriptValue> qScriptArgList; | |
| 473 | − QList<QVariant> qVarArgList; | |
| 474 | − QGenericArgument qGenArgs[10]; | |
| 484 | + qGenArgsVectors[i].resize(10); | |
| 485 | + conversionPenaltyScore[i] = 0; | |
| 475 | 486 | int conversionFailures = 0; |
| 487 | + | |
| 476 | 488 | for (int arg = 0; arg < numArgs; ++arg) { |
| 477 | 489 | int methodArgTypeId = meta.parameterType(arg); |
| 478 | 490 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); |
| 479 | 491 | QScriptValue argVal = context->argument(arg); |
| 480 | 492 | if (methodArgTypeId == scriptValueTypeId) { |
| 481 | − qScriptArgList.append(ScriptValue(new ScriptValueQtWrapper(_engine, argVal))); | |
| 482 | − qGenArgs[arg] = Q_ARG(ScriptValue, qScriptArgList.back()); | |
| 493 | + qScriptArgLists[i].append(ScriptValue(new ScriptValueQtWrapper(_engine, argVal))); | |
| 494 | + qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back()); | |
| 483 | 495 | } else if (methodArgTypeId == QMetaType::QVariant) { |
| 484 | − qVarArgList.append(argVal.toVariant()); | |
| 485 | − qGenArgs[arg] = Q_ARG(QVariant, qVarArgList.back()); | |
| 496 | + qVarArgLists[i].append(argVal.toVariant()); | |
| 497 | + qGenArgsVectors[i][arg] = Q_ARG(QVariant, qVarArgLists[i].back()); | |
| 486 | 498 | } else { |
| 487 | 499 | QVariant varArgVal; |
| 488 | 500 | if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) { |
| 489 | 501 | conversionFailures++; |
| 490 | 502 | } else { |
| 491 | − qVarArgList.append(varArgVal); | |
| 492 | − const QVariant& converted = qVarArgList.back(); | |
| 503 | + qVarArgLists[i].append(varArgVal); | |
| 504 | + const QVariant& converted = qVarArgLists[i].back(); | |
| 505 | + conversionPenaltyScore[i] = _engine->computeCastPenalty(argVal, methodArgTypeId); | |
| 493 | 506 | |
| 494 | 507 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant |
| 495 | 508 | // A const_cast is needed because calling data() would detach the QVariant. |
| 496 | − qGenArgs[arg] = | |
| 509 | + qGenArgsVectors[i][arg] = | |
| 497 | 510 | QGenericArgument(QMetaType::typeName(converted.userType()), const_cast<void*>(converted.constData())); |
| 498 | 511 | } |
| 499 | 512 | } |
| @@ -503,13 +516,30 @@ QVariant ScriptMethodQtProxy::extension(Extension extension, const QVariant& arg · 3 unmodified lines | ||
| 503 | 516 | parameterConversionFailureCount = conversionFailures; |
| 504 | 517 | parameterConversionFailureId = meta.methodIndex(); |
| 505 | 518 | } |
| 519 | + isMetaRejected[i] = true; | |
| 506 | 520 | continue; |
| 507 | 521 | } |
| 508 | 522 | |
| 509 | 523 | ScriptContextQtWrapper ourContext(_engine, context); |
| 510 | 524 | ScriptContextGuard guard(&ourContext); |
| 525 | + } | |
| 526 | + | |
| 527 | + bool isValidMetaSelected = false; | |
| 528 | + int bestMeta = 0; | |
| 529 | + for (int i = 0; i < num_metas; i++) { | |
| 530 | + if (!isValidMetaSelected && !isMetaRejected[i]) { | |
| 531 | + isValidMetaSelected = true; | |
| 532 | + bestMeta = i; | |
| 533 | + } | |
| 534 | + if (isValidMetaSelected && !isMetaRejected[i] && conversionPenaltyScore[bestMeta] > conversionPenaltyScore[i]) { | |
| 535 | + bestMeta = i; | |
| 536 | + } | |
| 537 | + } | |
| 511 | 538 | |
| 539 | + if (isValidMetaSelected) { | |
| 540 | + const QMetaMethod& meta = _metas[bestMeta]; | |
| 512 | 541 | int returnTypeId = meta.returnType(); |
| 542 | + QVector <QGenericArgument> &qGenArgs = qGenArgsVectors[bestMeta]; | |
| 513 | 543 | |
| 514 | 544 | // The Qt MOC engine will automatically call qRegisterMetaType on invokable parameters and properties, but there's |
| 515 | 545 | // nothing in there for return values so these need to be explicitly runtime-registered! |
| @@ -579,9 +609,9 @@ QVariant ScriptMethodQtProxy::extension(Extension extension, const QVariant& arg · 63 unmodified lines | ||
| 579 | 609 | } |
| 580 | 610 | } |
| 581 | 611 | |
| 612 | + context->throwError(QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName())); | |
| 582 | 613 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? |
| 583 | 614 | return QVariant(); |
| 584 | − context->throwError(QString("Native call of %1 failed: could not locate an overload with the requested arguments").arg(fullName())); | |
| 585 | 615 | } |
| 586 | 616 | |
| 587 | 617 | QString ScriptSignalQtProxy::fullName() const { |