src/script/api/qscriptengine.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    62 #include "bridge/qscriptclassobject_p.h"
    62 #include "bridge/qscriptclassobject_p.h"
    63 #include "bridge/qscriptvariant_p.h"
    63 #include "bridge/qscriptvariant_p.h"
    64 #include "bridge/qscriptqobject_p.h"
    64 #include "bridge/qscriptqobject_p.h"
    65 #include "bridge/qscriptglobalobject_p.h"
    65 #include "bridge/qscriptglobalobject_p.h"
    66 #include "bridge/qscriptactivationobject_p.h"
    66 #include "bridge/qscriptactivationobject_p.h"
       
    67 #include "bridge/qscriptstaticscopeobject_p.h"
    67 
    68 
    68 #ifndef QT_NO_QOBJECT
    69 #ifndef QT_NO_QOBJECT
    69 #include <QtCore/qcoreapplication.h>
    70 #include <QtCore/qcoreapplication.h>
    70 #include <QtCore/qdir.h>
    71 #include <QtCore/qdir.h>
    71 #include <QtCore/qfile.h>
    72 #include <QtCore/qfile.h>
   434 {
   435 {
   435     return ((JSC::UString)value).toDouble();
   436     return ((JSC::UString)value).toDouble();
   436 }
   437 }
   437 
   438 
   438 #endif
   439 #endif
       
   440 
       
   441 static const qsreal MsPerSecond = 1000.0;
       
   442 
       
   443 static inline int MsFromTime(qsreal t)
       
   444 {
       
   445     int r = int(::fmod(t, MsPerSecond));
       
   446     return (r >= 0) ? r : r + int(MsPerSecond);
       
   447 }
       
   448 
       
   449 /*!
       
   450   \internal
       
   451   Converts a JS date value (milliseconds) to a QDateTime (local time).
       
   452 */
       
   453 QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t)
       
   454 {
       
   455     if (qIsNaN(t))
       
   456         return QDateTime();
       
   457     JSC::GregorianDateTime tm;
       
   458     JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm);
       
   459     int ms = MsFromTime(t);
       
   460     QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
       
   461                                        QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
       
   462     return convertedUTC.toLocalTime();
       
   463 }
       
   464 
       
   465 /*!
       
   466   \internal
       
   467   Converts a QDateTime to a JS date value (milliseconds).
       
   468 */
       
   469 qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt)
       
   470 {
       
   471     if (!dt.isValid())
       
   472         return qSNaN();
       
   473     QDateTime utc = dt.toUTC();
       
   474     QDate date = utc.date();
       
   475     QTime time = utc.time();
       
   476     JSC::GregorianDateTime tm;
       
   477     tm.year = date.year() - 1900;
       
   478     tm.month = date.month() - 1;
       
   479     tm.monthDay = date.day();
       
   480     tm.weekDay = date.dayOfWeek();
       
   481     tm.yearDay = date.dayOfYear();
       
   482     tm.hour = time.hour();
       
   483     tm.minute = time.minute();
       
   484     tm.second = time.second();
       
   485     return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true);
       
   486 }
   439 
   487 
   440 void GlobalClientData::mark(JSC::MarkStack& markStack)
   488 void GlobalClientData::mark(JSC::MarkStack& markStack)
   441 {
   489 {
   442     engine->mark(markStack);
   490     engine->mark(markStack);
   443 }
   491 }
   903     JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
   951     JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
   904 
   952 
   905     JSC::ExecState* exec = globalObject->globalExec();
   953     JSC::ExecState* exec = globalObject->globalExec();
   906 
   954 
   907     scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
   955     scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype());
       
   956     staticScopeObjectStructure = QScriptStaticScopeObject::createStructure(JSC::jsNull());
   908 
   957 
   909     qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
   958     qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
   910     qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
   959     qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype);
   911 
   960 
   912     qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
   961     qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure());
  1009     for (int i = 0; i < lst.size(); ++i)
  1058     for (int i = 0; i < lst.size(); ++i)
  1010         setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i)));
  1059         setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i)));
  1011     return arr;
  1060     return arr;
  1012 }
  1061 }
  1013 
  1062 
  1014 QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSValue arr)
  1063 QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSArray *arr)
  1015 {
  1064 {
       
  1065     QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
       
  1066     if (eng->visitedConversionObjects.contains(arr))
       
  1067         return QVariantList(); // Avoid recursion.
       
  1068     eng->visitedConversionObjects.insert(arr);
  1016     QVariantList lst;
  1069     QVariantList lst;
  1017     uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
  1070     uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length));
  1018     for (uint i = 0; i < len; ++i)
  1071     for (uint i = 0; i < len; ++i)
  1019         lst.append(toVariant(exec, property(exec, arr, i)));
  1072         lst.append(toVariant(exec, property(exec, arr, i)));
       
  1073     eng->visitedConversionObjects.remove(arr);
  1020     return lst;
  1074     return lst;
  1021 }
  1075 }
  1022 
  1076 
  1023 JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap)
  1077 JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap)
  1024 {
  1078 {
  1027     for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
  1081     for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
  1028         setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value()));
  1082         setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value()));
  1029     return obj;
  1083     return obj;
  1030 }
  1084 }
  1031 
  1085 
  1032 QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSValue obj)
  1086 QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSObject *obj)
  1033 {
  1087 {
       
  1088     QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec);
       
  1089     if (eng->visitedConversionObjects.contains(obj))
       
  1090         return QVariantMap(); // Avoid recursion.
       
  1091     eng->visitedConversionObjects.insert(obj);
  1034     JSC::PropertyNameArray propertyNames(exec);
  1092     JSC::PropertyNameArray propertyNames(exec);
  1035     JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties);
  1093     obj->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties);
  1036     QVariantMap vmap;
  1094     QVariantMap vmap;
  1037     JSC::PropertyNameArray::const_iterator it = propertyNames.begin();
  1095     JSC::PropertyNameArray::const_iterator it = propertyNames.begin();
  1038     for( ; it != propertyNames.end(); ++it)
  1096     for( ; it != propertyNames.end(); ++it)
  1039         vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it)));
  1097         vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it)));
       
  1098     eng->visitedConversionObjects.remove(obj);
  1040     return vmap;
  1099     return vmap;
  1041 }
  1100 }
  1042 
  1101 
  1043 JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
  1102 JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
  1044 {
  1103 {
  1523     registeredScriptStrings = 0;
  1582     registeredScriptStrings = 0;
  1524 }
  1583 }
  1525 
  1584 
  1526 #ifndef QT_NO_REGEXP
  1585 #ifndef QT_NO_REGEXP
  1527 
  1586 
  1528 Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
  1587 Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
  1529 
  1588 
  1530 JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp &regexp)
  1589 JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp &regexp)
  1531 {
  1590 {
  1532     JSC::JSValue buf[2];
  1591     JSC::JSValue buf[2];
  1533     JSC::ArgList args(buf, sizeof(buf));
  1592     JSC::ArgList args(buf, sizeof(buf));
  1659 #ifndef QT_NO_REGEXP
  1718 #ifndef QT_NO_REGEXP
  1660         else if (isRegExp(value))
  1719         else if (isRegExp(value))
  1661             return QVariant(toRegExp(exec, value));
  1720             return QVariant(toRegExp(exec, value));
  1662 #endif
  1721 #endif
  1663         else if (isArray(value))
  1722         else if (isArray(value))
  1664             return variantListFromArray(exec, value);
  1723             return variantListFromArray(exec, JSC::asArray(value));
  1665         else if (QScriptDeclarativeClass *dc = declarativeClass(value))
  1724         else if (QScriptDeclarativeClass *dc = declarativeClass(value))
  1666             return dc->toVariant(declarativeObject(value));
  1725             return dc->toVariant(declarativeObject(value));
  1667         // try to convert to primitive
  1726         return variantMapFromObject(exec, JSC::asObject(value));
  1668         JSC::JSValue savedException;
       
  1669         saveException(exec, &savedException);
       
  1670         JSC::JSValue prim = value.toPrimitive(exec);
       
  1671         restoreException(exec, savedException);
       
  1672         if (!prim.isObject())
       
  1673             return toVariant(exec, prim);
       
  1674     } else if (value.isNumber()) {
  1727     } else if (value.isNumber()) {
  1675         return QVariant(toNumber(exec, value));
  1728         return QVariant(toNumber(exec, value));
  1676     } else if (value.isString()) {
  1729     } else if (value.isString()) {
  1677         return QVariant(toString(exec, value));
  1730         return QVariant(toString(exec, value));
  1678     } else if (value.isBoolean()) {
  1731     } else if (value.isBoolean()) {
  1764             // ### check if it's a getter/setter property
  1817             // ### check if it's a getter/setter property
  1765             thisObject->deleteProperty(exec, id);
  1818             thisObject->deleteProperty(exec, id);
  1766         } else if (flags != QScriptValue::KeepExistingFlags) {
  1819         } else if (flags != QScriptValue::KeepExistingFlags) {
  1767             if (thisObject->hasOwnProperty(exec, id))
  1820             if (thisObject->hasOwnProperty(exec, id))
  1768                 thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes?
  1821                 thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes?
  1769             unsigned attribs = 0;
  1822             thisObject->putWithAttributes(exec, id, value, propertyFlagsToJSCAttributes(flags));
  1770             if (flags & QScriptValue::ReadOnly)
       
  1771                 attribs |= JSC::ReadOnly;
       
  1772             if (flags & QScriptValue::SkipInEnumeration)
       
  1773                 attribs |= JSC::DontEnum;
       
  1774             if (flags & QScriptValue::Undeletable)
       
  1775                 attribs |= JSC::DontDelete;
       
  1776             attribs |= flags & QScriptValue::UserRange;
       
  1777             thisObject->putWithAttributes(exec, id, value, attribs);
       
  1778         } else {
  1823         } else {
  1779             JSC::PutPropertySlot slot;
  1824             JSC::PutPropertySlot slot;
  1780             thisObject->put(exec, id, value, slot);
  1825             thisObject->put(exec, id, value, slot);
  1781         }
  1826         }
  1782     }
  1827     }
  2017                      QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
  2062                      QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
  2018     return result;
  2063     return result;
  2019 }
  2064 }
  2020 
  2065 
  2021 #ifndef QT_NO_REGEXP
  2066 #ifndef QT_NO_REGEXP
  2022 
       
  2023 Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
       
  2024 
  2067 
  2025 /*!
  2068 /*!
  2026   Creates a QtScript object of class RegExp with the given
  2069   Creates a QtScript object of class RegExp with the given
  2027   \a regexp.
  2070   \a regexp.
  2028 
  2071 
  3129             *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value);
  3172             *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value);
  3130             return true;
  3173             return true;
  3131         } break;
  3174         } break;
  3132     case QMetaType::QVariantList:
  3175     case QMetaType::QVariantList:
  3133         if (isArray(value)) {
  3176         if (isArray(value)) {
  3134             *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, value);
  3177             *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, JSC::asArray(value));
  3135             return true;
  3178             return true;
  3136         } break;
  3179         } break;
  3137     case QMetaType::QVariantMap:
  3180     case QMetaType::QVariantMap:
  3138         if (isObject(value)) {
  3181         if (isObject(value)) {
  3139             *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, value);
  3182             *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, JSC::asObject(value));
  3140             return true;
  3183             return true;
  3141         } break;
  3184         } break;
  3142     case QMetaType::QVariant:
  3185     case QMetaType::QVariant:
  3143         *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value);
  3186         *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value);
  3144         return true;
  3187         return true;