📄 qt_runtime.cpp
字号:
if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/) return i; } return -1;}// Helper function for resolving methods// Largely based on code in QtScript for compatibility reasonsstatic int findMethodIndex(ExecState* exec, const QMetaObject* meta, const QByteArray& signature, bool allowPrivate, const ArgList& jsArgs, QVarLengthArray<QVariant, 10> &vars, void** vvars, JSObject **pError){ QList<int> matchingIndices; bool overloads = !signature.contains('('); int count = meta->methodCount(); for (int i = count - 1; i >= 0; --i) { const QMetaMethod m = meta->method(i); // Don't choose private methods if (m.access() == QMetaMethod::Private && !allowPrivate) continue; // try and find all matching named methods if (m.signature() == signature) matchingIndices.append(i); else if (overloads) { QByteArray rawsignature = m.signature(); rawsignature.truncate(rawsignature.indexOf('(')); if (rawsignature == signature) matchingIndices.append(i); } } int chosenIndex = -1; *pError = 0; QVector<QtMethodMatchType> chosenTypes; QVarLengthArray<QVariant, 10> args; QVector<QtMethodMatchData> candidates; QVector<QtMethodMatchData> unresolved; QVector<int> tooFewArgs; QVector<int> conversionFailed; foreach(int index, matchingIndices) { QMetaMethod method = meta->method(index); QVector<QtMethodMatchType> types; bool unresolvedTypes = false; // resolve return type QByteArray returnTypeName = method.typeName(); int rtype = QMetaType::type(returnTypeName); if ((rtype == 0) && !returnTypeName.isEmpty()) { if (returnTypeName == "QVariant") { types.append(QtMethodMatchType::variant()); } else if (returnTypeName.endsWith('*')) { types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName)); } else { int enumIndex = indexOfMetaEnum(meta, returnTypeName); if (enumIndex != -1) types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName)); else { unresolvedTypes = true; types.append(QtMethodMatchType::unresolved(returnTypeName)); } } } else { if (returnTypeName == "QVariant") types.append(QtMethodMatchType::variant()); else types.append(QtMethodMatchType::metaType(rtype, returnTypeName)); } // resolve argument types QList<QByteArray> parameterTypeNames = method.parameterTypes(); for (int i = 0; i < parameterTypeNames.count(); ++i) { QByteArray argTypeName = parameterTypeNames.at(i); int atype = QMetaType::type(argTypeName); if (atype == 0) { if (argTypeName == "QVariant") { types.append(QtMethodMatchType::variant()); } else { int enumIndex = indexOfMetaEnum(meta, argTypeName); if (enumIndex != -1) types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName)); else { unresolvedTypes = true; types.append(QtMethodMatchType::unresolved(argTypeName)); } } } else { if (argTypeName == "QVariant") types.append(QtMethodMatchType::variant()); else types.append(QtMethodMatchType::metaType(atype, argTypeName)); } } // If the native method requires more arguments than what was passed from JavaScript if (jsArgs.size() < (types.count() - 1)) { qMatchDebug() << "Match:too few args for" << method.signature(); tooFewArgs.append(index); continue; } if (unresolvedTypes) { qMatchDebug() << "Match:unresolved arg types for" << method.signature(); // remember it so we can give an error message later, if necessary unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index, types, QVarLengthArray<QVariant, 10>())); continue; } // Now convert arguments if (args.count() != types.count()) args.resize(types.count()); QtMethodMatchType retType = types[0]; args[0] = QVariant(retType.typeId(), (void *)0); // the return value bool converted = true; int matchDistance = 0; for (int i = 0; converted && i < types.count() - 1; ++i) { JSValuePtr arg = i < jsArgs.size() ? jsArgs.at(exec, i) : jsUndefined(); int argdistance = -1; QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance); if (argdistance >= 0) { matchDistance += argdistance; args[i+1] = v; } else { qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId()); converted = false; } } qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance; if (converted) { if ((jsArgs.size() == types.count() - 1) && (matchDistance == 0)) { // perfect match, use this one chosenIndex = index; break; } else { QtMethodMatchData currentMatch(matchDistance, index, types, args); if (candidates.isEmpty()) { candidates.append(currentMatch); } else { QtMethodMatchData bestMatchSoFar = candidates.at(0); if ((args.count() > bestMatchSoFar.args.count()) || ((args.count() == bestMatchSoFar.args.count()) && (matchDistance <= bestMatchSoFar.matchDistance))) { candidates.prepend(currentMatch); } else { candidates.append(currentMatch); } } } } else { conversionFailed.append(index); } if (!overloads) break; } if (chosenIndex == -1 && candidates.count() == 0) { // No valid functions at all - format an error message if (!conversionFailed.isEmpty()) { QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n") .arg(QLatin1String(signature)); for (int i = 0; i < conversionFailed.size(); ++i) { if (i > 0) message += QLatin1String("\n"); QMetaMethod mtd = meta->method(conversionFailed.at(i)); message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); } *pError = throwError(exec, TypeError, message.toLatin1().constData()); } else if (!unresolved.isEmpty()) { QtMethodMatchData argsInstance = unresolved.first(); int unresolvedIndex = argsInstance.firstUnresolvedIndex(); Q_ASSERT(unresolvedIndex != -1); QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex); QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'") .arg(QString::fromLatin1(signature)) .arg(QLatin1String(unresolvedType.name())); *pError = throwError(exec, TypeError, message.toLatin1().constData()); } else { QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n") .arg(QLatin1String(signature)); for (int i = 0; i < tooFewArgs.size(); ++i) { if (i > 0) message += QLatin1String("\n"); QMetaMethod mtd = meta->method(tooFewArgs.at(i)); message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); } *pError = throwError(exec, SyntaxError, message.toLatin1().constData()); } } if (chosenIndex == -1 && candidates.count() > 0) { QtMethodMatchData bestMatch = candidates.at(0); if ((candidates.size() > 1) && (bestMatch.args.count() == candidates.at(1).args.count()) && (bestMatch.matchDistance == candidates.at(1).matchDistance)) { // ambiguous call QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n") .arg(QLatin1String(signature)); for (int i = 0; i < candidates.size(); ++i) { // Only candidate for overload if argument count and match distance is same as best match if (candidates.at(i).args.count() == bestMatch.args.count() || candidates.at(i).matchDistance == bestMatch.matchDistance) { if (i > 0) message += QLatin1String("\n"); QMetaMethod mtd = meta->method(candidates.at(i).index); message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); } } *pError = throwError(exec, TypeError, message.toLatin1().constData()); } else { chosenIndex = bestMatch.index; args = bestMatch.args; } } if (chosenIndex != -1) { /* Copy the stuff over */ int i; vars.resize(args.count()); for (i=0; i < args.count(); i++) { vars[i] = args[i]; vvars[i] = vars[i].data(); } } return chosenIndex;}// Signals are not fuzzy matched as much as methodsstatic int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature){ int index = initialIndex; QMetaMethod method = meta->method(index); bool overloads = !signature.contains('('); if (overloads && (method.attributes() & QMetaMethod::Cloned)) { // find the most general method do { method = meta->method(--index); } while (method.attributes() & QMetaMethod::Cloned); } return index;}QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate) : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst){ QW_D(QtRuntimeMetaMethod); d->m_signature = signature; d->m_index = index; d->m_connect = 0; d->m_disconnect = 0; d->m_allowPrivate = allowPrivate;}void QtRuntimeMetaMethod::mark(){ QtRuntimeMethod::mark(); QW_D(QtRuntimeMetaMethod); if (d->m_connect) d->m_connect->mark(); if (d->m_disconnect) d->m_disconnect->mark();}JSValuePtr QtRuntimeMetaMethod::call(ExecState* exec, JSObject* functionObject, JSValuePtr thisValue, const ArgList& args){ QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(functionObject)->d_func(); // We're limited to 10 args if (args.size() > 10) return jsUndefined(); // We have to pick a method that matches.. JSLock lock(false); QObject *obj = d->m_instance->getObject(); if (obj) { QVarLengthArray<QVariant, 10> vargs; void *qargs[11]; int methodIndex; JSObject* errorObj = 0; if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, args, vargs, (void **)qargs, &errorObj)) != -1) { if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0) return jsUndefined(); if (vargs[0].isValid()) return convertQVariantToValue(exec, d->m_instance->rootObject(), vargs[0]); } if (errorObj) return errorObj; } else { return throwError(exec, GeneralError, "cannot call function of deleted QObject"); } // void functions return undefined return jsUndefined();}CallType QtRuntimeMetaMethod::getCallData(CallData& callData){ callData.native.function = call; return CallTypeHost;}bool QtRuntimeMetaMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot){ if (propertyName == "connect") { slot.setCustom(this, connectGetter); return true; } else if (propertyName == "disconnect") { slot.setCustom(this, disconnectGetter); return true; } else if (propertyName == exec->propertyNames().length) { slot.setCustom(this, lengthGetter); return true; } return QtRuntimeMethod::getOwnPropertySlot(exec, propertyName, slot);}JSValuePtr QtRuntimeMetaMethod::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot&){ // QtScript always returns 0 return jsNumber(exec, 0);}JSValuePtr QtRuntimeMetaMethod::connectGetter(ExecState* exec, const Identifier& ident, const PropertySlot& slot){ QtRuntimeMetaMethod* thisObj = static_cast<QtRuntimeMetaMethod*>(asObject(slot.slotBase())); QW_DS(QtRuntimeMetaMethod, thisObj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -