src/script/bridge/qscriptqobject.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    33 #include "../api/qscriptcontext_p.h"
    33 #include "../api/qscriptcontext_p.h"
    34 #include "qscriptfunction_p.h"
    34 #include "qscriptfunction_p.h"
    35 
    35 
    36 #include "Error.h"
    36 #include "Error.h"
    37 #include "PrototypeFunction.h"
    37 #include "PrototypeFunction.h"
       
    38 #include "NativeFunctionWrapper.h"
    38 #include "PropertyNameArray.h"
    39 #include "PropertyNameArray.h"
    39 #include "JSFunction.h"
    40 #include "JSFunction.h"
    40 #include "JSString.h"
    41 #include "JSString.h"
    41 #include "JSValue.h"
    42 #include "JSValue.h"
    42 #include "JSArray.h"
    43 #include "JSArray.h"
   149 };
   150 };
   150 
   151 
   151 static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt)
   152 static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt)
   152 {
   153 {
   153     return (method.access() != QMetaMethod::Private)
   154     return (method.access() != QMetaMethod::Private)
   154         && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater));
   155         && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater))
       
   156         && (!(opt & QScriptEngine::ExcludeSlots) || (method.methodType() != QMetaMethod::Slot));
   155 }
   157 }
   156 
   158 
   157 static bool isEnumerableMetaProperty(const QMetaProperty &prop,
   159 static bool isEnumerableMetaProperty(const QMetaProperty &prop,
   158                                      const QMetaObject *mo, int index)
   160                                      const QMetaObject *mo, int index)
   159 {
   161 {
   161         // the following lookup is to ensure that we have the
   163         // the following lookup is to ensure that we have the
   162         // "most derived" occurrence of the property with this name
   164         // "most derived" occurrence of the property with this name
   163         && (mo->indexOfProperty(prop.name()) == index);
   165         && (mo->indexOfProperty(prop.name()) == index);
   164 }
   166 }
   165 
   167 
   166 static inline QByteArray methodName(const QMetaMethod &method)
   168 /*! \internal
   167 {
   169   Calculates the length of the name of the given \a method by looking
   168     QByteArray signature = method.signature();
   170   for the first '(' character.
   169     return signature.left(signature.indexOf('('));
   171 */
   170 }
   172 static inline int methodNameLength(const QMetaMethod &method)
   171 
   173 {
   172 static QVariant variantFromValue(QScriptEnginePrivate *eng,
   174     const char *signature = method.signature();
   173                                  int targetType, const QScriptValue &value)
   175     const char *s = signature;
       
   176     while (*s && (*s != '('))
       
   177         ++s;
       
   178     return s - signature;
       
   179 }
       
   180 
       
   181 /*! \internal
       
   182   Makes a deep copy of the first \a nameLength characters of the given
       
   183   method \a signature and returns the copy.
       
   184 */
       
   185 static inline QByteArray methodName(const char *signature, int nameLength)
       
   186 {
       
   187     return QByteArray(signature, nameLength);
       
   188 }
       
   189 
       
   190 /*! \internal
       
   191 
       
   192   Returns true if the name of the given \a method is the same as that
       
   193   specified by the (signature, nameLength) pair, otherwise returns
       
   194   false.
       
   195 */
       
   196 static inline bool methodNameEquals(const QMetaMethod &method,
       
   197                                     const char *signature, int nameLength)
       
   198 {
       
   199     const char *otherSignature = method.signature();
       
   200     return !qstrncmp(otherSignature, signature, nameLength)
       
   201         && (otherSignature[nameLength] == '(');
       
   202 }
       
   203 
       
   204 static QVariant variantFromValue(JSC::ExecState *exec, int targetType, JSC::JSValue value)
   174 {
   205 {
   175     QVariant v(targetType, (void *)0);
   206     QVariant v(targetType, (void *)0);
   176     Q_ASSERT(eng);
   207     if (QScriptEnginePrivate::convertValue(exec, value, targetType, v.data()))
   177     if (QScriptEnginePrivate::convert(value, targetType, v.data(), eng))
       
   178         return v;
   208         return v;
   179     if (uint(targetType) == QVariant::LastType)
   209     if (uint(targetType) == QVariant::LastType)
   180         return value.toVariant();
   210         return QScriptEnginePrivate::toVariant(exec, value);
   181     if (value.isVariant()) {
   211     if (QScriptEnginePrivate::isVariant(value)) {
   182         v = value.toVariant();
   212         v = QScriptEnginePrivate::variantValue(value);
   183         if (v.canConvert(QVariant::Type(targetType))) {
   213         if (v.canConvert(QVariant::Type(targetType))) {
   184             v.convert(QVariant::Type(targetType));
   214             v.convert(QVariant::Type(targetType));
   185             return v;
   215             return v;
   186         }
   216         }
   187         QByteArray typeName = v.typeName();
   217         QByteArray typeName = v.typeName();
   310 QList<int> QScript::QtFunction::overloadedIndexes() const
   340 QList<int> QScript::QtFunction::overloadedIndexes() const
   311 {
   341 {
   312     if (!maybeOverloaded())
   342     if (!maybeOverloaded())
   313         return QList<int>();
   343         return QList<int>();
   314     QList<int> result;
   344     QList<int> result;
   315     QString name = functionName();
       
   316     const QMetaObject *meta = metaObject();
   345     const QMetaObject *meta = metaObject();
       
   346     QMetaMethod method = meta->method(initialIndex());
       
   347     int nameLength = methodNameLength(method);
   317     for (int index = mostGeneralMethod() - 1; index >= 0; --index) {
   348     for (int index = mostGeneralMethod() - 1; index >= 0; --index) {
   318         QString otherName = QString::fromLatin1(methodName(meta->method(index)));
   349         if (methodNameEquals(meta->method(index), method.signature(), nameLength))
   319         if (otherName == name)
       
   320             result.append(index);
   350             result.append(index);
   321     }
   351     }
   322     return result;
   352     return result;
   323 }
       
   324 
       
   325 QString QtFunction::functionName() const
       
   326 {
       
   327     const QMetaObject *meta = metaObject();
       
   328     if (!meta)
       
   329         return QString();
       
   330     QMetaMethod method = meta->method(initialIndex());
       
   331     return QLatin1String(methodName(method));
       
   332 }
   353 }
   333 
   354 
   334 class QScriptMetaType
   355 class QScriptMetaType
   335 {
   356 {
   336 public:
   357 public:
   415 class QScriptMetaMethod
   436 class QScriptMetaMethod
   416 {
   437 {
   417 public:
   438 public:
   418     inline QScriptMetaMethod()
   439     inline QScriptMetaMethod()
   419         { }
   440         { }
   420     inline QScriptMetaMethod(const QByteArray &name, const QVector<QScriptMetaType> &types)
   441     inline QScriptMetaMethod(const QVector<QScriptMetaType> &types)
   421         : m_name(name), m_types(types), m_firstUnresolvedIndex(-1)
   442         : m_types(types), m_firstUnresolvedIndex(-1)
   422     {
   443     {
   423         QVector<QScriptMetaType>::const_iterator it;
   444         QVector<QScriptMetaType>::const_iterator it;
   424         for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) {
   445         for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) {
   425             if ((*it).kind() == QScriptMetaType::Unresolved) {
   446             if ((*it).kind() == QScriptMetaType::Unresolved) {
   426                 m_firstUnresolvedIndex = it - m_types.constBegin();
   447                 m_firstUnresolvedIndex = it - m_types.constBegin();
   429         }
   450         }
   430     }
   451     }
   431     inline bool isValid() const
   452     inline bool isValid() const
   432     { return !m_types.isEmpty(); }
   453     { return !m_types.isEmpty(); }
   433 
   454 
   434     QByteArray name() const
       
   435     { return m_name; }
       
   436 
       
   437     inline QScriptMetaType returnType() const
   455     inline QScriptMetaType returnType() const
   438     { return m_types.at(0); }
   456     { return m_types.at(0); }
   439 
   457 
   440     inline int argumentCount() const
   458     inline int argumentCount() const
   441     { return m_types.count() - 1; }
   459     { return m_types.count() - 1; }
   460 
   478 
   461     inline QVector<QScriptMetaType> types() const
   479     inline QVector<QScriptMetaType> types() const
   462     { return m_types; }
   480     { return m_types; }
   463 
   481 
   464 private:
   482 private:
   465     QByteArray m_name;
       
   466     QVector<QScriptMetaType> m_types;
   483     QVector<QScriptMetaType> m_types;
   467     int m_firstUnresolvedIndex;
   484     int m_firstUnresolvedIndex;
   468 };
   485 };
   469 
   486 
   470 struct QScriptMetaArguments
   487 struct QScriptMetaArguments
   497 static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType callType,
   514 static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType callType,
   498                                  QObject *thisQObject, const JSC::ArgList &scriptArgs,
   515                                  QObject *thisQObject, const JSC::ArgList &scriptArgs,
   499                                  const QMetaObject *meta, int initialIndex,
   516                                  const QMetaObject *meta, int initialIndex,
   500                                  bool maybeOverloaded)
   517                                  bool maybeOverloaded)
   501 {
   518 {
   502     QByteArray funName;
       
   503     QScriptMetaMethod chosenMethod;
   519     QScriptMetaMethod chosenMethod;
   504     int chosenIndex = -1;
   520     int chosenIndex = -1;
   505     QVarLengthArray<QVariant, 9> args;
   521     QVarLengthArray<QVariant, 9> args;
   506     QVector<QScriptMetaArguments> candidates;
   522     QVector<QScriptMetaArguments> candidates;
   507     QVector<QScriptMetaArguments> unresolved;
   523     QVector<QScriptMetaArguments> unresolved;
   508     QVector<int> tooFewArgs;
   524     QVector<int> tooFewArgs;
   509     QVector<int> conversionFailed;
   525     QVector<int> conversionFailed;
   510     int index;
   526     int index;
       
   527     int nameLength = 0;
       
   528     const char *initialMethodSignature = 0;
   511     exec->clearException();
   529     exec->clearException();
   512     QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(exec);
   530     QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(exec);
   513     for (index = initialIndex; index >= 0; --index) {
   531     for (index = initialIndex; index >= 0; --index) {
   514         QMetaMethod method = metaMethod(meta, callType, index);
   532         QMetaMethod method = metaMethod(meta, callType, index);
   515 
   533 
   516         if (index == initialIndex)
   534         if (index == initialIndex) {
   517             funName = methodName(method);
   535             initialMethodSignature = method.signature();
   518         else {
   536             nameLength = methodNameLength(method);
   519             if (methodName(method) != funName)
   537         } else {
       
   538             if (!methodNameEquals(method, initialMethodSignature, nameLength))
   520                 continue;
   539                 continue;
   521         }
   540         }
   522 
   541 
       
   542         QList<QByteArray> parameterTypeNames = method.parameterTypes();
       
   543 
   523         QVector<QScriptMetaType> types;
   544         QVector<QScriptMetaType> types;
       
   545         types.resize(1 + parameterTypeNames.size());
       
   546         QScriptMetaType *typesData = types.data();
   524         // resolve return type
   547         // resolve return type
   525         QByteArray returnTypeName = method.typeName();
   548         QByteArray returnTypeName = method.typeName();
   526         int rtype = QMetaType::type(returnTypeName);
   549         int rtype = QMetaType::type(returnTypeName);
   527         if ((rtype == 0) && !returnTypeName.isEmpty()) {
   550         if ((rtype == 0) && !returnTypeName.isEmpty()) {
   528             if (returnTypeName == "QVariant") {
   551             int enumIndex = indexOfMetaEnum(meta, returnTypeName);
   529                 types.append(QScriptMetaType::variant());
   552             if (enumIndex != -1)
   530             } else {
   553                 typesData[0] = QScriptMetaType::metaEnum(enumIndex, returnTypeName);
   531                 int enumIndex = indexOfMetaEnum(meta, returnTypeName);
   554             else
   532                 if (enumIndex != -1)
   555                 typesData[0] = QScriptMetaType::unresolved(returnTypeName);
   533                     types.append(QScriptMetaType::metaEnum(enumIndex, returnTypeName));
       
   534                 else
       
   535                     types.append(QScriptMetaType::unresolved(returnTypeName));
       
   536             }
       
   537         } else {
   556         } else {
   538             if (callType == QMetaMethod::Constructor)
   557             if (callType == QMetaMethod::Constructor)
   539                 types.append(QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*"));
   558                 typesData[0] = QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*");
   540             else if (returnTypeName == "QVariant")
   559             else if (rtype == QMetaType::QVariant)
   541                 types.append(QScriptMetaType::variant());
   560                 typesData[0] = QScriptMetaType::variant();
   542             else
   561             else
   543                 types.append(QScriptMetaType::metaType(rtype, returnTypeName));
   562                 typesData[0] = QScriptMetaType::metaType(rtype, returnTypeName);
   544         }
   563         }
   545 
   564 
   546         // resolve argument types
   565         // resolve argument types
   547         QList<QByteArray> parameterTypeNames = method.parameterTypes();
       
   548         for (int i = 0; i < parameterTypeNames.count(); ++i) {
   566         for (int i = 0; i < parameterTypeNames.count(); ++i) {
   549             QByteArray argTypeName = parameterTypeNames.at(i);
   567             QByteArray argTypeName = parameterTypeNames.at(i);
   550             int atype = QMetaType::type(argTypeName);
   568             int atype = QMetaType::type(argTypeName);
   551             if (atype == 0) {
   569             if (atype == 0) {
   552                 if (argTypeName == "QVariant") {
   570                 int enumIndex = indexOfMetaEnum(meta, argTypeName);
   553                     types.append(QScriptMetaType::variant());
   571                 if (enumIndex != -1)
   554                 } else {
   572                     typesData[1 + i] = QScriptMetaType::metaEnum(enumIndex, argTypeName);
   555                     int enumIndex = indexOfMetaEnum(meta, argTypeName);
   573                 else
   556                     if (enumIndex != -1)
   574                     typesData[1 + i] = QScriptMetaType::unresolved(argTypeName);
   557                         types.append(QScriptMetaType::metaEnum(enumIndex, argTypeName));
   575             } else if (atype == QMetaType::QVariant) {
   558                     else
   576                 typesData[1 + i] = QScriptMetaType::variant();
   559                         types.append(QScriptMetaType::unresolved(argTypeName));
       
   560                 }
       
   561             } else {
   577             } else {
   562                 if (argTypeName == "QVariant")
   578                 typesData[1 + i] = QScriptMetaType::metaType(atype, argTypeName);
   563                     types.append(QScriptMetaType::variant());
   579             }
   564                 else
   580         }
   565                     types.append(QScriptMetaType::metaType(atype, argTypeName));
   581 
   566             }
   582         QScriptMetaMethod mtd = QScriptMetaMethod(types);
   567         }
       
   568 
       
   569         QScriptMetaMethod mtd = QScriptMetaMethod(methodName(method), types);
       
   570 
   583 
   571         if (int(scriptArgs.size()) < mtd.argumentCount()) {
   584         if (int(scriptArgs.size()) < mtd.argumentCount()) {
   572             tooFewArgs.append(index);
   585             tooFewArgs.append(index);
   573             continue;
   586             continue;
   574         }
   587         }
   589 
   602 
   590         // try to convert arguments
   603         // try to convert arguments
   591         bool converted = true;
   604         bool converted = true;
   592         int matchDistance = 0;
   605         int matchDistance = 0;
   593         for (int i = 0; converted && i < mtd.argumentCount(); ++i) {
   606         for (int i = 0; converted && i < mtd.argumentCount(); ++i) {
   594             QScriptValue actual;
   607             JSC::JSValue actual;
   595             if (i < (int)scriptArgs.size())
   608             if (i < (int)scriptArgs.size())
   596                 actual = engine->scriptValueFromJSCValue(scriptArgs.at(i));
   609                 actual = scriptArgs.at(i);
   597             else
   610             else
   598                 actual = QScriptValue(QScriptValue::UndefinedValue);
   611                 actual = JSC::jsUndefined();
   599             QScriptMetaType argType = mtd.argumentType(i);
   612             QScriptMetaType argType = mtd.argumentType(i);
   600             int tid = -1;
   613             int tid = -1;
   601             QVariant v;
   614             QVariant v;
   602             if (argType.isUnresolved()) {
   615             if (argType.isUnresolved()) {
   603                 v = QVariant(QMetaType::QObjectStar, (void *)0);
   616                 v = QVariant(QMetaType::QObjectStar, (void *)0);
   604                 converted = engine->convertToNativeQObject(
   617                 converted = QScriptEnginePrivate::convertToNativeQObject(
   605                     actual, argType.name(), reinterpret_cast<void* *>(v.data()));
   618                     exec, actual, argType.name(), reinterpret_cast<void* *>(v.data()));
   606             } else if (argType.isVariant()) {
   619             } else if (argType.isVariant()) {
   607                 if (actual.isVariant()) {
   620                 if (QScriptEnginePrivate::isVariant(actual)) {
   608                     v = actual.toVariant();
   621                     v = QScriptEnginePrivate::variantValue(actual);
   609                 } else {
   622                 } else {
   610                     v = actual.toVariant();
   623                     v = QScriptEnginePrivate::toVariant(exec, actual);
   611                     converted = v.isValid() || actual.isUndefined() || actual.isNull();
   624                     converted = v.isValid() || actual.isUndefined() || actual.isNull();
   612                 }
   625                 }
   613             } else {
   626             } else {
   614                 tid = argType.typeId();
   627                 tid = argType.typeId();
   615                 v = QVariant(tid, (void *)0);
   628                 v = QVariant(tid, (void *)0);
   616                 converted = QScriptEnginePrivate::convert(actual, tid, v.data(), engine);
   629                 converted = QScriptEnginePrivate::convertValue(exec, actual, tid, v.data());
   617                 if (exec->hadException())
   630                 if (exec->hadException())
   618                     return exec->exception();
   631                     return exec->exception();
   619             }
   632             }
   620 
   633 
   621             if (!converted) {
   634             if (!converted) {
   622                 if (actual.isVariant()) {
   635                 if (QScriptEnginePrivate::isVariant(actual)) {
   623                     if (tid == -1)
   636                     if (tid == -1)
   624                         tid = argType.typeId();
   637                         tid = argType.typeId();
   625                     QVariant vv = actual.toVariant();
   638                     QVariant vv = QScriptEnginePrivate::variantValue(actual);
   626                     if (vv.canConvert(QVariant::Type(tid))) {
   639                     if (vv.canConvert(QVariant::Type(tid))) {
   627                         v = vv;
   640                         v = vv;
   628                         converted = v.convert(QVariant::Type(tid));
   641                         converted = v.convert(QVariant::Type(tid));
   629                         if (converted && (vv.userType() != tid))
   642                         if (converted && (vv.userType() != tid))
   630                             matchDistance += 10;
   643                             matchDistance += 10;
   647                         if (mi != -1)
   660                         if (mi != -1)
   648                             m = meta->enumerator(mi);
   661                             m = meta->enumerator(mi);
   649                     }
   662                     }
   650                     if (m.isValid()) {
   663                     if (m.isValid()) {
   651                         if (actual.isNumber()) {
   664                         if (actual.isNumber()) {
   652                             int ival = actual.toInt32();
   665                             int ival = QScriptEnginePrivate::toInt32(exec, actual);
   653                             if (m.valueToKey(ival) != 0) {
   666                             if (m.valueToKey(ival) != 0) {
   654                                 qVariantSetValue(v, ival);
   667                                 qVariantSetValue(v, ival);
   655                                 converted = true;
   668                                 converted = true;
   656                                 matchDistance += 10;
   669                                 matchDistance += 10;
   657                             }
   670                             }
   658                         } else {
   671                         } else {
   659                             QString sval = actual.toString();
   672                             JSC::UString sval = QScriptEnginePrivate::toString(exec, actual);
   660                             int ival = m.keyToValue(sval.toLatin1());
   673                             int ival = m.keyToValue(convertToLatin1(sval));
   661                             if (ival != -1) {
   674                             if (ival != -1) {
   662                                 qVariantSetValue(v, ival);
   675                                 qVariantSetValue(v, ival);
   663                                 converted = true;
   676                                 converted = true;
   664                                 matchDistance += 10;
   677                                 matchDistance += 10;
   665                             }
   678                             }
   716                         break;
   729                         break;
   717                     default:
   730                     default:
   718                         matchDistance += 10;
   731                         matchDistance += 10;
   719                         break;
   732                         break;
   720                     }
   733                     }
   721                 } else if (actual.isDate()) {
   734                 } else if (QScriptEnginePrivate::isDate(actual)) {
   722                     switch (tid) {
   735                     switch (tid) {
   723                     case QMetaType::QDateTime:
   736                     case QMetaType::QDateTime:
   724                         // perfect
   737                         // perfect
   725                         break;
   738                         break;
   726                     case QMetaType::QDate:
   739                     case QMetaType::QDate:
   731                         break;
   744                         break;
   732                     default:
   745                     default:
   733                         matchDistance += 10;
   746                         matchDistance += 10;
   734                         break;
   747                         break;
   735                     }
   748                     }
   736                 } else if (actual.isRegExp()) {
   749                 } else if (QScriptEnginePrivate::isRegExp(actual)) {
   737                     switch (tid) {
   750                     switch (tid) {
   738                     case QMetaType::QRegExp:
   751                     case QMetaType::QRegExp:
   739                         // perfect
   752                         // perfect
   740                         break;
   753                         break;
   741                     default:
   754                     default:
   742                         matchDistance += 10;
   755                         matchDistance += 10;
   743                         break;
   756                         break;
   744                     }
   757                     }
   745                 } else if (actual.isVariant()) {
   758                 } else if (QScriptEnginePrivate::isVariant(actual)) {
   746                     if (argType.isVariant()
   759                     if (argType.isVariant()
   747                         || (actual.toVariant().userType() == tid)) {
   760                         || (QScriptEnginePrivate::toVariant(exec, actual).userType() == tid)) {
   748                         // perfect
   761                         // perfect
   749                     } else {
   762                     } else {
   750                         matchDistance += 10;
   763                         matchDistance += 10;
   751                     }
   764                     }
   752                 } else if (actual.isArray()) {
   765                 } else if (QScriptEnginePrivate::isArray(actual)) {
   753                     switch (tid) {
   766                     switch (tid) {
   754                     case QMetaType::QStringList:
   767                     case QMetaType::QStringList:
   755                     case QMetaType::QVariantList:
   768                     case QMetaType::QVariantList:
   756                         matchDistance += 5;
   769                         matchDistance += 5;
   757                         break;
   770                         break;
   758                     default:
   771                     default:
   759                         matchDistance += 10;
   772                         matchDistance += 10;
   760                         break;
   773                         break;
   761                     }
   774                     }
   762                 } else if (actual.isQObject()) {
   775                 } else if (QScriptEnginePrivate::isQObject(actual)) {
   763                     switch (tid) {
   776                     switch (tid) {
   764                     case QMetaType::QObjectStar:
   777                     case QMetaType::QObjectStar:
   765                     case QMetaType::QWidgetStar:
   778                     case QMetaType::QWidgetStar:
   766                         // perfect
   779                         // perfect
   767                         break;
   780                         break;
   839     if ((chosenIndex == -1) && candidates.isEmpty()) {
   852     if ((chosenIndex == -1) && candidates.isEmpty()) {
   840 //        context->calleeMetaIndex = initialIndex;
   853 //        context->calleeMetaIndex = initialIndex;
   841 //#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
   854 //#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
   842 //        engine->notifyFunctionEntry(context);
   855 //        engine->notifyFunctionEntry(context);
   843 //#endif
   856 //#endif
       
   857         QString funName = QString::fromLatin1(methodName(initialMethodSignature, nameLength));
   844         if (!conversionFailed.isEmpty()) {
   858         if (!conversionFailed.isEmpty()) {
   845             QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
   859             QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
   846                               .arg(QLatin1String(funName));
   860                               .arg(funName);
   847             for (int i = 0; i < conversionFailed.size(); ++i) {
   861             for (int i = 0; i < conversionFailed.size(); ++i) {
   848                 if (i > 0)
   862                 if (i > 0)
   849                     message += QLatin1String("\n");
   863                     message += QLatin1String("\n");
   850                 QMetaMethod mtd = metaMethod(meta, callType, conversionFailed.at(i));
   864                 QMetaMethod mtd = metaMethod(meta, callType, conversionFailed.at(i));
   851                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
   865                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
   856             int unresolvedIndex = argsInstance.method.firstUnresolvedIndex();
   870             int unresolvedIndex = argsInstance.method.firstUnresolvedIndex();
   857             Q_ASSERT(unresolvedIndex != -1);
   871             Q_ASSERT(unresolvedIndex != -1);
   858             QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex);
   872             QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex);
   859             QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name());
   873             QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name());
   860             QString message = QString::fromLatin1("cannot call %0(): ")
   874             QString message = QString::fromLatin1("cannot call %0(): ")
   861                               .arg(QString::fromLatin1(funName));
   875                               .arg(funName);
   862             if (unresolvedIndex > 0) {
   876             if (unresolvedIndex > 0) {
   863                 message.append(QString::fromLatin1("argument %0 has unknown type `%1'").
   877                 message.append(QString::fromLatin1("argument %0 has unknown type `%1'").
   864                                arg(unresolvedIndex).arg(unresolvedTypeName));
   878                                arg(unresolvedIndex).arg(unresolvedTypeName));
   865             } else {
   879             } else {
   866                 message.append(QString::fromLatin1("unknown return type `%0'")
   880                 message.append(QString::fromLatin1("unknown return type `%0'")
   868             }
   882             }
   869             message.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())"));
   883             message.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())"));
   870             result = JSC::throwError(exec, JSC::TypeError, message);
   884             result = JSC::throwError(exec, JSC::TypeError, message);
   871         } else {
   885         } else {
   872             QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
   886             QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
   873                               .arg(QLatin1String(funName));
   887                               .arg(funName);
   874             for (int i = 0; i < tooFewArgs.size(); ++i) {
   888             for (int i = 0; i < tooFewArgs.size(); ++i) {
   875                 if (i > 0)
   889                 if (i > 0)
   876                     message += QLatin1String("\n");
   890                     message += QLatin1String("\n");
   877                 QMetaMethod mtd = metaMethod(meta, callType, tooFewArgs.at(i));
   891                 QMetaMethod mtd = metaMethod(meta, callType, tooFewArgs.at(i));
   878                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
   892                 message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
   884             QScriptMetaArguments metaArgs = candidates.at(0);
   898             QScriptMetaArguments metaArgs = candidates.at(0);
   885             if ((candidates.size() > 1)
   899             if ((candidates.size() > 1)
   886                 && (metaArgs.args.count() == candidates.at(1).args.count())
   900                 && (metaArgs.args.count() == candidates.at(1).args.count())
   887                 && (metaArgs.matchDistance == candidates.at(1).matchDistance)) {
   901                 && (metaArgs.matchDistance == candidates.at(1).matchDistance)) {
   888                 // ambiguous call
   902                 // ambiguous call
       
   903                 QByteArray funName = methodName(initialMethodSignature, nameLength);
   889                 QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
   904                 QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
   890                                   .arg(QLatin1String(funName));
   905                                   .arg(QLatin1String(funName));
   891                 for (int i = 0; i < candidates.size(); ++i) {
   906                 for (int i = 0; i < candidates.size(); ++i) {
   892                     if (i > 0)
   907                     if (i > 0)
   893                         message += QLatin1String("\n");
   908                         message += QLatin1String("\n");
   951             if (exec->hadException()) {
   966             if (exec->hadException()) {
   952                 result = exec->exception() ; // propagate
   967                 result = exec->exception() ; // propagate
   953             } else {
   968             } else {
   954                 QScriptMetaType retType = chosenMethod.returnType();
   969                 QScriptMetaType retType = chosenMethod.returnType();
   955                 if (retType.isVariant()) {
   970                 if (retType.isVariant()) {
   956                     result = engine->jscValueFromVariant(*(QVariant *)params[0]);
   971                     result = QScriptEnginePrivate::jscValueFromVariant(exec, *(QVariant *)params[0]);
   957                 } else if (retType.typeId() != 0) {
   972                 } else if (retType.typeId() != 0) {
   958                     result = engine->scriptValueToJSCValue(engine->create(retType.typeId(), params[0]));
   973                     result = QScriptEnginePrivate::create(exec, retType.typeId(), params[0]);
   959                     if (!result) {
   974                     if (!result)
   960                         QScriptValue sv = QScriptEnginePrivate::get(engine)->newVariant(QVariant(retType.typeId(), params[0]));
   975                         result = engine->newVariant(QVariant(retType.typeId(), params[0]));
   961                         result = engine->scriptValueToJSCValue(sv);
       
   962                     }
       
   963                 } else {
   976                 } else {
   964                     result = JSC::jsUndefined();
   977                     result = JSC::jsUndefined();
   965                 }
   978                 }
   966             }
   979             }
   967         }
   980         }
  1047     JSC::JSValue thisValue, const JSC::ArgList &args)
  1060     JSC::JSValue thisValue, const JSC::ArgList &args)
  1048 {
  1061 {
  1049     if (!callee->inherits(&QtPropertyFunction::info))
  1062     if (!callee->inherits(&QtPropertyFunction::info))
  1050         return throwError(exec, JSC::TypeError, "callee is not a QtPropertyFunction object");
  1063         return throwError(exec, JSC::TypeError, "callee is not a QtPropertyFunction object");
  1051     QtPropertyFunction *qfun =  static_cast<QtPropertyFunction*>(callee);
  1064     QtPropertyFunction *qfun =  static_cast<QtPropertyFunction*>(callee);
  1052     QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec);
  1065     return qfun->execute(exec, thisValue, args);
  1053     JSC::ExecState *previousFrame = eng_p->currentFrame;
       
  1054     eng_p->currentFrame = exec;
       
  1055     eng_p->pushContext(exec, thisValue, args, callee);
       
  1056     JSC::JSValue result = qfun->execute(eng_p->currentFrame, thisValue, args);
       
  1057     eng_p->popContext();
       
  1058     eng_p->currentFrame = previousFrame;
       
  1059     return result;
       
  1060 }
  1066 }
  1061 
  1067 
  1062 JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec,
  1068 JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec,
  1063                                          JSC::JSValue thisValue,
  1069                                          JSC::JSValue thisValue,
  1064                                          const JSC::ArgList &args)
  1070                                          const JSC::ArgList &args)
  1065 {
  1071 {
  1066     JSC::JSValue result = JSC::jsUndefined();
  1072     JSC::JSValue result = JSC::jsUndefined();
  1067 
  1073 
  1068     // ### don't go via QScriptValue
       
  1069     QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
  1074     QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
  1070     thisValue = engine->toUsableValue(thisValue);
  1075     JSC::ExecState *previousFrame = engine->currentFrame;
  1071     QScriptValue object = engine->scriptValueFromJSCValue(thisValue);
  1076     engine->currentFrame = exec;
  1072     QObject *qobject = object.toQObject();
  1077 
       
  1078     JSC::JSValue qobjectValue = engine->toUsableValue(thisValue);
       
  1079     QObject *qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue);
  1073     while ((!qobject || (qobject->metaObject() != data->meta))
  1080     while ((!qobject || (qobject->metaObject() != data->meta))
  1074            && object.prototype().isObject()) {
  1081         && JSC::asObject(qobjectValue)->prototype().isObject()) {
  1075         object = object.prototype();
  1082         qobjectValue = JSC::asObject(qobjectValue)->prototype();
  1076         qobject = object.toQObject();
  1083         qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue);
  1077     }
  1084     }
  1078     Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject");
  1085     Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject");
  1079 
  1086 
  1080     QMetaProperty prop = data->meta->property(data->index);
  1087     QMetaProperty prop = data->meta->property(data->index);
  1081     Q_ASSERT(prop.isScriptable());
  1088     Q_ASSERT(prop.isScriptable());
  1083         // get
  1090         // get
  1084         if (prop.isValid()) {
  1091         if (prop.isValid()) {
  1085             QScriptable *scriptable = scriptableFromQObject(qobject);
  1092             QScriptable *scriptable = scriptableFromQObject(qobject);
  1086             QScriptEngine *oldEngine = 0;
  1093             QScriptEngine *oldEngine = 0;
  1087             if (scriptable) {
  1094             if (scriptable) {
       
  1095                 engine->pushContext(exec, thisValue, args, this);
  1088                 oldEngine = QScriptablePrivate::get(scriptable)->engine;
  1096                 oldEngine = QScriptablePrivate::get(scriptable)->engine;
  1089                 QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
  1097                 QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
  1090             }
  1098             }
  1091 
  1099 
  1092             QVariant v = prop.read(qobject);
  1100             QVariant v = prop.read(qobject);
  1093 
  1101 
  1094             if (scriptable)
  1102             if (scriptable) {
  1095                 QScriptablePrivate::get(scriptable)->engine = oldEngine;
  1103                 QScriptablePrivate::get(scriptable)->engine = oldEngine;
  1096 
  1104                 engine->popContext();
  1097             result = engine->jscValueFromVariant(v);
  1105             }
       
  1106 
       
  1107             result = QScriptEnginePrivate::jscValueFromVariant(exec, v);
  1098         }
  1108         }
  1099     } else {
  1109     } else {
  1100         // set
  1110         // set
  1101         JSC::JSValue arg = args.at(0);
  1111         JSC::JSValue arg = args.at(0);
  1102         QVariant v;
  1112         QVariant v;
  1104             && !engine->hasDemarshalFunction(prop.userType())) {
  1114             && !engine->hasDemarshalFunction(prop.userType())) {
  1105             // give QMetaProperty::write() a chance to convert from
  1115             // give QMetaProperty::write() a chance to convert from
  1106             // string to enum value
  1116             // string to enum value
  1107             v = (QString)arg.toString(exec);
  1117             v = (QString)arg.toString(exec);
  1108         } else {
  1118         } else {
  1109             // ### don't go via QScriptValue
  1119             v = variantFromValue(exec, prop.userType(), arg);
  1110             QScriptValue tmp = engine->scriptValueFromJSCValue(arg);
       
  1111             v = variantFromValue(engine, prop.userType(), tmp);
       
  1112         }
  1120         }
  1113 
  1121 
  1114         QScriptable *scriptable = scriptableFromQObject(qobject);
  1122         QScriptable *scriptable = scriptableFromQObject(qobject);
  1115         QScriptEngine *oldEngine = 0;
  1123         QScriptEngine *oldEngine = 0;
  1116         if (scriptable) {
  1124         if (scriptable) {
       
  1125             engine->pushContext(exec, thisValue, args, this);
  1117             oldEngine = QScriptablePrivate::get(scriptable)->engine;
  1126             oldEngine = QScriptablePrivate::get(scriptable)->engine;
  1118             QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
  1127             QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine);
  1119         }
  1128         }
  1120 
  1129 
  1121         prop.write(qobject, v);
  1130         prop.write(qobject, v);
  1122 
  1131 
  1123         if (scriptable)
  1132         if (scriptable) {
  1124             QScriptablePrivate::get(scriptable)->engine = oldEngine;
  1133             QScriptablePrivate::get(scriptable)->engine = oldEngine;
       
  1134             engine->popContext();
       
  1135         }
  1125 
  1136 
  1126         result = arg;
  1137         result = arg;
  1127     }
  1138     }
       
  1139     engine->currentFrame = previousFrame;
  1128     return result;
  1140     return result;
  1129 }
  1141 }
  1130 
  1142 
  1131 const QMetaObject *QtPropertyFunction::metaObject() const
  1143 const QMetaObject *QtPropertyFunction::metaObject() const
  1132 {
  1144 {
  1174                                          const JSC::Identifier &propertyName,
  1186                                          const JSC::Identifier &propertyName,
  1175                                          JSC::PropertySlot &slot)
  1187                                          JSC::PropertySlot &slot)
  1176 {
  1188 {
  1177     //Note: this has to be kept in sync with getOwnPropertyDescriptor
  1189     //Note: this has to be kept in sync with getOwnPropertyDescriptor
  1178 #ifndef QT_NO_PROPERTIES
  1190 #ifndef QT_NO_PROPERTIES
  1179     QByteArray name = QString(propertyName.ustring()).toLatin1();
  1191     QByteArray name = convertToLatin1(propertyName.ustring());
  1180     QObject *qobject = data->value;
  1192     QObject *qobject = data->value;
  1181     if (!qobject) {
  1193     if (!qobject) {
  1182         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1194         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1183                           .arg(QString::fromLatin1(name));
  1195                           .arg(QString::fromLatin1(name));
  1184         slot.setValue(JSC::throwError(exec, JSC::GeneralError, message));
  1196         slot.setValue(JSC::throwError(exec, JSC::GeneralError, message));
  1235                 } else {
  1247                 } else {
  1236                     JSC::JSValue val;
  1248                     JSC::JSValue val;
  1237                     if (!prop.isValid())
  1249                     if (!prop.isValid())
  1238                         val = JSC::jsUndefined();
  1250                         val = JSC::jsUndefined();
  1239                     else
  1251                     else
  1240                         val = eng->jscValueFromVariant(prop.read(qobject));
  1252                         val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject));
  1241                     slot.setValue(val);
  1253                     slot.setValue(val);
  1242                 }
  1254                 }
  1243                 return true;
  1255                 return true;
  1244             }
  1256             }
  1245         }
  1257         }
  1246     }
  1258     }
  1247 
  1259 
  1248     index = qobject->dynamicPropertyNames().indexOf(name);
  1260     index = qobject->dynamicPropertyNames().indexOf(name);
  1249     if (index != -1) {
  1261     if (index != -1) {
  1250         JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name));
  1262         JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name));
  1251         slot.setValue(val);
  1263         slot.setValue(val);
  1252         return true;
  1264         return true;
  1253     }
  1265     }
  1254 
  1266 
  1255     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1267     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1256                        ? meta->methodOffset() : 0;
  1268                        ? meta->methodOffset() : 0;
  1257     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1269     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1258         QMetaMethod method = meta->method(index);
  1270         QMetaMethod method = meta->method(index);
  1259         if (hasMethodAccess(method, index, opt)
  1271         if (hasMethodAccess(method, index, opt)
  1260             && (methodName(method) == name)) {
  1272             && methodNameEquals(method, name.constData(), name.length())) {
  1261             QtFunction *fun = new (exec)QtFunction(
  1273             QtFunction *fun = new (exec)QtFunction(
  1262                 object, index, /*maybeOverloaded=*/true,
  1274                 object, index, /*maybeOverloaded=*/true,
  1263                 &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
  1275                 &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
  1264                 propertyName);
  1276                 propertyName);
  1265             slot.setValue(fun);
  1277             slot.setValue(fun);
  1272         QList<QObject*> children = qobject->children();
  1284         QList<QObject*> children = qobject->children();
  1273         for (index = 0; index < children.count(); ++index) {
  1285         for (index = 0; index < children.count(); ++index) {
  1274             QObject *child = children.at(index);
  1286             QObject *child = children.at(index);
  1275             if (child->objectName() == QString(propertyName.ustring())) {
  1287             if (child->objectName() == QString(propertyName.ustring())) {
  1276                 QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
  1288                 QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
  1277                 QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt);
  1289                 slot.setValue(eng->newQObject(child, QScriptEngine::QtOwnership, opt));
  1278                 slot.setValue(eng->scriptValueToJSCValue(tmp));
       
  1279                 return true;
  1290                 return true;
  1280             }
  1291             }
  1281         }
  1292         }
  1282     }
  1293     }
  1283 
  1294 
  1290 
  1301 
  1291 bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecState *exec,
  1302 bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecState *exec,
  1292                                          const JSC::Identifier &propertyName,
  1303                                          const JSC::Identifier &propertyName,
  1293                                          JSC::PropertyDescriptor &descriptor)
  1304                                          JSC::PropertyDescriptor &descriptor)
  1294 {
  1305 {
  1295     //Note: this has to be kept in sync with getOwnPropertySlot abd getPropertyAttributes
  1306     //Note: this has to be kept in sync with getOwnPropertySlot
  1296 #ifndef QT_NO_PROPERTIES
  1307 #ifndef QT_NO_PROPERTIES
  1297     QByteArray name = QString(propertyName.ustring()).toLatin1();
  1308     QByteArray name = convertToLatin1(propertyName.ustring());
  1298     QObject *qobject = data->value;
  1309     QObject *qobject = data->value;
  1299     if (!qobject) {
  1310     if (!qobject) {
  1300         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1311         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1301                           .arg(QString::fromLatin1(name));
  1312                           .arg(QString::fromLatin1(name));
  1302         descriptor.setValue(JSC::throwError(exec, JSC::GeneralError, message));
  1313         descriptor.setValue(JSC::throwError(exec, JSC::GeneralError, message));
  1368                 } else {
  1379                 } else {
  1369                     JSC::JSValue val;
  1380                     JSC::JSValue val;
  1370                     if (!prop.isValid())
  1381                     if (!prop.isValid())
  1371                         val = JSC::jsUndefined();
  1382                         val = JSC::jsUndefined();
  1372                     else
  1383                     else
  1373                         val = eng->jscValueFromVariant(prop.read(qobject));
  1384                         val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject));
  1374                     descriptor.setDescriptor(val, attributes);
  1385                     descriptor.setDescriptor(val, attributes);
  1375                 }
  1386                 }
  1376                 return true;
  1387                 return true;
  1377             }
  1388             }
  1378         }
  1389         }
  1379     }
  1390     }
  1380 
  1391 
  1381     index = qobject->dynamicPropertyNames().indexOf(name);
  1392     index = qobject->dynamicPropertyNames().indexOf(name);
  1382     if (index != -1) {
  1393     if (index != -1) {
  1383         JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name));
  1394         JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name));
  1384         descriptor.setDescriptor(val, QObjectMemberAttribute);
  1395         descriptor.setDescriptor(val, QObjectMemberAttribute);
  1385         return true;
  1396         return true;
  1386     }
  1397     }
  1387 
  1398 
  1388     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1399     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1389                        ? meta->methodOffset() : 0;
  1400                        ? meta->methodOffset() : 0;
  1390     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1401     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1391         QMetaMethod method = meta->method(index);
  1402         QMetaMethod method = meta->method(index);
  1392         if (hasMethodAccess(method, index, opt)
  1403         if (hasMethodAccess(method, index, opt)
  1393             && (methodName(method) == name)) {
  1404             && methodNameEquals(method, name.constData(), name.length())) {
  1394             QtFunction *fun = new (exec)QtFunction(
  1405             QtFunction *fun = new (exec)QtFunction(
  1395                 object, index, /*maybeOverloaded=*/true,
  1406                 object, index, /*maybeOverloaded=*/true,
  1396                 &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
  1407                 &exec->globalData(), eng->originalGlobalObject()->functionStructure(),
  1397                 propertyName);
  1408                 propertyName);
  1398             unsigned attributes = QObjectMemberAttribute;
  1409             unsigned attributes = QObjectMemberAttribute;
  1408         QList<QObject*> children = qobject->children();
  1419         QList<QObject*> children = qobject->children();
  1409         for (index = 0; index < children.count(); ++index) {
  1420         for (index = 0; index < children.count(); ++index) {
  1410             QObject *child = children.at(index);
  1421             QObject *child = children.at(index);
  1411             if (child->objectName() == QString(propertyName.ustring())) {
  1422             if (child->objectName() == QString(propertyName.ustring())) {
  1412                 QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
  1423                 QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject;
  1413                 QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt);
  1424                 descriptor.setDescriptor(eng->newQObject(child, QScriptEngine::QtOwnership, opt),
  1414                 descriptor.setDescriptor(eng->scriptValueToJSCValue(tmp), JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum);
  1425                                          JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum);
  1415                 return true;
  1426                 return true;
  1416             }
  1427             }
  1417         }
  1428         }
  1418     }
  1429     }
  1419 
  1430 
  1426 void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec,
  1437 void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec,
  1427                           const JSC::Identifier& propertyName,
  1438                           const JSC::Identifier& propertyName,
  1428                           JSC::JSValue value, JSC::PutPropertySlot &slot)
  1439                           JSC::JSValue value, JSC::PutPropertySlot &slot)
  1429 {
  1440 {
  1430 #ifndef QT_NO_PROPERTIES
  1441 #ifndef QT_NO_PROPERTIES
  1431     QByteArray name = ((QString)propertyName.ustring()).toLatin1();
  1442     QByteArray name = convertToLatin1(propertyName.ustring());
  1432     QObject *qobject = data->value;
  1443     QObject *qobject = data->value;
  1433     if (!qobject) {
  1444     if (!qobject) {
  1434         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1445         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1435                           .arg(QString::fromLatin1(name));
  1446                           .arg(QString::fromLatin1(name));
  1436         JSC::throwError(exec, JSC::GeneralError, message);
  1447         JSC::throwError(exec, JSC::GeneralError, message);
  1488                         && !eng->hasDemarshalFunction(prop.userType())) {
  1499                         && !eng->hasDemarshalFunction(prop.userType())) {
  1489                         // give QMetaProperty::write() a chance to convert from
  1500                         // give QMetaProperty::write() a chance to convert from
  1490                         // string to enum value
  1501                         // string to enum value
  1491                         v = (QString)value.toString(exec);
  1502                         v = (QString)value.toString(exec);
  1492                     } else {
  1503                     } else {
  1493                         v = eng->jscValueToVariant(value, prop.userType());
  1504                         v = QScriptEnginePrivate::jscValueToVariant(exec, value, prop.userType());
  1494                     }
  1505                     }
  1495                     (void)prop.write(qobject, v);
  1506                     (void)prop.write(qobject, v);
  1496                 }
  1507                 }
  1497                 return;
  1508                 return;
  1498             }
  1509             }
  1502     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1513     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
  1503                        ? meta->methodOffset() : 0;
  1514                        ? meta->methodOffset() : 0;
  1504     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1515     for (index = meta->methodCount() - 1; index >= offset; --index) {
  1505         QMetaMethod method = meta->method(index);
  1516         QMetaMethod method = meta->method(index);
  1506         if (hasMethodAccess(method, index, opt)
  1517         if (hasMethodAccess(method, index, opt)
  1507             && (methodName(method) == name)) {
  1518             && methodNameEquals(method, name.constData(), name.length())) {
  1508             data->cachedMembers.insert(name, value);
  1519             data->cachedMembers.insert(name, value);
  1509             return;
  1520             return;
  1510         }
  1521         }
  1511     }
  1522     }
  1512 
  1523 
  1513     index = qobject->dynamicPropertyNames().indexOf(name);
  1524     index = qobject->dynamicPropertyNames().indexOf(name);
  1514     if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) {
  1525     if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) {
  1515         QVariant v = eng->scriptValueFromJSCValue(value).toVariant();
  1526         QVariant v = QScriptEnginePrivate::toVariant(exec, value);
  1516         (void)qobject->setProperty(name, v);
  1527         (void)qobject->setProperty(name, v);
  1517         return;
  1528         return;
  1518     }
  1529     }
  1519 
  1530 
  1520     QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
  1531     QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
  1521 #endif //QT_NO_PROPERTIES
  1532 #endif //QT_NO_PROPERTIES
  1522 }
  1533 }
  1523 
  1534 
  1524 bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec,
  1535 bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec,
  1525                                      const JSC::Identifier& propertyName,
  1536                                      const JSC::Identifier& propertyName)
  1526                                      bool checkDontDelete)
       
  1527 {
  1537 {
  1528 #ifndef QT_NO_PROPERTIES
  1538 #ifndef QT_NO_PROPERTIES
  1529     QByteArray name = ((QString)propertyName.ustring()).toLatin1();
  1539     QByteArray name = convertToLatin1(propertyName.ustring());
  1530     QObject *qobject = data->value;
  1540     QObject *qobject = data->value;
  1531     if (!qobject) {
  1541     if (!qobject) {
  1532         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1542         QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject")
  1533                           .arg(QString::fromLatin1(name));
  1543                           .arg(QString::fromLatin1(name));
  1534         JSC::throwError(exec, JSC::GeneralError, message);
  1544         JSC::throwError(exec, JSC::GeneralError, message);
  1561     if (index != -1) {
  1571     if (index != -1) {
  1562         (void)qobject->setProperty(name, QVariant());
  1572         (void)qobject->setProperty(name, QVariant());
  1563         return true;
  1573         return true;
  1564     }
  1574     }
  1565 
  1575 
  1566     return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete);
  1576     return QScriptObjectDelegate::deleteProperty(object, exec, propertyName);
  1567 #else //QT_NO_PROPERTIES
  1577 #else //QT_NO_PROPERTIES
  1568     return false;
  1578     return false;
  1569 #endif //QT_NO_PROPERTIES
  1579 #endif //QT_NO_PROPERTIES
  1570 }
  1580 }
  1571 
  1581 
  1572 bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object,
       
  1573                                             JSC::ExecState *exec,
       
  1574                                             const JSC::Identifier &propertyName,
       
  1575                                             unsigned &attributes) const
       
  1576 {
       
  1577 #ifndef QT_NO_PROPERTIES
       
  1578     //Note: this has to be kept in sync with getOwnPropertyDescriptor and getOwnPropertySlot
       
  1579     QByteArray name = ((QString)propertyName.ustring()).toLatin1();
       
  1580     QObject *qobject = data->value;
       
  1581     if (!qobject)
       
  1582         return false;
       
  1583 
       
  1584     const QScriptEngine::QObjectWrapOptions &opt = data->options;
       
  1585     const QMetaObject *meta = qobject->metaObject();
       
  1586     int index = -1;
       
  1587     if (name.contains('(')) {
       
  1588         QByteArray normalized = QMetaObject::normalizedSignature(name);
       
  1589         if (-1 != (index = meta->indexOfMethod(normalized))) {
       
  1590             QMetaMethod method = meta->method(index);
       
  1591             if (hasMethodAccess(method, index, opt)) {
       
  1592                 if (!(opt & QScriptEngine::ExcludeSuperClassMethods)
       
  1593                     || (index >= meta->methodOffset())) {
       
  1594                     attributes = QObjectMemberAttribute;
       
  1595                     if (opt & QScriptEngine::SkipMethodsInEnumeration)
       
  1596                         attributes |= JSC::DontEnum;
       
  1597                     return true;
       
  1598                 }
       
  1599             }
       
  1600         }
       
  1601     }
       
  1602 
       
  1603     index = meta->indexOfProperty(name);
       
  1604     if (index != -1) {
       
  1605         QMetaProperty prop = meta->property(index);
       
  1606         if (prop.isScriptable()) {
       
  1607             if (!(opt & QScriptEngine::ExcludeSuperClassProperties)
       
  1608                 || (index >= meta->propertyOffset())) {
       
  1609                 attributes = flagsForMetaProperty(prop);
       
  1610                 return true;
       
  1611             }
       
  1612         }
       
  1613     }
       
  1614 
       
  1615     index = qobject->dynamicPropertyNames().indexOf(name);
       
  1616     if (index != -1) {
       
  1617         attributes = QObjectMemberAttribute;
       
  1618         return true;
       
  1619     }
       
  1620 
       
  1621     const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods)
       
  1622                        ? meta->methodOffset() : 0;
       
  1623     for (index = meta->methodCount() - 1; index >= offset; --index) {
       
  1624         QMetaMethod method = meta->method(index);
       
  1625         if (hasMethodAccess(method, index, opt)
       
  1626             && (methodName(method) == name)) {
       
  1627             attributes = QObjectMemberAttribute;
       
  1628             if (opt & QScriptEngine::SkipMethodsInEnumeration)
       
  1629                 attributes |= JSC::DontEnum;
       
  1630             return true;
       
  1631         }
       
  1632     }
       
  1633 
       
  1634     if (!(opt & QScriptEngine::ExcludeChildObjects)) {
       
  1635         QList<QObject*> children = qobject->children();
       
  1636         for (index = 0; index < children.count(); ++index) {
       
  1637             QObject *child = children.at(index);
       
  1638             if (child->objectName() == (QString)(propertyName.ustring())) {
       
  1639                 attributes = JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum;
       
  1640                 return true;
       
  1641             }
       
  1642         }
       
  1643     }
       
  1644 
       
  1645     return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attributes);
       
  1646 #else //QT_NO_PROPERTIES
       
  1647     return false;
       
  1648 #endif //QT_NO_PROPERTIES
       
  1649 }
       
  1650 
       
  1651 void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec,
  1582 void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec,
  1652                                           JSC::PropertyNameArray &propertyNames,
  1583                                           JSC::PropertyNameArray &propertyNames,
  1653                                           bool includeNonEnumerable)
  1584                                           JSC::EnumerationMode mode)
  1654 {
  1585 {
  1655 #ifndef QT_NO_PROPERTIES
  1586 #ifndef QT_NO_PROPERTIES
  1656     QObject *qobject = data->value;
  1587     QObject *qobject = data->value;
  1657     if (!qobject) {
  1588     if (!qobject) {
  1658         QString message = QString::fromLatin1("cannot get property names of deleted QObject");
  1589         QString message = QString::fromLatin1("cannot get property names of deleted QObject");
  1693                 propertyNames.add(JSC::Identifier(exec, sig));
  1624                 propertyNames.add(JSC::Identifier(exec, sig));
  1694             }
  1625             }
  1695         }
  1626         }
  1696     }
  1627     }
  1697 
  1628 
  1698     QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable);
  1629     QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode);
  1699 #endif //QT_NO_PROPERTIES
  1630 #endif //QT_NO_PROPERTIES
  1700 }
  1631 }
  1701 
  1632 
  1702 void QObjectDelegate::markChildren(QScriptObject *object, JSC::MarkStack& markStack)
  1633 void QObjectDelegate::markChildren(QScriptObject *object, JSC::MarkStack& markStack)
  1703 {
  1634 {
  1821     setDelegate(new QObjectDelegate(new QObjectPrototypeObject(), QScriptEngine::AutoOwnership,
  1752     setDelegate(new QObjectDelegate(new QObjectPrototypeObject(), QScriptEngine::AutoOwnership,
  1822                                     QScriptEngine::ExcludeSuperClassMethods
  1753                                     QScriptEngine::ExcludeSuperClassMethods
  1823                                     | QScriptEngine::ExcludeSuperClassProperties
  1754                                     | QScriptEngine::ExcludeSuperClassProperties
  1824                                     | QScriptEngine::ExcludeChildObjects));
  1755                                     | QScriptEngine::ExcludeChildObjects));
  1825 
  1756 
  1826     putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum);
  1757     putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum);
  1827     putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum);
  1758     putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum);
  1828     putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum);
  1759     putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum);
  1829     this->structure()->setHasGetterSetterProperties(true);
  1760     this->structure()->setHasGetterSetterProperties(true);
  1830 }
  1761 }
  1831 
  1762 
  1832 const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 };
  1763 const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 };
  1833 
  1764 
  1860         else
  1791         else
  1861             slot.setValue(data->prototype);
  1792             slot.setValue(data->prototype);
  1862         return true;
  1793         return true;
  1863     }
  1794     }
  1864 
  1795 
  1865     QByteArray name = QString(propertyName.ustring()).toLatin1();
  1796     QByteArray name = convertToLatin1(propertyName.ustring());
  1866 
  1797 
  1867     for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1798     for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1868         QMetaEnum e = meta->enumerator(i);
  1799         QMetaEnum e = meta->enumerator(i);
  1869         for (int j = 0; j < e.keyCount(); ++j) {
  1800         for (int j = 0; j < e.keyCount(); ++j) {
  1870             const char *key = e.key(j);
  1801             const char *key = e.key(j);
  1876     }
  1807     }
  1877 
  1808 
  1878     return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot);
  1809     return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot);
  1879 }
  1810 }
  1880 
  1811 
       
  1812 bool QMetaObjectWrapperObject::getOwnPropertyDescriptor(
       
  1813     JSC::ExecState* exec, const JSC::Identifier& propertyName,
       
  1814     JSC::PropertyDescriptor& descriptor)
       
  1815 {
       
  1816     const QMetaObject *meta = data->value;
       
  1817     if (!meta)
       
  1818         return false;
       
  1819 
       
  1820     if (propertyName == exec->propertyNames().prototype) {
       
  1821         descriptor.setDescriptor(data->ctor
       
  1822                                  ? data->ctor.get(exec, propertyName)
       
  1823                                  : data->prototype,
       
  1824                                  JSC::DontDelete | JSC::DontEnum);
       
  1825         return true;
       
  1826     }
       
  1827 
       
  1828     QByteArray name = QString(propertyName.ustring()).toLatin1();
       
  1829 
       
  1830     for (int i = 0; i < meta->enumeratorCount(); ++i) {
       
  1831         QMetaEnum e = meta->enumerator(i);
       
  1832         for (int j = 0; j < e.keyCount(); ++j) {
       
  1833             const char *key = e.key(j);
       
  1834             if (!qstrcmp(key, name.constData())) {
       
  1835                 descriptor.setDescriptor(JSC::JSValue(exec, e.value(j)),
       
  1836                                          JSC::ReadOnly | JSC::DontDelete);
       
  1837                 return true;
       
  1838             }
       
  1839         }
       
  1840     }
       
  1841 
       
  1842     return JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
       
  1843 }
       
  1844 
  1881 void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
  1845 void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName,
  1882                                    JSC::JSValue value, JSC::PutPropertySlot &slot)
  1846                                    JSC::JSValue value, JSC::PutPropertySlot &slot)
  1883 {
  1847 {
  1884     if (propertyName == exec->propertyNames().prototype) {
  1848     if (propertyName == exec->propertyNames().prototype) {
  1885         if (data->ctor)
  1849         if (data->ctor)
  1888             data->prototype = value;
  1852             data->prototype = value;
  1889         return;
  1853         return;
  1890     }
  1854     }
  1891     const QMetaObject *meta = data->value;
  1855     const QMetaObject *meta = data->value;
  1892     if (meta) {
  1856     if (meta) {
  1893         QByteArray name = QString(propertyName.ustring()).toLatin1();
  1857         QByteArray name = convertToLatin1(propertyName.ustring());
  1894         for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1858         for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1895             QMetaEnum e = meta->enumerator(i);
  1859             QMetaEnum e = meta->enumerator(i);
  1896             for (int j = 0; j < e.keyCount(); ++j) {
  1860             for (int j = 0; j < e.keyCount(); ++j) {
  1897                 if (!qstrcmp(e.key(j), name.constData()))
  1861                 if (!qstrcmp(e.key(j), name.constData()))
  1898                     return;
  1862                     return;
  1901     }
  1865     }
  1902     JSC::JSObject::put(exec, propertyName, value, slot);
  1866     JSC::JSObject::put(exec, propertyName, value, slot);
  1903 }
  1867 }
  1904 
  1868 
  1905 bool QMetaObjectWrapperObject::deleteProperty(
  1869 bool QMetaObjectWrapperObject::deleteProperty(
  1906     JSC::ExecState *exec, const JSC::Identifier& propertyName,
  1870     JSC::ExecState *exec, const JSC::Identifier& propertyName)
  1907     bool checkDontDelete)
       
  1908 {
  1871 {
  1909     if (propertyName == exec->propertyNames().prototype)
  1872     if (propertyName == exec->propertyNames().prototype)
  1910         return false;
  1873         return false;
  1911     const QMetaObject *meta = data->value;
  1874     const QMetaObject *meta = data->value;
  1912     if (meta) {
  1875     if (meta) {
  1913         QByteArray name = QString(propertyName.ustring()).toLatin1();
  1876         QByteArray name = convertToLatin1(propertyName.ustring());
  1914         for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1877         for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1915             QMetaEnum e = meta->enumerator(i);
  1878             QMetaEnum e = meta->enumerator(i);
  1916             for (int j = 0; j < e.keyCount(); ++j) {
  1879             for (int j = 0; j < e.keyCount(); ++j) {
  1917                 if (!qstrcmp(e.key(j), name.constData()))
  1880                 if (!qstrcmp(e.key(j), name.constData()))
  1918                     return false;
  1881                     return false;
  1919             }
  1882             }
  1920         }
  1883         }
  1921     }
  1884     }
  1922     return JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete);
  1885     return JSC::JSObject::deleteProperty(exec, propertyName);
  1923 }
       
  1924 
       
  1925 bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec,
       
  1926                                                      const JSC::Identifier &propertyName,
       
  1927                                                      unsigned &attributes) const
       
  1928 {
       
  1929     if (propertyName == exec->propertyNames().prototype) {
       
  1930         attributes = JSC::DontDelete;
       
  1931         return true;
       
  1932     }
       
  1933     const QMetaObject *meta = data->value;
       
  1934     if (meta) {
       
  1935         QByteArray name = QString(propertyName.ustring()).toLatin1();
       
  1936         for (int i = 0; i < meta->enumeratorCount(); ++i) {
       
  1937             QMetaEnum e = meta->enumerator(i);
       
  1938             for (int j = 0; j < e.keyCount(); ++j) {
       
  1939                 if (!qstrcmp(e.key(j), name.constData())) {
       
  1940                     attributes = JSC::ReadOnly | JSC::DontDelete;
       
  1941                     return true;
       
  1942                 }
       
  1943             }
       
  1944         }
       
  1945     }
       
  1946     return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes);
       
  1947 }
  1886 }
  1948 
  1887 
  1949 void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec,
  1888 void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec,
  1950                                                    JSC::PropertyNameArray &propertyNames,
  1889                                                    JSC::PropertyNameArray &propertyNames,
  1951                                                    bool includeNonEnumerable)
  1890                                                    JSC::EnumerationMode mode)
  1952 {
  1891 {
  1953     const QMetaObject *meta = data->value;
  1892     const QMetaObject *meta = data->value;
  1954     if (!meta)
  1893     if (!meta)
  1955         return;
  1894         return;
  1956     for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1895     for (int i = 0; i < meta->enumeratorCount(); ++i) {
  1957         QMetaEnum e = meta->enumerator(i);
  1896         QMetaEnum e = meta->enumerator(i);
  1958         for (int j = 0; j < e.keyCount(); ++j)
  1897         for (int j = 0; j < e.keyCount(); ++j)
  1959             propertyNames.add(JSC::Identifier(exec, e.key(j)));
  1898             propertyNames.add(JSC::Identifier(exec, e.key(j)));
  1960     }
  1899     }
  1961     JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable);
  1900     JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode);
  1962 }
  1901 }
  1963 
  1902 
  1964 void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack)
  1903 void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack)
  1965 {
  1904 {
  1966     if (data->ctor)
  1905     if (data->ctor)
  2075 QMetaObjectPrototype::QMetaObjectPrototype(
  2014 QMetaObjectPrototype::QMetaObjectPrototype(
  2076     JSC::ExecState *exec, WTF::PassRefPtr<JSC::Structure> structure,
  2015     JSC::ExecState *exec, WTF::PassRefPtr<JSC::Structure> structure,
  2077     JSC::Structure* prototypeFunctionStructure)
  2016     JSC::Structure* prototypeFunctionStructure)
  2078     : QMetaObjectWrapperObject(exec, StaticQtMetaObject::get(), /*ctor=*/JSC::JSValue(), structure)
  2017     : QMetaObjectWrapperObject(exec, StaticQtMetaObject::get(), /*ctor=*/JSC::JSValue(), structure)
  2079 {
  2018 {
  2080     putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, JSC::Identifier(exec, "className"), qmetaobjectProtoFuncClassName), JSC::DontEnum);
  2019     putDirectFunction(exec, new (exec) JSC::NativeFunctionWrapper(exec, prototypeFunctionStructure, /*length=*/0, JSC::Identifier(exec, "className"), qmetaobjectProtoFuncClassName), JSC::DontEnum);
  2081 }
  2020 }
  2082 
  2021 
  2083 static const uint qt_meta_data_QObjectConnectionManager[] = {
  2022 static const uint qt_meta_data_QObjectConnectionManager[] = {
  2084 
  2023 
  2085  // content:
  2024  // content:
  2134 {
  2073 {
  2135     JSC::JSValue receiver;
  2074     JSC::JSValue receiver;
  2136     JSC::JSValue slot;
  2075     JSC::JSValue slot;
  2137     JSC::JSValue senderWrapper;
  2076     JSC::JSValue senderWrapper;
  2138     int signalIndex = -1;
  2077     int signalIndex = -1;
       
  2078     QScript::APIShim shim(engine);
  2139     for (int i = 0; i < connections.size(); ++i) {
  2079     for (int i = 0; i < connections.size(); ++i) {
  2140         const QVector<QObjectConnection> &cs = connections.at(i);
  2080         const QVector<QObjectConnection> &cs = connections.at(i);
  2141         for (int j = 0; j < cs.size(); ++j) {
  2081         for (int j = 0; j < cs.size(); ++j) {
  2142             const QObjectConnection &c = cs.at(j);
  2082             const QObjectConnection &c = cs.at(j);
  2143             if (c.slotIndex == slotIndex) {
  2083             if (c.slotIndex == slotIndex) {
  2176     int argc = parameterTypes.count();
  2116     int argc = parameterTypes.count();
  2177 
  2117 
  2178     JSC::ExecState *exec = engine->currentFrame;
  2118     JSC::ExecState *exec = engine->currentFrame;
  2179     QVarLengthArray<JSC::JSValue, 8> argsVector(argc);
  2119     QVarLengthArray<JSC::JSValue, 8> argsVector(argc);
  2180     for (int i = 0; i < argc; ++i) {
  2120     for (int i = 0; i < argc; ++i) {
  2181         // ### optimize -- no need to convert via QScriptValue
  2121         JSC::JSValue actual;
  2182         QScriptValue actual;
       
  2183         void *arg = argv[i + 1];
  2122         void *arg = argv[i + 1];
  2184         QByteArray typeName = parameterTypes.at(i);
  2123         QByteArray typeName = parameterTypes.at(i);
  2185         int argType = QMetaType::type(parameterTypes.at(i));
  2124         int argType = QMetaType::type(parameterTypes.at(i));
  2186         if (!argType) {
  2125         if (!argType) {
  2187             if (typeName == "QVariant") {
  2126             qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' "
  2188                 actual = engine->scriptValueFromVariant(*reinterpret_cast<QVariant*>(arg));
  2127                         "when invoking handler of signal %s::%s",
  2189             } else {
  2128                         typeName.constData(), meta->className(), method.signature());
  2190                 qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' "
  2129             actual = JSC::jsUndefined();
  2191                          "when invoking handler of signal %s::%s",
  2130         } else if (argType == QMetaType::QVariant) {
  2192                          typeName.constData(), meta->className(), method.signature());
  2131             actual = QScriptEnginePrivate::jscValueFromVariant(exec, *reinterpret_cast<QVariant*>(arg));
  2193                 actual = QScriptValue(QScriptValue::UndefinedValue);
       
  2194             }
       
  2195         } else {
  2132         } else {
  2196             actual = engine->create(argType, arg);
  2133             actual = QScriptEnginePrivate::create(exec, argType, arg);
  2197         }
  2134         }
  2198         argsVector[i] = engine->scriptValueToJSCValue(actual);
  2135         argsVector[i] = actual;
  2199     }
  2136     }
  2200     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  2137     JSC::ArgList jscArgs(argsVector.data(), argsVector.size());
  2201 
  2138 
  2202     JSC::JSValue senderObject;
  2139     JSC::JSValue senderObject;
  2203     if (senderWrapper && senderWrapper.inherits(&QScriptObject::info)) // ### check if it's actually a QObject wrapper
  2140     if (senderWrapper && senderWrapper.inherits(&QScriptObject::info)) // ### check if it's actually a QObject wrapper