PageRenderTime 137ms CodeModel.GetById 15ms app.highlight 110ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/external/webkit/WebCore/bridge/qt/qt_runtime.cpp

https://github.com/aharish/totoro-gb-opensource-update2
C++ | 1838 lines | 1508 code | 225 blank | 105 comment | 496 complexity | 4475539f91cffb28f44463913fecd2c6 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
   3 *
   4 *  This library is free software; you can redistribute it and/or
   5 *  modify it under the terms of the GNU Lesser General Public
   6 *  License as published by the Free Software Foundation; either
   7 *  version 2 of the License, or (at your option) any later version.
   8 *
   9 *  This library is distributed in the hope that it will be useful,
  10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12 *  Lesser General Public License for more details.
  13 *
  14 *  You should have received a copy of the GNU Lesser General Public
  15 *  License along with this library; if not, write to the Free Software
  16 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  17 *
  18 */
  19
  20#include "config.h"
  21#include "qt_runtime.h"
  22
  23#include "BooleanObject.h"
  24#include "DateInstance.h"
  25#include "DateMath.h"
  26#include "DatePrototype.h"
  27#include "FunctionPrototype.h"
  28#include "Interpreter.h"
  29#include "JSArray.h"
  30#include "JSByteArray.h"
  31#include "JSDOMBinding.h"
  32#include "JSGlobalObject.h"
  33#include "JSLock.h"
  34#include "JSObject.h"
  35#include "ObjectPrototype.h"
  36#include "PropertyNameArray.h"
  37#include "RegExpConstructor.h"
  38#include "RegExpObject.h"
  39#include "qdatetime.h"
  40#include "qdebug.h"
  41#include "qmetaobject.h"
  42#include "qmetatype.h"
  43#include "qobject.h"
  44#include "qstringlist.h"
  45#include "qt_instance.h"
  46#include "qt_pixmapruntime.h"
  47#include "qvarlengtharray.h"
  48#include <JSFunction.h>
  49#include <limits.h>
  50#include <runtime/Error.h>
  51#include <runtime_array.h>
  52#include <runtime_object.h>
  53
  54// QtScript has these
  55Q_DECLARE_METATYPE(QObjectList);
  56Q_DECLARE_METATYPE(QList<int>);
  57Q_DECLARE_METATYPE(QVariant);
  58
  59using namespace WebCore;
  60
  61namespace JSC {
  62namespace Bindings {
  63
  64// Debugging
  65//#define QTWK_RUNTIME_CONVERSION_DEBUG
  66//#define QTWK_RUNTIME_MATCH_DEBUG
  67
  68class QWKNoDebug
  69{
  70public:
  71    inline QWKNoDebug(){}
  72    inline ~QWKNoDebug(){}
  73
  74    template<typename T>
  75    inline QWKNoDebug &operator<<(const T &) { return *this; }
  76};
  77
  78#ifdef QTWK_RUNTIME_CONVERSION_DEBUG
  79#define qConvDebug() qDebug()
  80#else
  81#define qConvDebug() QWKNoDebug()
  82#endif
  83
  84#ifdef QTWK_RUNTIME_MATCH_DEBUG
  85#define qMatchDebug() qDebug()
  86#else
  87#define qMatchDebug() QWKNoDebug()
  88#endif
  89
  90typedef enum {
  91    Variant = 0,
  92    Number,
  93    Boolean,
  94    String,
  95    Date,
  96    RegExp,
  97    Array,
  98    QObj,
  99    Object,
 100    Null,
 101    RTArray,
 102    JSByteArray
 103} JSRealType;
 104
 105#if defined(QTWK_RUNTIME_CONVERSION_DEBUG) || defined(QTWK_RUNTIME_MATCH_DEBUG)
 106QDebug operator<<(QDebug dbg, const JSRealType &c)
 107{
 108     const char *map[] = { "Variant", "Number", "Boolean", "String", "Date",
 109         "RegExp", "Array", "RTObject", "Object", "Null", "RTArray"};
 110
 111     dbg.nospace() << "JSType(" << ((int)c) << ", " <<  map[c] << ")";
 112
 113     return dbg.space();
 114}
 115#endif
 116
 117static JSRealType valueRealType(ExecState* exec, JSValue val)
 118{
 119    if (val.isNumber())
 120        return Number;
 121    else if (val.isString())
 122        return String;
 123    else if (val.isBoolean())
 124        return Boolean;
 125    else if (val.isNull())
 126        return Null;
 127    else if (isJSByteArray(&exec->globalData(), val))
 128        return JSByteArray;
 129    else if (val.isObject()) {
 130        JSObject *object = val.toObject(exec);
 131        if (object->inherits(&RuntimeArray::s_info))  // RuntimeArray 'inherits' from Array, but not in C++
 132            return RTArray;
 133        else if (object->inherits(&JSArray::info))
 134            return Array;
 135        else if (object->inherits(&DateInstance::info))
 136            return Date;
 137        else if (object->inherits(&RegExpObject::info))
 138            return RegExp;
 139        else if (object->inherits(&RuntimeObjectImp::s_info))
 140            return QObj;
 141        return Object;
 142    }
 143
 144    return String; // I don't know.
 145}
 146
 147QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance, HashSet<JSObject*>* visitedObjects)
 148{
 149    if (!value)
 150        return QVariant();
 151
 152    JSObject* object = 0;
 153    if (value.isObject()) {
 154        object = value.toObject(exec);
 155        if (visitedObjects->contains(object))
 156            return QVariant();
 157
 158        visitedObjects->add(object);
 159    }
 160
 161    // check magic pointer values before dereferencing value
 162    if (value == jsNaN(exec)
 163        || (value == jsUndefined()
 164            && hint != QMetaType::QString
 165            && hint != (QMetaType::Type) qMetaTypeId<QVariant>())) {
 166        if (distance)
 167            *distance = -1;
 168        return QVariant();
 169    }
 170
 171    JSLock lock(SilenceAssertionsOnly);
 172    JSRealType type = valueRealType(exec, value);
 173    if (hint == QMetaType::Void) {
 174        switch(type) {
 175            case Number:
 176                hint = QMetaType::Double;
 177                break;
 178            case Boolean:
 179                hint = QMetaType::Bool;
 180                break;
 181            case String:
 182            default:
 183                hint = QMetaType::QString;
 184                break;
 185            case Date:
 186                hint = QMetaType::QDateTime;
 187                break;
 188            case RegExp:
 189                hint = QMetaType::QRegExp;
 190                break;
 191            case Object:
 192                if (object->inherits(&NumberObject::info))
 193                    hint = QMetaType::Double;
 194                else if (object->inherits(&BooleanObject::info))
 195                    hint = QMetaType::Bool;
 196                else
 197                    hint = QMetaType::QVariantMap;
 198                break;
 199            case QObj:
 200                hint = QMetaType::QObjectStar;
 201                break;
 202            case JSByteArray:
 203                hint = QMetaType::QByteArray;
 204                break;
 205            case Array:
 206            case RTArray:
 207                hint = QMetaType::QVariantList;
 208                break;
 209        }
 210    }
 211
 212    qConvDebug() << "convertValueToQVariant: jstype is " << type << ", hint is" << hint;
 213
 214    if (value == jsNull()
 215        && hint != QMetaType::QObjectStar
 216        && hint != QMetaType::VoidStar
 217        && hint != QMetaType::QString
 218        && hint != (QMetaType::Type) qMetaTypeId<QVariant>()) {
 219        if (distance)
 220            *distance = -1;
 221        return QVariant();
 222    }
 223
 224    QVariant ret;
 225    int dist = -1;
 226    switch (hint) {
 227        case QMetaType::Bool:
 228            if (type == Object && object->inherits(&BooleanObject::info))
 229                ret = QVariant(asBooleanObject(value)->internalValue().toBoolean(exec));
 230            else
 231                ret = QVariant(value.toBoolean(exec));
 232            if (type == Boolean)
 233                dist = 0;
 234            else
 235                dist = 10;
 236            break;
 237
 238        case QMetaType::Int:
 239        case QMetaType::UInt:
 240        case QMetaType::Long:
 241        case QMetaType::ULong:
 242        case QMetaType::LongLong:
 243        case QMetaType::ULongLong:
 244        case QMetaType::Short:
 245        case QMetaType::UShort:
 246        case QMetaType::Float:
 247        case QMetaType::Double:
 248            ret = QVariant(value.toNumber(exec));
 249            ret.convert((QVariant::Type)hint);
 250            if (type == Number) {
 251                switch (hint) {
 252                case QMetaType::Double:
 253                    dist = 0;
 254                    break;
 255                case QMetaType::Float:
 256                    dist = 1;
 257                    break;
 258                case QMetaType::LongLong:
 259                case QMetaType::ULongLong:
 260                    dist = 2;
 261                    break;
 262                case QMetaType::Long:
 263                case QMetaType::ULong:
 264                    dist = 3;
 265                    break;
 266                case QMetaType::Int:
 267                case QMetaType::UInt:
 268                    dist = 4;
 269                    break;
 270                case QMetaType::Short:
 271                case QMetaType::UShort:
 272                    dist = 5;
 273                    break;
 274                    break;
 275                default:
 276                    dist = 10;
 277                    break;
 278                }
 279            } else {
 280                dist = 10;
 281            }
 282            break;
 283
 284        case QMetaType::QChar:
 285            if (type == Number || type == Boolean) {
 286                ret = QVariant(QChar((ushort)value.toNumber(exec)));
 287                if (type == Boolean)
 288                    dist = 3;
 289                else
 290                    dist = 6;
 291            } else {
 292                UString str = value.toString(exec);
 293                ret = QVariant(QChar(str.size() ? *(const ushort*)str.rep()->data() : 0));
 294                if (type == String)
 295                    dist = 3;
 296                else
 297                    dist = 10;
 298            }
 299            break;
 300
 301        case QMetaType::QString: {
 302            if (value.isUndefinedOrNull()) {
 303                if (distance)
 304                    *distance = 1;
 305                return QString();
 306            } else {
 307                UString ustring = value.toString(exec);
 308                ret = QVariant(QString((const QChar*)ustring.rep()->data(), ustring.size()));
 309                if (type == String)
 310                    dist = 0;
 311                else
 312                    dist = 10;
 313            }
 314            break;
 315        }
 316
 317        case QMetaType::QVariantMap: 
 318            if (type == Object || type == Array || type == RTArray) {
 319                // Enumerate the contents of the object
 320                PropertyNameArray properties(exec);
 321                object->getPropertyNames(exec, properties);
 322                PropertyNameArray::const_iterator it = properties.begin();
 323
 324                QVariantMap result;
 325                int objdist = 0;
 326                while(it != properties.end()) {
 327                    if (object->propertyIsEnumerable(exec, *it)) {
 328                        JSValue val = object->get(exec, *it);
 329                        QVariant v = convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects);
 330                        if (objdist >= 0) {
 331                            UString ustring = (*it).ustring();
 332                            QString id = QString((const QChar*)ustring.rep()->data(), ustring.size());
 333                            result.insert(id, v);
 334                        }
 335                    }
 336                    ++it;
 337                }
 338                dist = 1;
 339                ret = QVariant(result);
 340            }
 341            break;
 342
 343        case QMetaType::QVariantList:
 344            if (type == RTArray) {
 345                RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
 346
 347                QVariantList result;
 348                int len = rtarray->getLength();
 349                int objdist = 0;
 350                qConvDebug() << "converting a " << len << " length Array";
 351                for (int i = 0; i < len; ++i) {
 352                    JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
 353                    result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects));
 354                    if (objdist == -1) {
 355                        qConvDebug() << "Failed converting element at index " << i;
 356                        break; // Failed converting a list entry, so fail the array
 357                    }
 358                }
 359                if (objdist != -1) {
 360                    dist = 5;
 361                    ret = QVariant(result);
 362                }
 363            } else if (type == Array) {
 364                JSArray* array = static_cast<JSArray*>(object);
 365
 366                QVariantList result;
 367                int len = array->length();
 368                int objdist = 0;
 369                qConvDebug() << "converting a " << len << " length Array";
 370                for (int i = 0; i < len; ++i) {
 371                    JSValue val = array->get(exec, i);
 372                    result.append(convertValueToQVariant(exec, val, QMetaType::Void, &objdist, visitedObjects));
 373                    if (objdist == -1) {
 374                        qConvDebug() << "Failed converting element at index " << i;
 375                        break; // Failed converting a list entry, so fail the array
 376                    }
 377                }
 378                if (objdist != -1) {
 379                    dist = 5;
 380                    ret = QVariant(result);
 381                }
 382            } else {
 383                // Make a single length array
 384                int objdist;
 385                qConvDebug() << "making a single length variantlist";
 386                QVariant var = convertValueToQVariant(exec, value, QMetaType::Void, &objdist, visitedObjects);
 387                if (objdist != -1) {
 388                    QVariantList result;
 389                    result << var;
 390                    ret = QVariant(result);
 391                    dist = 10;
 392                } else {
 393                    qConvDebug() << "failed making single length varlist";
 394                }
 395            }
 396            break;
 397
 398        case QMetaType::QStringList: {
 399            if (type == RTArray) {
 400                RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
 401
 402                QStringList result;
 403                int len = rtarray->getLength();
 404                for (int i = 0; i < len; ++i) {
 405                    JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
 406                    UString ustring = val.toString(exec);
 407                    QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 408
 409                    result.append(qstring);
 410                }
 411                dist = 5;
 412                ret = QVariant(result);
 413            } else if (type == Array) {
 414                JSArray* array = static_cast<JSArray*>(object);
 415
 416                QStringList result;
 417                int len = array->length();
 418                for (int i = 0; i < len; ++i) {
 419                    JSValue val = array->get(exec, i);
 420                    UString ustring = val.toString(exec);
 421                    QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 422
 423                    result.append(qstring);
 424                }
 425                dist = 5;
 426                ret = QVariant(result);
 427            } else {
 428                // Make a single length array
 429                UString ustring = value.toString(exec);
 430                QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 431                QStringList result;
 432                result.append(qstring);
 433                ret = QVariant(result);
 434                dist = 10;
 435            }
 436            break;
 437        }
 438
 439        case QMetaType::QByteArray: {
 440            if (type == JSByteArray) {
 441                WTF::ByteArray* arr = asByteArray(value)->storage();
 442                ret = QVariant(QByteArray(reinterpret_cast<const char*>(arr->data()), arr->length()));
 443                dist = 0;
 444            } else {
 445                UString ustring = value.toString(exec);
 446                ret = QVariant(QString((const QChar*)ustring.rep()->data(), ustring.size()).toLatin1());
 447                if (type == String)
 448                    dist = 5;
 449                else
 450                    dist = 10;
 451            }
 452            break;
 453        }
 454
 455        case QMetaType::QDateTime:
 456        case QMetaType::QDate:
 457        case QMetaType::QTime:
 458            if (type == Date) {
 459                DateInstance* date = static_cast<DateInstance*>(object);
 460                GregorianDateTime gdt;
 461                msToGregorianDateTime(exec, date->internalNumber(), true, gdt);
 462                if (hint == QMetaType::QDateTime) {
 463                    ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
 464                    dist = 0;
 465                } else if (hint == QMetaType::QDate) {
 466                    ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
 467                    dist = 1;
 468                } else {
 469                    ret = QTime(gdt.hour + 1900, gdt.minute, gdt.second);
 470                    dist = 2;
 471                }
 472            } else if (type == Number) {
 473                double b = value.toNumber(exec);
 474                GregorianDateTime gdt;
 475                msToGregorianDateTime(exec, b, true, gdt);
 476                if (hint == QMetaType::QDateTime) {
 477                    ret = QDateTime(QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay), QTime(gdt.hour, gdt.minute, gdt.second), Qt::UTC);
 478                    dist = 6;
 479                } else if (hint == QMetaType::QDate) {
 480                    ret = QDate(gdt.year + 1900, gdt.month + 1, gdt.monthDay);
 481                    dist = 8;
 482                } else {
 483                    ret = QTime(gdt.hour, gdt.minute, gdt.second);
 484                    dist = 10;
 485                }
 486            } else if (type == String) {
 487                UString ustring = value.toString(exec);
 488                QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 489
 490                if (hint == QMetaType::QDateTime) {
 491                    QDateTime dt = QDateTime::fromString(qstring, Qt::ISODate);
 492                    if (!dt.isValid())
 493                        dt = QDateTime::fromString(qstring, Qt::TextDate);
 494                    if (!dt.isValid())
 495                        dt = QDateTime::fromString(qstring, Qt::SystemLocaleDate);
 496                    if (!dt.isValid())
 497                        dt = QDateTime::fromString(qstring, Qt::LocaleDate);
 498                    if (dt.isValid()) {
 499                        ret = dt;
 500                        dist = 2;
 501                    }
 502                } else if (hint == QMetaType::QDate) {
 503                    QDate dt = QDate::fromString(qstring, Qt::ISODate);
 504                    if (!dt.isValid())
 505                        dt = QDate::fromString(qstring, Qt::TextDate);
 506                    if (!dt.isValid())
 507                        dt = QDate::fromString(qstring, Qt::SystemLocaleDate);
 508                    if (!dt.isValid())
 509                        dt = QDate::fromString(qstring, Qt::LocaleDate);
 510                    if (dt.isValid()) {
 511                        ret = dt;
 512                        dist = 3;
 513                    }
 514                } else {
 515                    QTime dt = QTime::fromString(qstring, Qt::ISODate);
 516                    if (!dt.isValid())
 517                        dt = QTime::fromString(qstring, Qt::TextDate);
 518                    if (!dt.isValid())
 519                        dt = QTime::fromString(qstring, Qt::SystemLocaleDate);
 520                    if (!dt.isValid())
 521                        dt = QTime::fromString(qstring, Qt::LocaleDate);
 522                    if (dt.isValid()) {
 523                        ret = dt;
 524                        dist = 3;
 525                    }
 526                }
 527            }
 528            break;
 529
 530        case QMetaType::QRegExp:
 531            if (type == RegExp) {
 532/*
 533                RegExpObject *re = static_cast<RegExpObject*>(object);
 534*/
 535                // Attempt to convert.. a bit risky
 536                UString ustring = value.toString(exec);
 537                QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 538
 539                // this is of the form '/xxxxxx/i'
 540                int firstSlash = qstring.indexOf(QLatin1Char('/'));
 541                int lastSlash = qstring.lastIndexOf(QLatin1Char('/'));
 542                if (firstSlash >=0 && lastSlash > firstSlash) {
 543                    QRegExp realRe;
 544
 545                    realRe.setPattern(qstring.mid(firstSlash + 1, lastSlash - firstSlash - 1));
 546
 547                    if (qstring.mid(lastSlash + 1).contains(QLatin1Char('i')))
 548                        realRe.setCaseSensitivity(Qt::CaseInsensitive);
 549
 550                    ret = qVariantFromValue(realRe);
 551                    dist = 0;
 552                } else {
 553                    qConvDebug() << "couldn't parse a JS regexp";
 554                }
 555            } else if (type == String) {
 556                UString ustring = value.toString(exec);
 557                QString qstring = QString((const QChar*)ustring.rep()->data(), ustring.size());
 558
 559                QRegExp re(qstring);
 560                if (re.isValid()) {
 561                    ret = qVariantFromValue(re);
 562                    dist = 10;
 563                }
 564            }
 565            break;
 566
 567        case QMetaType::QObjectStar:
 568            if (type == QObj) {
 569                QtInstance* qtinst = QtInstance::getInstance(object);
 570                if (qtinst) {
 571                    if (qtinst->getObject()) {
 572                        qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
 573                        ret = qVariantFromValue(qtinst->getObject());
 574                        qConvDebug() << ret;
 575                        dist = 0;
 576                    } else {
 577                        qConvDebug() << "can't convert deleted qobject";
 578                    }
 579                } else {
 580                    qConvDebug() << "wasn't a qtinstance";
 581                }
 582            } else if (type == Null) {
 583                QObject* nullobj = 0;
 584                ret = qVariantFromValue(nullobj);
 585                dist = 0;
 586            } else {
 587                qConvDebug() << "previous type was not an object:" << type;
 588            }
 589            break;
 590
 591        case QMetaType::VoidStar:
 592            if (type == QObj) {
 593                QtInstance* qtinst = QtInstance::getInstance(object);
 594                if (qtinst) {
 595                    if (qtinst->getObject()) {
 596                        qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject();
 597                        ret = qVariantFromValue((void *)qtinst->getObject());
 598                        qConvDebug() << ret;
 599                        dist = 0;
 600                    } else {
 601                        qConvDebug() << "can't convert deleted qobject";
 602                    }
 603                } else {
 604                    qConvDebug() << "wasn't a qtinstance";
 605                }
 606            } else if (type == Null) {
 607                ret = qVariantFromValue((void*)0);
 608                dist = 0;
 609            } else if (type == Number) {
 610                // I don't think that converting a double to a pointer is a wise
 611                // move.  Except maybe 0.
 612                qConvDebug() << "got number for void * - not converting, seems unsafe:" << value.toNumber(exec);
 613            } else {
 614                qConvDebug() << "void* - unhandled type" << type;
 615            }
 616            break;
 617
 618        default:
 619            // Non const type ids
 620            if (hint == (QMetaType::Type) qMetaTypeId<QObjectList>())
 621            {
 622                if (type == RTArray) {
 623                    RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
 624
 625                    QObjectList result;
 626                    int len = rtarray->getLength();
 627                    for (int i = 0; i < len; ++i) {
 628                        JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
 629                        int itemdist = -1;
 630                        QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects);
 631                        if (itemdist >= 0)
 632                            result.append(item.value<QObject*>());
 633                        else
 634                            break;
 635                    }
 636                    // If we didn't fail conversion
 637                    if (result.count() == len) {
 638                        dist = 5;
 639                        ret = QVariant::fromValue(result);
 640                    }
 641                } else if (type == Array) {
 642                    JSObject* object = value.toObject(exec);
 643                    JSArray* array = static_cast<JSArray *>(object);
 644                    QObjectList result;
 645                    int len = array->length();
 646                    for (int i = 0; i < len; ++i) {
 647                        JSValue val = array->get(exec, i);
 648                        int itemdist = -1;
 649                        QVariant item = convertValueToQVariant(exec, val, QMetaType::QObjectStar, &itemdist, visitedObjects);
 650                        if (itemdist >= 0)
 651                            result.append(item.value<QObject*>());
 652                        else
 653                            break;
 654                    }
 655                    // If we didn't fail conversion
 656                    if (result.count() == len) {
 657                        dist = 5;
 658                        ret = QVariant::fromValue(result);
 659                    }
 660                } else {
 661                    // Make a single length array
 662                    QObjectList result;
 663                    int itemdist = -1;
 664                    QVariant item = convertValueToQVariant(exec, value, QMetaType::QObjectStar, &itemdist, visitedObjects);
 665                    if (itemdist >= 0) {
 666                        result.append(item.value<QObject*>());
 667                        dist = 10;
 668                        ret = QVariant::fromValue(result);
 669                    }
 670                }
 671                break;
 672            } else if (hint == (QMetaType::Type) qMetaTypeId<QList<int> >()) {
 673                if (type == RTArray) {
 674                    RuntimeArray* rtarray = static_cast<RuntimeArray*>(object);
 675
 676                    QList<int> result;
 677                    int len = rtarray->getLength();
 678                    for (int i = 0; i < len; ++i) {
 679                        JSValue val = rtarray->getConcreteArray()->valueAt(exec, i);
 680                        int itemdist = -1;
 681                        QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects);
 682                        if (itemdist >= 0)
 683                            result.append(item.value<int>());
 684                        else
 685                            break;
 686                    }
 687                    // If we didn't fail conversion
 688                    if (result.count() == len) {
 689                        dist = 5;
 690                        ret = QVariant::fromValue(result);
 691                    }
 692                } else if (type == Array) {
 693                    JSArray* array = static_cast<JSArray *>(object);
 694
 695                    QList<int> result;
 696                    int len = array->length();
 697                    for (int i = 0; i < len; ++i) {
 698                        JSValue val = array->get(exec, i);
 699                        int itemdist = -1;
 700                        QVariant item = convertValueToQVariant(exec, val, QMetaType::Int, &itemdist, visitedObjects);
 701                        if (itemdist >= 0)
 702                            result.append(item.value<int>());
 703                        else
 704                            break;
 705                    }
 706                    // If we didn't fail conversion
 707                    if (result.count() == len) {
 708                        dist = 5;
 709                        ret = QVariant::fromValue(result);
 710                    }
 711                } else {
 712                    // Make a single length array
 713                    QList<int> result;
 714                    int itemdist = -1;
 715                    QVariant item = convertValueToQVariant(exec, value, QMetaType::Int, &itemdist, visitedObjects);
 716                    if (itemdist >= 0) {
 717                        result.append(item.value<int>());
 718                        dist = 10;
 719                        ret = QVariant::fromValue(result);
 720                    }
 721                }
 722                break;
 723            } else if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) {
 724                ret = QtPixmapInstance::variantFromObject(object, static_cast<QMetaType::Type>(hint));
 725            } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) {
 726                if (value.isUndefinedOrNull()) {
 727                    if (distance)
 728                        *distance = 1;
 729                    return QVariant();
 730                } else {
 731                    if (type == Object) {
 732                        // Since we haven't really visited this object yet, we remove it
 733                        visitedObjects->remove(object);
 734                    }
 735
 736                    // And then recurse with the autodetect flag
 737                    ret = convertValueToQVariant(exec, value, QMetaType::Void, distance, visitedObjects);
 738                    dist = 10;
 739                }
 740                break;
 741            }
 742
 743            dist = 10;
 744            break;
 745    }
 746
 747    if (!ret.isValid())
 748        dist = -1;
 749    if (distance)
 750        *distance = dist;
 751
 752    return ret;
 753}
 754
 755QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance)
 756{
 757    HashSet<JSObject*> visitedObjects;
 758    return convertValueToQVariant(exec, value, hint, distance, &visitedObjects);
 759}
 760
 761JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant)
 762{
 763    // Variants with QObject * can be isNull but not a null pointer
 764    // An empty QString variant is also null
 765    QMetaType::Type type = (QMetaType::Type) variant.userType();
 766
 767    qConvDebug() << "convertQVariantToValue: metatype:" << type << ", isnull: " << variant.isNull();
 768    if (variant.isNull() &&
 769        type != QMetaType::QObjectStar &&
 770        type != QMetaType::VoidStar &&
 771        type != QMetaType::QWidgetStar &&
 772        type != QMetaType::QString) {
 773        return jsNull();
 774    }
 775
 776    JSLock lock(SilenceAssertionsOnly);
 777
 778    if (type == QMetaType::Bool)
 779        return jsBoolean(variant.toBool());
 780
 781    if (type == QMetaType::Int ||
 782        type == QMetaType::UInt ||
 783        type == QMetaType::Long ||
 784        type == QMetaType::ULong ||
 785        type == QMetaType::LongLong ||
 786        type == QMetaType::ULongLong ||
 787        type == QMetaType::Short ||
 788        type == QMetaType::UShort ||
 789        type == QMetaType::Float ||
 790        type == QMetaType::Double)
 791        return jsNumber(exec, variant.toDouble());
 792
 793    if (type == QMetaType::QRegExp) {
 794        QRegExp re = variant.value<QRegExp>();
 795
 796        if (re.isValid()) {
 797            UString uflags;
 798            if (re.caseSensitivity() == Qt::CaseInsensitive)
 799                uflags = "i"; // ### Can't do g or m
 800
 801            UString pattern((UChar*)re.pattern().utf16(), re.pattern().length());
 802
 803            RefPtr<JSC::RegExp> regExp = JSC::RegExp::create(&exec->globalData(), pattern, uflags);
 804            if (regExp->isValid())
 805                return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
 806            else
 807                return jsNull();
 808        }
 809    }
 810
 811    if (type == QMetaType::QDateTime ||
 812        type == QMetaType::QDate ||
 813        type == QMetaType::QTime) {
 814
 815        QDate date = QDate::currentDate();
 816        QTime time(0,0,0); // midnight
 817
 818        if (type == QMetaType::QDate)
 819            date = variant.value<QDate>();
 820        else if (type == QMetaType::QTime)
 821            time = variant.value<QTime>();
 822        else {
 823            QDateTime dt = variant.value<QDateTime>().toLocalTime();
 824            date = dt.date();
 825            time = dt.time();
 826        }
 827
 828        // Dates specified this way are in local time (we convert DateTimes above)
 829        GregorianDateTime dt;
 830        dt.year = date.year() - 1900;
 831        dt.month = date.month() - 1;
 832        dt.monthDay = date.day();
 833        dt.hour = time.hour();
 834        dt.minute = time.minute();
 835        dt.second = time.second();
 836        dt.isDST = -1;
 837        double ms = gregorianDateTimeToMS(exec, dt, time.msec(), /*inputIsUTC*/ false);
 838
 839        return new (exec) DateInstance(exec, trunc(ms));
 840    }
 841
 842    if (type == QMetaType::QByteArray) {
 843        QByteArray qtByteArray = variant.value<QByteArray>();
 844        WTF::RefPtr<WTF::ByteArray> wtfByteArray = WTF::ByteArray::create(qtByteArray.length());
 845        qMemCopy(wtfByteArray->data(), qtByteArray.constData(), qtByteArray.length());
 846        return new (exec) JSC::JSByteArray(exec, JSC::JSByteArray::createStructure(jsNull()), wtfByteArray.get());
 847    }
 848
 849    if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
 850        QObject* obj = variant.value<QObject*>();
 851        return QtInstance::getQtInstance(obj, root, QScriptEngine::QtOwnership)->createRuntimeObject(exec);
 852    }
 853
 854    if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type())))
 855        return QtPixmapInstance::createRuntimeObject(exec, root, variant);
 856
 857    if (type == QMetaType::QVariantMap) {
 858        // create a new object, and stuff properties into it
 859        JSObject* ret = constructEmptyObject(exec);
 860        QVariantMap map = variant.value<QVariantMap>();
 861        QVariantMap::const_iterator i = map.constBegin();
 862        while (i != map.constEnd()) {
 863            QString s = i.key();
 864            JSValue val = convertQVariantToValue(exec, root, i.value());
 865            if (val) {
 866                PutPropertySlot slot;
 867                ret->put(exec, Identifier(exec, (const UChar *)s.constData(), s.length()), val, slot);
 868                // ### error case?
 869            }
 870            ++i;
 871        }
 872
 873        return ret;
 874    }
 875
 876    // List types
 877    if (type == QMetaType::QVariantList) {
 878        QVariantList vl = variant.toList();
 879        qConvDebug() << "got a " << vl.count() << " length list:" << vl;
 880        return new (exec) RuntimeArray(exec, new QtArray<QVariant>(vl, QMetaType::Void, root));
 881    } else if (type == QMetaType::QStringList) {
 882        QStringList sl = variant.value<QStringList>();
 883        return new (exec) RuntimeArray(exec, new QtArray<QString>(sl, QMetaType::QString, root));
 884    } else if (type == (QMetaType::Type) qMetaTypeId<QObjectList>()) {
 885        QObjectList ol= variant.value<QObjectList>();
 886        return new (exec) RuntimeArray(exec, new QtArray<QObject*>(ol, QMetaType::QObjectStar, root));
 887    } else if (type == (QMetaType::Type)qMetaTypeId<QList<int> >()) {
 888        QList<int> il= variant.value<QList<int> >();
 889        return new (exec) RuntimeArray(exec, new QtArray<int>(il, QMetaType::Int, root));
 890    }
 891
 892    if (type == (QMetaType::Type)qMetaTypeId<QVariant>()) {
 893        QVariant real = variant.value<QVariant>();
 894        qConvDebug() << "real variant is:" << real;
 895        return convertQVariantToValue(exec, root, real);
 896    }
 897
 898    qConvDebug() << "fallback path for" << variant << variant.userType();
 899
 900    QString string = variant.toString();
 901    UString ustring((UChar*)string.utf16(), string.length());
 902    return jsString(exec, ustring);
 903}
 904
 905// ===============
 906
 907// Qt-like macros
 908#define QW_D(Class) Class##Data* d = d_func()
 909#define QW_DS(Class,Instance) Class##Data* d = Instance->d_func()
 910
 911const ClassInfo QtRuntimeMethod::s_info = { "QtRuntimeMethod", 0, 0, 0 };
 912
 913QtRuntimeMethod::QtRuntimeMethod(QtRuntimeMethodData* dd, ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst)
 914    : InternalFunction(&exec->globalData(), deprecatedGetDOMStructure<QtRuntimeMethod>(exec), ident)
 915    , d_ptr(dd)
 916{
 917    QW_D(QtRuntimeMethod);
 918    d->m_instance = inst;
 919}
 920
 921QtRuntimeMethod::~QtRuntimeMethod()
 922{
 923    QW_D(QtRuntimeMethod);
 924    d->m_instance->removeCachedMethod(this);
 925    delete d_ptr;
 926}
 927
 928// ===============
 929
 930QtRuntimeMethodData::~QtRuntimeMethodData()
 931{
 932}
 933
 934QtRuntimeMetaMethodData::~QtRuntimeMetaMethodData()
 935{
 936
 937}
 938
 939QtRuntimeConnectionMethodData::~QtRuntimeConnectionMethodData()
 940{
 941
 942}
 943
 944// ===============
 945
 946// Type conversion metadata (from QtScript originally)
 947class QtMethodMatchType
 948{
 949public:
 950    enum Kind {
 951        Invalid,
 952        Variant,
 953        MetaType,
 954        Unresolved,
 955        MetaEnum
 956    };
 957
 958
 959    QtMethodMatchType()
 960        : m_kind(Invalid) { }
 961
 962    Kind kind() const
 963    { return m_kind; }
 964
 965    QMetaType::Type typeId() const;
 966
 967    bool isValid() const
 968    { return (m_kind != Invalid); }
 969
 970    bool isVariant() const
 971    { return (m_kind == Variant); }
 972
 973    bool isMetaType() const
 974    { return (m_kind == MetaType); }
 975
 976    bool isUnresolved() const
 977    { return (m_kind == Unresolved); }
 978
 979    bool isMetaEnum() const
 980    { return (m_kind == MetaEnum); }
 981
 982    QByteArray name() const;
 983
 984    int enumeratorIndex() const
 985    { Q_ASSERT(isMetaEnum()); return m_typeId; }
 986
 987    static QtMethodMatchType variant()
 988    { return QtMethodMatchType(Variant); }
 989
 990    static QtMethodMatchType metaType(int typeId, const QByteArray &name)
 991    { return QtMethodMatchType(MetaType, typeId, name); }
 992
 993    static QtMethodMatchType metaEnum(int enumIndex, const QByteArray &name)
 994    { return QtMethodMatchType(MetaEnum, enumIndex, name); }
 995
 996    static QtMethodMatchType unresolved(const QByteArray &name)
 997    { return QtMethodMatchType(Unresolved, /*typeId=*/0, name); }
 998
 999private:
1000    QtMethodMatchType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray())
1001        : m_kind(kind), m_typeId(typeId), m_name(name) { }
1002
1003    Kind m_kind;
1004    int m_typeId;
1005    QByteArray m_name;
1006};
1007
1008QMetaType::Type QtMethodMatchType::typeId() const
1009{
1010    if (isVariant())
1011        return (QMetaType::Type) QMetaType::type("QVariant");
1012    return (QMetaType::Type) (isMetaEnum() ? QMetaType::Int : m_typeId);
1013}
1014
1015QByteArray QtMethodMatchType::name() const
1016{
1017    if (!m_name.isEmpty())
1018        return m_name;
1019    else if (m_kind == Variant)
1020        return "QVariant";
1021    return QByteArray();
1022}
1023
1024struct QtMethodMatchData
1025{
1026    int matchDistance;
1027    int index;
1028    QVector<QtMethodMatchType> types;
1029    QVarLengthArray<QVariant, 10> args;
1030
1031    QtMethodMatchData(int dist, int idx, QVector<QtMethodMatchType> typs,
1032                                const QVarLengthArray<QVariant, 10> &as)
1033        : matchDistance(dist), index(idx), types(typs), args(as) { }
1034    QtMethodMatchData()
1035        : index(-1) { }
1036
1037    bool isValid() const
1038    { return (index != -1); }
1039
1040    int firstUnresolvedIndex() const
1041    {
1042        for (int i=0; i < types.count(); i++) {
1043            if (types.at(i).isUnresolved())
1044                return i;
1045        }
1046        return -1;
1047    }
1048};
1049
1050static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str)
1051{
1052    QByteArray scope;
1053    QByteArray name;
1054    int scopeIdx = str.indexOf("::");
1055    if (scopeIdx != -1) {
1056        scope = str.left(scopeIdx);
1057        name = str.mid(scopeIdx + 2);
1058    } else {
1059        name = str;
1060    }
1061    for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
1062        QMetaEnum m = meta->enumerator(i);
1063        if ((m.name() == name)/* && (scope.isEmpty() || (m.scope() == scope))*/)
1064            return i;
1065    }
1066    return -1;
1067}
1068
1069// Helper function for resolving methods
1070// Largely based on code in QtScript for compatibility reasons
1071static int findMethodIndex(ExecState* exec,
1072                           const QMetaObject* meta,
1073                           const QByteArray& signature,
1074                           bool allowPrivate,
1075                           const ArgList& jsArgs,
1076                           QVarLengthArray<QVariant, 10> &vars,
1077                           void** vvars,
1078                           JSObject **pError)
1079{
1080    QList<int> matchingIndices;
1081
1082    bool overloads = !signature.contains('(');
1083
1084    int count = meta->methodCount();
1085    for (int i = count - 1; i >= 0; --i) {
1086        const QMetaMethod m = meta->method(i);
1087
1088        // Don't choose private methods
1089        if (m.access() == QMetaMethod::Private && !allowPrivate)
1090            continue;
1091
1092        // try and find all matching named methods
1093        if (m.signature() == signature)
1094            matchingIndices.append(i);
1095        else if (overloads) {
1096            QByteArray rawsignature = m.signature();
1097            rawsignature.truncate(rawsignature.indexOf('('));
1098            if (rawsignature == signature)
1099                matchingIndices.append(i);
1100        }
1101    }
1102
1103    int chosenIndex = -1;
1104    *pError = 0;
1105    QVector<QtMethodMatchType> chosenTypes;
1106
1107    QVarLengthArray<QVariant, 10> args;
1108    QVector<QtMethodMatchData> candidates;
1109    QVector<QtMethodMatchData> unresolved;
1110    QVector<int> tooFewArgs;
1111    QVector<int> conversionFailed;
1112
1113    foreach(int index, matchingIndices) {
1114        QMetaMethod method = meta->method(index);
1115
1116        QVector<QtMethodMatchType> types;
1117        bool unresolvedTypes = false;
1118
1119        // resolve return type
1120        QByteArray returnTypeName = method.typeName();
1121        int rtype = QMetaType::type(returnTypeName);
1122        if ((rtype == 0) && !returnTypeName.isEmpty()) {
1123            if (returnTypeName == "QVariant") {
1124                types.append(QtMethodMatchType::variant());
1125            } else if (returnTypeName.endsWith('*')) {
1126                types.append(QtMethodMatchType::metaType(QMetaType::VoidStar, returnTypeName));
1127            } else {
1128                int enumIndex = indexOfMetaEnum(meta, returnTypeName);
1129                if (enumIndex != -1)
1130                    types.append(QtMethodMatchType::metaEnum(enumIndex, returnTypeName));
1131                else {
1132                    unresolvedTypes = true;
1133                    types.append(QtMethodMatchType::unresolved(returnTypeName));
1134                }
1135            }
1136        } else {
1137            if (returnTypeName == "QVariant")
1138                types.append(QtMethodMatchType::variant());
1139            else
1140                types.append(QtMethodMatchType::metaType(rtype, returnTypeName));
1141        }
1142
1143        // resolve argument types
1144        QList<QByteArray> parameterTypeNames = method.parameterTypes();
1145        for (int i = 0; i < parameterTypeNames.count(); ++i) {
1146            QByteArray argTypeName = parameterTypeNames.at(i);
1147            int atype = QMetaType::type(argTypeName);
1148            if (atype == 0) {
1149                if (argTypeName == "QVariant") {
1150                    types.append(QtMethodMatchType::variant());
1151                } else {
1152                    int enumIndex = indexOfMetaEnum(meta, argTypeName);
1153                    if (enumIndex != -1)
1154                        types.append(QtMethodMatchType::metaEnum(enumIndex, argTypeName));
1155                    else {
1156                        unresolvedTypes = true;
1157                        types.append(QtMethodMatchType::unresolved(argTypeName));
1158                    }
1159                }
1160            } else {
1161                if (argTypeName == "QVariant")
1162                    types.append(QtMethodMatchType::variant());
1163                else
1164                    types.append(QtMethodMatchType::metaType(atype, argTypeName));
1165            }
1166        }
1167
1168        // If the native method requires more arguments than what was passed from JavaScript
1169        if (jsArgs.size() + 1 < static_cast<unsigned>(types.count())) {
1170            qMatchDebug() << "Match:too few args for" << method.signature();
1171            tooFewArgs.append(index);
1172            continue;
1173        }
1174
1175        if (unresolvedTypes) {
1176            qMatchDebug() << "Match:unresolved arg types for" << method.signature();
1177            // remember it so we can give an error message later, if necessary
1178            unresolved.append(QtMethodMatchData(/*matchDistance=*/INT_MAX, index,
1179                                                   types, QVarLengthArray<QVariant, 10>()));
1180            continue;
1181        }
1182
1183        // Now convert arguments
1184        if (args.count() != types.count())
1185            args.resize(types.count());
1186
1187        QtMethodMatchType retType = types[0];
1188        args[0] = QVariant(retType.typeId(), (void *)0); // the return value
1189
1190        bool converted = true;
1191        int matchDistance = 0;
1192        for (unsigned i = 0; converted && i + 1 < static_cast<unsigned>(types.count()); ++i) {
1193            JSValue arg = i < jsArgs.size() ? jsArgs.at(i) : jsUndefined();
1194
1195            int argdistance = -1;
1196            QVariant v = convertValueToQVariant(exec, arg, types.at(i+1).typeId(), &argdistance);
1197            if (argdistance >= 0) {
1198                matchDistance += argdistance;
1199                args[i+1] = v;
1200            } else {
1201                qMatchDebug() << "failed to convert argument " << i << "type" << types.at(i+1).typeId() << QMetaType::typeName(types.at(i+1).typeId());
1202                converted = false;
1203            }
1204        }
1205
1206        qMatchDebug() << "Match: " << method.signature() << (converted ? "converted":"failed to convert") << "distance " << matchDistance;
1207
1208        if (converted) {
1209            if ((jsArgs.size() + 1 == static_cast<unsigned>(types.count()))
1210                && (matchDistance == 0)) {
1211                // perfect match, use this one
1212                chosenIndex = index;
1213                break;
1214            } else {
1215                QtMethodMatchData currentMatch(matchDistance, index, types, args);
1216                if (candidates.isEmpty()) {
1217                    candidates.append(currentMatch);
1218                } else {
1219                    QtMethodMatchData bestMatchSoFar = candidates.at(0);
1220                    if ((args.count() > bestMatchSoFar.args.count())
1221                        || ((args.count() == bestMatchSoFar.args.count())
1222                            && (matchDistance <= bestMatchSoFar.matchDistance))) {
1223                        candidates.prepend(currentMatch);
1224                    } else {
1225                        candidates.append(currentMatch);
1226                    }
1227                }
1228            }
1229        } else {
1230            conversionFailed.append(index);
1231        }
1232
1233        if (!overloads)
1234            break;
1235    }
1236
1237    if (chosenIndex == -1 && candidates.count() == 0) {
1238        // No valid functions at all - format an error message
1239        if (!conversionFailed.isEmpty()) {
1240            QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n")
1241                              .arg(QLatin1String(signature));
1242            for (int i = 0; i < conversionFailed.size(); ++i) {
1243                if (i > 0)
1244                    message += QLatin1String("\n");
1245                QMetaMethod mtd = meta->method(conversionFailed.at(i));
1246                message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
1247            }
1248            *pError = throwError(exec, TypeError, message.toLatin1().constData());
1249        } else if (!unresolved.isEmpty()) {
1250            QtMethodMatchData argsInstance = unresolved.first();
1251            int unresolvedIndex = argsInstance.firstUnresolvedIndex();
1252            Q_ASSERT(unresolvedIndex != -1);
1253            QtMethodMatchType unresolvedType = argsInstance.types.at(unresolvedIndex);
1254            QString message = QString::fromLatin1("cannot call %0(): unknown type `%1'")
1255                .arg(QString::fromLatin1(signature))
1256                .arg(QLatin1String(unresolvedType.name()));
1257            *pError = throwError(exec, TypeError, message.toLatin1().constData());
1258        } else {
1259            QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n")
1260                              .arg(QLatin1String(signature));
1261            for (int i = 0; i < tooFewArgs.size(); ++i) {
1262                if (i > 0)
1263                    message += QLatin1String("\n");
1264                QMetaMethod mtd = meta->method(tooFewArgs.at(i));
1265                message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
1266            }
1267            *pError = throwError(exec, SyntaxError, message.toLatin1().constData());
1268        }
1269    }
1270
1271    if (chosenIndex == -1 && candidates.count() > 0) {
1272        QtMethodMatchData bestMatch = candidates.at(0);
1273        if ((candidates.size() > 1)
1274            && (bestMatch.args.count() == candidates.at(1).args.count())
1275            && (bestMatch.matchDistance == candidates.at(1).matchDistance)) {
1276            // ambiguous call
1277            QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n")
1278                                .arg(QLatin1String(signature));
1279            for (int i = 0; i < candidates.size(); ++i) {
1280                // Only candidate for overload if argument count and match distance is same as best match
1281                if (candidates.at(i).args.count() == bestMatch.args.count()
1282                    || candidates.at(i).matchDistance == bestMatch.matchDistance) {
1283                    if (i > 0)
1284                        message += QLatin1String("\n");
1285                    QMetaMethod mtd = meta->method(candidates.at(i).index);
1286                    message += QString::fromLatin1("    %0").arg(QString::fromLatin1(mtd.signature()));
1287                }
1288            }
1289            *pError = throwError(exec, TypeError, message.toLatin1().constData());
1290        } else {
1291            chosenIndex = bestMatch.index;
1292            args = bestMatch.args;
1293        }
1294    }
1295
1296    if (chosenIndex != -1) {
1297        /* Copy the stuff over */
1298        int i;
1299        vars.resize(args.count());
1300        for (i=0; i < args.count(); i++) {
1301            vars[i] = args[i];
1302            vvars[i] = vars[i].data();
1303        }
1304    }
1305
1306    return chosenIndex;
1307}
1308
1309// Signals are not fuzzy matched as much as methods
1310static int findSignalIndex(const QMetaObject* meta, int initialIndex, QByteArray signature)
1311{
1312    int index = initialIndex;
1313    QMetaMethod method = meta->method(index);
1314    bool overloads = !signature.contains('(');
1315    if (overloads && (method.attributes() & QMetaMethod::Cloned)) {
1316        // find the most general method
1317        do {
1318            method = meta->method(--index);
1319        } while (method.attributes() & QMetaMethod::Cloned);
1320    }
1321    return index;
1322}
1323
1324QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate)
1325    : QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst)
1326{
1327    QW_D(QtRuntimeMetaMethod);
1328    d->m_signature = signature;
1329    d->m_index = index;
1330    d->m_connect = 0;
1331    d->m_disconnect = 0;
1332    d->m_allowPrivate = allowPrivate;
1333}
1334
1335void QtRuntimeMetaMethod::markChildren(MarkStack& markStack)
1336{
1337    QtRuntimeMethod::markChildren(markStack);
1338    QW_D(QtRuntimeMetaMethod);
1339    if (d->m_connect)
1340        markStack.append(d->m_connect);
1341    if (d->m_disconnect)
1342        markStack.append(d->m_disconnect);
1343}
1344
1345JSValue QtRuntimeMetaMethod::call(ExecState* exec, JSObject* functionObject, JSValue, const ArgList& args)
1346{
1347    QtRuntimeMetaMethodData* d = static_cast<QtRuntimeMetaMethod *>(functionObject)->d_func();
1348
1349    // We're limited to 10 …

Large files files are truncated, but you can click here to view the full file