diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2010-02-18 14:29:32 (GMT) |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2010-02-18 16:36:22 (GMT) |
commit | d5af42b1b7d792188c689d5425493756f2dcb79e (patch) | |
tree | 3b0874e3409b53efe881171272cd1342cbf98515 | |
parent | 8e0a364f7baed4bbc7ff711be2a15692a40c3e93 (diff) | |
download | Qt-d5af42b1b7d792188c689d5425493756f2dcb79e.zip Qt-d5af42b1b7d792188c689d5425493756f2dcb79e.tar.gz Qt-d5af42b1b7d792188c689d5425493756f2dcb79e.tar.bz2 |
Avoid calling out to public API in the QtScript implementation
There's no reason to construct QScriptValues when JSC::JSValues
can be operated on directly. A benchmark showed that ~10% of the
time for reading a QObject property from a script was spent just
creating and destroying QScriptValue temporaries. It's time to
finally get rid of this potential bottleneck, not just in the
QObject integration but everywhere.
This change refactors the code so that all internal operations
are performed on JSC::JSValue (most importantly, conversion
from/to Qt types), and the public API functions are just thin
wrappers around these. E.g. instead of doing
enginePrivate->scriptValueFromJSCValue(jsValue).toQObject()
the implementation now does
QScriptEnginePrivate::toQObject(jsValue)
Other operations are delegated to the engine implementation
in similar style.
Task-number: QTBUG-8304
Reviewed-by: Jedrzej Nowacki
-rw-r--r-- | src/script/api/qscriptengine.cpp | 487 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 150 | ||||
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 106 | ||||
-rw-r--r-- | src/script/api/qscriptvalue_p.h | 3 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject.cpp | 2 | ||||
-rw-r--r-- | src/script/bridge/qscriptdeclarativeclass.cpp | 16 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 106 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant.cpp | 2 |
8 files changed, 513 insertions, 359 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index a045bab..739b3fc 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -54,6 +54,7 @@ #include "TimeoutChecker.h" #include "JSFunction.h" #include "Parser.h" +#include "PropertyNameArray.h" #include "Operations.h" #include "bridge/qscriptfunction_p.h" @@ -546,11 +547,9 @@ JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObjec if (isFunction(arg1)) slot = arg1; else { - // ### don't go via QScriptValue QScript::SaveFrameHelper saveFrame(engine, exec); - QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); - QString propertyName(arg1.toString(exec)); - slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); + QString propertyName(QScriptEnginePrivate::toString(exec, arg1)); + slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); } } @@ -630,11 +629,9 @@ JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * if (isFunction(arg1)) slot = arg1; else { - // ### don't go via QScriptValue QScript::SaveFrameHelper saveFrame(engine, exec); - QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); - QString propertyName = arg1.toString(exec); - slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); + QString propertyName = QScriptEnginePrivate::toString(exec, arg1); + slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); } } @@ -908,22 +905,15 @@ QScriptEnginePrivate::~QScriptEnginePrivate() } } -QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v) -{ - QScriptValue result = create(v.userType(), v.data()); - Q_ASSERT(result.isValid()); - return result; -} - -QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType) +QVariant QScriptEnginePrivate::jscValueToVariant(JSC::ExecState *exec, JSC::JSValue value, int targetType) { QVariant v(targetType, (void *)0); - if (QScriptEnginePrivate::convert(value, targetType, v.data(), this)) + if (convertValue(exec, value, targetType, v.data())) return v; if (uint(targetType) == QVariant::LastType) - return value.toVariant(); - if (value.isVariant()) { - v = value.toVariant(); + return toVariant(exec, value); + if (isVariant(value)) { + v = variantValue(value); if (v.canConvert(QVariant::Type(targetType))) { v.convert(QVariant::Type(targetType)); return v; @@ -934,88 +924,61 @@ QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, i return QVariant(targetType, *reinterpret_cast<void* *>(v.data())); } } - return QVariant(); } -JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v) -{ - // ### it's inefficient to convert to QScriptValue and then to JSValue - QScriptValue vv = scriptValueFromVariant(v); - QScriptValuePrivate *p = QScriptValuePrivate::get(vv); - switch (p->type) { - case QScriptValuePrivate::JavaScriptCore: - return p->jscValue; - case QScriptValuePrivate::Number: - return JSC::jsNumber(currentFrame, p->numberValue); - case QScriptValuePrivate::String: { - JSC::UString str = p->stringValue; - return JSC::jsString(currentFrame, str); - } - } - return JSC::JSValue(); -} - -QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType) +JSC::JSValue QScriptEnginePrivate::arrayFromStringList(JSC::ExecState *exec, const QStringList &lst) { - // ### it's inefficient to convert to QScriptValue and then to QVariant - return scriptValueToVariant(scriptValueFromJSCValue(value), targetType); -} - -QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst) -{ - Q_Q(QScriptEngine); - QScriptValue arr = q->newArray(lst.size()); + JSC::JSValue arr = newArray(exec, lst.size()); for (int i = 0; i < lst.size(); ++i) - arr.setProperty(i, QScriptValue(q, lst.at(i))); + setProperty(exec, arr, i, JSC::jsString(exec, lst.at(i))); return arr; } -QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr) +QStringList QScriptEnginePrivate::stringListFromArray(JSC::ExecState *exec, JSC::JSValue arr) { QStringList lst; - uint len = arr.property(QLatin1String("length")).toUInt32(); + uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length)); for (uint i = 0; i < len; ++i) - lst.append(arr.property(i).toString()); + lst.append(toString(exec, property(exec, arr, i))); return lst; } -QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst) +JSC::JSValue QScriptEnginePrivate::arrayFromVariantList(JSC::ExecState *exec, const QVariantList &lst) { - Q_Q(QScriptEngine); - QScriptValue arr = q->newArray(lst.size()); + JSC::JSValue arr = newArray(exec, lst.size()); for (int i = 0; i < lst.size(); ++i) - arr.setProperty(i, scriptValueFromVariant(lst.at(i))); + setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i))); return arr; } -QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr) +QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSValue arr) { QVariantList lst; - uint len = arr.property(QLatin1String("length")).toUInt32(); + uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length)); for (uint i = 0; i < len; ++i) - lst.append(arr.property(i).toVariant()); + lst.append(toVariant(exec, property(exec, arr, i))); return lst; } -QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap) +JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap) { - Q_Q(QScriptEngine); - QScriptValue obj = q->newObject(); + JSC::JSValue obj = JSC::constructEmptyObject(exec); QVariantMap::const_iterator it; for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) - obj.setProperty(it.key(), scriptValueFromVariant(it.value())); + setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value())); return obj; } -QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj) +QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSValue obj) { + JSC::PropertyNameArray propertyNames(exec); + propertyNames.setShouldCache(false); + JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, /*includeNonEnumerable=*/true); QVariantMap vmap; - QScriptValueIterator it(obj); - while (it.hasNext()) { - it.next(); - vmap.insert(it.name(), it.value().toVariant()); - } + JSC::PropertyNameArray::const_iterator it = propertyNames.begin(); + for( ; it != propertyNames.end(); ++it) + vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it))); return vmap; } @@ -1344,13 +1307,13 @@ JSC::JSValue QScriptEnginePrivate::newQMetaObject( return result; } -bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value, +bool QScriptEnginePrivate::convertToNativeQObject(JSC::ExecState *exec, JSC::JSValue value, const QByteArray &targetType, void **result) { if (!targetType.endsWith('*')) return false; - if (QObject *qobject = value.toQObject()) { + if (QObject *qobject = toQObject(exec, value)) { int start = targetType.startsWith("const ") ? 6 : 0; QByteArray className = targetType.mid(start, targetType.size()-start-1); if (void *instance = qobject->qt_metacast(className)) { @@ -1577,6 +1540,76 @@ JSC::JSValue QScriptEnginePrivate::newVariant(const QVariant &value) return obj; } +JSC::JSValue QScriptEnginePrivate::newVariant(JSC::JSValue objectValue, + const QVariant &value) +{ + if (!isObject(objectValue)) + return newVariant(value); + JSC::JSObject *jscObject = JSC::asObject(objectValue); + if (!jscObject->inherits(&QScriptObject::info)) { + qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); + return JSC::JSValue(); + } + QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); + if (!isVariant(objectValue)) { + jscScriptObject->setDelegate(new QScript::QVariantDelegate(value)); + } else { + setVariantValue(objectValue, value); + } + return objectValue; +} + +#ifndef QT_NO_REGEXP + +QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value) +{ + if (!isRegExp(value)) + return QRegExp(); + QString pattern = toString(exec, property(exec, value, QLatin1String("source"), QScriptValue::ResolvePrototype)); + Qt::CaseSensitivity kase = Qt::CaseSensitive; + if (toBool(exec, property(exec, value, QLatin1String("ignoreCase"), QScriptValue::ResolvePrototype))) + kase = Qt::CaseInsensitive; + return QRegExp(pattern, kase, QRegExp::RegExp2); +} + +#endif + +QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue value) +{ + if (isObject(value)) { + if (isVariant(value)) + return variantValue(value); +#ifndef QT_NO_QOBJECT + else if (isQObject(value)) + return qVariantFromValue(toQObject(exec, value)); +#endif + else if (isDate(value)) + return QVariant(toDateTime(exec, value)); +#ifndef QT_NO_REGEXP + else if (isRegExp(value)) + return QVariant(toRegExp(exec, value)); +#endif + else if (isArray(value)) + return variantListFromArray(exec, value); + else if (QScriptDeclarativeClass *dc = declarativeClass(value)) + return dc->toVariant(declarativeObject(value)); + // try to convert to primitive + JSC::JSValue savedException; + saveException(exec, &savedException); + JSC::JSValue prim = value.toPrimitive(exec); + restoreException(exec, savedException); + if (!prim.isObject()) + return toVariant(exec, prim); + } else if (value.isNumber()) { + return QVariant(toNumber(exec, value)); + } else if (value.isString()) { + return QVariant(toString(exec, value)); + } else if (value.isBoolean()) { + return QVariant(toBool(exec, value)); + } + return QVariant(); +} + JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode) { JSC::JSValue result; @@ -1963,20 +1996,9 @@ QScriptValue QScriptEngine::newVariant(const QVariant &value) QScriptValue QScriptEngine::newVariant(const QScriptValue &object, const QVariant &value) { - if (!object.isObject()) - return newVariant(value); - JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue); - if (!jscObject->inherits(&QScriptObject::info)) { - qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); - return QScriptValue(); - } - QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); - if (!object.isVariant()) { - jscScriptObject->setDelegate(new QScript::QVariantDelegate(value)); - } else { - QScriptValuePrivate::get(object)->setVariantValue(value); - } - return object; + Q_D(QScriptEngine); + JSC::JSValue jsObject = d->scriptValueToJSCValue(object); + return d->scriptValueFromJSCValue(d->newVariant(jsObject, value)); } #ifndef QT_NO_QOBJECT @@ -2789,128 +2811,126 @@ void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prot QScriptValue QScriptEngine::create(int type, const void *ptr) { Q_D(QScriptEngine); - return d->create(type, ptr); + return d->scriptValueFromJSCValue(d->create(d->currentFrame, type, ptr)); } -QScriptValue QScriptEnginePrivate::create(int type, const void *ptr) +JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const void *ptr) { - Q_Q(QScriptEngine); Q_ASSERT(ptr != 0); - QScriptValue result; - QScriptTypeInfo *info = m_typeInfos.value(type); + JSC::JSValue result; + QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0; + QScriptTypeInfo *info = eng ? eng->m_typeInfos.value(type) : 0; if (info && info->marshal) { - result = info->marshal(q, ptr); + result = eng->scriptValueToJSCValue(info->marshal(eng->q_func(), ptr)); } else { // check if it's one of the types we know switch (QMetaType::Type(type)) { case QMetaType::Void: - return QScriptValue(q, QScriptValue::UndefinedValue); + return JSC::jsUndefined(); case QMetaType::Bool: - return QScriptValue(q, *reinterpret_cast<const bool*>(ptr)); + return JSC::jsBoolean(*reinterpret_cast<const bool*>(ptr)); case QMetaType::Int: - return QScriptValue(q, *reinterpret_cast<const int*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const int*>(ptr)); case QMetaType::UInt: - return QScriptValue(q, *reinterpret_cast<const uint*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const uint*>(ptr)); case QMetaType::LongLong: - return QScriptValue(q, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); + return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); case QMetaType::ULongLong: #if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 #pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); + return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); #elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); + return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); #else - return QScriptValue(q, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); + return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); #endif case QMetaType::Double: - return QScriptValue(q, qsreal(*reinterpret_cast<const double*>(ptr))); + return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr))); case QMetaType::QString: - return QScriptValue(q, *reinterpret_cast<const QString*>(ptr)); + return JSC::jsString(exec, *reinterpret_cast<const QString*>(ptr)); case QMetaType::Float: - return QScriptValue(q, *reinterpret_cast<const float*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const float*>(ptr)); case QMetaType::Short: - return QScriptValue(q, *reinterpret_cast<const short*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const short*>(ptr)); case QMetaType::UShort: - return QScriptValue(q, *reinterpret_cast<const unsigned short*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const unsigned short*>(ptr)); case QMetaType::Char: - return QScriptValue(q, *reinterpret_cast<const char*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const char*>(ptr)); case QMetaType::UChar: - return QScriptValue(q, *reinterpret_cast<const unsigned char*>(ptr)); + return JSC::jsNumber(exec, *reinterpret_cast<const unsigned char*>(ptr)); case QMetaType::QChar: - return QScriptValue(q, (*reinterpret_cast<const QChar*>(ptr)).unicode()); + return JSC::jsNumber(exec, (*reinterpret_cast<const QChar*>(ptr)).unicode()); case QMetaType::QStringList: - result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr)); + result = arrayFromStringList(exec, *reinterpret_cast<const QStringList *>(ptr)); break; case QMetaType::QVariantList: - result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr)); + result = arrayFromVariantList(exec, *reinterpret_cast<const QVariantList *>(ptr)); break; case QMetaType::QVariantMap: - result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr)); + result = objectFromVariantMap(exec, *reinterpret_cast<const QVariantMap *>(ptr)); break; case QMetaType::QDateTime: - result = q->newDate(*reinterpret_cast<const QDateTime *>(ptr)); + result = newDate(exec, *reinterpret_cast<const QDateTime *>(ptr)); break; case QMetaType::QDate: - result = q->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr))); + result = newDate(exec, QDateTime(*reinterpret_cast<const QDate *>(ptr))); break; #ifndef QT_NO_REGEXP case QMetaType::QRegExp: - result = q->newRegExp(*reinterpret_cast<const QRegExp *>(ptr)); + result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr)); break; #endif #ifndef QT_NO_QOBJECT case QMetaType::QObjectStar: case QMetaType::QWidgetStar: - result = q->newQObject(*reinterpret_cast<QObject* const *>(ptr)); + result = eng->newQObject(*reinterpret_cast<QObject* const *>(ptr)); break; #endif default: if (type == qMetaTypeId<QScriptValue>()) { - result = *reinterpret_cast<const QScriptValue*>(ptr); - if (!result.isValid()) - return QScriptValue(q, QScriptValue::UndefinedValue); + result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr)); + if (!result) + return JSC::jsUndefined(); } #ifndef QT_NO_QOBJECT // lazy registration of some common list types else if (type == qMetaTypeId<QObjectList>()) { - qScriptRegisterSequenceMetaType<QObjectList>(q); - return create(type, ptr); + qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); + return create(exec, type, ptr); } #endif else if (type == qMetaTypeId<QList<int> >()) { - qScriptRegisterSequenceMetaType<QList<int> >(q); - return create(type, ptr); + qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); + return create(exec, type, ptr); } else { QByteArray typeName = QMetaType::typeName(type); if (typeName == "QVariant") - result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr)); + result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr)) - return QScriptValue(q, QScriptValue::NullValue); + return JSC::jsNull(); else - result = q->newVariant(QVariant(type, ptr)); + result = eng->newVariant(QVariant(type, ptr)); } } } - if (result.isObject() && info && info->prototype - && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) { - result.setPrototype(scriptValueFromJSCValue(info->prototype)); + if (result && result.isObject() && info && info->prototype + && JSC::JSValue::strictEqual(JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { + JSC::asObject(result)->setPrototype(info->prototype); } return result; } -bool QScriptEnginePrivate::convert(const QScriptValue &value, - int type, void *ptr, - QScriptEnginePrivate *eng) +bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value, + int type, void *ptr) { - if (!eng) - eng = QScriptValuePrivate::getEngine(value); + QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0; if (eng) { QScriptTypeInfo *info = eng->m_typeInfos.value(type); if (info && info->demarshal) { - info->demarshal(value, ptr); + info->demarshal(eng->scriptValueFromJSCValue(value), ptr); return true; } } @@ -2918,78 +2938,78 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, // check if it's one of the types we know switch (QMetaType::Type(type)) { case QMetaType::Bool: - *reinterpret_cast<bool*>(ptr) = value.toBoolean(); + *reinterpret_cast<bool*>(ptr) = toBool(exec, value); return true; case QMetaType::Int: - *reinterpret_cast<int*>(ptr) = value.toInt32(); + *reinterpret_cast<int*>(ptr) = toInt32(exec, value); return true; case QMetaType::UInt: - *reinterpret_cast<uint*>(ptr) = value.toUInt32(); + *reinterpret_cast<uint*>(ptr) = toUInt32(exec, value); return true; case QMetaType::LongLong: - *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger()); + *reinterpret_cast<qlonglong*>(ptr) = qlonglong(toInteger(exec, value)); return true; case QMetaType::ULongLong: - *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger()); + *reinterpret_cast<qulonglong*>(ptr) = qulonglong(toInteger(exec, value)); return true; case QMetaType::Double: - *reinterpret_cast<double*>(ptr) = value.toNumber(); + *reinterpret_cast<double*>(ptr) = toNumber(exec, value); return true; case QMetaType::QString: if (value.isUndefined() || value.isNull()) *reinterpret_cast<QString*>(ptr) = QString(); else - *reinterpret_cast<QString*>(ptr) = value.toString(); + *reinterpret_cast<QString*>(ptr) = toString(exec, value); return true; case QMetaType::Float: - *reinterpret_cast<float*>(ptr) = value.toNumber(); + *reinterpret_cast<float*>(ptr) = toNumber(exec, value); return true; case QMetaType::Short: - *reinterpret_cast<short*>(ptr) = short(value.toInt32()); + *reinterpret_cast<short*>(ptr) = short(toInt32(exec, value)); return true; case QMetaType::UShort: - *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16(); + *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(toNumber(exec, value)); return true; case QMetaType::Char: - *reinterpret_cast<char*>(ptr) = char(value.toInt32()); + *reinterpret_cast<char*>(ptr) = char(toInt32(exec, value)); return true; case QMetaType::UChar: - *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32()); + *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(toInt32(exec, value)); return true; case QMetaType::QChar: if (value.isString()) { - QString str = value.toString(); + QString str = toString(exec, value); *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0); } else { - *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16()); + *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(toNumber(exec, value))); } return true; case QMetaType::QDateTime: - if (value.isDate()) { - *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime(); + if (isDate(value)) { + *reinterpret_cast<QDateTime *>(ptr) = toDateTime(exec, value); return true; } break; case QMetaType::QDate: - if (value.isDate()) { - *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date(); + if (isDate(value)) { + *reinterpret_cast<QDate *>(ptr) = toDateTime(exec, value).date(); return true; } break; #ifndef QT_NO_REGEXP case QMetaType::QRegExp: - if (value.isRegExp()) { - *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp(); + if (isRegExp(value)) { + *reinterpret_cast<QRegExp *>(ptr) = toRegExp(exec, value); return true; } break; #endif #ifndef QT_NO_QOBJECT case QMetaType::QObjectStar: - if (value.isQObject() || value.isNull()) { - *reinterpret_cast<QObject* *>(ptr) = value.toQObject(); + if (isQObject(value) || value.isNull()) { + *reinterpret_cast<QObject* *>(ptr) = toQObject(exec, value); return true; } break; case QMetaType::QWidgetStar: - if (value.isQObject() || value.isNull()) { - QObject *qo = value.toQObject(); + if (isQObject(value) || value.isNull()) { + QObject *qo = toQObject(exec, value); if (!qo || qo->isWidgetType()) { *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo); return true; @@ -2997,18 +3017,18 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, } break; #endif case QMetaType::QStringList: - if (value.isArray()) { - *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value); + if (isArray(value)) { + *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value); return true; } break; case QMetaType::QVariantList: - if (value.isArray()) { - *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value); + if (isArray(value)) { + *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, value); return true; } break; case QMetaType::QVariantMap: - if (value.isObject()) { - *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value); + if (isObject(value)) { + *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, value); return true; } break; default: @@ -3017,28 +3037,28 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, QByteArray name = QMetaType::typeName(type); #ifndef QT_NO_QOBJECT - if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr))) + if (convertToNativeQObject(exec, value, name, reinterpret_cast<void* *>(ptr))) return true; #endif - if (value.isVariant() && name.endsWith('*')) { + if (isVariant(value) && name.endsWith('*')) { int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant &var = QScriptValuePrivate::get(value)->variantValue(); + QVariant &var = variantValue(value); if (valueType == var.userType()) { *reinterpret_cast<void* *>(ptr) = var.data(); return true; } else { // look in the prototype chain - QScriptValue proto = value.prototype(); + JSC::JSValue proto = JSC::asObject(value)->prototype(); while (proto.isObject()) { bool canCast = false; - if (proto.isVariant()) { - canCast = (type == proto.toVariant().userType()) - || (valueType && (valueType == proto.toVariant().userType())); + if (isVariant(proto)) { + canCast = (type == variantValue(proto).userType()) + || (valueType && (valueType == variantValue(proto).userType())); } #ifndef QT_NO_QOBJECT - else if (proto.isQObject()) { + else if (isQObject(proto)) { QByteArray className = name.left(name.size()-1); - if (QObject *qobject = proto.toQObject()) + if (QObject *qobject = toQObject(exec, proto)) canCast = qobject->qt_metacast(className) != 0; } #endif @@ -3050,7 +3070,7 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, *reinterpret_cast<void* *>(ptr) = var.data(); return true; } - proto = proto.prototype(); + proto = JSC::asObject(proto)->prototype(); } } } else if (value.isNull() && name.endsWith('*')) { @@ -3059,10 +3079,10 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, } else if (type == qMetaTypeId<QScriptValue>()) { if (!eng) return false; - *reinterpret_cast<QScriptValue*>(ptr) = value; + *reinterpret_cast<QScriptValue*>(ptr) = eng->scriptValueFromJSCValue(value); return true; } else if (name == "QVariant") { - *reinterpret_cast<QVariant*>(ptr) = value.toVariant(); + *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value); return true; } @@ -3072,14 +3092,14 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, if (!eng) return false; qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); - return convert(value, type, ptr, eng); + return convertValue(exec, value, type, ptr); } #endif else if (type == qMetaTypeId<QList<int> >()) { if (!eng) return false; qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); - return convert(value, type, ptr, eng); + return convertValue(exec, value, type, ptr); } #if 0 @@ -3091,6 +3111,102 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, return false; } +bool QScriptEnginePrivate::convertNumber(qsreal value, int type, void *ptr) +{ + switch (QMetaType::Type(type)) { + case QMetaType::Bool: + *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value); + return true; + case QMetaType::Int: + *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value); + return true; + case QMetaType::UInt: + *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value); + return true; + case QMetaType::LongLong: + *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value)); + return true; + case QMetaType::ULongLong: + *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value)); + return true; + case QMetaType::Double: + *reinterpret_cast<double*>(ptr) = value; + return true; + case QMetaType::QString: + *reinterpret_cast<QString*>(ptr) = QScript::ToString(value); + return true; + case QMetaType::Float: + *reinterpret_cast<float*>(ptr) = value; + return true; + case QMetaType::Short: + *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value)); + return true; + case QMetaType::UShort: + *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value); + return true; + case QMetaType::Char: + *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value)); + return true; + case QMetaType::UChar: + *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value)); + return true; + case QMetaType::QChar: + *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value)); + return true; + default: + break; + } + return false; +} + +bool QScriptEnginePrivate::convertString(const QString &value, int type, void *ptr) +{ + switch (QMetaType::Type(type)) { + case QMetaType::Bool: + *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value); + return true; + case QMetaType::Int: + *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value); + return true; + case QMetaType::UInt: + *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value); + return true; + case QMetaType::LongLong: + *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value)); + return true; + case QMetaType::ULongLong: + *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value)); + return true; + case QMetaType::Double: + *reinterpret_cast<double*>(ptr) = QScript::ToNumber(value); + return true; + case QMetaType::QString: + *reinterpret_cast<QString*>(ptr) = value; + return true; + case QMetaType::Float: + *reinterpret_cast<float*>(ptr) = QScript::ToNumber(value); + return true; + case QMetaType::Short: + *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value)); + return true; + case QMetaType::UShort: + *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value); + return true; + case QMetaType::Char: + *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value)); + return true; + case QMetaType::UChar: + *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value)); + return true; + case QMetaType::QChar: + *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value)); + return true; + default: + break; + } + return false; +} + bool QScriptEnginePrivate::hasDemarshalFunction(int type) const { QScriptTypeInfo *info = m_typeInfos.value(type); @@ -3103,7 +3219,7 @@ bool QScriptEnginePrivate::hasDemarshalFunction(int type) const bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) { Q_D(QScriptEngine); - return QScriptEnginePrivate::convert(value, type, ptr, d); + return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr); } /*! @@ -3111,7 +3227,20 @@ bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) */ bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) { - return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0); + QScriptValuePrivate *vp = QScriptValuePrivate::get(value); + if (vp) { + switch (vp->type) { + case QScriptValuePrivate::JavaScriptCore: { + JSC::ExecState *exec = vp->engine ? vp->engine->currentFrame : 0; + return QScriptEnginePrivate::convertValue(exec, vp->jscValue, type, ptr); + } + case QScriptValuePrivate::Number: + return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr); + case QScriptValuePrivate::String: + return QScriptEnginePrivate::convertString(vp->stringValue, type, ptr); + } + } + return false; } /*! diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 4be9146..eff34af 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -44,7 +44,12 @@ #include <QtCore/qset.h> #include "qscriptvalue_p.h" #include "qscriptstring_p.h" +#include "bridge/qscriptclassobject_p.h" +#include "bridge/qscriptdeclarativeclass_p.h" +#include "bridge/qscriptdeclarativeobject_p.h" #include "bridge/qscriptobject_p.h" +#include "bridge/qscriptqobject_p.h" +#include "bridge/qscriptvariant_p.h" #include "utils/qscriptdate_p.h" #include "DateConstructor.h" @@ -145,6 +150,8 @@ public: static inline bool isObject(JSC::JSValue); static inline bool isRegExp(JSC::JSValue); static inline bool isVariant(JSC::JSValue); + static inline bool isQObject(JSC::JSValue); + static inline bool isQMetaObject(JSC::JSValue); static inline bool toBool(JSC::ExecState *, JSC::JSValue); static inline qsreal toInteger(JSC::ExecState *, JSC::JSValue); @@ -155,6 +162,12 @@ public: static inline QString toString(JSC::ExecState *, JSC::JSValue); static inline QDateTime toDateTime(JSC::ExecState *, JSC::JSValue); +#ifndef QT_NO_REGEXP + static QRegExp toRegExp(JSC::ExecState*, JSC::JSValue); +#endif + static QVariant toVariant(JSC::ExecState *, JSC::JSValue); + static inline QObject *toQObject(JSC::ExecState *, JSC::JSValue); + static inline const QMetaObject *toQMetaObject(JSC::ExecState *, JSC::JSValue); static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, const JSC::Identifier &id, int resolveMode = QScriptValue::ResolvePrototype); @@ -174,29 +187,29 @@ public: static inline QScriptValue::PropertyFlags propertyFlags(JSC::ExecState*, JSC::JSValue value, const QString &name, const QScriptValue::ResolveFlags &mode); - static bool convert(const QScriptValue &value, - int type, void *ptr, - QScriptEnginePrivate *eng); - QScriptValue create(int type, const void *ptr); + static bool convertValue(JSC::ExecState*, JSC::JSValue value, + int type, void *ptr); + static bool convertNumber(qsreal, int type, void *ptr); + static bool convertString(const QString &, int type, void *ptr); + static JSC::JSValue create(JSC::ExecState*, int type, const void *ptr); bool hasDemarshalFunction(int type) const; inline QScriptValue scriptValueFromJSCValue(JSC::JSValue value); inline JSC::JSValue scriptValueToJSCValue(const QScriptValue &value); - QScriptValue scriptValueFromVariant(const QVariant &value); - QVariant scriptValueToVariant(const QScriptValue &value, int targetType); - - JSC::JSValue jscValueFromVariant(const QVariant &value); - QVariant jscValueToVariant(JSC::JSValue value, int targetType); + static inline JSC::JSValue jscValueFromVariant(JSC::ExecState*, const QVariant &value); + static QVariant jscValueToVariant(JSC::ExecState*, JSC::JSValue value, int targetType); + static inline QVariant &variantValue(JSC::JSValue value); + static inline void setVariantValue(JSC::JSValue objectValue, const QVariant &value); - QScriptValue arrayFromStringList(const QStringList &lst); - static QStringList stringListFromArray(const QScriptValue &arr); + static JSC::JSValue arrayFromStringList(JSC::ExecState*, const QStringList &lst); + static QStringList stringListFromArray(JSC::ExecState*, JSC::JSValue arr); - QScriptValue arrayFromVariantList(const QVariantList &lst); - static QVariantList variantListFromArray(const QScriptValue &arr); + static JSC::JSValue arrayFromVariantList(JSC::ExecState*, const QVariantList &lst); + static QVariantList variantListFromArray(JSC::ExecState*, JSC::JSValue arr); - QScriptValue objectFromVariantMap(const QVariantMap &vmap); - static QVariantMap variantMapFromObject(const QScriptValue &obj); + static JSC::JSValue objectFromVariantMap(JSC::ExecState*, const QVariantMap &vmap); + static QVariantMap variantMapFromObject(JSC::ExecState*, JSC::JSValue obj); JSC::JSValue defaultPrototype(int metaTypeId) const; void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype); @@ -269,6 +282,10 @@ public: static JSC::JSValue newRegExp(JSC::ExecState *, const QString &pattern, const QString &flags); JSC::JSValue newVariant(const QVariant &); + JSC::JSValue newVariant(JSC::JSValue objectValue, const QVariant &); + + static inline QScriptDeclarativeClass *declarativeClass(JSC::JSValue); + static inline QScriptDeclarativeClass::Object *declarativeObject(JSC::JSValue); #ifndef QT_NO_QOBJECT JSC::JSValue newQObject(QObject *object, @@ -277,7 +294,7 @@ public: JSC::JSValue newQMetaObject(const QMetaObject *metaObject, JSC::JSValue ctor); - static bool convertToNativeQObject(const QScriptValue &value, + static bool convertToNativeQObject(JSC::ExecState*, JSC::JSValue, const QByteArray &targetType, void **result); @@ -525,6 +542,13 @@ inline void QScriptEnginePrivate::unregisterScriptValue(QScriptValuePrivate *val value->next = 0; } +inline JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(JSC::ExecState *exec, const QVariant &v) +{ + JSC::JSValue result = create(exec, v.userType(), v.data()); + Q_ASSERT(result); + return result; +} + inline QScriptValue QScriptEnginePrivate::scriptValueFromJSCValue(JSC::JSValue value) { if (!value) @@ -801,6 +825,30 @@ inline bool QScriptEnginePrivate::isVariant(JSC::JSValue value) return (delegate && (delegate->type() == QScriptObjectDelegate::Variant)); } +inline bool QScriptEnginePrivate::isQObject(JSC::JSValue value) +{ +#ifndef QT_NO_QOBJECT + if (!isObject(value) || !value.inherits(&QScriptObject::info)) + return false; + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value)); + QScriptObjectDelegate *delegate = object->delegate(); + return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject || + (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject && + static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->isQObject()))); +#else + return false; +#endif +} + +inline bool QScriptEnginePrivate::isQMetaObject(JSC::JSValue value) +{ +#ifndef QT_NO_QOBJECT + return JSC::asObject(value)->inherits(&QScript::QMetaObjectWrapperObject::info); +#else + return false; +#endif +} + inline bool QScriptEnginePrivate::toBool(JSC::ExecState *exec, JSC::JSValue value) { JSC::JSValue savedException; @@ -876,6 +924,76 @@ inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *, JSC::JSValue return QScript::ToDateTime(t, Qt::LocalTime); } +inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value) +{ +#ifndef QT_NO_QOBJECT + if (isObject(value) && value.inherits(&QScriptObject::info)) { + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value)); + QScriptObjectDelegate *delegate = object->delegate(); + if (!delegate) + return 0; + if (delegate->type() == QScriptObjectDelegate::QtObject) + return static_cast<QScript::QObjectDelegate*>(delegate)->value(); + if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject) + return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->toQObject(declarativeObject(value)); + if (delegate->type() == QScriptObjectDelegate::Variant) { + QVariant var = variantValue(value); + int type = var.userType(); + if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar)) + return *reinterpret_cast<QObject* const *>(var.constData()); + } + } +#endif + return 0; +} + +inline const QMetaObject *QScriptEnginePrivate::toQMetaObject(JSC::ExecState*, JSC::JSValue value) +{ +#ifndef QT_NO_QOBJECT + if (isQMetaObject(value)) + return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(value))->value(); +#endif + return 0; +} + +inline QVariant &QScriptEnginePrivate::variantValue(JSC::JSValue value) +{ + Q_ASSERT(value.inherits(&QScriptObject::info)); + QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(value))->delegate(); + Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); + return static_cast<QScript::QVariantDelegate*>(delegate)->value(); +} + +inline void QScriptEnginePrivate::setVariantValue(JSC::JSValue objectValue, const QVariant &value) +{ + Q_ASSERT(objectValue.inherits(&QScriptObject::info)); + QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(objectValue))->delegate(); + Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); + static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value); +} + +inline QScriptDeclarativeClass *QScriptEnginePrivate::declarativeClass(JSC::JSValue v) +{ + if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info)) + return 0; + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(v)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return 0; + return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass(); +} + +inline QScriptDeclarativeClass::Object *QScriptEnginePrivate::declarativeObject(JSC::JSValue v) +{ + if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info)) + return 0; + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(v)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return 0; + return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object(); +} + QT_END_NAMESPACE #endif diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index a7d9f79..7f1fdaa 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -42,14 +42,6 @@ #include <QtCore/qvarlengtharray.h> #include <QtCore/qnumeric.h> -#include "utils/qscriptdate_p.h" -#include "bridge/qscriptobject_p.h" -#include "bridge/qscriptclassobject_p.h" -#include "bridge/qscriptvariant_p.h" -#include "bridge/qscriptqobject_p.h" -#include "bridge/qscriptdeclarativeclass_p.h" -#include "bridge/qscriptdeclarativeobject_p.h" - /*! \since 4.3 \class QScriptValue @@ -176,22 +168,6 @@ QT_BEGIN_NAMESPACE -QVariant &QScriptValuePrivate::variantValue() const -{ - Q_ASSERT(jscValue.inherits(&QScriptObject::info)); - QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate(); - Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); - return static_cast<QScript::QVariantDelegate*>(delegate)->value(); -} - -void QScriptValuePrivate::setVariantValue(const QVariant &value) -{ - Q_ASSERT(jscValue.inherits(&QScriptObject::info)); - QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate(); - Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); - static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value); -} - void QScriptValuePrivate::detachFromEngine() { if (isJSC()) @@ -1205,40 +1181,10 @@ QVariant QScriptValue::toVariant() const if (!d) return QVariant(); switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: - if (isObject()) { - if (isVariant()) - return d->variantValue(); -#ifndef QT_NO_QOBJECT - else if (isQObject()) - return qVariantFromValue(toQObject()); -#endif - else if (isDate()) - return QVariant(toDateTime()); -#ifndef QT_NO_REGEXP - else if (isRegExp()) - return QVariant(toRegExp()); -#endif - else if (isArray()) - return QScriptEnginePrivate::variantListFromArray(*this); - else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) - return dc->toVariant(QScriptDeclarativeClass::object(*this)); - // try to convert to primitive - JSC::ExecState *exec = d->engine->currentFrame; - JSC::JSValue savedException; - QScriptEnginePrivate::saveException(exec, &savedException); - JSC::JSValue prim = d->jscValue.toPrimitive(exec); - QScriptEnginePrivate::restoreException(exec, savedException); - if (!prim.isObject()) - return d->engine->scriptValueFromJSCValue(prim).toVariant(); - } else if (isNumber()) { - return QVariant(toNumber()); - } else if (isString()) { - return QVariant(toString()); - } else if (isBool()) { - return QVariant(toBool()); - } - return QVariant(); + case QScriptValuePrivate::JavaScriptCore: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + return QScriptEnginePrivate::toVariant(exec, d->jscValue); + } case QScriptValuePrivate::Number: return QVariant(d->numberValue); case QScriptValuePrivate::String: @@ -1286,13 +1232,9 @@ QDateTime QScriptValue::toDateTime() const QRegExp QScriptValue::toRegExp() const { Q_D(const QScriptValue); - if (!isRegExp()) - return QRegExp(); - QString pattern = property(QLatin1String("source"), QScriptValue::ResolvePrototype).toString(); - Qt::CaseSensitivity kase = Qt::CaseSensitive; - if (property(QLatin1String("ignoreCase"), QScriptValue::ResolvePrototype).toBool()) - kase = Qt::CaseInsensitive; - return QRegExp(pattern, kase, QRegExp::RegExp2); + if (!d || !d->engine) + return QRegExp(); + return QScriptEnginePrivate::toRegExp(d->engine->currentFrame, d->jscValue); } #endif // QT_NO_REGEXP @@ -1309,19 +1251,9 @@ QRegExp QScriptValue::toRegExp() const QObject *QScriptValue::toQObject() const { Q_D(const QScriptValue); - if (isQObject()) { - QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = object->delegate(); - if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject) - return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->toQObject(QScriptDeclarativeClass::object(*this)); - return static_cast<QScript::QObjectDelegate*>(delegate)->value(); - } else if (isVariant()) { - QVariant var = toVariant(); - int type = var.userType(); - if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar)) - return *reinterpret_cast<QObject* const *>(var.constData()); - } - return 0; + if (!d || !d->engine) + return 0; + return QScriptEnginePrivate::toQObject(d->engine->currentFrame, d->jscValue); } /*! @@ -1333,9 +1265,9 @@ QObject *QScriptValue::toQObject() const const QMetaObject *QScriptValue::toQMetaObject() const { Q_D(const QScriptValue); - if (isQMetaObject()) - return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(d->jscValue))->value(); - return 0; + if (!d || !d->engine) + return 0; + return QScriptEnginePrivate::toQMetaObject(d->engine->currentFrame, d->jscValue); } /*! @@ -1971,13 +1903,9 @@ bool QScriptValue::isVariant() const bool QScriptValue::isQObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) + if (!d || !d->isJSC()) return false; - QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = object->delegate(); - return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject || - (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject && - static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->isQObject()))); + return QScriptEnginePrivate::isQObject(d->jscValue); } /*! @@ -1989,9 +1917,9 @@ bool QScriptValue::isQObject() const bool QScriptValue::isQMetaObject() const { Q_D(const QScriptValue); - if (!d || !d->isObject()) + if (!d || !d->isJSC()) return false; - return JSC::asObject(d->jscValue)->inherits(&QScript::QMetaObjectWrapperObject::info); + return QScriptEnginePrivate::isQMetaObject(d->jscValue); } /*! diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index dedc250..77b7330 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -69,9 +69,6 @@ public: inline bool isJSC() const; inline bool isObject() const; - QVariant &variantValue() const; - void setVariantValue(const QVariant &value); - static inline QScriptValuePrivate *get(const QScriptValue &q) { return q.d_ptr.data(); diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index a3dd239..ce0a08e 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -206,7 +206,7 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC:: QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); eng_p->popContext(); eng_p->currentFrame = oldFrame; - return eng_p->jscValueFromVariant(result); + return QScriptEnginePrivate::jscValueFromVariant(exec, result); } JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index ce2fc23..1d11ede 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -207,25 +207,17 @@ QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine, QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) + if (!d || !d->isJSC()) return 0; - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) - return 0; - return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass(); + return QScriptEnginePrivate::declarativeClass(d->jscValue); } QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) - return 0; - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + if (!d || !d->isJSC()) return 0; - return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object(); + return QScriptEnginePrivate::declarativeObject(d->jscValue); } QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name) diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index db312bc..30e5a26 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -169,17 +169,15 @@ static inline QByteArray methodName(const QMetaMethod &method) return signature.left(signature.indexOf('(')); } -static QVariant variantFromValue(QScriptEnginePrivate *eng, - int targetType, const QScriptValue &value) +static QVariant variantFromValue(JSC::ExecState *exec, int targetType, JSC::JSValue value) { QVariant v(targetType, (void *)0); - Q_ASSERT(eng); - if (QScriptEnginePrivate::convert(value, targetType, v.data(), eng)) + if (QScriptEnginePrivate::convertValue(exec, value, targetType, v.data())) return v; if (uint(targetType) == QVariant::LastType) - return value.toVariant(); - if (value.isVariant()) { - v = value.toVariant(); + return QScriptEnginePrivate::toVariant(exec, value); + if (QScriptEnginePrivate::isVariant(value)) { + v = QScriptEnginePrivate::variantValue(value); if (v.canConvert(QVariant::Type(targetType))) { v.convert(QVariant::Type(targetType)); return v; @@ -591,38 +589,38 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c bool converted = true; int matchDistance = 0; for (int i = 0; converted && i < mtd.argumentCount(); ++i) { - QScriptValue actual; + JSC::JSValue actual; if (i < (int)scriptArgs.size()) - actual = engine->scriptValueFromJSCValue(scriptArgs.at(i)); + actual = scriptArgs.at(i); else - actual = QScriptValue(QScriptValue::UndefinedValue); + actual = JSC::jsUndefined(); QScriptMetaType argType = mtd.argumentType(i); int tid = -1; QVariant v; if (argType.isUnresolved()) { v = QVariant(QMetaType::QObjectStar, (void *)0); - converted = engine->convertToNativeQObject( - actual, argType.name(), reinterpret_cast<void* *>(v.data())); + converted = QScriptEnginePrivate::convertToNativeQObject( + exec, actual, argType.name(), reinterpret_cast<void* *>(v.data())); } else if (argType.isVariant()) { - if (actual.isVariant()) { - v = actual.toVariant(); + if (QScriptEnginePrivate::isVariant(actual)) { + v = QScriptEnginePrivate::variantValue(actual); } else { - v = actual.toVariant(); + v = QScriptEnginePrivate::toVariant(exec, actual); converted = v.isValid() || actual.isUndefined() || actual.isNull(); } } else { tid = argType.typeId(); v = QVariant(tid, (void *)0); - converted = QScriptEnginePrivate::convert(actual, tid, v.data(), engine); + converted = QScriptEnginePrivate::convertValue(exec, actual, tid, v.data()); if (exec->hadException()) return exec->exception(); } if (!converted) { - if (actual.isVariant()) { + if (QScriptEnginePrivate::isVariant(actual)) { if (tid == -1) tid = argType.typeId(); - QVariant vv = actual.toVariant(); + QVariant vv = QScriptEnginePrivate::variantValue(actual); if (vv.canConvert(QVariant::Type(tid))) { v = vv; converted = v.convert(QVariant::Type(tid)); @@ -649,14 +647,14 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c } if (m.isValid()) { if (actual.isNumber()) { - int ival = actual.toInt32(); + int ival = QScriptEnginePrivate::toInt32(exec, actual); if (m.valueToKey(ival) != 0) { qVariantSetValue(v, ival); converted = true; matchDistance += 10; } } else { - QString sval = actual.toString(); + QString sval = QScriptEnginePrivate::toString(exec, actual); int ival = m.keyToValue(sval.toLatin1()); if (ival != -1) { qVariantSetValue(v, ival); @@ -718,7 +716,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isDate()) { + } else if (QScriptEnginePrivate::isDate(actual)) { switch (tid) { case QMetaType::QDateTime: // perfect @@ -733,7 +731,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isRegExp()) { + } else if (QScriptEnginePrivate::isRegExp(actual)) { switch (tid) { case QMetaType::QRegExp: // perfect @@ -742,14 +740,14 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isVariant()) { + } else if (QScriptEnginePrivate::isVariant(actual)) { if (argType.isVariant() - || (actual.toVariant().userType() == tid)) { + || (QScriptEnginePrivate::toVariant(exec, actual).userType() == tid)) { // perfect } else { matchDistance += 10; } - } else if (actual.isArray()) { + } else if (QScriptEnginePrivate::isArray(actual)) { switch (tid) { case QMetaType::QStringList: case QMetaType::QVariantList: @@ -759,7 +757,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isQObject()) { + } else if (QScriptEnginePrivate::isQObject(actual)) { switch (tid) { case QMetaType::QObjectStar: case QMetaType::QWidgetStar: @@ -953,13 +951,11 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c } else { QScriptMetaType retType = chosenMethod.returnType(); if (retType.isVariant()) { - result = engine->jscValueFromVariant(*(QVariant *)params[0]); + result = QScriptEnginePrivate::jscValueFromVariant(exec, *(QVariant *)params[0]); } else if (retType.typeId() != 0) { - result = engine->scriptValueToJSCValue(engine->create(retType.typeId(), params[0])); - if (!result) { - QScriptValue sv = QScriptEnginePrivate::get(engine)->newVariant(QVariant(retType.typeId(), params[0])); - result = engine->scriptValueToJSCValue(sv); - } + result = QScriptEnginePrivate::create(exec, retType.typeId(), params[0]); + if (!result) + result = engine->newVariant(QVariant(retType.typeId(), params[0])); } else { result = JSC::jsUndefined(); } @@ -1065,15 +1061,13 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, { JSC::JSValue result = JSC::jsUndefined(); - // ### don't go via QScriptValue QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - QScriptValue object = engine->scriptValueFromJSCValue(thisValue); - QObject *qobject = object.toQObject(); + QObject *qobject = QScriptEnginePrivate::toQObject(exec, thisValue); while ((!qobject || (qobject->metaObject() != data->meta)) - && object.prototype().isObject()) { - object = object.prototype(); - qobject = object.toQObject(); + && JSC::asObject(thisValue)->prototype().isObject()) { + thisValue = JSC::asObject(thisValue)->prototype(); + qobject = QScriptEnginePrivate::toQObject(exec, thisValue); } Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject"); @@ -1094,7 +1088,7 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, if (scriptable) QScriptablePrivate::get(scriptable)->engine = oldEngine; - result = engine->jscValueFromVariant(v); + result = QScriptEnginePrivate::jscValueFromVariant(exec, v); } } else { // set @@ -1106,9 +1100,7 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, // string to enum value v = (QString)arg.toString(exec); } else { - // ### don't go via QScriptValue - QScriptValue tmp = engine->scriptValueFromJSCValue(arg); - v = variantFromValue(engine, prop.userType(), tmp); + v = variantFromValue(exec, prop.userType(), arg); } QScriptable *scriptable = scriptableFromQObject(qobject); @@ -1237,7 +1229,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * if (!prop.isValid()) val = JSC::jsUndefined(); else - val = eng->jscValueFromVariant(prop.read(qobject)); + val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject)); slot.setValue(val); } return true; @@ -1247,7 +1239,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * index = qobject->dynamicPropertyNames().indexOf(name); if (index != -1) { - JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); + JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name)); slot.setValue(val); return true; } @@ -1274,8 +1266,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * QObject *child = children.at(index); if (child->objectName() == QString(propertyName.ustring())) { QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); - slot.setValue(eng->scriptValueToJSCValue(tmp)); + slot.setValue(eng->newQObject(child, QScriptEngine::QtOwnership, opt)); return true; } } @@ -1370,7 +1361,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS if (!prop.isValid()) val = JSC::jsUndefined(); else - val = eng->jscValueFromVariant(prop.read(qobject)); + val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject)); descriptor.setDescriptor(val, attributes); } return true; @@ -1380,7 +1371,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS index = qobject->dynamicPropertyNames().indexOf(name); if (index != -1) { - JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); + JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name)); descriptor.setDescriptor(val, QObjectMemberAttribute); return true; } @@ -1410,8 +1401,8 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS QObject *child = children.at(index); if (child->objectName() == QString(propertyName.ustring())) { QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); - descriptor.setDescriptor(eng->scriptValueToJSCValue(tmp), JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum); + descriptor.setDescriptor(eng->newQObject(child, QScriptEngine::QtOwnership, opt), + JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum); return true; } } @@ -1490,7 +1481,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, // string to enum value v = (QString)value.toString(exec); } else { - v = eng->jscValueToVariant(value, prop.userType()); + v = QScriptEnginePrivate::jscValueToVariant(exec, value, prop.userType()); } (void)prop.write(qobject, v); } @@ -1512,7 +1503,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, index = qobject->dynamicPropertyNames().indexOf(name); if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) { - QVariant v = eng->scriptValueFromJSCValue(value).toVariant(); + QVariant v = QScriptEnginePrivate::toVariant(exec, value); (void)qobject->setProperty(name, v); return; } @@ -2178,24 +2169,23 @@ void QObjectConnectionManager::execute(int slotIndex, void **argv) JSC::ExecState *exec = engine->currentFrame; QVarLengthArray<JSC::JSValue, 8> argsVector(argc); for (int i = 0; i < argc; ++i) { - // ### optimize -- no need to convert via QScriptValue - QScriptValue actual; + JSC::JSValue actual; void *arg = argv[i + 1]; QByteArray typeName = parameterTypes.at(i); int argType = QMetaType::type(parameterTypes.at(i)); if (!argType) { if (typeName == "QVariant") { - actual = engine->scriptValueFromVariant(*reinterpret_cast<QVariant*>(arg)); + actual = QScriptEnginePrivate::jscValueFromVariant(exec, *reinterpret_cast<QVariant*>(arg)); } else { qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' " "when invoking handler of signal %s::%s", typeName.constData(), meta->className(), method.signature()); - actual = QScriptValue(QScriptValue::UndefinedValue); + actual = JSC::jsUndefined(); } } else { - actual = engine->create(argType, arg); + actual = QScriptEnginePrivate::create(exec, argType, arg); } - argsVector[i] = engine->scriptValueToJSCValue(actual); + argsVector[i] = actual; } JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp index 0287d24..b4f0365 100644 --- a/src/script/bridge/qscriptvariant.cpp +++ b/src/script/bridge/qscriptvariant.cpp @@ -133,7 +133,7 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, bool QVariantDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2) { const QVariant &variant1 = value(); - return variant1 == scriptEngineFromExec(exec)->scriptValueFromJSCValue(o2).toVariant(); + return variant1 == QScriptEnginePrivate::toVariant(exec, o2); } QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure, |