Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/script/api/qscriptengine.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    2525#include "qscriptengine.h"
    2626#include "qscriptsyntaxchecker_p.h"
    27 #include "qnumeric.h"
    2827
    2928#include "qscriptengine_p.h"
     
    4241#include <QtCore/qmetaobject.h>
    4342
     43#include <math.h>
     44
    4445#include "CodeBlock.h"
    4546#include "Error.h"
    46 #include "JSArray.h"
    47 #include "JSLock.h"
    4847#include "Interpreter.h"
    49 #include "DateConstructor.h"
    50 #include "RegExpConstructor.h"
    51 
     48
     49#include "ExceptionHelpers.h"
    5250#include "PrototypeFunction.h"
    5351#include "InitializeThreading.h"
     
    5856#include "JSFunction.h"
    5957#include "Parser.h"
     58#include "PropertyNameArray.h"
    6059#include "Operations.h"
    6160
    62 #include "utils/qscriptdate_p.h"
    6361#include "bridge/qscriptfunction_p.h"
    64 #include "bridge/qscriptobject_p.h"
    6562#include "bridge/qscriptclassobject_p.h"
    6663#include "bridge/qscriptvariant_p.h"
     
    6865#include "bridge/qscriptglobalobject_p.h"
    6966#include "bridge/qscriptactivationobject_p.h"
     67#include "bridge/qscriptstaticscopeobject_p.h"
    7068
    7169#ifndef QT_NO_QOBJECT
     
    155153  that case, you can call toString() on the error object to obtain an
    156154  error message. The current uncaught exception is also available
    157   through uncaughtException(). You can obtain a human-readable
    158   backtrace of the exception with uncaughtExceptionBacktrace().
     155  through uncaughtException().
    159156  Calling clearExceptions() will cause any uncaught exceptions to be
    160157  cleared.
     
    265262  isEvaluating().
    266263
     264  \section1 Garbage Collection
     265
     266  Qt Script objects may be garbage collected when they are no longer
     267  referenced. There is no guarantee as to when automatic garbage
     268  collection will take place.
     269
     270  The collectGarbage() function can be called to explicitly request
     271  garbage collection.
     272
     273  The reportAdditionalMemoryCost() function can be called to indicate
     274  that a Qt Script object occupies memory that isn't managed by the
     275  scripting environment. Reporting the additional cost makes it more
     276  likely that the garbage collector will be triggered. This can be
     277  useful, for example, when many custom, native Qt Script objects are
     278  allocated.
     279
    267280  \section1 Core Debugging/Tracing Facilities
    268281
     
    282295    This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject().
    283296
    284     \value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.)
    285     \value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value).
    286     \value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership).
     297    \value QtOwnership The standard Qt ownership rules apply, i.e. the
     298    associated object will never be explicitly deleted by the script
     299    engine. This is the default. (QObject ownership is explained in
     300    \l{Object Trees & Ownership}.)
     301
     302    \value ScriptOwnership The value is owned by the script
     303    environment. The associated data will be deleted when appropriate
     304    (i.e. after the garbage collector has discovered that there are no
     305    more live references to the value).
     306
     307    \value AutoOwnership If the associated object has a parent, the Qt
     308    ownership rules apply (QtOwnership); otherwise, the object is
     309    owned by the script environment (ScriptOwnership).
     310
    287311*/
    288312
     
    297321    \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties
    298322    \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot.
     323    \value ExcludeSlots The script object will not expose the QObject's slots.
    299324    \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object.
    300325    \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object.
     
    329354namespace QScript
    330355{
     356
     357static const qsreal D32 = 4294967296.0;
     358
     359qint32 ToInt32(qsreal n)
     360{
     361    if (qIsNaN(n) || qIsInf(n) || (n == 0))
     362        return 0;
     363
     364    qsreal sign = (n < 0) ? -1.0 : 1.0;
     365    qsreal abs_n = fabs(n);
     366
     367    n = ::fmod(sign * ::floor(abs_n), D32);
     368    const double D31 = D32 / 2.0;
     369
     370    if (sign == -1 && n < -D31)
     371        n += D32;
     372
     373    else if (sign != -1 && n >= D31)
     374        n -= D32;
     375
     376    return qint32 (n);
     377}
     378
     379quint32 ToUInt32(qsreal n)
     380{
     381    if (qIsNaN(n) || qIsInf(n) || (n == 0))
     382        return 0;
     383
     384    qsreal sign = (n < 0) ? -1.0 : 1.0;
     385    qsreal abs_n = fabs(n);
     386
     387    n = ::fmod(sign * ::floor(abs_n), D32);
     388
     389    if (n < 0)
     390        n += D32;
     391
     392    return quint32 (n);
     393}
     394
     395quint16 ToUInt16(qsreal n)
     396{
     397    static const qsreal D16 = 65536.0;
     398
     399    if (qIsNaN(n) || qIsInf(n) || (n == 0))
     400        return 0;
     401
     402    qsreal sign = (n < 0) ? -1.0 : 1.0;
     403    qsreal abs_n = fabs(n);
     404
     405    n = ::fmod(sign * ::floor(abs_n), D16);
     406
     407    if (n < 0)
     408        n += D16;
     409
     410    return quint16 (n);
     411}
     412
     413qsreal ToInteger(qsreal n)
     414{
     415    if (qIsNaN(n))
     416        return 0;
     417
     418    if (n == 0 || qIsInf(n))
     419        return n;
     420
     421    int sign = n < 0 ? -1 : 1;
     422    return sign * ::floor(::fabs(n));
     423}
     424
     425#ifdef Q_CC_MSVC
     426// MSVC2008 crashes if these are inlined.
     427
     428QString ToString(qsreal value)
     429{
     430    return JSC::UString::from(value);
     431}
     432
     433qsreal ToNumber(const QString &value)
     434{
     435    return ((JSC::UString)value).toDouble();
     436}
     437
     438#endif
     439
     440static const qsreal MsPerSecond = 1000.0;
     441
     442static inline int MsFromTime(qsreal t)
     443{
     444    int r = int(::fmod(t, MsPerSecond));
     445    return (r >= 0) ? r : r + int(MsPerSecond);
     446}
     447
     448/*!
     449  \internal
     450  Converts a JS date value (milliseconds) to a QDateTime (local time).
     451*/
     452QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t)
     453{
     454    if (qIsNaN(t))
     455        return QDateTime();
     456    JSC::GregorianDateTime tm;
     457    JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm);
     458    int ms = MsFromTime(t);
     459    QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
     460                                       QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
     461    return convertedUTC.toLocalTime();
     462}
     463
     464/*!
     465  \internal
     466  Converts a QDateTime to a JS date value (milliseconds).
     467*/
     468qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt)
     469{
     470    if (!dt.isValid())
     471        return qSNaN();
     472    QDateTime utc = dt.toUTC();
     473    QDate date = utc.date();
     474    QTime time = utc.time();
     475    JSC::GregorianDateTime tm;
     476    tm.year = date.year() - 1900;
     477    tm.month = date.month() - 1;
     478    tm.monthDay = date.day();
     479    tm.weekDay = date.dayOfWeek();
     480    tm.yearDay = date.dayOfYear();
     481    tm.hour = time.hour();
     482    tm.minute = time.minute();
     483    tm.second = time.second();
     484    return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true);
     485}
    331486
    332487void GlobalClientData::mark(JSC::MarkStack& markStack)
     
    484639            slot = arg1;
    485640        else {
    486             // ### don't go via QScriptValue
    487641            QScript::SaveFrameHelper saveFrame(engine, exec);
    488             QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
    489             QString propertyName(arg1.toString(exec));
    490             slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
     642            JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1);
     643            slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype);
    491644        }
    492645    }
     
    568721            slot = arg1;
    569722        else {
    570             // ### don't go via QScriptValue
    571723            QScript::SaveFrameHelper saveFrame(engine, exec);
    572             QScriptValue tmp = engine->scriptValueFromJSCValue(arg0);
    573             QString propertyName = arg1.toString(exec);
    574             slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype));
     724            JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1);
     725            slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype);
    575726        }
    576727    }
     
    633784static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
    634785static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
     786static JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
     787static JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
    635788
    636789JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
     
    649802        return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number");
    650803#ifndef QT_NO_QOBJECT
    651     QString context(args.at(0).toString(exec));
     804    JSC::UString context = args.at(0).toString(exec);
    652805#endif
    653     QString text(args.at(1).toString(exec));
     806    JSC::UString text = args.at(1).toString(exec);
    654807#ifndef QT_NO_QOBJECT
    655     QString comment;
     808    JSC::UString comment;
    656809    if (args.size() > 2)
    657810        comment = args.at(2).toString(exec);
    658811    QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr;
    659812    if (args.size() > 3) {
    660         QString encStr(args.at(3).toString(exec));
    661         if (encStr == QLatin1String("CodecForTr"))
     813        JSC::UString encStr = args.at(3).toString(exec);
     814        if (encStr == "CodecForTr")
    662815            encoding = QCoreApplication::CodecForTr;
    663         else if (encStr == QLatin1String("UnicodeUTF8"))
     816        else if (encStr == "UnicodeUTF8")
    664817            encoding = QCoreApplication::UnicodeUTF8;
    665818        else
     
    670823        n = args.at(4).toInt32(exec);
    671824#endif
    672     QString result;
     825    JSC::UString result;
    673826#ifndef QT_NO_QOBJECT
    674     result = QCoreApplication::translate(context.toLatin1().constData(),
    675                                          text.toLatin1().constData(),
    676                                          comment.toLatin1().constData(),
     827    result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(),
     828                                         QScript::convertToLatin1(text).constData(),
     829                                         QScript::convertToLatin1(comment).constData(),
    677830                                         encoding, n);
    678831#else
     
    700853        return JSC::throwError(exec, JSC::GeneralError, "qsTr(): third argument (n) must be a number");
    701854#ifndef QT_NO_QOBJECT
    702     QString context;
     855    QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
     856    JSC::UString context;
    703857    // The first non-empty source URL in the call stack determines the translation context.
    704858    {
    705         JSC::ExecState *frame = exec->removeHostCallFrameFlag();
     859        JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag();
    706860        while (frame) {
    707             if (frame->codeBlock() && frame->codeBlock()->source()
     861            if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)
     862                && frame->codeBlock()->source()
    708863                && !frame->codeBlock()->source()->url().isEmpty()) {
    709                 context = QFileInfo(frame->codeBlock()->source()->url()).baseName();
     864                context = engine->translationContextFromUrl(frame->codeBlock()->source()->url());
    710865                break;
    711866            }
     
    714869    }
    715870#endif
    716     QString text(args.at(0).toString(exec));
     871    JSC::UString text = args.at(0).toString(exec);
    717872#ifndef QT_NO_QOBJECT
    718     QString comment;
     873    JSC::UString comment;
    719874    if (args.size() > 1)
    720875        comment = args.at(1).toString(exec);
     
    723878        n = args.at(2).toInt32(exec);
    724879#endif
    725     QString result;
     880    JSC::UString result;
    726881#ifndef QT_NO_QOBJECT
    727     result = QCoreApplication::translate(context.toLatin1().constData(),
    728                                          text.toLatin1().constData(),
    729                                          comment.toLatin1().constData(),
     882    result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(),
     883                                         QScript::convertToLatin1(text).constData(),
     884                                         QScript::convertToLatin1(comment).constData(),
    730885                                         QCoreApplication::CodecForTr, n);
    731886#else
     
    736891
    737892JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
     893{
     894    if (args.size() < 1)
     895        return JSC::jsUndefined();
     896    return args.at(0);
     897}
     898
     899JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
     900{
     901    if (args.size() < 1)
     902        return JSC::throwError(exec, JSC::GeneralError, "qsTrId() requires at least one argument");
     903    if (!args.at(0).isString())
     904        return JSC::throwError(exec, JSC::TypeError, "qsTrId(): first argument (id) must be a string");
     905    if ((args.size() > 1) && !args.at(1).isNumber())
     906        return JSC::throwError(exec, JSC::TypeError, "qsTrId(): second argument (n) must be a number");
     907    JSC::UString id = args.at(0).toString(exec);
     908    int n = -1;
     909    if (args.size() > 1)
     910        n = args.at(1).toInt32(exec);
     911    return JSC::jsString(exec, qtTrId(QScript::convertToLatin1(id).constData(), n));
     912}
     913
     914JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
    738915{
    739916    if (args.size() < 1)
     
    793970    }
    794971    JSC::initializeThreading();
    795 
     972    JSC::IdentifierTable *oldTable = JSC::currentIdentifierTable();
    796973    globalData = JSC::JSGlobalData::create().releaseRef();
    797974    globalData->clientData = new QScript::GlobalClientData(this);
     
    801978
    802979    scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
     980    staticScopeObjectStructure = QScriptStaticScopeObject::createStructure(JSC::jsNull());
    803981
    804982    qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
     
    8291007    agentLineNumber = -1;
    8301008    processEventsInterval = -1;
     1009    cachedTranslationUrl = JSC::UString();
     1010    cachedTranslationContext = JSC::UString();
     1011    JSC::setCurrentIdentifierTable(oldTable);
    8311012}
    8321013
    8331014QScriptEnginePrivate::~QScriptEnginePrivate()
    8341015{
     1016    QScript::APIShim shim(this);
     1017
    8351018    //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
    8361019    QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
     
    8411024        delete ownedAgents.takeFirst();
    8421025
     1026    detachAllRegisteredScriptPrograms();
    8431027    detachAllRegisteredScriptValues();
    8441028    detachAllRegisteredScriptStrings();
    8451029    qDeleteAll(m_qobjectData);
    8461030    qDeleteAll(m_typeInfos);
    847     JSC::JSLock lock(false);
    8481031    globalData->heap.destroy();
    8491032    globalData->deref();
     
    8551038}
    8561039
    857 QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v)
    858 {
    859     Q_Q(QScriptEngine);
    860     QScriptValue result = q->create(v.userType(), v.data());
    861     Q_ASSERT(result.isValid());
    862     return result;
    863 }
    864 
    865 QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType)
     1040QVariant QScriptEnginePrivate::jscValueToVariant(JSC::ExecState *exec, JSC::JSValue value, int targetType)
    8661041{
    8671042    QVariant v(targetType, (void *)0);
    868     if (QScriptEnginePrivate::convert(value, targetType, v.data(), this))
     1043    if (convertValue(exec, value, targetType, v.data()))
    8691044        return v;
    8701045    if (uint(targetType) == QVariant::LastType)
    871         return value.toVariant();
    872     if (value.isVariant()) {
    873         v = value.toVariant();
     1046        return toVariant(exec, value);
     1047    if (isVariant(value)) {
     1048        v = variantValue(value);
    8741049        if (v.canConvert(QVariant::Type(targetType))) {
    8751050            v.convert(QVariant::Type(targetType));
     
    8821057        }
    8831058    }
    884 
    8851059    return QVariant();
    8861060}
    8871061
    888 JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v)
    889 {
    890     // ### it's inefficient to convert to QScriptValue and then to JSValue
    891     QScriptValue vv = scriptValueFromVariant(v);
    892     QScriptValuePrivate *p = QScriptValuePrivate::get(vv);
    893     switch (p->type) {
    894     case QScriptValuePrivate::JavaScriptCore:
    895         return p->jscValue;
    896     case QScriptValuePrivate::Number:
    897         return JSC::jsNumber(currentFrame, p->numberValue);
    898     case QScriptValuePrivate::String: {
    899         JSC::UString str = p->stringValue;
    900         return JSC::jsString(currentFrame, str);
    901       }
    902     }
    903     return JSC::JSValue();
    904 }
    905 
    906 QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType)
    907 {
    908     // ### it's inefficient to convert to QScriptValue and then to QVariant
    909     return scriptValueToVariant(scriptValueFromJSCValue(value), targetType);
    910 }
    911 
    912 QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst)
    913 {
    914     Q_Q(QScriptEngine);
    915     QScriptValue arr = q->newArray(lst.size());
     1062JSC::JSValue QScriptEnginePrivate::arrayFromStringList(JSC::ExecState *exec, const QStringList &lst)
     1063{
     1064    JSC::JSValue arr =  newArray(exec, lst.size());
    9161065    for (int i = 0; i < lst.size(); ++i)
    917         arr.setProperty(i, QScriptValue(q, lst.at(i)));
     1066        setProperty(exec, arr, i, JSC::jsString(exec, lst.at(i)));
    9181067    return arr;
    9191068}
    9201069
    921 QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr)
     1070QStringList QScriptEnginePrivate::stringListFromArray(JSC::ExecState *exec, JSC::JSValue arr)
    9221071{
    9231072    QStringList lst;
    924     uint len = arr.property(QLatin1String("length")).toUInt32();
     1073    uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
    9251074    for (uint i = 0; i < len; ++i)
    926         lst.append(arr.property(i).toString());
     1075        lst.append(toString(exec, property(exec, arr, i)));
    9271076    return lst;
    9281077}
    9291078
    930 QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst)
    931 {
    932     Q_Q(QScriptEngine);
    933     QScriptValue arr = q->newArray(lst.size());
     1079JSC::JSValue QScriptEnginePrivate::arrayFromVariantList(JSC::ExecState *exec, const QVariantList &lst)
     1080{
     1081    JSC::JSValue arr = newArray(exec, lst.size());
    9341082    for (int i = 0; i < lst.size(); ++i)
    935         arr.setProperty(i, scriptValueFromVariant(lst.at(i)));
     1083        setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i)));
    9361084    return arr;
    9371085}
    9381086
    939 QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr)
    940 {
     1087QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSArray *arr)
     1088{
     1089    QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
     1090    if (eng->visitedConversionObjects.contains(arr))
     1091        return QVariantList(); // Avoid recursion.
     1092    eng->visitedConversionObjects.insert(arr);
    9411093    QVariantList lst;
    942     uint len = arr.property(QLatin1String("length")).toUInt32();
     1094    uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
    9431095    for (uint i = 0; i < len; ++i)
    944         lst.append(arr.property(i).toVariant());
     1096        lst.append(toVariant(exec, property(exec, arr, i)));
     1097    eng->visitedConversionObjects.remove(arr);
    9451098    return lst;
    9461099}
    9471100
    948 QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap)
    949 {
    950     Q_Q(QScriptEngine);
    951     QScriptValue obj = q->newObject();
     1101JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap)
     1102{
     1103    JSC::JSValue obj = JSC::constructEmptyObject(exec);
    9521104    QVariantMap::const_iterator it;
    9531105    for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
    954         obj.setProperty(it.key(), scriptValueFromVariant(it.value()));
     1106        setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value()));
    9551107    return obj;
    9561108}
    9571109
    958 QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj)
    959 {
     1110QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSObject *obj)
     1111{
     1112    QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
     1113    if (eng->visitedConversionObjects.contains(obj))
     1114        return QVariantMap(); // Avoid recursion.
     1115    eng->visitedConversionObjects.insert(obj);
     1116    JSC::PropertyNameArray propertyNames(exec);
     1117    obj->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties);
    9601118    QVariantMap vmap;
    961     QScriptValueIterator it(obj);
    962     while (it.hasNext()) {
    963         it.next();
    964         vmap.insert(it.name(), it.value().toVariant());
    965     }
     1119    JSC::PropertyNameArray::const_iterator it = propertyNames.begin();
     1120    for( ; it != propertyNames.end(); ++it)
     1121        vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it)));
     1122    eng->visitedConversionObjects.remove(obj);
    9661123    return vmap;
    9671124}
     
    11601317void QScriptEnginePrivate::collectGarbage()
    11611318{
    1162     JSC::JSLock lock(false);
    1163     globalData->heap.collect();
     1319    QScript::APIShim shim(this);
     1320    globalData->heap.collectAllGarbage();
     1321}
     1322
     1323void QScriptEnginePrivate::reportAdditionalMemoryCost(int size)
     1324{
     1325    if (size > 0)
     1326        globalData->heap.reportExtraMemoryCost(size);
    11641327}
    11651328
     
    11831346{
    11841347    Q_Q(QScriptEngine);
    1185     JSC::JSLock lock(false); // ### hmmm
    11861348    QBoolBlocker inEvalBlocker(inEval, true);
    11871349    q->currentContext()->activationObject(); //force the creation of a context for native function;
     
    11921354
    11931355    q->clearExceptions();
    1194     JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
     1356    JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject);
    11951357
    11961358    if (compile) {
     
    12961458}
    12971459
    1298 bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value,
     1460bool QScriptEnginePrivate::convertToNativeQObject(JSC::ExecState *exec, JSC::JSValue value,
    12991461                                                  const QByteArray &targetType,
    13001462                                                  void **result)
     
    13021464    if (!targetType.endsWith('*'))
    13031465        return false;
    1304     if (QObject *qobject = value.toQObject()) {
     1466    if (QObject *qobject = toQObject(exec, value)) {
    13051467        int start = targetType.startsWith("const ") ? 6 : 0;
    13061468        QByteArray className = targetType.mid(start, targetType.size()-start-1);
     
    14171579#endif
    14181580
     1581void QScriptEnginePrivate::detachAllRegisteredScriptPrograms()
     1582{
     1583    QSet<QScriptProgramPrivate*>::const_iterator it;
     1584    for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it)
     1585        (*it)->detachFromEngine();
     1586    registeredScriptPrograms.clear();
     1587}
     1588
    14191589void QScriptEnginePrivate::detachAllRegisteredScriptValues()
    14201590{
     
    14431613}
    14441614
    1445 #ifdef QT_NO_QOBJECT
    1446 
    1447 QScriptEngine::QScriptEngine()
    1448     : d_ptr(new QScriptEnginePrivate)
    1449 {
    1450     d_ptr->q_ptr = this;
    1451 }
    1452 
    1453 /*! \internal
    1454 */
    1455 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
    1456     : d_ptr(&dd)
    1457 {
    1458     d_ptr->q_ptr = this;
    1459 }
    1460 #else
    1461 
    1462 /*!
    1463     Constructs a QScriptEngine object.
    1464 
    1465     The globalObject() is initialized to have properties as described in
    1466     \l{ECMA-262}, Section 15.1.
    1467 */
    1468 QScriptEngine::QScriptEngine()
    1469     : QObject(*new QScriptEnginePrivate, 0)
    1470 {
    1471 }
    1472 
    1473 /*!
    1474     Constructs a QScriptEngine object with the given \a parent.
    1475 
    1476     The globalObject() is initialized to have properties as described in
    1477     \l{ECMA-262}, Section 15.1.
    1478 */
    1479 
    1480 QScriptEngine::QScriptEngine(QObject *parent)
    1481     : QObject(*new QScriptEnginePrivate, parent)
    1482 {
    1483 }
    1484 
    1485 /*! \internal
    1486 */
    1487 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
    1488     : QObject(dd, parent)
    1489 {
    1490 }
    1491 #endif
    1492 
    1493 /*!
    1494   Destroys this QScriptEngine.
    1495 */
    1496 QScriptEngine::~QScriptEngine()
    1497 {
    1498 #ifdef QT_NO_QOBJECT
    1499     delete d_ptr;
    1500     d_ptr = 0;
    1501 #endif
    1502 }
    1503 
    1504 /*!
    1505   Returns this engine's Global Object.
    1506 
    1507   By default, the Global Object contains the built-in objects that are
    1508   part of \l{ECMA-262}, such as Math, Date and String. Additionally,
    1509   you can set properties of the Global Object to make your own
    1510   extensions available to all script code. Non-local variables in
    1511   script code will be created as properties of the Global Object, as
    1512   well as local variables in global code.
    1513 */
    1514 QScriptValue QScriptEngine::globalObject() const
    1515 {
    1516     Q_D(const QScriptEngine);
    1517     JSC::JSObject *result = d->globalObject();
    1518     return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
    1519 }
    1520 
    1521 /*!
    1522   \since 4.5
    1523 
    1524   Sets this engine's Global Object to be the given \a object.
    1525   If \a object is not a valid script object, this function does
    1526   nothing.
    1527 
    1528   When setting a custom global object, you may want to use
    1529   QScriptValueIterator to copy the properties of the standard Global
    1530   Object; alternatively, you can set the internal prototype of your
    1531   custom object to be the original Global Object.
    1532 */
    1533 void QScriptEngine::setGlobalObject(const QScriptValue &object)
    1534 {
    1535     Q_D(QScriptEngine);
    1536     if (!object.isObject())
    1537         return;
    1538     JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
    1539     d->setGlobalObject(jscObject);
    1540 }
    1541 
    1542 /*!
    1543   Returns a QScriptValue of the primitive type Null.
    1544 
    1545   \sa undefinedValue()
    1546 */
    1547 QScriptValue QScriptEngine::nullValue()
    1548 {
    1549     Q_D(QScriptEngine);
    1550     return d->scriptValueFromJSCValue(JSC::jsNull());
    1551 }
    1552 
    1553 /*!
    1554   Returns a QScriptValue of the primitive type Undefined.
    1555 
    1556   \sa nullValue()
    1557 */
    1558 QScriptValue QScriptEngine::undefinedValue()
    1559 {
    1560     Q_D(QScriptEngine);
    1561     return d->scriptValueFromJSCValue(JSC::jsUndefined());
    1562 }
    1563 
    1564 /*!
    1565   Creates a constructor function from \a fun, with the given \a length.
    1566   The \c{prototype} property of the resulting function is set to be the
    1567   given \a prototype. The \c{constructor} property of \a prototype is
    1568   set to be the resulting function.
    1569 
    1570   When a function is called as a constructor (e.g. \c{new Foo()}), the
    1571   `this' object associated with the function call is the new object
    1572   that the function is expected to initialize; the prototype of this
    1573   default constructed object will be the function's public
    1574   \c{prototype} property. If you always want the function to behave as
    1575   a constructor (e.g. \c{Foo()} should also create a new object), or
    1576   if you need to create your own object rather than using the default
    1577   `this' object, you should make sure that the prototype of your
    1578   object is set correctly; either by setting it manually, or, when
    1579   wrapping a custom type, by having registered the defaultPrototype()
    1580   of that type. Example:
    1581 
    1582   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
    1583 
    1584   To wrap a custom type and provide a constructor for it, you'd typically
    1585   do something like this:
    1586 
    1587   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
    1588 */
    1589 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
    1590                                         const QScriptValue &prototype,
    1591                                         int length)
    1592 {
    1593     Q_D(QScriptEngine);
    1594     JSC::ExecState* exec = d->currentFrame;
    1595     JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
    1596     QScriptValue result = d->scriptValueFromJSCValue(function);
    1597     result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);
    1598     const_cast<QScriptValue&>(prototype)
    1599         .setProperty(QLatin1String("constructor"), result,
    1600                      QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
    1601     return result;
    1602 }
    1603 
    16041615#ifndef QT_NO_REGEXP
    16051616
    1606 Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
    1607 
    1608 /*!
    1609   Creates a QtScript object of class RegExp with the given
    1610   \a regexp.
    1611 
    1612   \sa QScriptValue::toRegExp()
    1613 */
    1614 QScriptValue QScriptEngine::newRegExp(const QRegExp &regexp)
    1615 {
    1616     Q_D(QScriptEngine);
    1617     JSC::ExecState* exec = d->currentFrame;
     1617Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
     1618
     1619JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp &regexp)
     1620{
    16181621    JSC::JSValue buf[2];
    16191622    JSC::ArgList args(buf, sizeof(buf));
     
    16481651            case ']':
    16491652                inBracket = false;
    1650                 break;
     1653               break;
    16511654            default:
    16521655                break;
     
    16631666    buf[0] = JSC::jsString(exec, jscPattern);
    16641667    buf[1] = JSC::jsString(exec, jscFlags);
    1665     JSC::JSObject* result = JSC::constructRegExp(exec, args);
    1666     return d->scriptValueFromJSCValue(result);
    1667 }
    1668 
    1669 #endif // QT_NO_REGEXP
    1670 
    1671 /*!
    1672   Creates a QtScript object holding the given variant \a value.
    1673 
    1674   If a default prototype has been registered with the meta type id of
    1675   \a value, then the prototype of the created object will be that
    1676   prototype; otherwise, the prototype will be the Object prototype
    1677   object.
    1678 
    1679   \sa setDefaultPrototype(), QScriptValue::toVariant()
    1680 */
    1681 QScriptValue QScriptEngine::newVariant(const QVariant &value)
    1682 {
    1683     Q_D(QScriptEngine);
    1684     JSC::ExecState* exec = d->currentFrame;
    1685     QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure);
    1686     obj->setDelegate(new QScript::QVariantDelegate(value));
    1687     QScriptValue result = d->scriptValueFromJSCValue(obj);
    1688     QScriptValue proto = defaultPrototype(value.userType());
    1689     if (proto.isValid())
    1690         result.setPrototype(proto);
    1691     return result;
    1692 }
    1693 
    1694 /*!
    1695   \since 4.4
    1696   \overload
    1697 
    1698   Initializes the given Qt Script \a object to hold the given variant
    1699   \a value, and returns the \a object.
    1700 
    1701   This function enables you to "promote" a plain Qt Script object
    1702   (created by the newObject() function) to a variant, or to replace
    1703   the variant contained inside an object previously created by the
    1704   newVariant() function.
    1705 
    1706   The prototype() of the \a object will remain unchanged.
    1707 
    1708   If \a object is not an object, this function behaves like the normal
    1709   newVariant(), i.e. it creates a new script object and returns it.
    1710 
    1711   This function is useful when you want to provide a script
    1712   constructor for a C++ type. If your constructor is invoked in a
    1713   \c{new} expression (QScriptContext::isCalledAsConstructor() returns
    1714   true), you can pass QScriptContext::thisObject() (the default
    1715   constructed script object) to this function to initialize the new
    1716   object.
    1717 */
    1718 QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
    1719                                        const QVariant &value)
    1720 {
    1721     if (!object.isObject())
    1722         return newVariant(value);
    1723     JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue);
    1724     if (!jscObject->inherits(&QScriptObject::info)) {
    1725         qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
    1726         return QScriptValue();
    1727     }
    1728     QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
    1729     if (!object.isVariant()) {
    1730         jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
    1731     } else {
    1732         QScriptValuePrivate::get(object)->setVariantValue(value);
    1733     }
    1734     return object;
    1735 }
    1736 
    1737 #ifndef QT_NO_QOBJECT
    1738 /*!
    1739   Creates a QtScript object that wraps the given QObject \a
    1740   object, using the given \a ownership. The given \a options control
    1741   various aspects of the interaction with the resulting script object.
    1742 
    1743   Signals and slots, properties and children of \a object are
    1744   available as properties of the created QScriptValue. For more
    1745   information, see the \l{QtScript} documentation.
    1746 
    1747   If \a object is a null pointer, this function returns nullValue().
    1748 
    1749   If a default prototype has been registered for the \a object's class
    1750   (or its superclass, recursively), the prototype of the new script
    1751   object will be set to be that default prototype.
    1752 
    1753   If the given \a object is deleted outside of QtScript's control, any
    1754   attempt to access the deleted QObject's members through the QtScript
    1755   wrapper object (either by script code or C++) will result in a
    1756   script exception.
    1757 
    1758   \sa QScriptValue::toQObject()
    1759 */
    1760 QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
    1761                                        const QObjectWrapOptions &options)
    1762 {
    1763     Q_D(QScriptEngine);
    1764     JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
    1765     return d->scriptValueFromJSCValue(jscQObject);
    1766 }
    1767 
    1768 /*!
    1769   \since 4.4
    1770   \overload
    1771 
    1772   Initializes the given \a scriptObject to hold the given \a qtObject,
    1773   and returns the \a scriptObject.
    1774 
    1775   This function enables you to "promote" a plain Qt Script object
    1776   (created by the newObject() function) to a QObject proxy, or to
    1777   replace the QObject contained inside an object previously created by
    1778   the newQObject() function.
    1779 
    1780   The prototype() of the \a scriptObject will remain unchanged.
    1781 
    1782   If \a scriptObject is not an object, this function behaves like the
    1783   normal newQObject(), i.e. it creates a new script object and returns
    1784   it.
    1785 
    1786   This function is useful when you want to provide a script
    1787   constructor for a QObject-based class. If your constructor is
    1788   invoked in a \c{new} expression
    1789   (QScriptContext::isCalledAsConstructor() returns true), you can pass
    1790   QScriptContext::thisObject() (the default constructed script object)
    1791   to this function to initialize the new object.
    1792 */
    1793 QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
    1794                                        QObject *qtObject,
    1795                                        ValueOwnership ownership,
    1796                                        const QObjectWrapOptions &options)
    1797 {
    1798     if (!scriptObject.isObject())
    1799         return newQObject(qtObject, ownership, options);
    1800     JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
    1801     if (!jscObject->inherits(&QScriptObject::info)) {
    1802         qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
    1803         return QScriptValue();
    1804     }
    1805     QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
    1806     if (!scriptObject.isQObject()) {
    1807         jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
    1808     } else {
    1809         QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
    1810         delegate->setValue(qtObject);
    1811         delegate->setOwnership(ownership);
    1812         delegate->setOptions(options);
    1813     }
    1814     return scriptObject;
    1815 }
    1816 
    1817 #endif // QT_NO_QOBJECT
    1818 
    1819 /*!
    1820   Creates a QtScript object of class Object.
    1821 
    1822   The prototype of the created object will be the Object
    1823   prototype object.
    1824 
    1825   \sa newArray(), QScriptValue::setProperty()
    1826 */
    1827 QScriptValue QScriptEngine::newObject()
    1828 {
    1829     Q_D(QScriptEngine);
    1830     JSC::ExecState* exec = d->currentFrame;
    1831     JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure);
    1832     return d->scriptValueFromJSCValue(result);
    1833 }
    1834 
    1835 /*!
    1836   \since 4.4
    1837   \overload
    1838 
    1839   Creates a QtScript Object of the given class, \a scriptClass.
    1840 
    1841   The prototype of the created object will be the Object
    1842   prototype object.
    1843 
    1844   \a data, if specified, is set as the internal data of the
    1845   new object (using QScriptValue::setData()).
    1846 
    1847   \sa QScriptValue::scriptClass()
    1848 */
    1849 QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
    1850                                       const QScriptValue &data)
    1851 {
    1852     Q_D(QScriptEngine);
    1853     JSC::ExecState* exec = d->currentFrame;
    1854     QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
    1855     result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
    1856     QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
    1857     scriptObject.setData(data);
    1858     QScriptValue proto = scriptClass->prototype();
    1859     if (proto.isValid())
    1860         scriptObject.setPrototype(proto);
    1861     return scriptObject;
    1862 }
    1863 
    1864 /*!
    1865   \internal
    1866 */
    1867 QScriptValue QScriptEngine::newActivationObject()
    1868 {
    1869     qWarning("QScriptEngine::newActivationObject() not implemented");
    1870     // ### JSActivation or JSVariableObject?
    1871     return QScriptValue();
    1872 }
    1873 
    1874 /*!
    1875   Creates a QScriptValue that wraps a native (C++) function. \a fun
    1876   must be a C++ function with signature QScriptEngine::FunctionSignature.  \a
    1877   length is the number of arguments that \a fun expects; this becomes
    1878   the \c{length} property of the created QScriptValue.
    1879 
    1880   Note that \a length only gives an indication of the number of
    1881   arguments that the function expects; an actual invocation of a
    1882   function can include any number of arguments. You can check the
    1883   \l{QScriptContext::argumentCount()}{argumentCount()} of the
    1884   QScriptContext associated with the invocation to determine the
    1885   actual number of arguments passed.
    1886 
    1887   A \c{prototype} property is automatically created for the resulting
    1888   function object, to provide for the possibility that the function
    1889   will be used as a constructor.
    1890 
    1891   By combining newFunction() and the property flags
    1892   QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
    1893   can create script object properties that behave like normal
    1894   properties in script code, but are in fact accessed through
    1895   functions (analogous to how properties work in \l{Qt's Property
    1896   System}). Example:
    1897 
    1898   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
    1899 
    1900   When the property \c{foo} of the script object is subsequently
    1901   accessed in script code, \c{getSetFoo()} will be invoked to handle
    1902   the access.  In this particular case, we chose to store the "real"
    1903   value of \c{foo} as a property of the accessor function itself; you
    1904   are of course free to do whatever you like in this function.
    1905 
    1906   In the above example, a single native function was used to handle
    1907   both reads and writes to the property; the argument count is used to
    1908   determine if we are handling a read or write. You can also use two
    1909   separate functions; just specify the relevant flag
    1910   (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
    1911   setting the property, e.g.:
    1912 
    1913   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
    1914 
    1915   \sa QScriptValue::call()
    1916 */
    1917 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
    1918 {
    1919     Q_D(QScriptEngine);
    1920     JSC::ExecState* exec = d->currentFrame;
    1921     JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
    1922     QScriptValue result = d->scriptValueFromJSCValue(function);
    1923     QScriptValue proto = newObject();
    1924     result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
    1925     proto.setProperty(QLatin1String("constructor"), result,
    1926                       QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
    1927     return result;
    1928 }
    1929 
    1930 /*!
    1931   \internal
    1932   \since 4.4
    1933 */
    1934 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
    1935 {
    1936     Q_D(QScriptEngine);
    1937     JSC::ExecState* exec = d->currentFrame;
    1938     JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
    1939     QScriptValue result = d->scriptValueFromJSCValue(function);
    1940     QScriptValue proto = newObject();
    1941     result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
    1942     proto.setProperty(QLatin1String("constructor"), result,
    1943                       QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
    1944     return result;
    1945 }
    1946 
    1947 /*!
    1948   Creates a QtScript object of class Array with the given \a length.
    1949 
    1950   \sa newObject()
    1951 */
    1952 QScriptValue QScriptEngine::newArray(uint length)
    1953 {
    1954     Q_D(QScriptEngine);
    1955     JSC::ExecState* exec = d->currentFrame;
    1956     JSC::JSArray* result = JSC::constructEmptyArray(exec, length);
    1957     return d->scriptValueFromJSCValue(result);
    1958 }
    1959 
    1960 /*!
    1961   Creates a QtScript object of class RegExp with the given
    1962   \a pattern and \a flags.
    1963 
    1964   The legal flags are 'g' (global), 'i' (ignore case), and 'm'
    1965   (multiline).
    1966 */
    1967 QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
    1968 {
    1969     Q_D(QScriptEngine);
    1970     JSC::ExecState* exec = d->currentFrame;
     1668    return JSC::constructRegExp(exec, args);
     1669}
     1670
     1671#endif
     1672
     1673JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QString &pattern, const QString &flags)
     1674{
    19711675    JSC::JSValue buf[2];
    19721676    JSC::ArgList args(buf, sizeof(buf));
     
    19821686    buf[0] = JSC::jsString(exec, jscPattern);
    19831687    buf[1] = JSC::jsString(exec, jscFlags);
    1984     JSC::JSObject* result = JSC::constructRegExp(exec, args);
    1985     return d->scriptValueFromJSCValue(result);
     1688    return JSC::constructRegExp(exec, args);
     1689}
     1690
     1691JSC::JSValue QScriptEnginePrivate::newVariant(const QVariant &value)
     1692{
     1693    QScriptObject *obj = new (currentFrame) QScriptObject(variantWrapperObjectStructure);
     1694    obj->setDelegate(new QScript::QVariantDelegate(value));
     1695    JSC::JSValue proto = defaultPrototype(value.userType());
     1696    if (proto)
     1697        obj->setPrototype(proto);
     1698    return obj;
     1699}
     1700
     1701JSC::JSValue QScriptEnginePrivate::newVariant(JSC::JSValue objectValue,
     1702                                              const QVariant &value)
     1703{
     1704    if (!isObject(objectValue))
     1705        return newVariant(value);
     1706    JSC::JSObject *jscObject = JSC::asObject(objectValue);
     1707    if (!jscObject->inherits(&QScriptObject::info)) {
     1708        qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported");
     1709        return JSC::JSValue();
     1710    }
     1711    QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
     1712    if (!isVariant(objectValue)) {
     1713        jscScriptObject->setDelegate(new QScript::QVariantDelegate(value));
     1714    } else {
     1715        setVariantValue(objectValue, value);
     1716    }
     1717    return objectValue;
     1718}
     1719
     1720#ifndef QT_NO_REGEXP
     1721
     1722QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value)
     1723{
     1724    if (!isRegExp(value))
     1725        return QRegExp();
     1726    QString pattern = toString(exec, property(exec, value, "source", QScriptValue::ResolvePrototype));
     1727    Qt::CaseSensitivity kase = Qt::CaseSensitive;
     1728    if (toBool(exec, property(exec, value, "ignoreCase", QScriptValue::ResolvePrototype)))
     1729        kase = Qt::CaseInsensitive;
     1730    return QRegExp(pattern, kase, QRegExp::RegExp2);
     1731}
     1732
     1733#endif
     1734
     1735QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue value)
     1736{
     1737    if (!value) {
     1738        return QVariant();
     1739    } else if (isObject(value)) {
     1740        if (isVariant(value))
     1741            return variantValue(value);
     1742#ifndef QT_NO_QOBJECT
     1743        else if (isQObject(value))
     1744            return qVariantFromValue(toQObject(exec, value));
     1745#endif
     1746        else if (isDate(value))
     1747            return QVariant(toDateTime(exec, value));
     1748#ifndef QT_NO_REGEXP
     1749        else if (isRegExp(value))
     1750            return QVariant(toRegExp(exec, value));
     1751#endif
     1752        else if (isArray(value))
     1753            return variantListFromArray(exec, JSC::asArray(value));
     1754        else if (QScriptDeclarativeClass *dc = declarativeClass(value))
     1755            return dc->toVariant(declarativeObject(value));
     1756        return variantMapFromObject(exec, JSC::asObject(value));
     1757    } else if (value.isNumber()) {
     1758        return QVariant(toNumber(exec, value));
     1759    } else if (value.isString()) {
     1760        return QVariant(toString(exec, value));
     1761    } else if (value.isBoolean()) {
     1762        return QVariant(toBool(exec, value));
     1763    }
     1764    return QVariant();
     1765}
     1766
     1767JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode)
     1768{
     1769    JSC::JSValue result;
     1770    if (!(resolveMode & QScriptValue::ResolvePrototype)) {
     1771        // Look in the object's own properties
     1772        JSC::JSObject *object = JSC::asObject(value);
     1773        JSC::PropertySlot slot(object);
     1774        if (object->getOwnPropertySlot(exec, id, slot))
     1775            result = slot.getValue(exec, id);
     1776    }
     1777    if (!result && (resolveMode & QScriptValue::ResolveScope)) {
     1778        // ### check if it's a function object and look in the scope chain
     1779        JSC::JSValue scope = property(exec, value, "__qt_scope__", QScriptValue::ResolveLocal);
     1780        if (isObject(scope))
     1781            result = property(exec, scope, id, resolveMode);
     1782    }
     1783    return result;
     1784}
     1785
     1786JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, quint32 index, int resolveMode)
     1787{
     1788    JSC::JSValue result;
     1789    if (!(resolveMode & QScriptValue::ResolvePrototype)) {
     1790        // Look in the object's own properties
     1791        JSC::JSObject *object = JSC::asObject(value);
     1792        JSC::PropertySlot slot(object);
     1793        if (object->getOwnPropertySlot(exec, index, slot))
     1794            result = slot.getValue(exec, index);
     1795    }
     1796    return result;
     1797}
     1798
     1799void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, const JSC::Identifier &id,
     1800                                       JSC::JSValue value, const QScriptValue::PropertyFlags &flags)
     1801{
     1802    JSC::JSObject *thisObject = JSC::asObject(objectValue);
     1803    JSC::JSValue setter = thisObject->lookupSetter(exec, id);
     1804    JSC::JSValue getter = thisObject->lookupGetter(exec, id);
     1805    if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
     1806        if (!value) {
     1807            // deleting getter/setter
     1808            if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) {
     1809                // deleting both: just delete the property
     1810                thisObject->deleteProperty(exec, id);
     1811            } else if (flags & QScriptValue::PropertyGetter) {
     1812                // preserve setter, if there is one
     1813                thisObject->deleteProperty(exec, id);
     1814                if (setter && setter.isObject())
     1815                    thisObject->defineSetter(exec, id, JSC::asObject(setter));
     1816            } else { // flags & QScriptValue::PropertySetter
     1817                // preserve getter, if there is one
     1818                thisObject->deleteProperty(exec, id);
     1819                if (getter && getter.isObject())
     1820                    thisObject->defineGetter(exec, id, JSC::asObject(getter));
     1821            }
     1822        } else {
     1823            if (value.isObject()) { // ### should check if it has callData()
     1824                // defining getter/setter
     1825                if (id == exec->propertyNames().underscoreProto) {
     1826                    qWarning("QScriptValue::setProperty() failed: "
     1827                             "cannot set getter or setter of native property `__proto__'");
     1828                } else {
     1829                    if (flags & QScriptValue::PropertyGetter)
     1830                        thisObject->defineGetter(exec, id, JSC::asObject(value));
     1831                    if (flags & QScriptValue::PropertySetter)
     1832                        thisObject->defineSetter(exec, id, JSC::asObject(value));
     1833                }
     1834            } else {
     1835                qWarning("QScriptValue::setProperty(): getter/setter must be a function");
     1836            }
     1837        }
     1838    } else {
     1839        // setting the value
     1840        if (getter && getter.isObject() && !(setter && setter.isObject())) {
     1841            qWarning("QScriptValue::setProperty() failed: "
     1842                     "property '%s' has a getter but no setter",
     1843                     qPrintable(QString(id.ustring())));
     1844            return;
     1845        }
     1846        if (!value) {
     1847            // ### check if it's a getter/setter property
     1848            thisObject->deleteProperty(exec, id);
     1849        } else if (flags != QScriptValue::KeepExistingFlags) {
     1850            if (thisObject->hasOwnProperty(exec, id))
     1851                thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes?
     1852            thisObject->putWithAttributes(exec, id, value, propertyFlagsToJSCAttributes(flags));
     1853        } else {
     1854            JSC::PutPropertySlot slot;
     1855            thisObject->put(exec, id, value, slot);
     1856        }
     1857    }
     1858}
     1859
     1860void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, quint32 index,
     1861                                       JSC::JSValue value, const QScriptValue::PropertyFlags &flags)
     1862{
     1863    if (!value) {
     1864        JSC::asObject(objectValue)->deleteProperty(exec, index);
     1865    } else {
     1866        if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) {
     1867            // fall back to string-based setProperty(), since there is no
     1868            // JSC::JSObject::defineGetter(unsigned)
     1869            setProperty(exec, objectValue, JSC::Identifier::from(exec, index), value, flags);
     1870        } else {
     1871            if (flags != QScriptValue::KeepExistingFlags) {
     1872                //                if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, arrayIndex))
     1873                //                    JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex);
     1874                unsigned attribs = 0;
     1875                if (flags & QScriptValue::ReadOnly)
     1876                    attribs |= JSC::ReadOnly;
     1877                if (flags & QScriptValue::SkipInEnumeration)
     1878                    attribs |= JSC::DontEnum;
     1879                if (flags & QScriptValue::Undeletable)
     1880                    attribs |= JSC::DontDelete;
     1881                attribs |= flags & QScriptValue::UserRange;
     1882                JSC::asObject(objectValue)->putWithAttributes(exec, index, value, attribs);
     1883            } else {
     1884                JSC::asObject(objectValue)->put(exec, index, value);
     1885            }
     1886        }
     1887    }
     1888}
     1889
     1890QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id,
     1891                                                                const QScriptValue::ResolveFlags &mode)
     1892{
     1893    JSC::JSObject *object = JSC::asObject(value);
     1894    unsigned attribs = 0;
     1895    JSC::PropertyDescriptor descriptor;
     1896    if (object->getOwnPropertyDescriptor(exec, id, descriptor))
     1897        attribs = descriptor.attributes();
     1898    else {
     1899        if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) {
     1900            JSC::JSValue proto = object->prototype();
     1901            return propertyFlags(exec, proto, id, mode);
     1902        }
     1903        return 0;
     1904    }
     1905    QScriptValue::PropertyFlags result = 0;
     1906    if (attribs & JSC::ReadOnly)
     1907        result |= QScriptValue::ReadOnly;
     1908    if (attribs & JSC::DontEnum)
     1909        result |= QScriptValue::SkipInEnumeration;
     1910    if (attribs & JSC::DontDelete)
     1911        result |= QScriptValue::Undeletable;
     1912    //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?)
     1913    if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull())
     1914        result |= QScriptValue::PropertyGetter;
     1915    if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull())
     1916        result |= QScriptValue::PropertySetter;
     1917#ifndef QT_NO_QOBJECT
     1918    if (attribs & QScript::QObjectMemberAttribute)
     1919        result |= QScriptValue::QObjectMember;
     1920#endif
     1921    result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange);
     1922    return result;
     1923}
     1924
     1925QScriptString QScriptEnginePrivate::toStringHandle(const JSC::Identifier &name)
     1926{
     1927    QScriptString result;
     1928    QScriptStringPrivate *p = new QScriptStringPrivate(this, name, QScriptStringPrivate::HeapAllocated);
     1929    QScriptStringPrivate::init(result, p);
     1930    registerScriptString(p);
     1931    return result;
     1932}
     1933
     1934#ifdef QT_NO_QOBJECT
     1935
     1936QScriptEngine::QScriptEngine()
     1937    : d_ptr(new QScriptEnginePrivate)
     1938{
     1939    d_ptr->q_ptr = this;
     1940}
     1941
     1942/*! \internal
     1943*/
     1944QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)
     1945    : d_ptr(&dd)
     1946{
     1947    d_ptr->q_ptr = this;
     1948}
     1949#else
     1950
     1951/*!
     1952    Constructs a QScriptEngine object.
     1953
     1954    The globalObject() is initialized to have properties as described in
     1955    \l{ECMA-262}, Section 15.1.
     1956*/
     1957QScriptEngine::QScriptEngine()
     1958    : QObject(*new QScriptEnginePrivate, 0)
     1959{
     1960}
     1961
     1962/*!
     1963    Constructs a QScriptEngine object with the given \a parent.
     1964
     1965    The globalObject() is initialized to have properties as described in
     1966    \l{ECMA-262}, Section 15.1.
     1967*/
     1968
     1969QScriptEngine::QScriptEngine(QObject *parent)
     1970    : QObject(*new QScriptEnginePrivate, parent)
     1971{
     1972}
     1973
     1974/*! \internal
     1975*/
     1976QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)
     1977    : QObject(dd, parent)
     1978{
     1979}
     1980#endif
     1981
     1982/*!
     1983  Destroys this QScriptEngine.
     1984*/
     1985QScriptEngine::~QScriptEngine()
     1986{
     1987#ifdef QT_NO_QOBJECT
     1988    delete d_ptr;
     1989    d_ptr = 0;
     1990#endif
     1991}
     1992
     1993/*!
     1994  Returns this engine's Global Object.
     1995
     1996  By default, the Global Object contains the built-in objects that are
     1997  part of \l{ECMA-262}, such as Math, Date and String. Additionally,
     1998  you can set properties of the Global Object to make your own
     1999  extensions available to all script code. Non-local variables in
     2000  script code will be created as properties of the Global Object, as
     2001  well as local variables in global code.
     2002*/
     2003QScriptValue QScriptEngine::globalObject() const
     2004{
     2005    Q_D(const QScriptEngine);
     2006    QScript::APIShim shim(const_cast<QScriptEnginePrivate*>(d));
     2007    JSC::JSObject *result = d->globalObject();
     2008    return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);
     2009}
     2010
     2011/*!
     2012  \since 4.5
     2013
     2014  Sets this engine's Global Object to be the given \a object.
     2015  If \a object is not a valid script object, this function does
     2016  nothing.
     2017
     2018  When setting a custom global object, you may want to use
     2019  QScriptValueIterator to copy the properties of the standard Global
     2020  Object; alternatively, you can set the internal prototype of your
     2021  custom object to be the original Global Object.
     2022*/
     2023void QScriptEngine::setGlobalObject(const QScriptValue &object)
     2024{
     2025    Q_D(QScriptEngine);
     2026    if (!object.isObject())
     2027        return;
     2028    QScript::APIShim shim(d);
     2029    JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));
     2030    d->setGlobalObject(jscObject);
     2031}
     2032
     2033/*!
     2034  Returns a QScriptValue of the primitive type Null.
     2035
     2036  \sa undefinedValue()
     2037*/
     2038QScriptValue QScriptEngine::nullValue()
     2039{
     2040    Q_D(QScriptEngine);
     2041    return d->scriptValueFromJSCValue(JSC::jsNull());
     2042}
     2043
     2044/*!
     2045  Returns a QScriptValue of the primitive type Undefined.
     2046
     2047  \sa nullValue()
     2048*/
     2049QScriptValue QScriptEngine::undefinedValue()
     2050{
     2051    Q_D(QScriptEngine);
     2052    return d->scriptValueFromJSCValue(JSC::jsUndefined());
     2053}
     2054
     2055/*!
     2056  Creates a constructor function from \a fun, with the given \a length.
     2057  The \c{prototype} property of the resulting function is set to be the
     2058  given \a prototype. The \c{constructor} property of \a prototype is
     2059  set to be the resulting function.
     2060
     2061  When a function is called as a constructor (e.g. \c{new Foo()}), the
     2062  `this' object associated with the function call is the new object
     2063  that the function is expected to initialize; the prototype of this
     2064  default constructed object will be the function's public
     2065  \c{prototype} property. If you always want the function to behave as
     2066  a constructor (e.g. \c{Foo()} should also create a new object), or
     2067  if you need to create your own object rather than using the default
     2068  `this' object, you should make sure that the prototype of your
     2069  object is set correctly; either by setting it manually, or, when
     2070  wrapping a custom type, by having registered the defaultPrototype()
     2071  of that type. Example:
     2072
     2073  \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
     2074
     2075  To wrap a custom type and provide a constructor for it, you'd typically
     2076  do something like this:
     2077
     2078  \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
     2079*/
     2080QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,
     2081                                        const QScriptValue &prototype,
     2082                                        int length)
     2083{
     2084    Q_D(QScriptEngine);
     2085    QScript::APIShim shim(d);
     2086    JSC::ExecState* exec = d->currentFrame;
     2087    JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
     2088    QScriptValue result = d->scriptValueFromJSCValue(function);
     2089    result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);
     2090    const_cast<QScriptValue&>(prototype)
     2091        .setProperty(QLatin1String("constructor"), result,
     2092                     QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
     2093    return result;
     2094}
     2095
     2096#ifndef QT_NO_REGEXP
     2097
     2098/*!
     2099  Creates a QtScript object of class RegExp with the given
     2100  \a regexp.
     2101
     2102  \sa QScriptValue::toRegExp()
     2103*/
     2104QScriptValue QScriptEngine::newRegExp(const QRegExp &regexp)
     2105{
     2106    Q_D(QScriptEngine);
     2107    QScript::APIShim shim(d);
     2108    return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, regexp));
     2109}
     2110
     2111#endif // QT_NO_REGEXP
     2112
     2113/*!
     2114  Creates a QtScript object holding the given variant \a value.
     2115
     2116  If a default prototype has been registered with the meta type id of
     2117  \a value, then the prototype of the created object will be that
     2118  prototype; otherwise, the prototype will be the Object prototype
     2119  object.
     2120
     2121  \sa setDefaultPrototype(), QScriptValue::toVariant(), reportAdditionalMemoryCost()
     2122*/
     2123QScriptValue QScriptEngine::newVariant(const QVariant &value)
     2124{
     2125    Q_D(QScriptEngine);
     2126    QScript::APIShim shim(d);
     2127    return d->scriptValueFromJSCValue(d->newVariant(value));
     2128}
     2129
     2130/*!
     2131  \since 4.4
     2132  \overload
     2133
     2134  Initializes the given Qt Script \a object to hold the given variant
     2135  \a value, and returns the \a object.
     2136
     2137  This function enables you to "promote" a plain Qt Script object
     2138  (created by the newObject() function) to a variant, or to replace
     2139  the variant contained inside an object previously created by the
     2140  newVariant() function.
     2141
     2142  The prototype() of the \a object will remain unchanged.
     2143
     2144  If \a object is not an object, this function behaves like the normal
     2145  newVariant(), i.e. it creates a new script object and returns it.
     2146
     2147  This function is useful when you want to provide a script
     2148  constructor for a C++ type. If your constructor is invoked in a
     2149  \c{new} expression (QScriptContext::isCalledAsConstructor() returns
     2150  true), you can pass QScriptContext::thisObject() (the default
     2151  constructed script object) to this function to initialize the new
     2152  object.
     2153
     2154  \sa reportAdditionalMemoryCost()
     2155*/
     2156QScriptValue QScriptEngine::newVariant(const QScriptValue &object,
     2157                                       const QVariant &value)
     2158{
     2159    Q_D(QScriptEngine);
     2160    QScript::APIShim shim(d);
     2161    JSC::JSValue jsObject = d->scriptValueToJSCValue(object);
     2162    return d->scriptValueFromJSCValue(d->newVariant(jsObject, value));
     2163}
     2164
     2165#ifndef QT_NO_QOBJECT
     2166/*!
     2167  Creates a QtScript object that wraps the given QObject \a
     2168  object, using the given \a ownership. The given \a options control
     2169  various aspects of the interaction with the resulting script object.
     2170
     2171  Signals and slots, properties and children of \a object are
     2172  available as properties of the created QScriptValue. For more
     2173  information, see the \l{QtScript} documentation.
     2174
     2175  If \a object is a null pointer, this function returns nullValue().
     2176
     2177  If a default prototype has been registered for the \a object's class
     2178  (or its superclass, recursively), the prototype of the new script
     2179  object will be set to be that default prototype.
     2180
     2181  If the given \a object is deleted outside of QtScript's control, any
     2182  attempt to access the deleted QObject's members through the QtScript
     2183  wrapper object (either by script code or C++) will result in a
     2184  script exception.
     2185
     2186  \sa QScriptValue::toQObject(), reportAdditionalMemoryCost()
     2187*/
     2188QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership,
     2189                                       const QObjectWrapOptions &options)
     2190{
     2191    Q_D(QScriptEngine);
     2192    QScript::APIShim shim(d);
     2193    JSC::JSValue jscQObject = d->newQObject(object, ownership, options);
     2194    return d->scriptValueFromJSCValue(jscQObject);
     2195}
     2196
     2197/*!
     2198  \since 4.4
     2199  \overload
     2200
     2201  Initializes the given \a scriptObject to hold the given \a qtObject,
     2202  and returns the \a scriptObject.
     2203
     2204  This function enables you to "promote" a plain Qt Script object
     2205  (created by the newObject() function) to a QObject proxy, or to
     2206  replace the QObject contained inside an object previously created by
     2207  the newQObject() function.
     2208
     2209  The prototype() of the \a scriptObject will remain unchanged.
     2210
     2211  If \a scriptObject is not an object, this function behaves like the
     2212  normal newQObject(), i.e. it creates a new script object and returns
     2213  it.
     2214
     2215  This function is useful when you want to provide a script
     2216  constructor for a QObject-based class. If your constructor is
     2217  invoked in a \c{new} expression
     2218  (QScriptContext::isCalledAsConstructor() returns true), you can pass
     2219  QScriptContext::thisObject() (the default constructed script object)
     2220  to this function to initialize the new object.
     2221
     2222  \sa reportAdditionalMemoryCost()
     2223*/
     2224QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
     2225                                       QObject *qtObject,
     2226                                       ValueOwnership ownership,
     2227                                       const QObjectWrapOptions &options)
     2228{
     2229    Q_D(QScriptEngine);
     2230    if (!scriptObject.isObject())
     2231        return newQObject(qtObject, ownership, options);
     2232    QScript::APIShim shim(d);
     2233    JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue);
     2234    if (!jscObject->inherits(&QScriptObject::info)) {
     2235        qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported");
     2236        return QScriptValue();
     2237    }
     2238    QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject);
     2239    if (!scriptObject.isQObject()) {
     2240        jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options));
     2241    } else {
     2242        QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate());
     2243        delegate->setValue(qtObject);
     2244        delegate->setOwnership(ownership);
     2245        delegate->setOptions(options);
     2246    }
     2247    return scriptObject;
     2248}
     2249
     2250#endif // QT_NO_QOBJECT
     2251
     2252/*!
     2253  Creates a QtScript object of class Object.
     2254
     2255  The prototype of the created object will be the Object
     2256  prototype object.
     2257
     2258  \sa newArray(), QScriptValue::setProperty()
     2259*/
     2260QScriptValue QScriptEngine::newObject()
     2261{
     2262    Q_D(QScriptEngine);
     2263    QScript::APIShim shim(d);
     2264    return d->scriptValueFromJSCValue(d->newObject());
     2265}
     2266
     2267/*!
     2268  \since 4.4
     2269  \overload
     2270
     2271  Creates a QtScript Object of the given class, \a scriptClass.
     2272
     2273  The prototype of the created object will be the Object
     2274  prototype object.
     2275
     2276  \a data, if specified, is set as the internal data of the
     2277  new object (using QScriptValue::setData()).
     2278
     2279  \sa QScriptValue::scriptClass(), reportAdditionalMemoryCost()
     2280*/
     2281QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass,
     2282                                      const QScriptValue &data)
     2283{
     2284    Q_D(QScriptEngine);
     2285    QScript::APIShim shim(d);
     2286    JSC::ExecState* exec = d->currentFrame;
     2287    QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure);
     2288    result->setDelegate(new QScript::ClassObjectDelegate(scriptClass));
     2289    QScriptValue scriptObject = d->scriptValueFromJSCValue(result);
     2290    scriptObject.setData(data);
     2291    QScriptValue proto = scriptClass->prototype();
     2292    if (proto.isValid())
     2293        scriptObject.setPrototype(proto);
     2294    return scriptObject;
     2295}
     2296
     2297/*!
     2298  \internal
     2299*/
     2300QScriptValue QScriptEngine::newActivationObject()
     2301{
     2302    qWarning("QScriptEngine::newActivationObject() not implemented");
     2303    // ### JSActivation or JSVariableObject?
     2304    return QScriptValue();
     2305}
     2306
     2307/*!
     2308  Creates a QScriptValue that wraps a native (C++) function. \a fun
     2309  must be a C++ function with signature QScriptEngine::FunctionSignature.  \a
     2310  length is the number of arguments that \a fun expects; this becomes
     2311  the \c{length} property of the created QScriptValue.
     2312
     2313  Note that \a length only gives an indication of the number of
     2314  arguments that the function expects; an actual invocation of a
     2315  function can include any number of arguments. You can check the
     2316  \l{QScriptContext::argumentCount()}{argumentCount()} of the
     2317  QScriptContext associated with the invocation to determine the
     2318  actual number of arguments passed.
     2319
     2320  A \c{prototype} property is automatically created for the resulting
     2321  function object, to provide for the possibility that the function
     2322  will be used as a constructor.
     2323
     2324  By combining newFunction() and the property flags
     2325  QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
     2326  can create script object properties that behave like normal
     2327  properties in script code, but are in fact accessed through
     2328  functions (analogous to how properties work in \l{Qt's Property
     2329  System}). Example:
     2330
     2331  \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
     2332
     2333  When the property \c{foo} of the script object is subsequently
     2334  accessed in script code, \c{getSetFoo()} will be invoked to handle
     2335  the access.  In this particular case, we chose to store the "real"
     2336  value of \c{foo} as a property of the accessor function itself; you
     2337  are of course free to do whatever you like in this function.
     2338
     2339  In the above example, a single native function was used to handle
     2340  both reads and writes to the property; the argument count is used to
     2341  determine if we are handling a read or write. You can also use two
     2342  separate functions; just specify the relevant flag
     2343  (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
     2344  setting the property, e.g.:
     2345
     2346  \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
     2347
     2348  \sa QScriptValue::call()
     2349*/
     2350QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
     2351{
     2352    Q_D(QScriptEngine);
     2353    QScript::APIShim shim(d);
     2354    JSC::ExecState* exec = d->currentFrame;
     2355    JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);
     2356    QScriptValue result = d->scriptValueFromJSCValue(function);
     2357    QScriptValue proto = newObject();
     2358    result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
     2359    proto.setProperty(QLatin1String("constructor"), result,
     2360                      QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
     2361    return result;
     2362}
     2363
     2364/*!
     2365  \internal
     2366  \since 4.4
     2367*/
     2368QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg)
     2369{
     2370    Q_D(QScriptEngine);
     2371    QScript::APIShim shim(d);
     2372    JSC::ExecState* exec = d->currentFrame;
     2373    JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg);
     2374    QScriptValue result = d->scriptValueFromJSCValue(function);
     2375    QScriptValue proto = newObject();
     2376    result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable);
     2377    proto.setProperty(QLatin1String("constructor"), result,
     2378                      QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
     2379    return result;
     2380}
     2381
     2382/*!
     2383  Creates a QtScript object of class Array with the given \a length.
     2384
     2385  \sa newObject()
     2386*/
     2387QScriptValue QScriptEngine::newArray(uint length)
     2388{
     2389    Q_D(QScriptEngine);
     2390    QScript::APIShim shim(d);
     2391    return d->scriptValueFromJSCValue(d->newArray(d->currentFrame, length));
     2392}
     2393
     2394/*!
     2395  Creates a QtScript object of class RegExp with the given
     2396  \a pattern and \a flags.
     2397
     2398  The legal flags are 'g' (global), 'i' (ignore case), and 'm'
     2399  (multiline).
     2400*/
     2401QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags)
     2402{
     2403    Q_D(QScriptEngine);
     2404    QScript::APIShim shim(d);
     2405    return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, pattern, flags));
    19862406}
    19872407
     
    19942414{
    19952415    Q_D(QScriptEngine);
    1996     JSC::ExecState* exec = d->currentFrame;
    1997     JSC::JSValue val = JSC::jsNumber(exec, value);
    1998     JSC::ArgList args(&val, 1);
    1999     JSC::JSObject *result = JSC::constructDate(exec, args);
    2000     return d->scriptValueFromJSCValue(result);
     2416    QScript::APIShim shim(d);
     2417    return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value));
    20012418}
    20022419
     
    20082425QScriptValue QScriptEngine::newDate(const QDateTime &value)
    20092426{
    2010     return newDate(QScript::FromDateTime(value));
     2427    Q_D(QScriptEngine);
     2428    QScript::APIShim shim(d);
     2429    return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value));
    20112430}
    20122431
     
    20312450{
    20322451    Q_D(QScriptEngine);
     2452    QScript::APIShim shim(d);
    20332453    JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor);
    20342454    JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor);
     
    22052625{
    22062626    Q_D(QScriptEngine);
     2627    QScript::APIShim shim(d);
    22072628    WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
    22082629            = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d);
     
    22112632
    22122633    JSC::ExecState* exec = d->currentFrame;
    2213     JSC::EvalExecutable executable(exec, source);
     2634    WTF::RefPtr<JSC::EvalExecutable> executable = JSC::EvalExecutable::create(exec, source);
    22142635    bool compile = true;
    2215     return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, &executable, compile));
    2216 }
    2217 
    2218 /*!
    2219   \internal
    2220   \since 4.6
     2636    return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile));
     2637}
     2638
     2639/*!
     2640  \since 4.7
    22212641
    22222642  Evaluates the given \a program and returns the result of the
     
    22302650        return QScriptValue();
    22312651
     2652    QScript::APIShim shim(d);
    22322653    JSC::ExecState* exec = d->currentFrame;
    22332654    JSC::EvalExecutable *executable = program_d->executable(exec, d);
     
    22812702{
    22822703    Q_D(QScriptEngine);
     2704    QScript::APIShim shim(d);
    22832705
    22842706    JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
     
    23412763            newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
    23422764        } else {
    2343             JSC::JSObject *jscObject = originalGlobalObject();
    2344             JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject);
    2345             newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee);
     2765            newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
    23462766        }
    23472767    } else {
     
    23722792        agent()->contextPop();
    23732793    Q_D(QScriptEngine);
     2794    QScript::APIShim shim(d);
    23742795    if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0
    23752796        || !currentContext()->parentContext()) {
     
    24072828  The exception state is cleared when evaluate() is called.
    24082829
    2409   \sa uncaughtException(), uncaughtExceptionLineNumber(),
    2410       uncaughtExceptionBacktrace()
     2830  \sa uncaughtException(), uncaughtExceptionLineNumber()
    24112831*/
    24122832bool QScriptEngine::hasUncaughtException() const
     
    24262846
    24272847  \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
    2428       uncaughtExceptionBacktrace()
    24292848*/
    24302849QScriptValue QScriptEngine::uncaughtException() const
     
    24462865  the second argument to evaluate().
    24472866
    2448   \sa hasUncaughtException(), uncaughtExceptionBacktrace()
     2867  \sa hasUncaughtException()
    24492868*/
    24502869int QScriptEngine::uncaughtExceptionLineNumber() const
     
    24582877  Returns a human-readable backtrace of the last uncaught exception.
    24592878
    2460   Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
     2879  It is in the form \c{<function-name>()@<file-name>:<line-number>}.
    24612880
    24622881  \sa uncaughtException()
     
    25672986{
    25682987    Q_D(QScriptEngine);
    2569     return d->create(type, ptr);
    2570 }
    2571 
    2572 QScriptValue QScriptEnginePrivate::create(int type, const void *ptr)
    2573 {
    2574     Q_Q(QScriptEngine);
     2988    QScript::APIShim shim(d);
     2989    return d->scriptValueFromJSCValue(d->create(d->currentFrame, type, ptr));
     2990}
     2991
     2992JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const void *ptr)
     2993{
    25752994    Q_ASSERT(ptr != 0);
    2576     QScriptValue result;
    2577     QScriptTypeInfo *info = m_typeInfos.value(type);
     2995    JSC::JSValue result;
     2996    QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0;
     2997    QScriptTypeInfo *info = eng ? eng->m_typeInfos.value(type) : 0;
    25782998    if (info && info->marshal) {
    2579         result = info->marshal(q, ptr);
     2999        result = eng->scriptValueToJSCValue(info->marshal(eng->q_func(), ptr));
    25803000    } else {
    25813001        // check if it's one of the types we know
    25823002        switch (QMetaType::Type(type)) {
    25833003        case QMetaType::Void:
    2584             return QScriptValue(q, QScriptValue::UndefinedValue);
     3004            return JSC::jsUndefined();
    25853005        case QMetaType::Bool:
    2586             return QScriptValue(q, *reinterpret_cast<const bool*>(ptr));
     3006            return JSC::jsBoolean(*reinterpret_cast<const bool*>(ptr));
    25873007        case QMetaType::Int:
    2588             return QScriptValue(q, *reinterpret_cast<const int*>(ptr));
     3008            return JSC::jsNumber(exec, *reinterpret_cast<const int*>(ptr));
    25893009        case QMetaType::UInt:
    2590             return QScriptValue(q, *reinterpret_cast<const uint*>(ptr));
     3010            return JSC::jsNumber(exec, *reinterpret_cast<const uint*>(ptr));
    25913011        case QMetaType::LongLong:
    2592             return QScriptValue(q, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
     3012            return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));
    25933013        case QMetaType::ULongLong:
    25943014#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
    25953015#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
    2596             return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
     3016            return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
    25973017#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
    2598             return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
     3018            return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));
    25993019#else
    2600             return QScriptValue(q, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
     3020            return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));
    26013021#endif
    26023022        case QMetaType::Double:
    2603             return QScriptValue(q, qsreal(*reinterpret_cast<const double*>(ptr)));
     3023            return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr)));
    26043024        case QMetaType::QString:
    2605             return QScriptValue(q, *reinterpret_cast<const QString*>(ptr));
     3025            return JSC::jsString(exec, *reinterpret_cast<const QString*>(ptr));
    26063026        case QMetaType::Float:
    2607             return QScriptValue(q, *reinterpret_cast<const float*>(ptr));
     3027            return JSC::jsNumber(exec, *reinterpret_cast<const float*>(ptr));
    26083028        case QMetaType::Short:
    2609             return QScriptValue(q, *reinterpret_cast<const short*>(ptr));
     3029            return JSC::jsNumber(exec, *reinterpret_cast<const short*>(ptr));
    26103030        case QMetaType::UShort:
    2611             return QScriptValue(q, *reinterpret_cast<const unsigned short*>(ptr));
     3031            return JSC::jsNumber(exec, *reinterpret_cast<const unsigned short*>(ptr));
    26123032        case QMetaType::Char:
    2613             return QScriptValue(q, *reinterpret_cast<const char*>(ptr));
     3033            return JSC::jsNumber(exec, *reinterpret_cast<const char*>(ptr));
    26143034        case QMetaType::UChar:
    2615             return QScriptValue(q, *reinterpret_cast<const unsigned char*>(ptr));
     3035            return JSC::jsNumber(exec, *reinterpret_cast<const unsigned char*>(ptr));
    26163036        case QMetaType::QChar:
    2617             return QScriptValue(q, (*reinterpret_cast<const QChar*>(ptr)).unicode());
     3037            return JSC::jsNumber(exec, (*reinterpret_cast<const QChar*>(ptr)).unicode());
    26183038        case QMetaType::QStringList:
    2619             result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr));
     3039            result = arrayFromStringList(exec, *reinterpret_cast<const QStringList *>(ptr));
    26203040            break;
    26213041        case QMetaType::QVariantList:
    2622             result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr));
     3042            result = arrayFromVariantList(exec, *reinterpret_cast<const QVariantList *>(ptr));
    26233043            break;
    26243044        case QMetaType::QVariantMap:
    2625             result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr));
     3045            result = objectFromVariantMap(exec, *reinterpret_cast<const QVariantMap *>(ptr));
    26263046            break;
    26273047        case QMetaType::QDateTime:
    2628             result = q->newDate(*reinterpret_cast<const QDateTime *>(ptr));
     3048            result = newDate(exec, *reinterpret_cast<const QDateTime *>(ptr));
    26293049            break;
    26303050        case QMetaType::QDate:
    2631             result = q->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)));
     3051            result = newDate(exec, QDateTime(*reinterpret_cast<const QDate *>(ptr)));
    26323052            break;
    26333053#ifndef QT_NO_REGEXP
    26343054        case QMetaType::QRegExp:
    2635             result = q->newRegExp(*reinterpret_cast<const QRegExp *>(ptr));
     3055            result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr));
    26363056            break;
    26373057#endif
     
    26393059        case QMetaType::QObjectStar:
    26403060        case QMetaType::QWidgetStar:
    2641             result = q->newQObject(*reinterpret_cast<QObject* const *>(ptr));
     3061            result = eng->newQObject(*reinterpret_cast<QObject* const *>(ptr));
    26423062            break;
    26433063#endif
     3064        case QMetaType::QVariant:
     3065            result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr));
     3066            break;
    26443067        default:
    26453068            if (type == qMetaTypeId<QScriptValue>()) {
    2646                 result = *reinterpret_cast<const QScriptValue*>(ptr);
    2647                 if (!result.isValid())
    2648                     return QScriptValue(q, QScriptValue::UndefinedValue);
     3069                result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr));
     3070                if (!result)
     3071                    return JSC::jsUndefined();
    26493072            }
    26503073
     
    26523075            // lazy registration of some common list types
    26533076            else if (type == qMetaTypeId<QObjectList>()) {
    2654                 qScriptRegisterSequenceMetaType<QObjectList>(q);
    2655                 return create(type, ptr);
     3077                qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
     3078                return create(exec, type, ptr);
    26563079            }
    26573080#endif
    26583081            else if (type == qMetaTypeId<QList<int> >()) {
    2659                 qScriptRegisterSequenceMetaType<QList<int> >(q);
    2660                 return create(type, ptr);
     3082                qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
     3083                return create(exec, type, ptr);
    26613084            }
    26623085
    26633086            else {
    26643087                QByteArray typeName = QMetaType::typeName(type);
    2665                 if (typeName == "QVariant")
    2666                     result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr));
    26673088                if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
    2668                     return QScriptValue(q, QScriptValue::NullValue);
     3089                    return JSC::jsNull();
    26693090                else
    2670                     result = q->newVariant(QVariant(type, ptr));
     3091                    result = eng->newVariant(QVariant(type, ptr));
    26713092            }
    26723093        }
    26733094    }
    2674     if (result.isObject() && info && info->prototype
    2675         && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) {
    2676         result.setPrototype(scriptValueFromJSCValue(info->prototype));
     3095    if (result && result.isObject() && info && info->prototype
     3096        && JSC::JSValue::strictEqual(exec, JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) {
     3097        JSC::asObject(result)->setPrototype(info->prototype);
    26773098    }
    26783099    return result;
    26793100}
    26803101
    2681 bool QScriptEnginePrivate::convert(const QScriptValue &value,
    2682                                    int type, void *ptr,
    2683                                    QScriptEnginePrivate *eng)
    2684 {
    2685     if (!eng)
    2686         eng = QScriptValuePrivate::getEngine(value);
     3102bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value,
     3103                                        int type, void *ptr)
     3104{
     3105    QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0;
    26873106    if (eng) {
    26883107        QScriptTypeInfo *info = eng->m_typeInfos.value(type);
    26893108        if (info && info->demarshal) {
    2690             info->demarshal(value, ptr);
     3109            info->demarshal(eng->scriptValueFromJSCValue(value), ptr);
    26913110            return true;
    26923111        }
     
    26963115    switch (QMetaType::Type(type)) {
    26973116    case QMetaType::Bool:
    2698         *reinterpret_cast<bool*>(ptr) = value.toBoolean();
     3117        *reinterpret_cast<bool*>(ptr) = toBool(exec, value);
    26993118        return true;
    27003119    case QMetaType::Int:
    2701         *reinterpret_cast<int*>(ptr) = value.toInt32();
     3120        *reinterpret_cast<int*>(ptr) = toInt32(exec, value);
    27023121        return true;
    27033122    case QMetaType::UInt:
    2704         *reinterpret_cast<uint*>(ptr) = value.toUInt32();
     3123        *reinterpret_cast<uint*>(ptr) = toUInt32(exec, value);
    27053124        return true;
    27063125    case QMetaType::LongLong:
    2707         *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger());
     3126        *reinterpret_cast<qlonglong*>(ptr) = qlonglong(toInteger(exec, value));
    27083127        return true;
    27093128    case QMetaType::ULongLong:
    2710         *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger());
     3129        *reinterpret_cast<qulonglong*>(ptr) = qulonglong(toInteger(exec, value));
    27113130        return true;
    27123131    case QMetaType::Double:
    2713         *reinterpret_cast<double*>(ptr) = value.toNumber();
     3132        *reinterpret_cast<double*>(ptr) = toNumber(exec, value);
    27143133        return true;
    27153134    case QMetaType::QString:
     
    27173136            *reinterpret_cast<QString*>(ptr) = QString();
    27183137        else
    2719             *reinterpret_cast<QString*>(ptr) = value.toString();
     3138            *reinterpret_cast<QString*>(ptr) = toString(exec, value);
    27203139        return true;
    27213140    case QMetaType::Float:
    2722         *reinterpret_cast<float*>(ptr) = value.toNumber();
     3141        *reinterpret_cast<float*>(ptr) = toNumber(exec, value);
    27233142        return true;
    27243143    case QMetaType::Short:
    2725         *reinterpret_cast<short*>(ptr) = short(value.toInt32());
     3144        *reinterpret_cast<short*>(ptr) = short(toInt32(exec, value));
    27263145        return true;
    27273146    case QMetaType::UShort:
    2728         *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();
     3147        *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(toNumber(exec, value));
    27293148        return true;
    27303149    case QMetaType::Char:
    2731         *reinterpret_cast<char*>(ptr) = char(value.toInt32());
     3150        *reinterpret_cast<char*>(ptr) = char(toInt32(exec, value));
    27323151        return true;
    27333152    case QMetaType::UChar:
    2734         *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32());
     3153        *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(toInt32(exec, value));
    27353154        return true;
    27363155    case QMetaType::QChar:
    27373156        if (value.isString()) {
    2738             QString str = value.toString();
     3157            QString str = toString(exec, value);
    27393158            *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0);
    27403159        } else {
    2741             *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16());
     3160            *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(toNumber(exec, value)));
    27423161        }
    27433162        return true;
    27443163    case QMetaType::QDateTime:
    2745         if (value.isDate()) {
    2746             *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();
     3164        if (isDate(value)) {
     3165            *reinterpret_cast<QDateTime *>(ptr) = toDateTime(exec, value);
    27473166            return true;
    27483167        } break;
    27493168    case QMetaType::QDate:
    2750         if (value.isDate()) {
    2751             *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();
     3169        if (isDate(value)) {
     3170            *reinterpret_cast<QDate *>(ptr) = toDateTime(exec, value).date();
    27523171            return true;
    27533172        } break;
    27543173#ifndef QT_NO_REGEXP
    27553174    case QMetaType::QRegExp:
    2756         if (value.isRegExp()) {
    2757             *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();
     3175        if (isRegExp(value)) {
     3176            *reinterpret_cast<QRegExp *>(ptr) = toRegExp(exec, value);
    27583177            return true;
    27593178        } break;
     
    27613180#ifndef QT_NO_QOBJECT
    27623181    case QMetaType::QObjectStar:
    2763         if (value.isQObject() || value.isNull()) {
    2764             *reinterpret_cast<QObject* *>(ptr) = value.toQObject();
     3182        if (isQObject(value) || value.isNull()) {
     3183            *reinterpret_cast<QObject* *>(ptr) = toQObject(exec, value);
    27653184            return true;
    27663185        } break;
    27673186    case QMetaType::QWidgetStar:
    2768         if (value.isQObject() || value.isNull()) {
    2769             QObject *qo = value.toQObject();
     3187        if (isQObject(value) || value.isNull()) {
     3188            QObject *qo = toQObject(exec, value);
    27703189            if (!qo || qo->isWidgetType()) {
    27713190                *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo);
     
    27753194#endif
    27763195    case QMetaType::QStringList:
    2777         if (value.isArray()) {
    2778             *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value);
     3196        if (isArray(value)) {
     3197            *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value);
    27793198            return true;
    27803199        } break;
    27813200    case QMetaType::QVariantList:
    2782         if (value.isArray()) {
    2783             *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value);
     3201        if (isArray(value)) {
     3202            *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, JSC::asArray(value));
    27843203            return true;
    27853204        } break;
    27863205    case QMetaType::QVariantMap:
    2787         if (value.isObject()) {
    2788             *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value);
     3206        if (isObject(value)) {
     3207            *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, JSC::asObject(value));
    27893208            return true;
    27903209        } break;
     3210    case QMetaType::QVariant:
     3211        *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value);
     3212        return true;
    27913213    default:
    27923214    ;
     
    27953217    QByteArray name = QMetaType::typeName(type);
    27963218#ifndef QT_NO_QOBJECT
    2797     if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr)))
     3219    if (convertToNativeQObject(exec, value, name, reinterpret_cast<void* *>(ptr)))
    27983220        return true;
    27993221#endif
    2800     if (value.isVariant() && name.endsWith('*')) {
     3222    if (isVariant(value) && name.endsWith('*')) {
    28013223        int valueType = QMetaType::type(name.left(name.size()-1));
    2802         QVariant &var = QScriptValuePrivate::get(value)->variantValue();
     3224        QVariant &var = variantValue(value);
    28033225        if (valueType == var.userType()) {
    28043226            *reinterpret_cast<void* *>(ptr) = var.data();
     
    28063228        } else {
    28073229            // look in the prototype chain
    2808             QScriptValue proto = value.prototype();
     3230            JSC::JSValue proto = JSC::asObject(value)->prototype();
    28093231            while (proto.isObject()) {
    28103232                bool canCast = false;
    2811                 if (proto.isVariant()) {
    2812                     canCast = (type == proto.toVariant().userType())
    2813                               || (valueType && (valueType == proto.toVariant().userType()));
     3233                if (isVariant(proto)) {
     3234                    canCast = (type == variantValue(proto).userType())
     3235                              || (valueType && (valueType == variantValue(proto).userType()));
    28143236                }
    28153237#ifndef QT_NO_QOBJECT
    2816                 else if (proto.isQObject()) {
     3238                else if (isQObject(proto)) {
    28173239                    QByteArray className = name.left(name.size()-1);
    2818                     if (QObject *qobject = proto.toQObject())
     3240                    if (QObject *qobject = toQObject(exec, proto))
    28193241                        canCast = qobject->qt_metacast(className) != 0;
    28203242                }
     
    28283250                    return true;
    28293251                }
    2830                 proto = proto.prototype();
     3252                proto = JSC::asObject(proto)->prototype();
    28313253            }
    28323254        }
     
    28373259        if (!eng)
    28383260            return false;
    2839         *reinterpret_cast<QScriptValue*>(ptr) = value;
    2840         return true;
    2841     } else if (name == "QVariant") {
    2842         *reinterpret_cast<QVariant*>(ptr) = value.toVariant();
     3261        *reinterpret_cast<QScriptValue*>(ptr) = eng->scriptValueFromJSCValue(value);
    28433262        return true;
    28443263    }
     
    28503269            return false;
    28513270        qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
    2852         return convert(value, type, ptr, eng);
     3271        return convertValue(exec, value, type, ptr);
    28533272    }
    28543273#endif
     
    28573276            return false;
    28583277        qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
    2859         return convert(value, type, ptr, eng);
     3278        return convertValue(exec, value, type, ptr);
    28603279    }
    28613280
     
    28693288}
    28703289
     3290bool QScriptEnginePrivate::convertNumber(qsreal value, int type, void *ptr)
     3291{
     3292    switch (QMetaType::Type(type)) {
     3293    case QMetaType::Bool:
     3294        *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value);
     3295        return true;
     3296    case QMetaType::Int:
     3297        *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value);
     3298        return true;
     3299    case QMetaType::UInt:
     3300        *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value);
     3301        return true;
     3302    case QMetaType::LongLong:
     3303        *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value));
     3304        return true;
     3305    case QMetaType::ULongLong:
     3306        *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value));
     3307        return true;
     3308    case QMetaType::Double:
     3309        *reinterpret_cast<double*>(ptr) = value;
     3310        return true;
     3311    case QMetaType::QString:
     3312        *reinterpret_cast<QString*>(ptr) = QScript::ToString(value);
     3313        return true;
     3314    case QMetaType::Float:
     3315        *reinterpret_cast<float*>(ptr) = value;
     3316        return true;
     3317    case QMetaType::Short:
     3318        *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value));
     3319        return true;
     3320    case QMetaType::UShort:
     3321        *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value);
     3322        return true;
     3323    case QMetaType::Char:
     3324        *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value));
     3325        return true;
     3326    case QMetaType::UChar:
     3327        *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value));
     3328        return true;
     3329    case QMetaType::QChar:
     3330        *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value));
     3331        return true;
     3332    default:
     3333        break;
     3334    }
     3335    return false;
     3336}
     3337
     3338bool QScriptEnginePrivate::convertString(const QString &value, int type, void *ptr)
     3339{
     3340    switch (QMetaType::Type(type)) {
     3341    case QMetaType::Bool:
     3342        *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value);
     3343        return true;
     3344    case QMetaType::Int:
     3345        *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value);
     3346        return true;
     3347    case QMetaType::UInt:
     3348        *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value);
     3349        return true;
     3350    case QMetaType::LongLong:
     3351        *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value));
     3352        return true;
     3353    case QMetaType::ULongLong:
     3354        *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value));
     3355        return true;
     3356    case QMetaType::Double:
     3357        *reinterpret_cast<double*>(ptr) = QScript::ToNumber(value);
     3358        return true;
     3359    case QMetaType::QString:
     3360        *reinterpret_cast<QString*>(ptr) = value;
     3361        return true;
     3362    case QMetaType::Float:
     3363        *reinterpret_cast<float*>(ptr) = QScript::ToNumber(value);
     3364        return true;
     3365    case QMetaType::Short:
     3366        *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value));
     3367        return true;
     3368    case QMetaType::UShort:
     3369        *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value);
     3370        return true;
     3371    case QMetaType::Char:
     3372        *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value));
     3373        return true;
     3374    case QMetaType::UChar:
     3375        *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value));
     3376        return true;
     3377    case QMetaType::QChar:
     3378        *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value));
     3379        return true;
     3380    default:
     3381        break;
     3382    }
     3383    return false;
     3384}
     3385
    28713386bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
    28723387{
     
    28753390}
    28763391
     3392JSC::UString QScriptEnginePrivate::translationContextFromUrl(const JSC::UString &url)
     3393{
     3394    if (url != cachedTranslationUrl) {
     3395        cachedTranslationContext = QFileInfo(url).baseName();
     3396        cachedTranslationUrl = url;
     3397    }
     3398    return cachedTranslationContext;
     3399}
     3400
    28773401/*!
    28783402    \internal
     
    28813405{
    28823406    Q_D(QScriptEngine);
    2883     return QScriptEnginePrivate::convert(value, type, ptr, d);
     3407    QScript::APIShim shim(d);
     3408    return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr);
    28843409}
    28853410
     
    28893414bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
    28903415{
    2891     return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0);
     3416    QScriptValuePrivate *vp = QScriptValuePrivate::get(value);
     3417    if (vp) {
     3418        switch (vp->type) {
     3419        case QScriptValuePrivate::JavaScriptCore: {
     3420            if (vp->engine) {
     3421                QScript::APIShim shim(vp->engine);
     3422                return QScriptEnginePrivate::convertValue(vp->engine->currentFrame, vp->jscValue, type, ptr);
     3423            } else {
     3424                return QScriptEnginePrivate::convertValue(0, vp->jscValue, type, ptr);
     3425            }
     3426        }
     3427        case QScriptValuePrivate::Number:
     3428            return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr);
     3429        case QScriptValuePrivate::String:
     3430            return QScriptEnginePrivate::convertString(vp->stringValue, type, ptr);
     3431        }
     3432    }
     3433    return false;
    28923434}
    28933435
     
    29003442{
    29013443    Q_D(QScriptEngine);
     3444    QScript::APIShim shim(d);
    29023445    QScriptTypeInfo *info = d->m_typeInfos.value(type);
    29033446    if (!info) {
     
    29253468    \row    \o qsTranslate() \o QCoreApplication::translate()
    29263469    \row    \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
     3470    \row    \o qsTrId() (since 4.7) \o qtTrId()
     3471    \row    \o QT_TRID_NOOP() (since 4.7) \o QT_TRID_NOOP()
    29273472    \endtable
    29283473
     
    29323477{
    29333478    Q_D(QScriptEngine);
     3479    QScript::APIShim shim(d);
    29343480    JSC::ExecState* exec = d->currentFrame;
    29353481    JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
     
    29403486    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
    29413487    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
    2942     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::PrototypeFunction(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
     3488    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
    29433489    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
     3490    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "qsTrId"), QScript::functionQsTrId));
     3491    JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TRID_NOOP"), QScript::functionQsTrIdNoOp));
    29443492
    29453493    glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
     
    29653513#else
    29663514    Q_D(QScriptEngine);
     3515    QScript::APIShim shim(d);
    29673516    if (d->importedExtensions.contains(extension))
    29683517        return undefinedValue(); // already imported
     
    34614010  request that garbage collection should be performed as soon as
    34624011  possible.
     4012
     4013  \sa reportAdditionalMemoryCost()
    34634014*/
    34644015void QScriptEngine::collectGarbage()
     
    34664017    Q_D(QScriptEngine);
    34674018    d->collectGarbage();
     4019}
     4020
     4021/*!
     4022  \since 4.7
     4023
     4024  Reports an additional memory cost of the given \a size, measured in
     4025  bytes, to the garbage collector.
     4026
     4027  This function can be called to indicate that a Qt Script object has
     4028  memory associated with it that isn't managed by Qt Script itself.
     4029  Reporting the additional cost makes it more likely that the garbage
     4030  collector will be triggered.
     4031
     4032  Note that if the additional memory is shared with objects outside
     4033  the scripting environment, the cost should not be reported, since
     4034  collecting the Qt Script object would not cause the memory to be
     4035  freed anyway.
     4036
     4037  Negative \a size values are ignored, i.e. this function can't be
     4038  used to report that the additional memory has been deallocated.
     4039
     4040  \sa collectGarbage()
     4041*/
     4042void QScriptEngine::reportAdditionalMemoryCost(int size)
     4043{
     4044    Q_D(QScriptEngine);
     4045    d->reportAdditionalMemoryCost(size);
    34684046}
    34694047
     
    35484126{
    35494127    Q_D(QScriptEngine);
    3550 
     4128    if (!isEvaluating())
     4129        return;
     4130    d->abortResult = result;
    35514131    d->timeoutChecker()->setShouldAbort(true);
    3552     d->abortResult = result;
     4132    JSC::throwError(d->currentFrame, JSC::createInterruptedExecutionException(&d->currentFrame->globalData()).toObject(d->currentFrame));
    35534133}
    35544134
     
    35764156        return false;
    35774157    QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
     4158    QScript::APIShim shim(engine);
    35784159    JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
    35794160    JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
     
    36024183        return false;
    36034184    QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine());
     4185    QScript::APIShim shim(engine);
    36044186    JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver);
    36054187    JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function);
     
    36464228        return;
    36474229    }
     4230    QScript::APIShim shim(d);
    36484231    if (d->activeAgent)
    36494232        QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
     
    36814264{
    36824265    Q_D(QScriptEngine);
    3683     QScriptString result;
    3684     QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated);
    3685     QScriptStringPrivate::init(result, p);
    3686     d->registerScriptString(p);
    3687     return result;
     4266    QScript::APIShim shim(d);
     4267    return d->toStringHandle(JSC::Identifier(d->currentFrame, str));
    36884268}
    36894269
     
    37104290{
    37114291    Q_D(QScriptEngine);
     4292    QScript::APIShim shim(d);
    37124293    JSC::JSValue jscValue = d->scriptValueToJSCValue(value);
    37134294    if (!jscValue || jscValue.isUndefined() || jscValue.isNull())
     
    38614442#endif
    38624443
     4444#ifdef Q_CC_MSVC
     4445// Try to prevent compiler from crashing.
     4446#pragma optimize("", off)
     4447#endif
     4448
    38634449QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.