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 | int parameterConversionFailureId = 0; | 462 | int parameterConversionFailureId = 0; |
| 463 | int parameterConversionFailureCount = 0; | 463 | int parameterConversionFailureCount = 0; |
| 464 | 464 | ||
| 465 | for (auto iter = _metas.cbegin(); iter != _metas.end(); ++iter) { | 465 | int num_metas = _metas.size(); |
| 466 | const QMetaMethod& meta = *iter; | 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 | int methodNumArgs = meta.parameterCount(); | 478 | int methodNumArgs = meta.parameterCount(); |
| 468 | if (methodNumArgs != numArgs) { | 479 | if (methodNumArgs != numArgs) { |
| 480 | isMetaRejected[i] = true; | ||
| 469 | continue; | 481 | continue; |
| 470 | } | 482 | } |
| 471 | 483 | ||
| 472 | QList<ScriptValue> qScriptArgList; | 484 | qGenArgsVectors[i].resize(10); |
| 473 | QList<QVariant> qVarArgList; | 485 | conversionPenaltyScore[i] = 0; |
| 474 | QGenericArgument qGenArgs[10]; | ||
| 475 | int conversionFailures = 0; | 486 | int conversionFailures = 0; |
| 487 | |||
| 476 | for (int arg = 0; arg < numArgs; ++arg) { | 488 | for (int arg = 0; arg < numArgs; ++arg) { |
| 477 | int methodArgTypeId = meta.parameterType(arg); | 489 | int methodArgTypeId = meta.parameterType(arg); |
| 478 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); | 490 | Q_ASSERT(methodArgTypeId != QMetaType::UnknownType); |
| 479 | QScriptValue argVal = context->argument(arg); | 491 | QScriptValue argVal = context->argument(arg); |
| 480 | if (methodArgTypeId == scriptValueTypeId) { | 492 | if (methodArgTypeId == scriptValueTypeId) { |
| 481 | qScriptArgList.append(ScriptValue(new ScriptValueQtWrapper(_engine, argVal))); | 493 | qScriptArgLists[i].append(ScriptValue(new ScriptValueQtWrapper(_engine, argVal))); |
| 482 | qGenArgs[arg] = Q_ARG(ScriptValue, qScriptArgList.back()); | 494 | qGenArgsVectors[i][arg] = Q_ARG(ScriptValue, qScriptArgLists[i].back()); |
| 483 | } else if (methodArgTypeId == QMetaType::QVariant) { | 495 | } else if (methodArgTypeId == QMetaType::QVariant) { |
| 484 | qVarArgList.append(argVal.toVariant()); | 496 | qVarArgLists[i].append(argVal.toVariant()); |
| 485 | qGenArgs[arg] = Q_ARG(QVariant, qVarArgList.back()); | 497 | qGenArgsVectors[i][arg] = Q_ARG(QVariant, qVarArgLists[i].back()); |
| 486 | } else { | 498 | } else { |
| 487 | QVariant varArgVal; | 499 | QVariant varArgVal; |
| 488 | if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) { | 500 | if (!_engine->castValueToVariant(argVal, varArgVal, methodArgTypeId)) { |
| 489 | conversionFailures++; | 501 | conversionFailures++; |
| 490 | } else { | 502 | } else { |
| 491 | qVarArgList.append(varArgVal); | 503 | qVarArgLists[i].append(varArgVal); |
| 492 | const QVariant& converted = qVarArgList.back(); | 504 | const QVariant& converted = qVarArgLists[i].back(); |
| 505 | conversionPenaltyScore[i] = _engine->computeCastPenalty(argVal, methodArgTypeId); | ||
| 493 | 506 | ||
| 494 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant | 507 | // a lot of type conversion assistance thanks to https://stackoverflow.com/questions/28457819/qt-invoke-method-with-qvariant |
| 495 | // A const_cast is needed because calling data() would detach the QVariant. | 508 | // A const_cast is needed because calling data() would detach the QVariant. |
| 496 | qGenArgs[arg] = | 509 | qGenArgsVectors[i][arg] = |
| 497 | QGenericArgument(QMetaType::typeName(converted.userType()), const_cast<void*>(converted.constData())); | 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 | parameterConversionFailureCount = conversionFailures; | 516 | parameterConversionFailureCount = conversionFailures; |
| 504 | parameterConversionFailureId = meta.methodIndex(); | 517 | parameterConversionFailureId = meta.methodIndex(); |
| 505 | } | 518 | } |
| 519 | isMetaRejected[i] = true; | ||
| 506 | continue; | 520 | continue; |
| 507 | } | 521 | } |
| 508 | 522 | ||
| 509 | ScriptContextQtWrapper ourContext(_engine, context); | 523 | ScriptContextQtWrapper ourContext(_engine, context); |
| 510 | ScriptContextGuard guard(&ourContext); | 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 | int returnTypeId = meta.returnType(); | 541 | int returnTypeId = meta.returnType(); |
| 542 | QVector <QGenericArgument> &qGenArgs = qGenArgsVectors[bestMeta]; | ||
| 513 | 543 | ||
| 514 | // The Qt MOC engine will automatically call qRegisterMetaType on invokable parameters and properties, but there's | 544 | // The Qt MOC engine will automatically call qRegisterMetaType on invokable parameters and properties, but there's |
| 515 | // nothing in there for return values so these need to be explicitly runtime-registered! | 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 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? | 613 | Q_ASSERT(false); // really shouldn't have gotten here -- it didn't work before and it's working now? |
| 583 | return QVariant(); | 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 | QString ScriptSignalQtProxy::fullName() const { | 617 | QString ScriptSignalQtProxy::fullName() const { |